Compare commits

..

310 Commits

Author SHA1 Message Date
Tom Stellard
449c3ef93a Merging r300267:
------------------------------------------------------------------------
r300267 | tejohnson | 2017-04-13 17:51:49 -0400 (Thu, 13 Apr 2017) | 11 lines

[Support] Fix ErrorOr assertion when /proc/cpuinfo doesn't exist.

The ErrorOr should not be dereferenced on the error path.

Patch by Jacob Young

Reviewers: tejohnson

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D32032
------------------------------------------------------------------------

llvm-svn: 305264
2017-06-13 01:46:44 +00:00
Tom Stellard
fcf5f77b3e Merging r304537:
------------------------------------------------------------------------
r304537 | john.brawn | 2017-06-02 06:24:14 -0400 (Fri, 02 Jun 2017) | 9 lines

[GlobalMerge] Don't merge globals that may be preempted

When a global may be preempted it needs to be accessed directly, instead of
indirectly through a MergedGlobals symbol, for the preemption to work.

This fixes PR33136.

Differential Revision: https://reviews.llvm.org/D33727

------------------------------------------------------------------------

llvm-svn: 305187
2017-06-12 14:17:05 +00:00
Tom Stellard
162fcbc87e Revert "Driver: Don't mix system tools with devtoolset tools on RHEL"
This reverts commit r304293.

This was comitted accidentally.

llvm-svn: 304296
2017-05-31 10:01:14 +00:00
Tom Stellard
0405854650 Revert "Driver: Update devtoolset usage for RHEL"
This reverts commit r304292.

This was committed accidentally.

llvm-svn: 304295
2017-05-31 10:01:13 +00:00
Tom Stellard
88089ce734 Merging r298177:
------------------------------------------------------------------------
r298177 | niravd | 2017-03-17 20:43:39 -0400 (Fri, 17 Mar 2017) | 7 lines

[X86] Add NumRegisterParameters Module Flag.

Reviewers: rnk, mkuper

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D27051
------------------------------------------------------------------------

llvm-svn: 304294
2017-05-31 09:58:36 +00:00
Tom Stellard
5273e95db7 Driver: Don't mix system tools with devtoolset tools on RHEL
For example, we don't want to mix a devtoolset gcc with system ld, because
they don't always work together.

llvm-svn: 304293
2017-05-31 09:58:34 +00:00
Tom Stellard
ea94c6a3db Driver: Update devtoolset usage for RHEL
- remove path to dts-1.x (corresponds to gcc 4.7)
- add path to dts-6 (corresponds to 6.x)

Patch By: Maria Gottschalk

Differential Revision: https://reviews.llvm.org/D29855

llvm-svn: 304292
2017-05-31 09:58:32 +00:00
Tom Stellard
681ad6103c Merging r298179:
-----------------------------------------------------------------------
r298179 | niravd | 2017-03-17 20:44:07 -0400 (Fri, 17 Mar 2017) | 7 lines

Make library calls sensitive to regparm module flag (Fixes PR3997).

Reviewers: mkuper, rnk

Subscribers: mehdi_amini, jyknight, aemerson, llvm-commits, rengolin

Differential Revision: https://reviews.llvm.org/D27050
------------------------------------------------------------------------

llvm-svn: 304242
2017-05-30 20:36:49 +00:00
Tom Stellard
85556b078d Merging r293630:
------------------------------------------------------------------------
r293630 | mgorny | 2017-01-31 09:10:20 -0500 (Tue, 31 Jan 2017) | 22 lines

[cmake] Support running tests in stand-alone builds

Add the CMake bits necessary to run lld tests (and unittests) when
building stand-alone. The code is based on the equivalent code in clang,
and includes:

1. checking for Python, searching for lit and necessary LLVM test tools
(FileCount and not),

2. building LLVM test tools (FileCount and not) from LLVM sources if
they are not installed,

3. building gtest libraries from LLVM sources,

4. adjusting dependencies so that test targets depend only on those LLVM
targets that are available for a particular variant of stand-alone
build.

With this patch, I am able to successfully run 1002 (+10 unsupported)
lit tests on Gentoo using installed LLVM.

Differential Revision: https://reviews.llvm.org/D28750
------------------------------------------------------------------------

llvm-svn: 304238
2017-05-30 20:16:37 +00:00
Tom Stellard
e47a2cdbdf Merging r296994:
------------------------------------------------------------------------
r296994 | sanjoy | 2017-03-05 20:12:16 -0500 (Sun, 05 Mar 2017) | 10 lines

Adapt to llvm change r296992 to unbreak the bots

r296992 made ScalarEvolution's CompareValueComplexity less aggressive,
and that broke the polly test being fixed in this change.  This change
explicitly bumps CompareValueComplexity in said test case to make it
pass.

Can someone from the polly team please can give me an idea on if this
case is important enough to have
scalar-evolution-max-value-compare-depth be 3 by default?
------------------------------------------------------------------------

llvm-svn: 304213
2017-05-30 14:51:27 +00:00
Tom Stellard
3160d12317 Merging r302183:
------------------------------------------------------------------------
r302183 | kparzysz | 2017-05-04 15:14:54 -0400 (Thu, 04 May 2017) | 7 lines

[PPC] When restoring R30 (PIC base pointer), mark it as <def>

This happened on the PPC32/SVR4 path and was discovered when building
FreeBSD on PPC32. It was a typo-class error in the frame lowering code.

This fixes PR26519.

------------------------------------------------------------------------

llvm-svn: 304150
2017-05-29 11:56:29 +00:00
Tom Stellard
b98e0eb4fe Merging r303257:
------------------------------------------------------------------------
r303257 | kparzysz | 2017-05-17 09:25:09 -0400 (Wed, 17 May 2017) | 10 lines

[PPC] Properly update register save area offsets

The variables MinGPR/MinG8R were not updated properly when resetting the
offsets, which in the included testcase lead to saving the CR register
in the same location as R30.

This fixes another issue reported in PR26519.

Differential Revision: https://reviews.llvm.org/D33017

------------------------------------------------------------------------

llvm-svn: 304145
2017-05-29 10:36:17 +00:00
Tom Stellard
ae5b31fd8c Merging part of 292188:
------------------------------------------------------------------------
r292188 | ab | 2017-01-16 22:10:02 -0500 (Mon, 16 Jan 2017) | 11 lines

[TLI] Add prototype checking for all remaining LibFuncs.

This is another step towards unifying all LibFunc prototype checks.
This work started in r267758 (D19469);  add the remaining checks.

Also add a unittest that checks each libfunc declared with a known-valid
and known-invalid prototype.  New libfuncs added in the future are
required to have prototype checking in place; the known-valid test will
fail otherwise.

Differential Revision: https://reviews.llvm.org/D28030
------------------------------------------------------------------------

This ports just the fix for the log1p LibFunc to fix a crash on
FreeBSD.  See PR32494 and PR32495.

llvm-svn: 303992
2017-05-26 14:32:08 +00:00
Tom Stellard
0acbdf3faf Merging r303679:
------------------------------------------------------------------------
r303679 | oleg | 2017-05-23 15:38:37 -0400 (Tue, 23 May 2017) | 16 lines

[ARM] Temporarily disable globals promotion to constant pools to prevent miscompilation

Summary:
A temporary workaround for PR32780 - rematerialized instructions accessing the same promoted global through different constant pool entries.

The patch turns off the globals promotion optimization leaving all its code in place, so that it can be easily turned on once PR32780 is fixed.

Since this is a miscompilation issue causing generation of misbehaving code, and the problem is very subtle, the patch might be valuable enough to get into 4.0.1.

Reviewers: efriedma, jmolloy

Reviewed By: efriedma

Subscribers: aemerson, javed.absar, llvm-commits, rengolin, asl, tstellar

Differential Revision: https://reviews.llvm.org/D33446
------------------------------------------------------------------------

llvm-svn: 303749
2017-05-24 14:20:42 +00:00
Tom Stellard
7f150d5d55 Merging r302416:
------------------------------------------------------------------------
r302416 | mstorsjo | 2017-05-08 06:26:24 -0400 (Mon, 08 May 2017) | 19 lines

[ARM] Clear the constant pool cache on explicit .ltorg directives

Multiple ldr pseudoinstructions with the same constant value will
reuse the same constant pool entry. However, if the constant pool
is explicitly flushed with a .ltorg directive, we should not try
to reference constants in the previous pool any longer, since they
may be out of range.

This fixes assembling hand-written assembler source which repeatedly
loads the same constant value, across a binary size larger than the
pc-relative fixup range for ldr instructions (4096 bytes). Such
assembler source already uses explicit .ltorg instructions to emit
constant pools with regular intervals. However if we try to reuse
constants emitted in earlier pools, they end up out of range.

This makes the output of the testcase match what binutils gas does
(prior to this patch, it would fail to assemble).

Differential Revision: https://reviews.llvm.org/D32847
------------------------------------------------------------------------

llvm-svn: 303746
2017-05-24 14:08:01 +00:00
Tom Stellard
f6a7d32da8 Merging r303685:
------------------------------------------------------------------------
r303685 | tstellar | 2017-05-23 16:35:38 -0400 (Tue, 23 May 2017) | 5 lines

merge-request.sh: Use https url for bugzilla

With the http url, the script fails with:

Connection lost/failed: 411 Client Error: Length Required
------------------------------------------------------------------------

llvm-svn: 303688
2017-05-23 20:49:03 +00:00
Tom Stellard
050f5a34c0 Merging r303456:
------------------------------------------------------------------------
r303456 | eugenis | 2017-05-19 16:58:48 -0400 (Fri, 19 May 2017) | 3 lines

[safestack] Disable stack coloring by default.

Workaround for apparent miscompilation of PR32143.
------------------------------------------------------------------------

llvm-svn: 303687
2017-05-23 20:49:01 +00:00
Tom Stellard
fba307477f Merging r302137:
------------------------------------------------------------------------
r302137 | mstorsjo | 2017-05-04 06:54:35 -0400 (Thu, 04 May 2017) | 9 lines

[ArgPromotion] Fix a truncated variable

This fixes a regression since SVN rev 273808 (which was supposed to
not change functionality).

The regression caused miscompilations (noted in the wild when targeting
AArch64) on platforms with 32 bit long.

Differential Revision: https://reviews.llvm.org/D32850
------------------------------------------------------------------------

llvm-svn: 303661
2017-05-23 17:30:58 +00:00
Tom Stellard
baeb745dde Merging r299866:
------------------------------------------------------------------------
r299866 | arsenm | 2017-04-10 15:00:25 -0400 (Mon, 10 Apr 2017) | 3 lines

[MemCpyOpt] Only replace memcpy with bitcast if address spaces match

Patch by James Price
------------------------------------------------------------------------

llvm-svn: 303657
2017-05-23 17:13:15 +00:00
Jakub Kuderski
40078465cf [clang-tidy] Fix PR32896, PR33058: detect initializer lists in modernize-use-empalce
Summary:
The patch is backported from: r302281 to fix the 4.0.1 release blocker PR33058.
This patch fixes [[ https://bugs.llvm.org/show_bug.cgi?id=32896 | PR32896 ]].

The problem was that modernize-use-emplace incorrectly removed changed push_back into emplace_back, removing explicit constructor call with initializer list parameter, resulting in compiler error after applying fixits.
modernize-use-emplace used to check if matched constructor had InitListExpr, but didn't check against CXXStdInitializerListExpr.

Eg.

```
std::vector<std::vector<int>> v;
  v.push_back(std::vector<int>({1})); // --> v.emplace_back({1});
```

Reviewers: Prazek, alexfh, aaron.ballman

Reviewed By: Prazek, alexfh, aaron.ballman

Subscribers: xazax.hun, cfe-commits

Tags: #clang-tools-extra

Differential Revision: https://reviews.llvm.org/D32767

llvm-svn: 303524
2017-05-22 01:56:33 +00:00
Brad Smith
c128825cee Merging r298567:
------------------------------------------------------------------------
r298567 | davide | 2017-03-22 20:54:16 -0400 (Wed, 22 Mar 2017) | 3 lines

[ELF] Add -z nodlopen option.

Patch by Mark Kettenis.
------------------------------------------------------------------------

llvm-svn: 303455
2017-05-19 20:47:28 +00:00
Tom Stellard
c564b936c1 Merging r297403:
------------------------------------------------------------------------
r297403 | tstellar | 2017-03-09 14:24:07 -0500 (Thu, 09 Mar 2017) | 17 lines

CMake: Don't install llvm-tblgen twice

Summary:
The add_tablegen macros defines its own install target, and it was also calling
add_llvm_utility which adds another install target.

Configuring with -DLLVM_TOOLS_INSTALL_DIR set to something other than
'bin' along with -DLLVM_INSTALL_UTILS=ON was causing llvm-tablgen
to be installed to two separate directories.

Reviewers: beanz, hans

Reviewed By: beanz

Subscribers: llvm-commits, mgorny

Differential Revision: https://reviews.llvm.org/D30656
------------------------------------------------------------------------

llvm-svn: 303413
2017-05-19 10:13:18 +00:00
Tom Stellard
42ee3ff3c3 Merging r294690:
------------------------------------------------------------------------
r294690 | ericwf | 2017-02-09 20:59:20 -0500 (Thu, 09 Feb 2017) | 13 lines

[CMake] Fix pthread handling for out-of-tree builds

LLVM defines `PTHREAD_LIB` which is used by AddLLVM.cmake and various projects
to correctly link the threading library when needed. Unfortunately
`PTHREAD_LIB` is defined by LLVM's `config-ix.cmake` file which isn't installed
and therefore can't be used when configuring out-of-tree builds. This causes
such builds to fail since `pthread` isn't being correctly linked.

This patch attempts to fix that problem by renaming and exporting
`LLVM_PTHREAD_LIB` as part of`LLVMConfig.cmake`. I renamed `PTHREAD_LIB`
because It seemed likely to cause collisions with downstream users of
`LLVMConfig.cmake`.

------------------------------------------------------------------------

llvm-svn: 303401
2017-05-19 01:56:29 +00:00
Tom Stellard
3ff90e690e Merging r294690:
------------------------------------------------------------------------
r294690 | ericwf | 2017-02-09 20:59:20 -0500 (Thu, 09 Feb 2017) | 13 lines

[CMake] Fix pthread handling for out-of-tree builds

LLVM defines `PTHREAD_LIB` which is used by AddLLVM.cmake and various projects
to correctly link the threading library when needed. Unfortunately
`PTHREAD_LIB` is defined by LLVM's `config-ix.cmake` file which isn't installed
and therefore can't be used when configuring out-of-tree builds. This causes
such builds to fail since `pthread` isn't being correctly linked.

This patch attempts to fix that problem by renaming and exporting
`LLVM_PTHREAD_LIB` as part of`LLVMConfig.cmake`. I renamed `PTHREAD_LIB`
because It seemed likely to cause collisions with downstream users of
`LLVMConfig.cmake`.

------------------------------------------------------------------------

llvm-svn: 303400
2017-05-19 01:55:37 +00:00
Tom Stellard
ab5d0b03e4 Merging r294690:
------------------------------------------------------------------------
r294690 | ericwf | 2017-02-09 20:59:20 -0500 (Thu, 09 Feb 2017) | 13 lines

[CMake] Fix pthread handling for out-of-tree builds

LLVM defines `PTHREAD_LIB` which is used by AddLLVM.cmake and various projects
to correctly link the threading library when needed. Unfortunately
`PTHREAD_LIB` is defined by LLVM's `config-ix.cmake` file which isn't installed
and therefore can't be used when configuring out-of-tree builds. This causes
such builds to fail since `pthread` isn't being correctly linked.

This patch attempts to fix that problem by renaming and exporting
`LLVM_PTHREAD_LIB` as part of`LLVMConfig.cmake`. I renamed `PTHREAD_LIB`
because It seemed likely to cause collisions with downstream users of
`LLVMConfig.cmake`.

------------------------------------------------------------------------

llvm-svn: 303399
2017-05-19 01:55:05 +00:00
Tom Stellard
45e3f34afd Merging r302818:
------------------------------------------------------------------------
r302818 | rsmith | 2017-05-11 15:17:54 -0400 (Thu, 11 May 2017) | 2 lines

Work around different -std= default for PS4 target.

------------------------------------------------------------------------

llvm-svn: 303168
2017-05-16 13:33:50 +00:00
Tom Stellard
bef8b26033 Merging r302817:
------------------------------------------------------------------------
r302817 | rsmith | 2017-05-11 14:58:24 -0400 (Thu, 11 May 2017) | 9 lines

PR22877: When constructing an array via a constructor with a default argument
in list-initialization, run cleanups for the default argument after each
iteration of the initialization loop.

We previously only ran the destructor for any temporary once, at the end of the
complete loop, rather than once per iteration!

Re-commit of r302750, reverted in r302776.

------------------------------------------------------------------------

llvm-svn: 303167
2017-05-16 13:33:48 +00:00
Tom Stellard
f1f6d664a6 Merging r296163:
------------------------------------------------------------------------
r296163 | yaxunl | 2017-02-24 15:27:25 -0500 (Fri, 24 Feb 2017) | 9 lines

[InstCombine] Fix bug in pointer replacement

This optimisation was crashing when there was a chain of more than one bitcast
instruction to replace, as a result of the changes in D27283.

Patch by James Price.

Differential Revision: https://reviews.llvm.org/D30347

------------------------------------------------------------------------

llvm-svn: 303166
2017-05-16 12:48:20 +00:00
Tom Stellard
5ccc7f8d0f Merging r294313:
------------------------------------------------------------------------
r294313 | stulova | 2017-02-07 11:09:41 -0500 (Tue, 07 Feb 2017) | 9 lines

[OpenCL] Accept logical NOT for pointer types in CL1.1

Fix for bug 30217 - incorrect error given for logical
NOT operation with a pointer type: corrected sema check
and improved related tests.

Review: D29038

------------------------------------------------------------------------

llvm-svn: 303161
2017-05-16 12:00:44 +00:00
Renato Golin
a203fea142 Merging rr302639:
------------------------------------------------------------------------
r302639 | azanella | 2017-05-10 13:18:25 +0100 (Wed, 10 May 2017) | 11 lines

[msan] Fix getmntent{_r} for empty /etc/fstab

Some configuration (for instance default docker ubuntu images) uses
a default empty and invalid /etc/fstab configuration file.  It makes
any call to getmntent return NULL and it leads to failures on
Msan-aarch64{-with-call}-Test/MemorySanitizer.getmntent{_r}.

This patch fixes it by creating a temporary file with some valid
entries (although not valid for the system) to use along with
setmntent/getmntent.

------------------------------------------------------------------------

llvm-svn: 303146
2017-05-16 06:57:03 +00:00
Eric Fiselier
ebbec7be2b Merge r296561 - Fix PR32097 - is_abstract doesn't work on class templates.
llvm-svn: 302071
2017-05-03 19:50:39 +00:00
Eric Fiselier
28e24f9d8a Merge r300397 - Fix PR32642 - string::insert and string::append don't work with move_iterator.
llvm-svn: 302070
2017-05-03 19:48:55 +00:00
Brad Smith
6269fe4237 Merging r297098:
------------------------------------------------------------------------
r297098 | brad | 2017-03-06 18:48:31 -0500 (Mon, 06 Mar 2017) | 2 lines

Set the Int64Type / IntMaxType types correctly for OpenBSD/mips64
------------------------------------------------------------------------

llvm-svn: 301605
2017-04-28 00:36:13 +00:00
Krzysztof Parzyszek
ba8e6140c3 Merging r296645: (PR32253)
Included an updated testcase

------------------------------------------------------------------------
[Hexagon] Fix lowering of formal arguments of type i1

On Hexagon, values of type i1 are passed in registers of type i32,
even though i1 is not a legal value for these registers. This is a
special case and needs special handling to maintain consistency of
the lowering information.

This fixes PR32089.
------------------------------------------------------------------------

llvm-svn: 301550
2017-04-27 15:38:30 +00:00
Hans Wennborg
f761e7d6ca Merging r292034: (PR32315)
Tweaked to not remove the non-const variants as to not change the ABI.

------------------------------------------------------------------------
r292034 | majnemer | 2017-01-14 13:54:58 -0800 (Sat, 14 Jan 2017) | 7 lines

Adding const overloads of operator* and operator-> for DenseSet iterators

This fixes some problems when building ClangDiagnostics.cpp on Visual Studio 2017 RC. As far as I understand, there was a change in the implementation of the constructor for std::vector with two iterator parameters, which in our case causes an attempt to dereference const Iterator objects. Since there was no overload for a const Iterator, the compile would fail.

Patch by Hugo Puhlmann!

Differential Revision: https://reviews.llvm.org/D28726
------------------------------------------------------------------------

llvm-svn: 301479
2017-04-26 21:37:30 +00:00
Tom Stellard
6ccc7b4687 Merging r299574:
------------------------------------------------------------------------
r299574 | nico | 2017-04-05 14:10:42 -0400 (Wed, 05 Apr 2017) | 17 lines

clang-format: Support formatting utf-8 character literals in C++11+ mode.

clang-format <<END
auto c1 = u8'a';
auto c2 = u'a';
END

Before:
  auto c1 = u8 'a';
  auto c2 = u'a';

Now:
  auto c1 = u8'a';
  auto c2 = u'a';

Patch from Denis Gladkikh <llvm@denis.gladkikh.email>!

------------------------------------------------------------------------

llvm-svn: 301463
2017-04-26 20:48:39 +00:00
Tom Stellard
a6353c45f0 Merging r294786:
------------------------------------------------------------------------
r294786 | yaxunl | 2017-02-10 16:46:07 -0500 (Fri, 10 Feb 2017) | 24 lines

Fix invalid addrspacecast due to combining alloca with global var

For function-scope variables with large initialisation list, FE usually
generates a global variable to hold the initializer, then generates
memcpy intrinsic to initialize the alloca. InstCombiner::visitAllocaInst
identifies such allocas which are accessed only by reading and replaces
them with the global variable. This is done by casting the global variable
to the type of the alloca and replacing all references.

However, when the global variable is in a different address space which
is disjoint with addr space 0 (e.g. for IR generated from OpenCL,
global variable cannot be in private addr space i.e. addr space 0), casting
the global variable to addr space 0 results in invalid IR for certain
targets (e.g. amdgpu).

To fix this issue, when the global variable is not in addr space 0,
instead of casting it to addr space 0, this patch chases down the uses
of alloca until reaching the load instructions, then replaces load from
alloca with load from the global variable. If during the chasing
bitcast and GEP are encountered, new bitcast and GEP based on the global
variable are generated and used in the load instructions.

Differential Revision: https://reviews.llvm.org/D27283

------------------------------------------------------------------------

llvm-svn: 301452
2017-04-26 20:04:01 +00:00
Rui Ueyama
75bcf62c2c Merge r298569: Force @{init,fini}_array if section name starts with ".{init,fini}_array.".
Related bug: http://bugs.llvm.org/show_bug.cgi?id=32599

llvm-svn: 301447
2017-04-26 19:29:40 +00:00
Rui Ueyama
3c83314036 Merge r298568: Print out "suppoted targets"
llvm-svn: 301446
2017-04-26 19:20:41 +00:00
Rui Ueyama
af86b56438 Merge r298570: Fix Windows buildbots
llvm-svn: 301445
2017-04-26 19:17:54 +00:00
Rui Ueyama
57032a187e Merge r298532: Add "(compatible with GNU linkers)" to the -version output.
Cherrypick request: http://bugs.llvm.org/show_bug.cgi?id=32601

llvm-svn: 301444
2017-04-26 19:15:42 +00:00
Tom Stellard
1245486738 Merging r300429:
------------------------------------------------------------------------
r300429 | d0k | 2017-04-16 16:13:08 -0400 (Sun, 16 Apr 2017) | 7 lines

[X86] Remove special handling for 16 bit for A asm constraints.

Our 16 bit support is assembler-only + the terrible hack that is
.code16gcc. Simply using 32 bit registers does the right thing for the
latter.

Fixes PR32681.
------------------------------------------------------------------------

llvm-svn: 301437
2017-04-26 17:52:15 +00:00
Tom Stellard
39445ab0b1 Merging r300404:
------------------------------------------------------------------------
r300404 | dim | 2017-04-15 18:15:01 -0400 (Sat, 15 Apr 2017) | 22 lines

Use correct registers for "A" inline asm constraint

Summary:
In PR32594, inline assembly using the 'A' constraint on x86_64 causes
llvm to crash with a "Cannot select" stack trace.  This is because
`X86TargetLowering::getRegForInlineAsmConstraint` hardcodes that 'A'
means the EAX and EDX registers.

However, on x86_64 it means the RAX and RDX registers, and on 16-bit x86
(ia16?) it means the old AX and DX registers.

Add new register classes in `X86RegisterInfo.td` to support these cases,
and amend the logic in `getRegForInlineAsmConstraint` to cope with
different subtargets.  Also add a test case, derived from PR32594.

Reviewers: craig.topper, qcolombet, RKSimon, ab

Reviewed By: ab

Subscribers: ab, emaste, royger, llvm-commits

Differential Revision: https://reviews.llvm.org/D31902
------------------------------------------------------------------------

llvm-svn: 301436
2017-04-26 17:52:11 +00:00
Simon Dardis
933e616bc4 Merging r296105, r296016 and 296111:
------------------------------------------------------------------------
r296105 | sdardis | 2017-02-24 10:50:27 +0000 (Fri, 24 Feb 2017) | 13 lines

[mips][mc] Fix a crash when disassembling odd sized sections

Make the MIPS disassembler consistent with the other targets in returning
a Size of zero when the input buffer cannot contain an instruction due
to it's size. Previously it reported the minimum instruction size when
it failed due to the buffer not being big enough for an instruction
causing llvm-objdump to crash when disassembling all sections.

Reviewers: slthakur

Differential Revision: https://reviews.llvm.org/D29984


------------------------------------------------------------------------
------------------------------------------------------------------------
r296106 | sdardis | 2017-02-24 10:51:27 +0000 (Fri, 24 Feb 2017) | 5 lines

[mips][mc] Fix a crash when disassembling odd sized sections

Corresponding test.


------------------------------------------------------------------------
------------------------------------------------------------------------
r296111 | rovka | 2017-02-24 12:47:11 +0000 (Fri, 24 Feb 2017) | 1 line

Fixup r296105 - only run tests on Mips
------------------------------------------------------------------------

llvm-svn: 301169
2017-04-24 09:48:54 +00:00
Brad Smith
d14b74f6f6 Merging r299269:
------------------------------------------------------------------------
r299269 | brad | 2017-03-31 18:13:17 -0400 (Fri, 31 Mar 2017) | 2 lines

Add/update PIE defaults for OpenBSD.
------------------------------------------------------------------------

llvm-svn: 301087
2017-04-22 17:20:27 +00:00
Brad Smith
dabd1af01b Merging r296430:
------------------------------------------------------------------------
r296430 | brad | 2017-02-27 22:20:26 -0500 (Mon, 27 Feb 2017) | 2 lines

Set ABIs correctly for OpenBSD/arm; soft float and aapcs-linux.
------------------------------------------------------------------------

llvm-svn: 301086
2017-04-22 17:15:15 +00:00
Brad Smith
1e8b1a8861 Merging r295786:
------------------------------------------------------------------------
r295786 | brad | 2017-02-21 18:13:09 -0500 (Tue, 21 Feb 2017) | 2 lines

Hook up OpenBSD AArch64 support
------------------------------------------------------------------------

llvm-svn: 301085
2017-04-22 17:05:51 +00:00
Brad Smith
78b623bc6f Merging r295635:
------------------------------------------------------------------------
r295635 | brad | 2017-02-19 22:18:15 -0500 (Sun, 19 Feb 2017) | 5 lines

Enable support for __float128 in Clang on OpenBSD/X86

/usr/local/include/c++/4.9.4/type_traits:279:39: error: __float128 is not
supported on this target
------------------------------------------------------------------------

llvm-svn: 301084
2017-04-22 16:53:19 +00:00
Brad Smith
8abd5fe4ae Merging r295614:
------------------------------------------------------------------------
r295614 | brad | 2017-02-19 15:11:48 -0500 (Sun, 19 Feb 2017) | 2 lines

Always use --eh-frame-hdr on OpenBSD, even for -static
------------------------------------------------------------------------

llvm-svn: 301083
2017-04-22 16:45:56 +00:00
Brad Smith
200fcffe88 Merging r296493:
------------------------------------------------------------------------
r296493 | brad | 2017-02-28 12:28:35 -0500 (Tue, 28 Feb 2017) | 2 lines

Set default CPU for OpenBSD/arm to Cortex-A8
------------------------------------------------------------------------

llvm-svn: 301082
2017-04-22 16:34:38 +00:00
Tom Stellard
0d229e0c79 Merging r298604:
------------------------------------------------------------------------
r298604 | niravd | 2017-03-23 11:01:50 -0400 (Thu, 23 Mar 2017) | 14 lines

[SDAG] Fix zeroExtend assertion error

Move CombineTo preventing deleted node from being returned in
visitZERO_EXTEND.

Fixes PR32284.

Reviewers: RKSimon, bogner

Reviewed By: RKSimon

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D31254
------------------------------------------------------------------------

llvm-svn: 300979
2017-04-21 14:14:41 +00:00
Tom Stellard
2a8b38be5c Merging r296698:
------------------------------------------------------------------------
r296698 | rnk | 2017-03-01 17:41:12 -0500 (Wed, 01 Mar 2017) | 10 lines

[Constant Hoisting] Avoid inserting instructions before EH pads

Now that terminators can be EH pads, this code needs to iterate over the
immediate dominators of the EH pad to find a valid insertion point.

Fix for PR32107

Patch by Robert Olliff!

Differential Revision: https://reviews.llvm.org/D30511
------------------------------------------------------------------------

llvm-svn: 299670
2017-04-06 17:41:41 +00:00
Tom Stellard
d70b75e836 Merging r298705:
------------------------------------------------------------------------
r298705 | tstellar | 2017-03-24 12:13:18 -0400 (Fri, 24 Mar 2017) | 11 lines

stable-merge-request.sh: Add a script for submitting merge requests via bugzilla

Summary:
This script will automatically create a new stable merge request bug in
bugzilla for the given svn revision and release number.

Reviewers: hans

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D30905
------------------------------------------------------------------------

llvm-svn: 299455
2017-04-04 18:38:19 +00:00
Tom Stellard
52af6b973f Merging r298551:
------------------------------------------------------------------------
r298551 | kzhuravl | 2017-03-22 17:48:18 -0400 (Wed, 22 Mar 2017) | 4 lines

[AMDGPU] Fix bug 31610

Differential Revision: https://reviews.llvm.org/D31258

------------------------------------------------------------------------

llvm-svn: 299441
2017-04-04 15:23:53 +00:00
Tom Stellard
db94c8bf38 Partial merge of r293110 into the 4.0 branch
Avoid printing optimization remarks from llc unless they are enabled.

Fixes http://llvm.org/PR32184

llvm-svn: 299409
2017-04-04 01:17:09 +00:00
Craig Topper
09f3db4d40 Merging r299347:
------------------------------------------------------------------------
r299347 | ctopper | 2017-04-02 20:51:57 -0700 (Sun, 02 Apr 2017) | 1 line

[AVX-512] Fix a couple more intrinsic macros I missed in r299346.
------------------------------------------------------------------------

llvm-svn: 299405
2017-04-04 00:31:22 +00:00
Craig Topper
baa8fddf1c Merging r299346:
------------------------------------------------------------------------
r299346 | ctopper | 2017-04-02 20:41:29 -0700 (Sun, 02 Apr 2017) | 3 lines

[AVX-512] Fix some intrinsic macros that use the wrong macro parameter names and don't have parentheses around them.

Thanks to Matthew Barr for reporting this issue.
------------------------------------------------------------------------

llvm-svn: 299404
2017-04-04 00:28:56 +00:00
Tom Stellard
d2f4f1b802 Bump version to 4.0.1
llvm-svn: 298635
2017-03-23 19:17:39 +00:00
Hans Wennborg
ed7ec907af ReleaseNotes: fix indent
llvm-svn: 297204
2017-03-07 20:44:17 +00:00
Hans Wennborg
62364efb42 ReleaseNotes: fix the VS version; follow-up to r297097
llvm-svn: 297203
2017-03-07 20:43:19 +00:00
Hans Wennborg
ab7cbc9afc Merging r297075:
------------------------------------------------------------------------
r297075 | hans | 2017-03-06 13:10:40 -0800 (Mon, 06 Mar 2017) | 1 line

Disable gvn-hoist (PR32153)
------------------------------------------------------------------------

llvm-svn: 297165
2017-03-07 17:36:53 +00:00
Hans Wennborg
d251e94e80 Merging r296992:
------------------------------------------------------------------------
r296992 | sanjoy | 2017-03-05 15:49:17 -0800 (Sun, 05 Mar 2017) | 7 lines

[SCEV] Decrease the recursion threshold for CompareValueComplexity

Fixes PR32142.

r287232 accidentally increased the recursion threshold for
CompareValueComplexity from 2 to 32.  This change reverses that change
by introducing a separate flag for CompareValueComplexity's threshold.
------------------------------------------------------------------------

llvm-svn: 297164
2017-03-07 17:33:14 +00:00
Hans Wennborg
ed6aea839d ReleaseNotes: reformulate compiler version change text
llvm-svn: 297097
2017-03-06 23:43:34 +00:00
Renato Golin
2c879f4060 [notes] adding vulcan rename to release notes
llvm-svn: 297090
2017-03-06 22:56:55 +00:00
Eric Fiselier
d07c41fa3e Update ABI lists and changelog for final 4.0 release
llvm-svn: 296804
2017-03-02 19:56:59 +00:00
Hans Wennborg
4adb2ddb69 Merging r296656:
------------------------------------------------------------------------
r296656 | bruno | 2017-03-01 11:18:42 -0800 (Wed, 01 Mar 2017) | 34 lines

[PCH] Avoid VarDecl emission attempt if no owning module avaiable

This is a stopgap fix for PR31863, a regression introduced in r276159.

Consider this snippet:

struct FVector;
struct FVector {};
struct FBox {
  FVector Min;
  FBox(int);
};
namespace {
FBox InvalidBoundingBox(0);
}

While parsing the DECL_VAR for 'struct FBox', clang recursively read all the
dep decls until it finds the DECL_CXX_RECORD forward declaration for 'struct
FVector'. Then, it resumes all the way up back to DECL_VAR handling in
`ReadDeclRecord`, where it checks if `isConsumerInterestedIn` for the decl.

One of the condition for `isConsumerInterestedIn` to return false is if the
VarDecl is imported from a module `D->getImportedOwningModule()`, because it
will get emitted when we import the relevant module. However, before checking
if it comes from a module, clang checks if `Ctx.DeclMustBeEmitted(D)`, which
triggers the emission of 'struct FBox'. Since one of its fields is still
incomplete, it crashes.

Instead, check if `D->getImportedOwningModule()` is true before calling
`Ctx.DeclMustBeEmitted(D)`.

Differential Revision: https://reviews.llvm.org/D29753

rdar://problem/30173654
------------------------------------------------------------------------

llvm-svn: 296762
2017-03-02 16:47:48 +00:00
Hans Wennborg
f51dd7e30e Merging r296642:
------------------------------------------------------------------------
r296642 | hans | 2017-03-01 09:15:08 -0800 (Wed, 01 Mar 2017) | 5 lines

[GVNHoist] Don't hoist unsafe scalars at -Oz (PR31729)

Based on Aditya Kumar's patch:

Differential Revision: https://reviews.llvm.org/D29092
------------------------------------------------------------------------

llvm-svn: 296761
2017-03-02 16:44:46 +00:00
Pekka Jaaskelainen
39cb0a1ea9 Added pocl and TCE to releasenotes. Both of them now work with LLVM 4.0
llvm-svn: 296633
2017-03-01 15:44:10 +00:00
Craig Topper
e850a1b83c ReleaseNotes: Add some X86 target bullets.
llvm-svn: 296587
2017-03-01 08:04:06 +00:00
Hans Wennborg
4cff10f193 ReleaseNotes: mention the versioning scheme change
llvm-svn: 296509
2017-02-28 19:32:31 +00:00
Hans Wennborg
68b9f14fa4 Merging r296093 and r296260:
------------------------------------------------------------------------
r296093 | ctopper | 2017-02-23 22:38:24 -0800 (Thu, 23 Feb 2017) | 1 line

[ExecutionDepsFix] Use range-based for loop. NFC
------------------------------------------------------------------------

------------------------------------------------------------------------
r296260 | ctopper | 2017-02-25 10:12:25 -0800 (Sat, 25 Feb 2017) | 18 lines

[ExecutionDepsFix] Don't make copies of LiveReg objects when collecting operands for soft instructions

Summary:
While collecting operands we make copies of the LiveReg objects which are stored in the LiveRegs array. If the instruction uses the same register multiple times we end up with multiple copies. Later we iterate through the collected list of LiveReg objects and merge DomainValues. In the process of doing this the merge function can change the contents of the original LiveReg object in the LiveRegs array, but not the copies that have been made. So when we get to the second usage of the register we end up seeing a stale copy of the LiveReg object.

To fix this I've stopped copying and now just store a pointer to the original LiveReg object. Another option might be to avoid adding the same register to the Regs array twice, but this approach seemed simpler.

The included test case exposes this bug due to an AVX-512 masked OR instruction using the same register for the passthru operand and one of the inputs to the OR operation.

Fixes PR30284.

Reviewers: RKSimon, stoklund, MatzeB, spatel, myatsina

Reviewed By: RKSimon

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D30242
------------------------------------------------------------------------

llvm-svn: 296380
2017-02-27 20:53:28 +00:00
Hans Wennborg
a20b011d5c Merging r296358 and r296359:
------------------------------------------------------------------------
r296358 | aadg | 2017-02-27 09:33:20 -0800 (Mon, 27 Feb 2017) | 8 lines

Add libcxxabi's LICENSE.TXT to libunwind.

When libunwind was spinned off libcxxabi, most file were copied from
libcxxabi to libunwind.  However, libc++abi's toplevel LICENSE.TXT was
forgotten in the copying. It's considered a good practice to have the
license file at the root of the project, and making linunwind a separate
project was not supposed to change its licensing. Besides, several
header files refer to the LICENSE.TXT, so copy the one from libc++abi.
------------------------------------------------------------------------

------------------------------------------------------------------------
r296359 | aadg | 2017-02-27 09:47:58 -0800 (Mon, 27 Feb 2017) | 1 line

Fix the project name in the license file.
------------------------------------------------------------------------

llvm-svn: 296364
2017-02-27 18:03:07 +00:00
Hans Wennborg
5a1a5cc8e2 Merging r295116:
------------------------------------------------------------------------
r295116 | dim | 2017-02-14 14:49:49 -0800 (Tue, 14 Feb 2017) | 18 lines

Disable wrapping llvm-xray YAML output

Summary:
The YAML output produced by llvm-xray is supposed to be wrapped at the
arbitrary default of 70 columns set by `yaml:Output`.  Unfortunately,
the wrapping is rather unpredictable, and can easily go past the set
number of columns, depending on the execution environment.

To make the YAML output environment-independent, disable wrapping
instead.

Reviewers: dberris

Reviewed By: dberris

Subscribers: fhahn, llvm-commits

Differential Revision: https://reviews.llvm.org/D29962
------------------------------------------------------------------------

llvm-svn: 296357
2017-02-27 17:01:04 +00:00
Simon Dardis
3fde7cb012 [ReleaseNotes] Add MIPS release notes.
llvm-svn: 296340
2017-02-27 13:25:42 +00:00
Hans Wennborg
71de8646ae RelaseNotes: tweaks
llvm-svn: 296204
2017-02-24 23:50:13 +00:00
Hans Wennborg
cda0841fa5 ReleaseNotes: drop in-progress warning
llvm-svn: 296203
2017-02-24 23:48:51 +00:00
Hans Wennborg
3b6421a28a RelaseNotes: tweaks
llvm-svn: 296202
2017-02-24 23:48:15 +00:00
Hans Wennborg
416c5877f9 ReleaseNotes: drop empty sections
llvm-svn: 296200
2017-02-24 23:38:14 +00:00
Hans Wennborg
061f469882 ReleaseNotes: drop in-progress warning
llvm-svn: 296199
2017-02-24 23:35:53 +00:00
Hans Wennborg
2a03288383 RelaseNotes: tweaks
llvm-svn: 296197
2017-02-24 23:35:04 +00:00
Hans Wennborg
1df636a4f2 ReleaseNotes: drop dead sections
llvm-svn: 296195
2017-02-24 23:29:12 +00:00
Hans Wennborg
6a9cef28f2 ReleaseNotes: tweaks
llvm-svn: 296194
2017-02-24 23:27:41 +00:00
Hans Wennborg
7e19e2d677 ReleaseNotes: drop in-progress warning
llvm-svn: 296192
2017-02-24 23:23:34 +00:00
Hans Wennborg
6d574b622e ReleaseNotes: typos and tweaks
llvm-svn: 296191
2017-02-24 23:18:49 +00:00
Hans Wennborg
c77d26c972 ReleaseNotes: drop in-progress warning
llvm-svn: 296189
2017-02-24 23:11:56 +00:00
Hans Wennborg
b283ed6bc3 Revert r288115 for PR31847.
------------------------------------------------------------------------
r288115 | abataev | 2016-11-29 09:21:14 +0100 (Tue, 29 Nov 2016) | 8 lines

[SLPVectorizer] Improved support of partial tree vectorization.

Currently SLP vectorizer tries to vectorize a binary operation and dies
immediately after unsuccessful the first unsuccessfull attempt. Patch
tries to improve the situation, trying to vectorize all binary
operations of all children nodes in the binop tree.

Differential Revision: https://reviews.llvm.org/D25517
------------------------------------------------------------------------

llvm-svn: 296185
2017-02-24 22:33:47 +00:00
Hans Wennborg
b0465c9cdc Merging r295990:
------------------------------------------------------------------------
r295990 | jvesely | 2017-02-23 08:12:21 -0800 (Thu, 23 Feb 2017) | 5 lines

AMDGPU/SI: Fix trunc i16 pattern

Hit on ASICs that support 16bit instructions.

Differential Revision: https://reviews.llvm.org/D30281
------------------------------------------------------------------------

llvm-svn: 296158
2017-02-24 18:56:41 +00:00
Hans Wennborg
1f7b90c813 Merging r296003:
------------------------------------------------------------------------
r296003 | mcrosier | 2017-02-23 10:49:03 -0800 (Thu, 23 Feb 2017) | 32 lines

[Reassociate] Add negated value of negative constant to the Duplicates list.

In OptimizeAdd, we scan the operand list to see if there are any common factors
between operands that can be factored out to reduce the number of multiplies
(e.g., 'A*A+A*B*C+D' -> 'A*(A+B*C)+D'). For each operand of the operand list, we
only consider unique factors (which is tracked by the Duplicate set). Now if we
find a factor that is a negative constant, we add the negated value as a factor
as well, because we can percolate the negate out. However, we mistakenly don't
add this negated constant to the Duplicates set.

Consider the expression A*2*-2 + B. Obviously, nothing to factor.

For the added value A*2*-2 we over count 2 as a factor without this change,
which causes the assert reported in PR30256.  The problem is that this code is
assuming that all the multiply operands of the add are already reassociated.
This change avoids the issue by making OptimizeAdd tolerate multiplies which
haven't been completely optimized; this sort of works, but we're doing wasted
work: we'll end up revisiting the add later anyway.

Another possible approach would be to enforce RPO iteration order more strongly.
If we have RedoInsts, we process them immediately in RPO order, rather than
waiting until we've finished processing the whole function. Intuitively, it
seems like the natural approach: reassociation works on expression trees, so
the optimization only works in one direction. That said, I'm not sure how
practical that is given the current Reassociate; the "optimal" form for an
expression depends on its use list (see all the uses of "user_back()"), so
Reassociate is really an iterative optimization of sorts, so any changes here
would probably get messy.

PR30256

Differential Revision: https://reviews.llvm.org/D30228
------------------------------------------------------------------------

llvm-svn: 296156
2017-02-24 18:53:54 +00:00
Hans Wennborg
e6df079e92 Merging r293604:
------------------------------------------------------------------------
r293604 | sammccall | 2017-01-30 21:23:20 -0800 (Mon, 30 Jan 2017) | 12 lines

In VirtualCallChecker, handle indirect calls

Summary:
In VirtualCallChecker, handle indirect calls.

getDirectCallee() can be nullptr, and dyn_cast(nullptr) is UB

Reviewers: bkramer

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D29303
------------------------------------------------------------------------

llvm-svn: 296154
2017-02-24 18:49:54 +00:00
Hans Wennborg
e6ba2e0c90 Merging r296063:
------------------------------------------------------------------------
r296063 | hans | 2017-02-23 17:16:34 -0800 (Thu, 23 Feb 2017) | 4 lines

Revert r291477 "[Frontend] Correct values of ATOMIC_*_LOCK_FREE to match builtin"

It caused PR31864. There is a patch in progress to fix that, but let's
revert in the meantime.
------------------------------------------------------------------------

llvm-svn: 296152
2017-02-24 18:46:08 +00:00
Hans Wennborg
ad64c684f0 Merging r295474:
------------------------------------------------------------------------
r295474 | hahnfeld | 2017-02-17 10:32:58 -0800 (Fri, 17 Feb 2017) | 6 lines

[OpenMP] Fix cancellation point in task with no cancel

With tasks, the cancel may happen in another task. This has a different
region info which means that we can't find it here.

Differential Revision: https://reviews.llvm.org/D30091
------------------------------------------------------------------------

llvm-svn: 296151
2017-02-24 18:44:42 +00:00
Hans Wennborg
8e1284a292 Revert r296139; it accidentally merged multiple things
llvm-svn: 296150
2017-02-24 18:42:59 +00:00
Hans Wennborg
4cd2bf3c82 Merging r296030:
------------------------------------------------------------------------
r296030 | hans | 2017-02-23 14:29:00 -0800 (Thu, 23 Feb 2017) | 7 lines

Revert r282872 "CVP. Turn marking adds as no wrap on by default"

While not CVP's fault, this caused miscompiles (PR31181). Reverting
until those are resolved.

(This also reverts the follow-ups r288154 and r288161 which removed the
flag.)
------------------------------------------------------------------------

llvm-svn: 296148
2017-02-24 18:37:22 +00:00
Hans Wennborg
7f6e1fc69c Merging r295474:
------------------------------------------------------------------------
r295474 | hahnfeld | 2017-02-17 10:32:58 -0800 (Fri, 17 Feb 2017) | 6 lines

[OpenMP] Fix cancellation point in task with no cancel

With tasks, the cancel may happen in another task. This has a different
region info which means that we can't find it here.

Differential Revision: https://reviews.llvm.org/D30091
------------------------------------------------------------------------

llvm-svn: 296139
2017-02-24 17:26:20 +00:00
Hans Wennborg
94fdaca663 Merging r295762:
------------------------------------------------------------------------
r295762 | eugenis | 2017-02-21 12:17:34 -0800 (Tue, 21 Feb 2017) | 3 lines

Fix PR31896.

Address of an alias of a global with offset is incorrectly lowered as an address of the global (i.e. ignoring offset).
------------------------------------------------------------------------

llvm-svn: 296002
2017-02-23 18:39:15 +00:00
Hans Wennborg
2fc968b740 Merging r295843:
------------------------------------------------------------------------
r295843 | jvesely | 2017-02-22 07:01:42 -0800 (Wed, 22 Feb 2017) | 3 lines

[OpenCL] r600 needs OpenCL kernel calling convention

Differential Revision: https://reviews.llvm.org/D30236
------------------------------------------------------------------------

llvm-svn: 296001
2017-02-23 18:36:11 +00:00
Hans Wennborg
d63cfd6596 Merging r295473:
------------------------------------------------------------------------
r295473 | hahnfeld | 2017-02-17 10:32:51 -0800 (Fri, 17 Feb 2017) | 13 lines

[OpenMP] Remove barriers at cancel and cancellation point

This resolves a deadlock with the cancel directive when there is no explicit
cancellation point. In that case, the implicit barrier acts as cancellation
point. After removing the barrier after cancel, the now unmatched barrier for
the explicit cancellation point has to go as well.

This has probably worked before rL255992: With the calls for the explicit
barrier, it was sure that all threads passed a barrier before exiting.

Reported by Simon Convent and Joachim Protze!

Differential Revision: https://reviews.llvm.org/D30088
------------------------------------------------------------------------

llvm-svn: 296000
2017-02-23 18:33:45 +00:00
Hans Wennborg
1a5584f8e5 Backport r293433, ARM: support -mlong-calls with AEABI TLS on ELF
Support lowering AEABI TLS access (__aeabi_read_tp) with long calls.
This requires adjusting the call sequence to use an indirect call to get
full addressability.

Resolves PR31769!

By Saleem Abdulrasool!

llvm-svn: 295910
2017-02-23 00:14:14 +00:00
Hans Wennborg
6aa5628ba8 Merging r294954 and r295592:
------------------------------------------------------------------------
r294954 | chapuni | 2017-02-13 06:59:53 -0800 (Mon, 13 Feb 2017) | 5 lines

Fix r291495 -- Normalize LLVM_CMAKE_PATH in clang standalone build.

CMake handles paths with slashes. It caused cmake/install failure on msbuild.exe.

Note, Other llvm-config-oriented variables have been normalized since they are stored in the cache attributed with PATH.
------------------------------------------------------------------------

------------------------------------------------------------------------
r295592 | chapuni | 2017-02-18 19:17:31 -0800 (Sat, 18 Feb 2017) | 1 line

clang/CMakeLists.txt: Rework r294954 -- use file(TO_CMAKE_PATH).
------------------------------------------------------------------------

llvm-svn: 295760
2017-02-21 19:55:46 +00:00
Hans Wennborg
2fb894962b Merging r295610:
------------------------------------------------------------------------
r295610 | brad | 2017-02-19 11:33:26 -0800 (Sun, 19 Feb 2017) | 4 lines

Link static PIE programs against rcrt0.o on OpenBSD

Patch by Stefan Kempf.

------------------------------------------------------------------------

llvm-svn: 295752
2017-02-21 19:11:22 +00:00
Hans Wennborg
d05e1bb960 Merging r293273:
------------------------------------------------------------------------
r293273 | chandlerc | 2017-01-27 02:27:32 -0800 (Fri, 27 Jan 2017) | 19 lines

[LICM] When we are recomputing the alias sets for a subloop, we cannot
skip sub-subloops.

The logic to skip subloops dated from when this code was shared with the
cached case. Once it was factored out to only run in the case of
recomputed subloops it became a dangerous bug. If a subsubloop contained
an interfering instruction it would be silently skipped from the alias
sets for LICM.

With the old pass manager this was extremely hard to trigger as it would
require failing to visit these subloops with the LICM pass but then
visiting the outer loop somehow. I've not yet contrived any test case
that actually manages to trigger this.

But with the new pass manager we don't do the cross-loop caching hack
that the old PM does and so we recompute alias set information from
first principles. While this seems much cleaner and simpler it exposed
this bug and would subtly miscompile code due to failing to correctly
model the aliasing constraints of deeply nested loops.
------------------------------------------------------------------------

llvm-svn: 295748
2017-02-21 19:01:56 +00:00
Hans Wennborg
78c8b20d1b Merging r295486 and r295490:
------------------------------------------------------------------------
r295486 | adrian | 2017-02-17 11:42:32 -0800 (Fri, 17 Feb 2017) | 6 lines

Debug Info: Sort frame index expressions before emitting them.
This fixes PR31381, which caused an assertion and/or invalid debug info.

This affects debug variables that have multiple fragments in the MMI
side (i.e.: in the stack frame) table.
rdar://problem/30571676
------------------------------------------------------------------------

------------------------------------------------------------------------
r295490 | adrian | 2017-02-17 12:02:26 -0800 (Fri, 17 Feb 2017) | 1 line

Fix windows bots by locking down the target triple on this testcase.
------------------------------------------------------------------------

llvm-svn: 295747
2017-02-21 18:53:27 +00:00
Hans Wennborg
e1a150a824 Merging r295512:
------------------------------------------------------------------------
r295512 | matze | 2017-02-17 15:15:03 -0800 (Fri, 17 Feb 2017) | 8 lines

AArch64LoadStoreOptimizer: Correctly clear kill flags

When promoting the Load of a Store-Load pair to a COPY all kill flags
between the store and the load need to be cleared.

rdar://30402435

Differential Revision: https://reviews.llvm.org/D30110
------------------------------------------------------------------------

llvm-svn: 295744
2017-02-21 18:46:57 +00:00
Hans Wennborg
fed41450da ReleaseNotes: GVNHoist; by Sepastian Pop
llvm-svn: 295743
2017-02-21 18:30:34 +00:00
Hans Wennborg
7ee1a6c010 ReleaseNotes: static analyzer; by Anna Zaks
llvm-svn: 295742
2017-02-21 18:27:27 +00:00
Hans Wennborg
55dd7c0720 Merging r293124:
------------------------------------------------------------------------
r293124 | mkuper | 2017-01-25 17:04:11 -0800 (Wed, 25 Jan 2017) | 9 lines

[LoopUnroll] Properly update loopinfo for runtime unrolling by 2

Even when we don't create a remainder loop (that is, when we unroll by 2), we
may duplicate nested loops into the remainder. This is complicated by the fact
the remainder may itself be either inserted into an outer loop, or at the top
level. In the latter case, we may need to create new top-level loops.

Differential Revision: https://reviews.llvm.org/D29156

------------------------------------------------------------------------

llvm-svn: 295380
2017-02-16 21:50:00 +00:00
Hans Wennborg
92842cac21 Merging r295230:
------------------------------------------------------------------------
r295230 | arnolds | 2017-02-15 12:43:43 -0800 (Wed, 15 Feb 2017) | 11 lines

AddressSanitizer: don't track swifterror memory addresses

They are register promoted by ISel and so it makes no sense to treat them as
memory.

Inserting calls to the thread sanitizer would also generate invalid IR.

You would hit:

"swifterror value can only be loaded and stored from, or as a swifterror
argument!"
------------------------------------------------------------------------

llvm-svn: 295377
2017-02-16 21:17:54 +00:00
Hans Wennborg
8585b8b2e9 Merging r295215:
------------------------------------------------------------------------
r295215 | arnolds | 2017-02-15 10:57:06 -0800 (Wed, 15 Feb 2017) | 11 lines

ThreadSanitizer: don't track swifterror memory addresses

They are register promoted by ISel and so it makes no sense to treat them as
memory.

Inserting calls to the thread sanitizer would also generate invalid IR.

You would hit:

"swifterror value can only be loaded and stored from, or as a swifterror
argument!"
------------------------------------------------------------------------

llvm-svn: 295376
2017-02-16 21:15:37 +00:00
Hans Wennborg
f22ee64548 Merging r295224:
------------------------------------------------------------------------
r295224 | rsmith | 2017-02-15 11:57:10 -0800 (Wed, 15 Feb 2017) | 2 lines

PR24440: Do not silently discard a fold-expression appearing as the operand of a cast-expression.

------------------------------------------------------------------------

llvm-svn: 295375
2017-02-16 21:13:06 +00:00
Hans Wennborg
58fb9a0f93 Merging r295213:
------------------------------------------------------------------------
r295213 | mkuper | 2017-02-15 10:37:26 -0800 (Wed, 15 Feb 2017) | 10 lines

[DAG] Don't try to create an INSERT_SUBVECTOR with an illegal source

We currently can't legalize those, but we should really not be creating
them in the first place, since legalization would probably look similar to the
way we legalize CONCAT_VECTORS - basically replace the INSERT with a BUILD.

This fixes PR311956.

Differential Revision: https://reviews.llvm.org/D29961

------------------------------------------------------------------------

llvm-svn: 295374
2017-02-16 21:11:04 +00:00
Kai Nacke
4ef9a35c38 Add external project LDC to release notes.
LDC, the LLVM-based D compiler, is already ready for LLVM 4.0.

llvm-svn: 295367
2017-02-16 19:35:37 +00:00
Hans Wennborg
23de435531 Merging r292271:
------------------------------------------------------------------------
r292271 | aaron | 2017-01-17 21:48:31 +0000 (Tue, 17 Jan 2017) | 2 lines

Silence some Sphinx diagnostics in an attempt to get the documentation builder back to green (http://lab.llvm.org:8011/builders/llvm-sphinx-docs/builds/1895).
------------------------------------------------------------------------

llvm-svn: 295344
2017-02-16 17:59:33 +00:00
Hans Wennborg
e85e175ad4 Merging r295313:
------------------------------------------------------------------------
r295313 | stulova | 2017-02-16 04:49:29 -0800 (Thu, 16 Feb 2017) | 9 lines

[OpenCL][Doc] Added OpenCL vendor extension description to user manual doc

Added description of a new feature that allows to specify
vendor extension in flexible way using compiler pragma instead
of modifying source code directly (committed in clang@r289979).

Review: D29829


------------------------------------------------------------------------

llvm-svn: 295340
2017-02-16 17:10:08 +00:00
Anastasia Stulova
6ed89d2703 [OpenCL][Doc] Relase 4.0 notes for OpenCL
Review: D29830
llvm-svn: 295315
2017-02-16 12:55:39 +00:00
Hans Wennborg
d3a5999fee Merging r294129:
------------------------------------------------------------------------
r294129 | gberry | 2017-02-05 10:28:14 -0800 (Sun, 05 Feb 2017) | 16 lines

[SelectionDAG] In InstrEmitter, handle EXTRACT_SUBREG of a physical register.

Summary:
Without this change, the getVR() call would hit an assert since it was
being passed a physical register.

Update the AArch64/ldst-opt.ll test with a case that triggers this
behavior by adding a run with strict-align, which causes an unaligned
STR XZR instruction to be split into byte stores, creating an
EXTRACT_SUBREG of XZR that triggers the original problem.

Reviewers: bogner, qcolombet, MatzeB, atrick

Subscribers: aemerson, mcrosier, llvm-commits

Differential Revision: https://reviews.llvm.org/D29495
------------------------------------------------------------------------

llvm-svn: 295250
2017-02-15 22:36:35 +00:00
Hans Wennborg
f80119723d Merging r294003:
------------------------------------------------------------------------
r294003 | abataev | 2017-02-03 04:28:40 -0800 (Fri, 03 Feb 2017) | 8 lines

[SelectionDAG] Fix for PR30775: Assertion `NodeToMatch->getOpcode() !=
ISD::DELETED_NODE && "NodeToMatch was removed partway through
selection"' failed.

NodeToMatch can be modified during matching, but code does not handle
this situation.

Differential Revision: https://reviews.llvm.org/D29292
------------------------------------------------------------------------

llvm-svn: 295249
2017-02-15 22:34:24 +00:00
Hans Wennborg
1191d42eb1 Merging r295150:
------------------------------------------------------------------------
r295150 | ahatanak | 2017-02-14 21:15:28 -0800 (Tue, 14 Feb 2017) | 13 lines

[Sema] Disallow returning a __block variable via a move.

r274291 made changes to prefer calling a move constructor to calling a
copy constructor when returning from a function. This caused programs to
crash when a __block variable in the heap was moved out and used later.

This commit fixes the bug by disallowing moving out of __block variables
implicitly.

rdar://problem/28181080

Differential Revision: https://reviews.llvm.org/D29908

------------------------------------------------------------------------

llvm-svn: 295234
2017-02-15 20:51:59 +00:00
Hans Wennborg
8a9e6cd196 Merging r295149:
------------------------------------------------------------------------
r295149 | rsmith | 2017-02-14 20:18:23 -0800 (Tue, 14 Feb 2017) | 2 lines

Fix assertion failure due to implicit special member lookup lacking a source location.

------------------------------------------------------------------------

llvm-svn: 295233
2017-02-15 20:49:39 +00:00
Hans Wennborg
8048852215 Merging r294982:
------------------------------------------------------------------------
r294982 | arnolds | 2017-02-13 11:58:28 -0800 (Mon, 13 Feb 2017) | 6 lines

swiftcc: Don't emit tail calls from callers with swifterror parameters

Backends don't support this yet. They would have to move to the swifterror
register before the tail call to make sure it is live-in to the call.

rdar://30495920
------------------------------------------------------------------------

llvm-svn: 295219
2017-02-15 19:12:45 +00:00
Hans Wennborg
aed1f61fe2 Merging r292729:
------------------------------------------------------------------------
r292729 | mgorny | 2017-01-21 13:55:00 -0800 (Sat, 21 Jan 2017) | 17 lines

[test] Fix page address logic in clear_cache_test

Fix the logic used to calculate page boundaries in clear_cache_test to
use correct masks -- e.g. -4096 rather than -4095. The latter gives
incorrect result since:

  -4095 -> 0xfffff001
  -4096 -> 0xfffff000 (== ~4095)

The issue went unnoticed so far because the array alignment caused
the last bit not to be set. However, on 32-bit x86 no such alignment is
enforced and the wrong page address caused the test to fail.

Furthermore, obtain the page size from the system instead of hardcoding
4096.

Differential Revision: https://reviews.llvm.org/D28849
------------------------------------------------------------------------

llvm-svn: 295218
2017-02-15 19:06:24 +00:00
Hans Wennborg
77df9b8b22 Merging r292257:
------------------------------------------------------------------------
r292257 | mgorny | 2017-01-17 13:08:25 -0800 (Tue, 17 Jan 2017) | 17 lines

[test] [builtins] Remove obsolete/UB tests in __fixuns?fdi based

Remove the failing tests for __fixunssfdi() and __fixunsdfdi() that
relied on undefined (and most likely obsolete in terms of compiler-rt
implementation behavior).

Both tests presumed that 0x1.p+64 would be converted to
0xFFFFFFFFFFFFFFFFLL, that is the largest value in uint64 range.
However, the C/C++ standards do not specify the behavior for converting
a floating-point value to an integer of smaller range, and in this case
both libgcc and compiler-rt implementations return 0 instead.

Since the current behavior is correct with regards to standards
and there is no good way of expressing 0xFFFFFFFFFFFFFFFFLL in single-
or double-precision float, I've removed the failing test altogether.

Differential Revision: https://reviews.llvm.org/D28146
------------------------------------------------------------------------

llvm-svn: 295217
2017-02-15 19:02:22 +00:00
Hans Wennborg
bfc8113a74 Merging r294425:
------------------------------------------------------------------------
r294425 | mgorny | 2017-02-08 00:43:44 -0800 (Wed, 08 Feb 2017) | 3 lines

[test] Enable the strace_test only if strace is installed

Differential Revision: https://reviews.llvm.org/D29628
------------------------------------------------------------------------

llvm-svn: 295216
2017-02-15 19:01:37 +00:00
Hans Wennborg
41bc86e79a Merging r294431:
------------------------------------------------------------------------
r294431 | mgorny | 2017-02-08 01:57:32 -0800 (Wed, 08 Feb 2017) | 7 lines

[test] Fix hard_link_count test to account for fs with dir nlink==1

Filesystems are not required to maintain a hard link count consistent
with number of subdirectories. For example, on btrfs all directories
have nlink==1. Account for that in the test.

Differential Revision: https://reviews.llvm.org/D29706
------------------------------------------------------------------------

llvm-svn: 295214
2017-02-15 18:40:52 +00:00
Oren Ben Simhon
17a0408a39 Added a section about Regcall and Vectorcall calling convention changes.
llvm-svn: 295165
2017-02-15 10:50:01 +00:00
Hans Wennborg
0b0176ce4f Merging r294527:
------------------------------------------------------------------------
r294527 | arnolds | 2017-02-08 14:30:47 -0800 (Wed, 08 Feb 2017) | 14 lines

[ARM/AArch ISel] SwiftCC: First parameters that are marked swiftself are not 'this returns'

We mark X0 as preserved by a call that passes the returned parameter.

 x0 = ...
 fun(x0) // no implicit def of x0

This no longer is valid if we pass the parameter in a different register then
the returned value as is the case with a swiftself parameter (passed in x20).

x20 = ...
fun(x20) // there should be an implict def of x8

rdar://30425845
------------------------------------------------------------------------

llvm-svn: 295135
2017-02-15 01:06:12 +00:00
Dimitry Andric
79c14f4133 Merging r294806:
------------------------------------------------------------------------
r294806 | dim | 2017-02-11 00:48:40 +0100 (Sat, 11 Feb 2017) | 15 lines

Remove struct_rtentry_sz on FreeBSD

Summary:
Since struct rtentry is an internal kernel-only structure on FreeBSD,
and SIOCADDRT and SIOCDELRT are not supported anyway, stop including
socketvar.h and attempting to get at the definition of struct rtentry,
and move the line with struct_rtentry_sz to the SANIZER_LINUX block.

Reviewers: kcc, kutuzov.viktor.84, emaste

Reviewed By: kcc, emaste

Subscribers: emaste, llvm-commits, kubamracek

Differential Revision: https://reviews.llvm.org/D29832
------------------------------------------------------------------------

llvm-svn: 295095
2017-02-14 19:40:03 +00:00
Hans Wennborg
de06b1bf9d Merging r294800:
------------------------------------------------------------------------
r294800 | gbiv | 2017-02-10 14:52:29 -0800 (Fri, 10 Feb 2017) | 10 lines

Don't let EvaluationModes dictate whether an invalid base is OK

What we want to actually control this behavior is something more local
than an EvalutationMode. Please see the linked revision for more
discussion on why/etc.

This fixes PR31843.

Differential Revision: https://reviews.llvm.org/D29469

------------------------------------------------------------------------

llvm-svn: 295087
2017-02-14 19:03:31 +00:00
Hans Wennborg
234ff406d2 Merging r294551:
------------------------------------------------------------------------
r294551 | arnolds | 2017-02-08 17:52:17 -0800 (Wed, 08 Feb 2017) | 10 lines

SwiftCC: swifterror register cannot be as the base register

Functions that have a dynamic alloca require a base register which is defined to
be X19 on AArch64 and r6 on ARM.  We have defined the swifterror register to be
the same register. Use a different callee save register for swifterror instead:

 X21 on AArch64
 R8 on ARM

rdar://30433803
------------------------------------------------------------------------

llvm-svn: 295079
2017-02-14 17:39:39 +00:00
Hans Wennborg
16744f7cf3 Merging r294855:
------------------------------------------------------------------------
r294855 | compnerd | 2017-02-11 09:24:09 -0800 (Sat, 11 Feb 2017) | 3 lines

docs: update docs for objc_storeStrong behaviour

objc_storeStrong does not return a value.
------------------------------------------------------------------------

llvm-svn: 295076
2017-02-14 17:35:55 +00:00
Hans Wennborg
f5820e511c Merging r294886:
------------------------------------------------------------------------
r294886 | weimingz | 2017-02-11 21:10:25 -0800 (Sat, 11 Feb 2017) | 9 lines

[Builtin][ARM] Fix subsf3vfp for non-HF target

Reviewers: rengolin, compnerd

Reviewed By: compnerd

Subscribers: hans, aemerson

Differential Revision: https://reviews.llvm.org/D29869
------------------------------------------------------------------------

llvm-svn: 295074
2017-02-14 17:29:27 +00:00
Hans Wennborg
da493bb956 ReleaseNotes: coroutines; by Gor Nishanov
llvm-svn: 295070
2017-02-14 17:20:43 +00:00
Hans Wennborg
5fc99d2679 ReleaseNotes: llvm-cov blurb; by Vedant Kumar
llvm-svn: 295069
2017-02-14 17:19:38 +00:00
Mehdi Amini
5935de89ba [ThinLTO] Make a copy of buffer identifier in ThinLTOCodeGenerator
This is anticipating a crash with ThinLTO and Xcode 8.3.

llvm-svn: 295024
2017-02-14 04:49:31 +00:00
Dylan McKay
0023824740 Add release notes for the AVR backend
llvm-svn: 294803
2017-02-10 23:13:12 +00:00
Hans Wennborg
923a5b34d9 ReleaseNotes: ADCE; patch by David Callahan
llvm-svn: 294797
2017-02-10 22:42:53 +00:00
Eric Fiselier
4bee246aee Merge r294612 - Fix PR31916 - std::visit rejects visitors accepting lvalue arguments
A static assertion was misfiring since it checked
is_callable<Visitor, decltype(__variant_alt<T>.value)>. However
the decltype expression doesn't capture the value category as
required. This patch applies extra braces to decltype to fix
that.

llvm-svn: 294681
2017-02-10 00:37:47 +00:00
Matthias Braun
53ca7d6cba ReleaseNotes.rst: Add a section about .mir testing
llvm-svn: 294656
2017-02-09 23:25:27 +00:00
Matthias Braun
9162f0c09b RegisterCoalescer: Fix joinReservedPhysReg()
Merging r294268:

joinReservedPhysReg() can only deal with a liverange in a single basic
block when copying from a vreg into a physreg.

See also rdar://30306405

Differential Revision: https://reviews.llvm.org/D29436

Fixes http://llvm.org/PR31889

llvm-svn: 294631
2017-02-09 21:45:33 +00:00
Matthias Braun
23abc38d36 RegisterCoalescer: Cleanup joinReservedPhysReg(); NFC
Merging r293856:

- Factor out a common subexpression
- Add some helpful comments
- Fix printing of a register in a debug message

Preparation for http://llvm.org/PR31889

llvm-svn: 294630
2017-02-09 21:45:29 +00:00
Hans Wennborg
982b3b4adf build_llvm_package.bat: remove lldb, as it doesn't work
llvm-svn: 294535
2017-02-09 00:13:15 +00:00
Hans Wennborg
02637b33ca Docs: update version and drop minor component
llvm-svn: 294486
2017-02-08 17:29:08 +00:00
Hans Wennborg
2f000b80c6 Docs: drop minor version
llvm-svn: 294485
2017-02-08 17:28:49 +00:00
Hans Wennborg
df01d54011 Docs: drop minor version
llvm-svn: 294484
2017-02-08 17:28:37 +00:00
Hans Wennborg
eb22dc0105 Docs: drop minor version
llvm-svn: 294483
2017-02-08 17:28:23 +00:00
Hans Wennborg
c227fac4cd Docs: drop minor version
llvm-svn: 294482
2017-02-08 17:28:09 +00:00
Hans Wennborg
1193838a48 Docs: drop minor version
llvm-svn: 294481
2017-02-08 17:27:55 +00:00
Hans Wennborg
e54e2f2f9d Remove dead doxygen link
llvm-svn: 294480
2017-02-08 17:20:05 +00:00
Hans Wennborg
2e90d3afe5 Merging r292949:
------------------------------------------------------------------------
r292949 | rnk | 2017-01-24 08:57:55 -0800 (Tue, 24 Jan 2017) | 6 lines

[CodeView] Fix off-by-one error in def range gap emission

Also fixes a much worse bug where we emitted the wrong gap size for the
def range uncovered by the test for this issue.

Fixes PR31726.
------------------------------------------------------------------------

llvm-svn: 294479
2017-02-08 17:14:38 +00:00
Hans Wennborg
914f2d0d28 Release notes for ilist changes, by Duncan
llvm-svn: 294478
2017-02-08 17:04:11 +00:00
Hans Wennborg
0655e6d88c Merging r294349 and r294357:
------------------------------------------------------------------------
r294349 | dexonsmith | 2017-02-07 13:03:50 -0800 (Tue, 07 Feb 2017) | 12 lines

ADT: Add explicit conversions for reverse ilist iterators

Add explicit conversions between forward and reverse ilist iterators.
These follow the conversion conventions of std::reverse_iterator, which
are off-by-one: the newly-constructed "reverse" iterator dereferences to
the previous node of the one sent in.  This has the benefit of
converting reverse ranges in place:
  - If [I, E) is a valid range,
  - then [reverse(E), reverse(I)) gives the same range in reverse order.

ilist_iterator::getReverse() is unchanged: it returns a reverse iterator
to the *same* node.
------------------------------------------------------------------------

------------------------------------------------------------------------
r294357 | dblaikie | 2017-02-07 13:31:03 -0800 (Tue, 07 Feb 2017) | 1 line

Fix some missing negations in the traits checking from r294349
------------------------------------------------------------------------

llvm-svn: 294477
2017-02-08 17:02:53 +00:00
Hans Wennborg
f3b5cd166e Merging r294348:
------------------------------------------------------------------------
r294348 | hans | 2017-02-07 12:37:45 -0800 (Tue, 07 Feb 2017) | 6 lines

[X86] Disable conditional tail calls (PR31257)

They are currently modelled incorrectly (as calls, which clobber
registers, confusing e.g. Machine Copy Propagation).

Reverting until we figure out the proper solution.
------------------------------------------------------------------------

llvm-svn: 294476
2017-02-08 16:50:40 +00:00
Hans Wennborg
fc2173cc0d Forgot to add this in r294473
llvm-svn: 294474
2017-02-08 16:47:33 +00:00
Hans Wennborg
409a1aa043 MachineCopyPropagation: Respect implicit operands of COPY
Cherry pick llvm r294088 to 4.0 branch with slight changes to the way
undef operands are handled.

llvm-svn: 294473
2017-02-08 16:42:21 +00:00
Hans Wennborg
8f87030580 Merging r294318:
------------------------------------------------------------------------
r294318 | adrian | 2017-02-07 09:35:41 -0800 (Tue, 07 Feb 2017) | 12 lines

Fix the bitcode upgrade for DIGlobalVariable in a DIImportedEntity context.

The bitcode upgrade for DIGlobalVariable unconditionally wrapped
DIGlobalVariables in a DIGlobalVariableExpression. When a
DIGlobalVariable is referenced by a DIImportedEntity, however, this is
wrong. This patch fixes the bitcode upgrade by deferring the creation
of DIGlobalVariableExpressions until we know the context of the
DIGlobalVariable.

<rdar://problem/30134279>

Differential Revision: https://reviews.llvm.org/D29349
------------------------------------------------------------------------

llvm-svn: 294352
2017-02-07 21:15:12 +00:00
Hans Wennborg
16f21230c5 Merging r293017 and r294267:
------------------------------------------------------------------------
r293017 | chapuni | 2017-01-24 20:26:29 -0800 (Tue, 24 Jan 2017) | 5 lines

Rewind instantiations of OuterAnalysisManagerProxy in r289317, r291651, and r291662.

I found root class should be instantiated for variadic tempate to instantiate static member explicitly.

This will fix failures in mingw DLL build.
------------------------------------------------------------------------

------------------------------------------------------------------------
r294267 | chandlerc | 2017-02-06 17:50:48 -0800 (Mon, 06 Feb 2017) | 18 lines

Revert r293017 and fix the actual underlying issue.

The patch committed in r293017, as discussed on the list, doesn't really
make sense but was causing an actual issue to go away.

The issue turns out to be that in one place the extra template arguments
were dropped from the OuterAnalysisManagerProxy. This in turn caused the
types used in one set of places to access the key to be completely
different from the types used in another set of places for both Loop and
CGSCC cases where there are extra arguments.

I have literally no idea how anything seemed to work with this bug in
place. It blows my mind. But it did except for mingw64 in a DLL build.

I've added a really handy static assert that helps ensure we don't break
this in the future. It immediately diagnoses the issue with a compile
failure and a very clear error message. Much better that staring at
backtraces on a build bot. =]
------------------------------------------------------------------------

llvm-svn: 294335
2017-02-07 19:09:04 +00:00
Hans Wennborg
f07e3e8691 Merging r294133 and r294142:
------------------------------------------------------------------------
r294133 | marshall | 2017-02-05 12:06:38 -0800 (Sun, 05 Feb 2017) | 1 line

Change the base class of std::bad_optional_access.  This is a (subtle) ABI change, and is in response to http://http://wg21.link/LWG2806, which I *expect* to be adopted in Kona. I am making this change now in anticipation, and will get it into 4.0, because (a) 4.0 is the first release with std::optional, and (b) I don't want to make an ABI-change later, when the user base should be significantly larger. Note that I didn't change std::experimental::bad_optional_access, because that's still specified to derive from std::logic_error.
------------------------------------------------------------------------

------------------------------------------------------------------------
r294142 | marshall | 2017-02-05 12:52:32 -0800 (Sun, 05 Feb 2017) | 1 line

Restore the _NOEXCEPT on the dtor of bad_optional_access. Destructors are noexcept by default, so it's not really needed, but the other exception classes have the _NOEXCEPT, and gcc complains if these are missing. I think we should remove them all - but not today.
------------------------------------------------------------------------

llvm-svn: 294249
2017-02-06 21:59:19 +00:00
Hans Wennborg
95582bf245 Merging r294203:
------------------------------------------------------------------------
r294203 | john.brawn | 2017-02-06 10:07:20 -0800 (Mon, 06 Feb 2017) | 9 lines

[AArch64] Fix incorrect MachinePointerInfo in splitStoreSplat

When splitting up one store into several in splitStoreSplat we have to
make sure we get the MachinePointerInfo right, otherwise alias
analysis thinks they all store to the same location. This can then
cause invalid scheduling later on.

Differential Revision: https://reviews.llvm.org/D29446

------------------------------------------------------------------------

llvm-svn: 294242
2017-02-06 21:27:55 +00:00
Dimitry Andric
644f5a99e7 Merging r294102:
------------------------------------------------------------------------
r294102 | dim | 2017-02-04 23:24:55 +0100 (Sat, 04 Feb 2017) | 13 lines

Add lld to the test-release.sh script

Building lld is enabled by default, but it can be disabled using the
-no-lld option.

Reviewers: tstellarAMD, rengolin, hans

Reviewed By: hans

Subscribers: grosser, wdng, emaste, llvm-commits

Differential Revision: https://reviews.llvm.org/D29539

------------------------------------------------------------------------

llvm-svn: 294123
2017-02-05 12:01:07 +00:00
Eric Fiselier
0f6491a13f Merge r294099 - Undefine min/max in __tree
llvm-svn: 294103
2017-02-04 22:36:27 +00:00
Hans Wennborg
addec11899 Merging r294008:
------------------------------------------------------------------------
r294008 | arphaman | 2017-02-03 06:22:33 -0800 (Fri, 03 Feb 2017) | 14 lines

[Sema][ObjC++] Typo correction should handle ivars and properties

After r260016 and r260017 disabled typo correction for ivars and properties
clang didn't report errors about unresolved identifier in the base of ivar and
property ref expressions. This meant that clang invoked CodeGen on invalid AST
which then caused a crash.

This commit re-enables typo correction for ivars and properites, and fixes the
PR25113 & PR26486 (that were originally fixed in r260017 and r260016) in a
different manner by transforming the Objective-C ivar reference expression with
'IsFreeIvar' preserved.

rdar://30310772

------------------------------------------------------------------------

llvm-svn: 294059
2017-02-03 22:23:11 +00:00
Hans Wennborg
b2ebcccb49 Merging r293043:
------------------------------------------------------------------------
r293043 | dergachev | 2017-01-25 02:21:45 -0800 (Wed, 25 Jan 2017) | 12 lines

[analyzer] Fix MacOSXAPIChecker fp with static locals seen from nested blocks.

This is an attempt to avoid new false positives caused by the reverted r292800,
however the scope of the fix is significantly reduced - some variables are still
in incorrect memory spaces.

Relevant test cases added.

rdar://problem/30105546
rdar://problem/30156693
Differential revision: https://reviews.llvm.org/D28946

------------------------------------------------------------------------

llvm-svn: 294050
2017-02-03 21:45:29 +00:00
Hans Wennborg
a65b909eb7 Merging r293345:
------------------------------------------------------------------------
r293345 | spatel | 2017-01-27 15:26:27 -0800 (Fri, 27 Jan 2017) | 19 lines

[InstCombine] move icmp transforms that might be recognized as min/max and inf-loop (PR31751)

This is a minimal patch to avoid the infinite loop in:
https://llvm.org/bugs/show_bug.cgi?id=31751

But the general problem is bigger: we're not canonicalizing all of the min/max forms reported
by value tracking's matchSelectPattern(), and we don't define min/max consistently. Some code
uses matchSelectPattern(), other code uses matchers like m_Umax, and others have their own
inline definitions which may be subtly different from any of the above.

The reason that the test cases in this patch need a cast op to trigger is because we don't
(yet) canonicalize all min/max forms based on matchSelectPattern() in 
canonicalizeMinMaxWithConstant(), but we do make min/max+cast transforms based on 
matchSelectPattern() in visitSelectInst().

The location of the icmp transforms that trigger the inf-loop seems arbitrary at best, so
I'm moving those behind the min/max fence in visitICmpInst() as the quick fix.


------------------------------------------------------------------------

llvm-svn: 293947
2017-02-02 22:19:34 +00:00
Hans Wennborg
f5184c7bb6 Merging r292167:
------------------------------------------------------------------------
r292167 | davide | 2017-01-16 14:01:41 -0800 (Mon, 16 Jan 2017) | 3 lines

[llvm-objdump] Dump PT_OPENBSD_{BOOTDATA,RANDOMIZE,WXNEEDED}.

PR: 31641
------------------------------------------------------------------------
Merging r292169:
------------------------------------------------------------------------
r292169 | davide | 2017-01-16 14:58:26 -0800 (Mon, 16 Jan 2017) | 3 lines

[llvm-objdump] Dump PT_GNU_RELRO as part of -p.

PR: 31641
------------------------------------------------------------------------
Merging r292170:
------------------------------------------------------------------------
r292170 | davide | 2017-01-16 15:13:46 -0800 (Mon, 16 Jan 2017) | 3 lines

[llvm-objdump] Dump PT_NOTE as part of -p.

PR: 31641
------------------------------------------------------------------------

llvm-svn: 293942
2017-02-02 21:44:30 +00:00
Hans Wennborg
0b1f180ff5 Merging r293635:
------------------------------------------------------------------------
r293635 | nha | 2017-01-31 06:35:37 -0800 (Tue, 31 Jan 2017) | 16 lines

[DAGCombine] require UnsafeFPMath for re-association of addition

Summary:
The affected transforms all implicitly use associativity of addition,
for which we usually require unsafe math to be enabled.

The "Aggressive" flag is only meant to convey information about the
performance of the fused ops relative to a fmul+fadd sequence.

Fixes Bug 31626.

Reviewers: spatel, hfinkel, mehdi_amini, arsenm, tstellarAMD

Subscribers: jholewinski, nemanjai, wdng, llvm-commits

Differential Revision: https://reviews.llvm.org/D28675
------------------------------------------------------------------------

llvm-svn: 293940
2017-02-02 21:34:25 +00:00
Hans Wennborg
fb895f1bc6 Merging r293536:
------------------------------------------------------------------------
r293536 | dim | 2017-01-30 11:06:13 -0800 (Mon, 30 Jan 2017) | 27 lines

Recommit: Stop intercepting some malloc-related functions on FreeBSD and
macOS

Summary:
In https://bugs.freebsd.org/215125 I was notified that some configure
scripts attempt to test for the Linux-specific `mallinfo` and `mallopt`
functions by compiling and linking small programs which references the
functions, and observing whether that results in errors.

FreeBSD and macOS do not have the `mallinfo` and `mallopt` functions, so
normally these tests would fail, but when sanitizers are enabled, they
incorrectly succeed, because the sanitizers define interceptors for
these functions.  This also applies to some other malloc-related
functions, such as `memalign`, `pvalloc` and `cfree`.

Fix this by not intercepting `mallinfo`, `mallopt`, `memalign`,
`pvalloc` and `cfree` for FreeBSD and macOS, in all sanitizers.

Also delete the non-functional `cfree` wrapper for Windows, to fix the
test cases on that platform.

Reviewers: emaste, kcc, rnk

Subscribers: timurrrr, eugenis, hans, joerg, llvm-commits, kubamracek

Differential Revision: https://reviews.llvm.org/D27654

------------------------------------------------------------------------

llvm-svn: 293917
2017-02-02 18:28:41 +00:00
Simon Atanasyan
d7b75d62a0 Port r292160 and r292161.
r292161:
    [ELF][MIPS] Exclude mips .got from PT_GNU_RELRO segment

    On MIPS .got section cannot be included into the PT_GNU_RELRO segment.
    Sometimes it might work, but in general it is unsupported. One of the
    problem is that all sections marked by SHF_MIPS_GPREL should be grouped
    together because data in these sections is addressable with a gp
    relative address, but such sections might be writable.

    This patch exclude mips .got from PT_GNU_RELRO segment and group
    SHF_MIPS_GPREL sections.

r292160:
    [ELF][MIPS] Remove redundant checkings from test cases. NFC

    This change is a prerequisite for the r292161.

llvm-svn: 293879
2017-02-02 11:46:01 +00:00
Peter Collingbourne
6fc60ab46b Update test expectation as followup to r293674.
llvm-svn: 293838
2017-02-01 23:20:54 +00:00
Hans Wennborg
b52e7e1091 Merging r292878:
------------------------------------------------------------------------
r292878 | ruiu | 2017-01-23 19:41:20 -0800 (Mon, 23 Jan 2017) | 12 lines

Do not allocate space for common symbols with -r

Currently ld.lld -r allocates space for common symbols, whereas ld.bfd
-r doesn't.  As a result the OpenBSD makefile bits for creating libraries
fail as they use ld -X -r to strip local symbols, which results in
duplicate symbol errors because space for the common symbols has been
allocated.

The diff also implements the --define-commons option such that allocation
of commons can be forced even if -r is used.

Patch by Mark Kettenis.
------------------------------------------------------------------------

llvm-svn: 293835
2017-02-01 22:45:57 +00:00
Hans Wennborg
7c5b3e87a1 Merging r293542:
------------------------------------------------------------------------
r293542 | arsenm | 2017-01-30 11:50:17 -0800 (Mon, 30 Jan 2017) | 7 lines

LSR: Don't drop address space when type doesn't match

For targets with different addressing modes in each address space,
if this is dropped querying isLegalAddressingMode later with this
will give a nonsense result, breaking the isLegalUse assertions.

This is a candidate for the 4.0 release branch.
------------------------------------------------------------------------

llvm-svn: 293819
2017-02-01 22:00:37 +00:00
Hans Wennborg
1484a723be Merging r292638:
------------------------------------------------------------------------
r292638 | ericwf | 2017-01-20 11:34:19 -0800 (Fri, 20 Jan 2017) | 9 lines

Fix catch_reference_nullptr.pass.cpp test for GCC.

This test contained an implicit conversion from nullptr to bool.
Clang warns about this but the test had supressed that warning.
However GCC diagnoses the same code as an error and requires
-fpermissive to accept it.

This patch fixes both the warning and the error by explicitly
converting the pointer to bool.
------------------------------------------------------------------------

llvm-svn: 293813
2017-02-01 21:30:36 +00:00
Hans Wennborg
26f923df50 Merging r293730:
------------------------------------------------------------------------
r293730 | matze | 2017-01-31 17:31:36 -0800 (Tue, 31 Jan 2017) | 3 lines

MCMacho: Allow __thread_ptr section after dwarf sections

Differential Revision: https://reviews.llvm.org/D29315
------------------------------------------------------------------------

llvm-svn: 293807
2017-02-01 19:45:51 +00:00
Hans Wennborg
9babc4d687 Merging r293673:
------------------------------------------------------------------------
r293673 | matze | 2017-01-31 10:37:53 -0800 (Tue, 31 Jan 2017) | 6 lines

InterleaveAccessPass: Avoid constructing invalid shuffle masks

Fix a bug where we would construct shufflevector instructions addressing
invalid elements.

Differential Revision: https://reviews.llvm.org/D29313
------------------------------------------------------------------------

llvm-svn: 293805
2017-02-01 19:41:46 +00:00
Hans Wennborg
35514e8588 Merging r293309:
------------------------------------------------------------------------
r293309 | mssimpso | 2017-01-27 09:33:16 -0800 (Fri, 27 Jan 2017) | 20 lines

[ARM/AArch64] Relocate and update InterleavedAccessPass tests (NFC)

The interleaved access pass is an IR-to-IR transformation that runs before code
generation. It matches interleaved memory operations to target-specific
intrinsics (that are later lowered to load and store multiple instructions on
ARM/AArch64). We place tests for similar passes (e.g., GlobalMergePass) under
test/Transforms. This patch moves the InterleavedAccessPass tests out of
test/CodeGen and into target-specific directories under
test/Transforms/InterleavedAccess.

Although the pass is an IR pass, many of the existing tests were llc tests
rather opt tests. For example, the tests would check for ldN/stN instructions
generated by llc rather than the intrinsic calls the pass actually inserts.
Thus, this patch updates all tests to be opt tests that check for the inserted
intrinsics. We already have separate CodeGen tests that ensure we lower the
interleaved access intrinsics to their corresponding ldN/stN instructions. In
addition to migrating the tests to opt, this patch also performs some minor
clean-up (to ensure consistent naming, etc.).

Differential Revision: https://reviews.llvm.org/D29184
------------------------------------------------------------------------

llvm-svn: 293804
2017-02-01 19:40:39 +00:00
Hans Wennborg
2c0d496735 Merging r293787:
------------------------------------------------------------------------
r293787 | arphaman | 2017-02-01 09:37:28 -0800 (Wed, 01 Feb 2017) | 5 lines

[CodeGen][ObjC] Avoid asserting on block pointer types in
isPointerZeroInitializable

rdar://30111891

------------------------------------------------------------------------

llvm-svn: 293797
2017-02-01 18:45:31 +00:00
Hans Wennborg
8e9a4a8168 Merging r293727:
------------------------------------------------------------------------
r293727 | davide | 2017-01-31 17:01:22 -0800 (Tue, 31 Jan 2017) | 3 lines

[IPSCCP] Teach how to not propagate return values of naked functions.

Differential Revision:  https://reviews.llvm.org/D29360
------------------------------------------------------------------------

llvm-svn: 293796
2017-02-01 18:42:29 +00:00
Hans Wennborg
4bf43dd3dc Merging r293360:
------------------------------------------------------------------------
r293360 | gbiv | 2017-01-27 18:19:40 -0800 (Fri, 27 Jan 2017) | 11 lines

Change how we handle diagnose_if attributes.

This patch changes how we handle argument-dependent `diagnose_if`
attributes. In particular, we now check them in the same place that we
check for things like passing NULL to Nonnull args, etc. This is
basically better in every way than how we were handling them before. :)

This fixes PR31638, PR31639, and PR31640.

Differential Revision: https://reviews.llvm.org/D28889

------------------------------------------------------------------------
Merging r293369:
------------------------------------------------------------------------
r293369 | gbiv | 2017-01-27 20:16:32 -0800 (Fri, 27 Jan 2017) | 7 lines

Attempt to unbreak buildbots.

r293360 broke some ARM bots, because size_t on those targets is
apparently `unsigned int`, not `unsigned long`. `sizeof(whatever)`
should to give us a `size_t`, so we can just use the type of that
instead.

------------------------------------------------------------------------

llvm-svn: 293784
2017-02-01 17:13:26 +00:00
Hans Wennborg
46b2df1b39 Merging r291963:
------------------------------------------------------------------------
r291963 | ericwf | 2017-01-13 14:11:40 -0800 (Fri, 13 Jan 2017) | 9 lines

[clang] Emit `diagnose_if` warnings from system headers

Summary: In order for libc++ to meaningfully use `diagnose_if` warnings they need to be emitted from system headers by default. This patch changes the `diagnose_if` warning diagnostic to be shown in system headers.

Reviewers: george.burgess.iv, rsmith, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D28703
------------------------------------------------------------------------

llvm-svn: 293783
2017-02-01 17:10:26 +00:00
Hans Wennborg
e87c6f41e3 Merging r293678:
------------------------------------------------------------------------
r293678 | ahatanak | 2017-01-31 11:53:32 -0800 (Tue, 31 Jan 2017) | 9 lines

[Sema] Transform a templated name before looking it up in
FindInstantiatedDecl or passing it to RebuildMemberExpr.

This fixes PR30361.

rdar://problem/17341274

Differential Revision: https://reviews.llvm.org/D24969

------------------------------------------------------------------------

llvm-svn: 293782
2017-02-01 16:59:51 +00:00
Hans Wennborg
14948450ff Merging r293658:
------------------------------------------------------------------------
r293658 | arnolds | 2017-01-31 09:53:49 -0800 (Tue, 31 Jan 2017) | 1 line

Don't combine stores to a swifterror pointer operand to a different type
------------------------------------------------------------------------

llvm-svn: 293781
2017-02-01 16:56:48 +00:00
Hans Wennborg
e986c1479c Merging r293230:
------------------------------------------------------------------------
r293230 | yuyichao | 2017-01-26 15:50:18 -0800 (Thu, 26 Jan 2017) | 11 lines

CMake is funky on detecting Intel 17 as GCC compatible.

Summary: This adds a fallback in case that the Intel compiler is failed to be detected correctly.

Reviewers: chapuni

Reviewed By: chapuni

Subscribers: llvm-commits, mgorny

Differential Revision: https://reviews.llvm.org/D27610
------------------------------------------------------------------------

llvm-svn: 293780
2017-02-01 16:54:47 +00:00
Hans Wennborg
f76e64eddf Merging r292194:
------------------------------------------------------------------------
r292194 | majnemer | 2017-01-16 20:14:25 -0800 (Mon, 16 Jan 2017) | 8 lines

[AST] AttributedType should derive type properties from the EquivalentType

Using the canonical type instead of the equivalent type can result in
insufficient template instantiations.

This fixes PR31656.

Differential Revision: https://reviews.llvm.org/D28788
------------------------------------------------------------------------

llvm-svn: 293702
2017-01-31 22:31:45 +00:00
Peter Collingbourne
ef9d113ae9 Port r293519 and r293529.
r293519:
    ELF: Align RELRO to the target page size rather than the max page size.
    
    If no bss sections appear after the relro segment, the loader will round
    the r/w segment size to the target's page size. Align the relro size in the
    same way to ensure that it does not extend past the end of the program's
    own memory region.
    
    Differential Revision: https://reviews.llvm.org/D29242

r293529:
    Add missing aarch64 requirement.

llvm-svn: 293674
2017-01-31 18:38:56 +00:00
Hans Wennborg
0daccddcee Merging r293629:
------------------------------------------------------------------------
r293629 | sbaranga | 2017-01-31 06:04:15 -0800 (Tue, 31 Jan 2017) | 15 lines

[InstCombine] Make sure that LHS and RHS have the same type in
transformToIndexedCompare

If they don't have the same type, the size of the constant
index would need to be adjusted (and this wouldn't be always
possible).

Alternatively we could try the analysis with the initial
RHS value, which would guarantee that the two sides have
the same type. However it is unlikely that in practice this
would pass our transformation requirements.

Fixes PR31808 (https://llvm.org/bugs/show_bug.cgi?id=31808).


------------------------------------------------------------------------

llvm-svn: 293669
2017-01-31 18:33:00 +00:00
Hans Wennborg
98fac4776f Merging r292117:
------------------------------------------------------------------------
r292117 | sdardis | 2017-01-16 05:55:58 -0800 (Mon, 16 Jan 2017) | 14 lines

[mips] Correct c.cond.fmt instruction definition.

Permit explicit $fcc<X> operand in c.cond.fmt instruction.

Add c.cond.fmt to the MIPS to microMIPS instruction mapping table.

Check that $fcc1 - $fcc7 are unusable for MIPS-I to MIPS-III for
c.cond.fmt, bc1t, bc1f.

Reviewers: seanbruno, zoran.jovanovic, vkalintiris

Differential Revision: https://reviews.llvm.org/D24510


------------------------------------------------------------------------

llvm-svn: 293665
2017-01-31 18:23:49 +00:00
Hans Wennborg
148dbe6143 Merging r292624:
------------------------------------------------------------------------
r292624 | petarj | 2017-01-20 09:53:30 -0800 (Fri, 20 Jan 2017) | 9 lines

[mips] Fix debug information for __thread variable

This patch fixes debug information for __thread variable on Mips
using .dtprelword and .dtpreldword directives.

Patch by Aleksandar Beserminji.

Differential Revision: http://reviews.llvm.org/D28770

------------------------------------------------------------------------

llvm-svn: 293664
2017-01-31 18:21:40 +00:00
Hans Wennborg
a6cdac02a3 Merging r293596:
------------------------------------------------------------------------
r293596 | ahatanak | 2017-01-30 18:31:39 -0800 (Mon, 30 Jan 2017) | 7 lines

Handle ObjCEncodeExpr in extractStringLiteralCharacter.

This fixes an assertion failure that occurs later in the function when
an ObjCEncodeExpr is cast to StringLiteral.

rdar://problem/30111207

------------------------------------------------------------------------

llvm-svn: 293653
2017-01-31 17:27:07 +00:00
Hans Wennborg
4989996dd6 Merging r293417:
------------------------------------------------------------------------
r293417 | jhibbits | 2017-01-28 20:55:57 -0800 (Sat, 28 Jan 2017) | 16 lines

Add some Book-E instructions to the asm parser and printer.

Summary:
Adds the following instructions:
* mfpmr
* mtpmr
* icblc
* icblq
* icbtls

Fix the scheduling for mtspr on e5500, which uses CFX0, instead of
SFX0/SFX1 as on e500mc.

Addresses PR 31538.

Differential Revision: https://reviews.llvm.org/D29002
------------------------------------------------------------------------

llvm-svn: 293651
2017-01-31 17:23:10 +00:00
Hans Wennborg
cb7645093f Merging r293522:
------------------------------------------------------------------------
r293522 | bogner | 2017-01-30 10:29:46 -0800 (Mon, 30 Jan 2017) | 8 lines

SDAG: Update ChainNodesMatched during UpdateChains if a node is replaced

Previously, we would hit UB (or the ISD::DELETED_NODE assert) if we
happened to replace a node during UpdateChains, because it would be
left in the list we were iterating over. This nulls out the pointer
when that happens so that we can avoid the issue.

Fixes llvm.org/PR31710
------------------------------------------------------------------------

llvm-svn: 293650
2017-01-31 17:02:48 +00:00
Hans Wennborg
c7af7a06f8 Merging r293581:
------------------------------------------------------------------------
r293581 | bogner | 2017-01-30 17:26:09 -0800 (Mon, 30 Jan 2017) | 12 lines

Revert "Adorn __call_once_proxy with `inline` and `_LIBCPP_INLINE_VISIBILITY`"

While this change didn't really hurt, it does lead to spurious
warnings about not being able to override weak symbols if you end up
linking objects built with this change to ones built without it.
Furthermore, since __call_once_proxy is called indirectly anyway it
doesn't actually inline ever.

Longer term, it would probably make sense to give this symbol internal
visibility instead.

This reverts r291497
------------------------------------------------------------------------

llvm-svn: 293645
2017-01-31 16:40:22 +00:00
Hans Wennborg
8facb9c510 Merging r293021:
------------------------------------------------------------------------
r293021 | chapuni | 2017-01-24 21:26:23 -0800 (Tue, 24 Jan 2017) | 4 lines

Ignore llvm/test/tools/llvm-symbolizer/coff-exports.test on mingw.

FIXME: Demangler could behave along not host but target.
For example, assume host=mingw, target=msc.
------------------------------------------------------------------------

llvm-svn: 293575
2017-01-31 00:39:51 +00:00
Rafael Espindola
42a16cb20d Port r292910.
[ELF] Correct sh_info for static symbol table

    The sh_info field of the SHT_SYMTAB section holds the index for the
    first non-local symbol. When there are global symbols that are output
    with STB_LOCAL binding due to having hidden visibility or matching
    the local version from a version script, the calculated value of
    NumLocals + 1 does not account for them. This change accounts for
    global symbols being output with local binding.

    Differential Revision: https://reviews.llvm.org/D28950

llvm-svn: 293513
2017-01-30 18:03:21 +00:00
Rafael Espindola
125ee05005 Fix binary file that was corrupted in the svn move.
llvm-svn: 293497
2017-01-30 16:42:16 +00:00
Rafael Espindola
486b977073 Port r292789 and r293177.
r293177:
    Fix -r when the input has a relocation with no symbol.

    Should fix a few freebsd packages with dtrace.

r292789:
    [ELF] - Stop handling local symbols in a special way.

    Previously we stored kept locals in a KeptLocalSyms arrays,
    belonged to files.

    Patch makes SymbolTableSection to store locals in Symbols member,
    that already present and was used for globals.
    SymbolTableSection already had NumLocals counter member, so change
    itself is trivial.

    That allows to simplify handling of -r,
    Body::DynsymIndex is no more used as "symbol table index" for relocatable
    output.

    Change was suggested during review of D28773 and opens road for D28612.

    Differential revision: https://reviews.llvm.org/D29021

llvm-svn: 293495
2017-01-30 16:34:23 +00:00
Dimitry Andric
b450b3fb54 Merging r293197:
------------------------------------------------------------------------
r293197 | dim | 2017-01-26 19:37:18 +0100 (Thu, 26 Jan 2017) | 43 lines

Disable thread safety analysis for some functions in __thread_support

Many thread-related libc++ test cases fail on FreeBSD, due to the
following -Werror warnings:

    In file included from test/std/thread/thread.threads/thread.thread.this/sleep_until.pass.cpp:17:
    In file included from include/thread:97:
    In file included from include/__mutex_base:17:
    include/__threading_support:222:1: error: mutex '__m' is still held at the end of function [-Werror,-Wthread-safety-analysis]
    }
    ^
    include/__threading_support:221:10: note: mutex acquired here
      return pthread_mutex_lock(__m);
             ^
    include/__threading_support:231:10: error: releasing mutex '__m' that was not held [-Werror,-Wthread-safety-analysis]
      return pthread_mutex_unlock(__m);
             ^
    include/__threading_support:242:1: error: mutex '__m' is still held at the end of function [-Werror,-Wthread-safety-analysis]
    }
    ^
    include/__threading_support:241:10: note: mutex acquired here
      return pthread_mutex_lock(__m);
             ^
    include/__threading_support:251:10: error: releasing mutex '__m' that was not held [-Werror,-Wthread-safety-analysis]
      return pthread_mutex_unlock(__m);
             ^
    include/__threading_support:272:10: error: calling function 'pthread_cond_wait' requires holding mutex '__m' exclusively [-Werror,-Wthread-safety-analysis]
      return pthread_cond_wait(__cv, __m);
             ^
    include/__threading_support:278:10: error: calling function 'pthread_cond_timedwait' requires holding mutex '__m' exclusively [-Werror,-Wthread-safety-analysis]
      return pthread_cond_timedwait(__cv, __m, __ts);
             ^
    6 errors generated.

This is because on FreeBSD, the pthread functions have lock annotations.
Since the functions in __thread_support are internal to libc++ only, add
no_thread_safety_analysis attributes to suppress these warnings.

Reviewers: mclow.lists, EricWF, delesley, aaron.ballman
Reviewed By: aaron.ballman
Subscribers: ed, aaron.ballman, joerg, emaste, cfe-commits
Differential Revision: https://reviews.llvm.org/D28520

------------------------------------------------------------------------

llvm-svn: 293443
2017-01-29 20:30:51 +00:00
Hans Wennborg
3e156b37a5 Merging r291918:
------------------------------------------------------------------------
r291918 | krasin | 2017-01-13 09:30:10 -0800 (Fri, 13 Jan 2017) | 13 lines

Fix UBSan bots by blacklisting bits/stl_tree.h.

Summary:
libstdc++ has some undefined behavior in bits/stl_tree.h that
has recently became excercised by some of the LLVM code.
Given that fixing libstdc++ will take years, adding the file
into a blacklist to fix bots seems like a necessity.

Reviewers: vitalybuka

Subscribers: llvm-commits, mgorny

Differential Revision: https://reviews.llvm.org/D28686
------------------------------------------------------------------------

llvm-svn: 293342
2017-01-27 22:55:50 +00:00
Evandro Menezes
6e7efc606d [AArch64] Rename 'no-quad-ldst-pairs' to 'slow-paired-128'
In order to follow the pattern of the existing 'slow-misaligned-128store'
option, rename the option 'no-quad-ldst-pairs' to 'slow-paired-128'.

llvm-svn: 293332
2017-01-27 20:57:35 +00:00
Matt Arsenault
ca356cdf32 Merging r293310:
------------------------------------------------------------------------
r293310 | arsenm | 2017-01-27 09:42:26 -0800 (Fri, 27 Jan 2017) | 8 lines

AMDGPU: Enable FeatureFlatForGlobal on Volcanic Islands

Accomplishes what r292982 was supposed to, which ended up
only really making the necessary test changes.

This should be applied to the 4.0 branch.

Patch by Vedran Miletić <vedran@miletic.net>
------------------------------------------------------------------------

llvm-svn: 293329
2017-01-27 20:21:31 +00:00
Matt Arsenault
a617c74b04 Merging r292982:
------------------------------------------------------------------------
r292982 | arsenm | 2017-01-24 14:02:15 -0800 (Tue, 24 Jan 2017) | 8 lines

Enable FeatureFlatForGlobal on Volcanic Islands

This switches to the workaround that HSA defaults to
for the mesa path.

This should be applied to the 4.0 branch.

Patch by Vedran Miletić <vedran@miletic.net>
------------------------------------------------------------------------

llvm-svn: 293326
2017-01-27 19:26:48 +00:00
Matt Arsenault
54c90c26f1 Merging r292473:
------------------------------------------------------------------------
r292473 | arsenm | 2017-01-18 22:35:27 -0800 (Wed, 18 Jan 2017) | 9 lines

AMDGPU: Disable some fneg combines unless nsz

For -(x + y) -> (-x) + (-y), if x == -y, this would
change the result from -0.0 to 0.0. Since the fma/fmad
combine is an extension of this problem it also
applies there.

fmul should be fine, and I don't think any of the unary
operators or conversions should be a problem either.
------------------------------------------------------------------------

llvm-svn: 293319
2017-01-27 18:39:19 +00:00
Matt Arsenault
f6a398a4b0 Merging r292472:
------------------------------------------------------------------------
r292472 | arsenm | 2017-01-18 22:04:12 -0800 (Wed, 18 Jan 2017) | 5 lines

AMDGPU: Remove modifiers from v_div_scale_*

They seem to produce nonsense results when used.

This should be applied to the release branch.
------------------------------------------------------------------------

llvm-svn: 293317
2017-01-27 18:31:33 +00:00
Hans Wennborg
e7f9ae42bd Merging r293259:
------------------------------------------------------------------------
r293259 | compnerd | 2017-01-26 19:41:53 -0800 (Thu, 26 Jan 2017) | 11 lines

ARM: fix vectorized division on WoA

The Windows on ARM target uses custom division for normal division as
the backend needs to insert division-by-zero checks.  However, it is
designed to only handle non-vectorized division.  ARM has custom
lowering for vectorized division as that can avoid loading registers
with the values and invoke a division routine for each one, preferring
to lower using NEON instructions.  Fall back to the custom lowering for
the NEON instructions if we encounter a vectorized division.

Resolves PR31778!
------------------------------------------------------------------------

llvm-svn: 293306
2017-01-27 17:13:59 +00:00
Hans Wennborg
79bfb19177 Merging r293134:
------------------------------------------------------------------------
r293134 | akirtzidis | 2017-01-25 18:11:50 -0800 (Wed, 25 Jan 2017) | 4 lines

[index] When indexing an ObjC method declaration use its base name for the location.

Instead of using the location of the beginning '-'/'+'.
This is consistent with location used for function decls and ObjC method calls where we use the base name as the location as well.
------------------------------------------------------------------------

llvm-svn: 293303
2017-01-27 16:56:16 +00:00
Hans Wennborg
0a051746b1 Merging r292590:
------------------------------------------------------------------------
r292590 | abataev | 2017-01-20 00:57:28 -0800 (Fri, 20 Jan 2017) | 6 lines

[OPENMP] Fix for PR31643: Clang crashes when compiling code on Windows
with SEH and openmp

In some cituations (during codegen for Windows SEH constructs)
CodeGenFunction instance may have CurFn equal to nullptr. OpenMP related
code does not expect such situation during cleanup.
------------------------------------------------------------------------

llvm-svn: 293302
2017-01-27 16:45:42 +00:00
Hans Wennborg
d31514d884 Merging r292607:
------------------------------------------------------------------------
r292607 | ericwf | 2017-01-20 04:54:45 -0800 (Fri, 20 Jan 2017) | 1 line

Don't default older GCC's to C++17, but C++14 or C++11 instead
------------------------------------------------------------------------

llvm-svn: 293301
2017-01-27 16:41:31 +00:00
Hans Wennborg
082c529196 Merging r292712 and r292713:
------------------------------------------------------------------------
r292712 | ctopper | 2017-01-20 22:59:35 -0800 (Fri, 20 Jan 2017) | 1 line

[X86] Add test cases that show bad commuting being allowed to create a phsub operation.
------------------------------------------------------------------------

------------------------------------------------------------------------
r292713 | ctopper | 2017-01-20 22:59:38 -0800 (Fri, 20 Jan 2017) | 3 lines

[X86] Don't allow commuting to form phsub operations.

Fixes PR31714.
------------------------------------------------------------------------

llvm-svn: 293299
2017-01-27 16:37:00 +00:00
Hans Wennborg
7bb9251e16 Merging r292723:
------------------------------------------------------------------------
r292723 | compnerd | 2017-01-21 08:22:59 -0800 (Sat, 21 Jan 2017) | 17 lines

X86: swap EBP, ESP on !APPLE

Restore the `libunwind.h` enumeration values back to the inverted
values.  This diverges from the DWARF definition of the register values.
However, this allows our header to be compatible with other unwind
implementations (e.g. HP, GNU Savannah, GCC).

The register IDs are only swapped in the header and need to be unswapped
when accessing the unwind register file.  The flipped EBP and ESP only
applies on non-Apple x86 targets.

When optimizations were enabled, EBP and ESP would no longer be
equivalent.  As a result, the incorrect access on Linux would manifest
as a failure to unwind the stack.  We can now unwind the stack with and
without FPO on Linux x86.

Resolves PR30879!
------------------------------------------------------------------------

llvm-svn: 293298
2017-01-27 16:27:43 +00:00
Hans Wennborg
849e38e42e Merging r292561:
------------------------------------------------------------------------
r292561 | rsmith | 2017-01-19 17:19:46 -0800 (Thu, 19 Jan 2017) | 3 lines

PR31701: Fix crash on invalid caused by parsing a dependent initializer when we
don't know we're in a dependent context.

------------------------------------------------------------------------

llvm-svn: 293297
2017-01-27 16:26:10 +00:00
Hans Wennborg
11077cf7d9 Merging r292517:
------------------------------------------------------------------------
r292517 | rserge | 2017-01-19 12:27:11 -0800 (Thu, 19 Jan 2017) | 14 lines

[XRay][Arm] Enable back XRay testing on Arm32 and fix the failing tests

Summary:
Testing of XRay was occasionally disabled on 32-bit Arm targets (someone assumed that XRay was supported on 64-bit targets only). This patch should fix that problem. Also here the instruction&data cache incoherency problem is fixed, because it may be causing a test to fail.
This patch is one of a series: see also
- https://reviews.llvm.org/D28624

Reviewers: dberris, rengolin

Reviewed By: rengolin

Subscribers: llvm-commits, aemerson, rengolin, dberris, iid_iunknown

Differential Revision: https://reviews.llvm.org/D28623
------------------------------------------------------------------------

llvm-svn: 293296
2017-01-27 16:23:36 +00:00
Hans Wennborg
1106495b9c Merging r292516:
------------------------------------------------------------------------
r292516 | rserge | 2017-01-19 12:24:23 -0800 (Thu, 19 Jan 2017) | 14 lines

[XRay][Arm] Repair XRay table emission on Arm32 and add tests to identify such problem earlier

Summary:
Emission of XRay table was occasionally disabled for Arm32, but this bug was not then detected because earlier (also by mistake) testing of XRay was occasionally disabled on 32-bit Arm targets. This patch should fix that problem and detect such problems in the future.
This patch is one of a series, see also
- https://reviews.llvm.org/D28623

Reviewers: rengolin, dberris

Reviewed By: dberris

Subscribers: llvm-commits, aemerson, rengolin, dberris, iid_iunknown

Differential Revision: https://reviews.llvm.org/D28624
------------------------------------------------------------------------

llvm-svn: 293295
2017-01-27 16:17:56 +00:00
Mehdi Amini
0b6e976e71 LLVM 4.0: cherry-pick r293293 - "Fix BasicAA incorrect assumption on GEP"
llvm-svn: 293294
2017-01-27 16:16:33 +00:00
Mehdi Amini
f71ea20b69 LLVM 4.0: cherry-pick r293291 - Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
llvm-svn: 293292
2017-01-27 16:06:47 +00:00
Hans Wennborg
59913f7bdf Merging r293078:
------------------------------------------------------------------------
r293078 | mgorny | 2017-01-25 11:33:14 -0800 (Wed, 25 Jan 2017) | 8 lines

[cmake] Fix -rpath-link in stand-alone build

Set LLVM_LIBRARY_OUTPUT_INTDIR as expected by llvm_setup_rpath() macro
when doing stand-alone builds. This is required to pass correct
-rpath-link when linking shared libraries, and therefore ensure that
the linker can find dependency libraries correctly during the build.

Differential Revision: https://reviews.llvm.org/D29099
------------------------------------------------------------------------

llvm-svn: 293289
2017-01-27 15:42:27 +00:00
Hans Wennborg
672fd5906f Merging r292909:
------------------------------------------------------------------------
r292909 | labath | 2017-01-24 02:41:02 -0800 (Tue, 24 Jan 2017) | 16 lines

[lld][cmake] Fix BUILD_SHARED_LIBS installation

Summary:
This fixes a regression caused by D28397, which switched lld from using
add_llvm_library to llvm_add_library. The latter does not automatically set up
install rules for libraries, as it's expected the project will set them up
manually based on its own needs.

This adds the install rules to add_lld_library for lld. They were inspired by
the similar add_clang_library macro in clang.

Reviewers: ruiu, beanz, davidlt, EricWF, dtzWill

Subscribers: mgorny, llvm-commits

Differential Revision: https://reviews.llvm.org/D29007
------------------------------------------------------------------------

llvm-svn: 293288
2017-01-27 15:40:40 +00:00
Rafael Espindola
7c71653b25 Port r292594.
[ELF] - Do not crash when assign common symbol's values in script

Found that during attempts of linking linux kernel,
previously we partially duplicated code from getOutputSection(),
and it missed commons symbol case.

Differential revision: https://reviews.llvm.org/D28903

llvm-svn: 293284
2017-01-27 13:13:45 +00:00
Peter Smith
345e75945d The AArch64 release notes are actually the ARM release notes. Changed
AArch64 port to ARM port.

llvm-svn: 293271
2017-01-27 09:35:11 +00:00
Tom Stellard
94bba4c367 Merging r293000:
------------------------------------------------------------------------
r293000 | thomas.stellard | 2017-01-24 17:25:13 -0800 (Tue, 24 Jan 2017) | 15 lines

AMDGPU add support for spilling to a user sgpr pointed buffers

Summary:
This lets you select which sort of spilling you want, either s[0:1] or 64-bit loads from s[0:1].

Patch By: Dave Airlie

Reviewers: nhaehnle, arsenm, tstellarAMD

Reviewed By: arsenm

Subscribers: mareko, llvm-commits, kzhuravl, wdng, yaxunl, tony-tye

Differential Revision: https://reviews.llvm.org/D25428

------------------------------------------------------------------------

llvm-svn: 293240
2017-01-27 00:45:06 +00:00
Rui Ueyama
87ba102f58 Add release notes for AArch64 and MIPS.
llvm-svn: 293203
2017-01-26 20:09:50 +00:00
Hans Wennborg
ee55104010 Merging r293154:
------------------------------------------------------------------------
r293154 | marshall | 2017-01-25 22:58:29 -0800 (Wed, 25 Jan 2017) | 1 line

Use the new __has_feature(cxx_constexpr_string_builtins) for detection of the C-string intrinsics for constexpr support in std::char_traits. Thanks to Richard for the intrisic support.
------------------------------------------------------------------------

llvm-svn: 293193
2017-01-26 17:55:46 +00:00
Hans Wennborg
cfa120d2cf Merging r292990:
------------------------------------------------------------------------
r292990 | marshall | 2017-01-24 15:09:12 -0800 (Tue, 24 Jan 2017) | 1 line

Change the return type of emplace_[front|back] back to void when building with C++14 or before. Resolves PR31680.
------------------------------------------------------------------------

llvm-svn: 293192
2017-01-26 17:51:25 +00:00
Hans Wennborg
806b2bf92f Merging r293120:
------------------------------------------------------------------------
r293120 | compnerd | 2017-01-25 16:37:55 -0800 (Wed, 25 Jan 2017) | 3 lines

builtins: remove an errant ':'

Thanks to Dave Lee for pointing this out!
------------------------------------------------------------------------

llvm-svn: 293191
2017-01-26 17:13:15 +00:00
Hans Wennborg
21f71c38d1 Merging r292651:
------------------------------------------------------------------------
r292651 | jvesely | 2017-01-20 13:24:26 -0800 (Fri, 20 Jan 2017) | 8 lines

AMDGPU/R600: Serialize vector trunc stores to private AS

Add DUMMY_CHAIN SDNode to denote stores of interest

Bugzilla: https://llvm.org/bugs/show_bug.cgi?id=28915
Bugzilla: https://llvm.org/bugs/show_bug.cgi?id=30411

Differential Revision: https://reviews.llvm.org/D27964
------------------------------------------------------------------------

llvm-svn: 293118
2017-01-26 00:26:36 +00:00
Tim Northover
ecea256a09 Merging rr293088:
------------------------------------------------------------------------
r293088 | tnorthover | 2017-01-25 12:58:26 -0800 (Wed, 25 Jan 2017) | 5 lines

SDag: fix how initial loads are formed when splitting vector ops.

Later code expects the vector loads produced to be directly
concatenable, which means we shouldn't pad anything except the last load
produced with UNDEF.
------------------------------------------------------------------------

llvm-svn: 293103
2017-01-25 22:10:07 +00:00
Hans Wennborg
2d8d46c951 Merging r293025:
------------------------------------------------------------------------
r293025 | ahatanak | 2017-01-24 22:21:51 -0800 (Tue, 24 Jan 2017) | 29 lines

[SimplifyCFG] Do not sink and merge inline-asm instructions.

Conservatively disable sinking and merging inline-asm instructions as doing so
can potentially create arguments that cannot satisfy the inline-asm constraints.

For example, SimplifyCFG used to do the following transformation:

(before)
if.then:
  %0 = call i32 asm "rorl $2, $0", "=&r,0,n"(i32 %r6, i32 8)
  br label %if.end
if.else:
  %1 = call i32 asm "rorl $2, $0", "=&r,0,n"(i32 %r6, i32 6)
  br label %if.end

(after)
  %.sink = select i1 %tobool, i32 6, i32 8
  %0 = call i32 asm "rorl $2, $0", "=&r,0,n"(i32 %r6, i32 %.sink)

This would result in a crash in the backend since only immediate integer operands
are permitted for constraint "n".

rdar://problem/30110806

Differential Revision: https://reviews.llvm.org/D29111




------------------------------------------------------------------------

llvm-svn: 293074
2017-01-25 17:14:48 +00:00
Hans Wennborg
b328f90bb0 Merging r292991:
------------------------------------------------------------------------
r292991 | rsmith | 2017-01-24 15:18:28 -0800 (Tue, 24 Jan 2017) | 3 lines

PR31742: Don't emit a bogus "zero size array" extwarn when initializing a
runtime-sized array from an empty list in an array new.

------------------------------------------------------------------------

llvm-svn: 293072
2017-01-25 17:04:26 +00:00
Hans Wennborg
030d435aba Merging r292444:
------------------------------------------------------------------------
r292444 | mkuper | 2017-01-18 15:05:58 -0800 (Wed, 18 Jan 2017) | 7 lines

Revert r291670 because it introduces a crash.

r291670 doesn't crash on the original testcase from PR31589,
but it crashes on a slightly more complex one.

PR31589 has the new reproducer.

------------------------------------------------------------------------

llvm-svn: 293070
2017-01-25 16:57:43 +00:00
Peter Collingbourne
ccd3c5f205 ReleaseNotes: Add a release note for the COFF linker.
llvm-svn: 293037
2017-01-25 08:54:31 +00:00
Rui Ueyama
5bc64df31f Write release notes for LLD 4.0.
llvm-svn: 293027
2017-01-25 06:26:55 +00:00
Hans Wennborg
27eda48a9b Merging r291909:
------------------------------------------------------------------------
r291909 | compnerd | 2017-01-13 08:25:33 -0800 (Fri, 13 Jan 2017) | 9 lines

ARM: match GCC's behaviour for builtins

GCC changes the CC between the user-code and the builtins based on the
value of `-target` rather than `-mfloat-abi`.  When a HF target is used,
the VFP variant of the AAPCS CC is used.  Otherwise, the AAPCS variant
is used.  In all cases, the AEABI functions use the AAPCS CC.  Adjust
the calling convention based on the target.

Resolves PR30543!
------------------------------------------------------------------------

llvm-svn: 292951
2017-01-24 16:58:58 +00:00
Hans Wennborg
ee10bd510c Merging r292874:
------------------------------------------------------------------------
r292874 | dcoughlin | 2017-01-23 18:10:59 -0800 (Mon, 23 Jan 2017) | 6 lines

Revert "[analyzer] Fix memory space of static locals seen from nested blocks."

This reverts commit r292800.

It is causing null pointer dereference false positives when a block that
captures a static local is evaluated at the top level.
------------------------------------------------------------------------

llvm-svn: 292947
2017-01-24 16:53:43 +00:00
Eric Fiselier
287cff3451 Merge r292822 - Fixed a typo in __config that prevented the aligned new/delete tests from passing on Mac OS.
llvm-svn: 292869
2017-01-24 01:05:56 +00:00
Eric Fiselier
79c5e5c618 Merge r292830 - Fix GCC C++03 build by hiding default template argument in C++03
llvm-svn: 292867
2017-01-24 01:03:36 +00:00
Eric Fiselier
82156583ba Merge r292833 - Manually force the use of __decltype in C++03 with Clang 3.4.
This merges a version of r292833 since it didn't apply cleanly due to other
upstream changes. Original commit message below:

<string> uses `decltype` in a way incompatible with `__typeof__`.
This is problematic when compiling <string> with Clang 3.4 because
even though it provides `__decltype` libc++ still used `__typeof__`
because clang 3.4 doesn't provide __is_identifier which libc++
uses to detect __decltype.

llvm-svn: 292866
2017-01-24 01:01:55 +00:00
Hans Wennborg
3c66179f3e Merging r292467:
------------------------------------------------------------------------
r292467 | compnerd | 2017-01-18 18:58:46 -0800 (Wed, 18 Jan 2017) | 7 lines

llvm-cxxfilt: filter out invalid manglings

c++filt does not attempt to demangle symbols which do not match its
expected format.  This means that the symbol must start with _Z or ___Z
(block invocation function extension).  Any other symbols are returned
as is.  Note that this is different from the behaviour of __cxa_demangle
which will demangle fragments.
------------------------------------------------------------------------

llvm-svn: 292861
2017-01-24 00:26:12 +00:00
Hans Wennborg
92cca6eadc Merging r292847:
------------------------------------------------------------------------
r292847 | rsmith | 2017-01-23 15:14:23 -0800 (Mon, 23 Jan 2017) | 2 lines

PR31692: Don't mark a declaration as invalid if we haven't necessarily emitted a (user-visible) error.

------------------------------------------------------------------------

llvm-svn: 292859
2017-01-24 00:14:31 +00:00
Hans Wennborg
1fd2a397de Merging r292800:
------------------------------------------------------------------------
r292800 | dergachev | 2017-01-23 08:57:11 -0800 (Mon, 23 Jan 2017) | 13 lines

[analyzer] Fix memory space of static locals seen from nested blocks.

When a block within a function accesses a function's static local variable,
this local is captured by reference rather than copied to the heap.

Therefore this variable's memory space is known: StaticGlobalSpaceRegion.
Used to be UnknownSpaceRegion, same as for stack locals.

Fixes a false positive in MacOSXAPIChecker.

rdar://problem/30105546
Differential revision: https://reviews.llvm.org/D28946

------------------------------------------------------------------------

llvm-svn: 292858
2017-01-24 00:08:26 +00:00
Hans Wennborg
1ff0096c9c Merging r291892:
------------------------------------------------------------------------
r291892 | d0k | 2017-01-13 02:14:07 -0800 (Fri, 13 Jan 2017) | 7 lines

Fix the build of the include-fixer plugin for some shared cmake builds and MSVC.

- The include fixer plugin does not directly depend on pthread, but can
pick up pthread references transitively through inlining. Just add
pthreads to the linked libs unconditionally.
- MSVC emits bogus warnings when including <future> and building without
exceptions. Blacklist the warnings explicitly.
------------------------------------------------------------------------

llvm-svn: 292834
2017-01-23 22:06:11 +00:00
Hans Wennborg
4f3c87e181 Merging r292758:
------------------------------------------------------------------------
r292758 | spatel | 2017-01-22 09:06:12 -0800 (Sun, 22 Jan 2017) | 4 lines

[x86] avoid crashing with illegal vector type (PR31672)

https://llvm.org/bugs/show_bug.cgi?id=31672

------------------------------------------------------------------------

llvm-svn: 292832
2017-01-23 21:33:34 +00:00
Hans Wennborg
3f93c63924 Merging r292323:
------------------------------------------------------------------------
r292323 | pzheng | 2017-01-17 17:03:29 -0800 (Tue, 17 Jan 2017) | 9 lines

[test-release.sh] Add Polly to the list of projects

Reviewers: zinob, hans, grosser

Reviewed By: hans, grosser

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D28712
------------------------------------------------------------------------

llvm-svn: 292831
2017-01-23 21:30:13 +00:00
Matthias Braun
1b49743c23 Cherry pick r292625
llvm-svn: 292820
2017-01-23 19:26:12 +00:00
Hans Wennborg
d4f58435ae Merging r292583:
------------------------------------------------------------------------
r292583 | dannyb | 2017-01-19 22:38:41 -0800 (Thu, 19 Jan 2017) | 4 lines

NewGVN: Fix PR 31682, an overactive assert.
Part of the assert has been left active for further debugging.
The other part has been turned into a stat for tracking for the
moment.
------------------------------------------------------------------------

llvm-svn: 292810
2017-01-23 18:08:20 +00:00
Hans Wennborg
3b3171ba92 Merging r292497:
------------------------------------------------------------------------
r292497 | arphaman | 2017-01-19 09:17:57 -0800 (Thu, 19 Jan 2017) | 6 lines

[Sema] Fix PR28181 by avoiding calling BuildOverloadedBinOp in C mode

rdar://28532840

Differential Revision: https://reviews.llvm.org/D25213

------------------------------------------------------------------------

llvm-svn: 292808
2017-01-23 17:59:45 +00:00
Hans Wennborg
4a242dbced Merging r292555, r292558 and r292559:
------------------------------------------------------------------------
r292555 | rsmith | 2017-01-19 16:45:35 -0800 (Thu, 19 Jan 2017) | 6 lines

P0426: Make the library implementation of constexpr char_traits a little easier
by providing a memchr builtin that returns char* instead of void*.

Also add a __has_feature flag to indicate the presence of constexpr forms of
the relevant <string> functions.

------------------------------------------------------------------------

------------------------------------------------------------------------
r292558 | rsmith | 2017-01-19 16:57:59 -0800 (Thu, 19 Jan 2017) | 2 lines

Add documentation for constexpr string builtin support.

------------------------------------------------------------------------

------------------------------------------------------------------------
r292559 | rsmith | 2017-01-19 17:08:15 -0800 (Thu, 19 Jan 2017) | 2 lines

Fix documentation typo.

------------------------------------------------------------------------

llvm-svn: 292807
2017-01-23 17:55:50 +00:00
Hans Wennborg
47548bc4ae Merging r291858 and r291859:
------------------------------------------------------------------------
r291858 | eugenis | 2017-01-12 15:03:03 -0800 (Thu, 12 Jan 2017) | 1 line

[asan] Refactor instrumentation of globals.
------------------------------------------------------------------------

------------------------------------------------------------------------
r291859 | eugenis | 2017-01-12 15:26:20 -0800 (Thu, 12 Jan 2017) | 6 lines

[asan] Don't overalign global metadata.

Other than on COFF with incremental linking, global metadata should
not need any extra alignment.

Differential Revision: https://reviews.llvm.org/D28628
------------------------------------------------------------------------

llvm-svn: 292802
2017-01-23 17:07:52 +00:00
Mehdi Amini
63f24abef6 LLVM 4.0: Merge r292641 "[ThinLTO] Fix lazy-loading of MDString instruction attachments"
llvm-svn: 292760
2017-01-22 19:37:24 +00:00
Mehdi Amini
5f0f07e1cc LLVM 4.0: cherry-pick r292711 Add missing dependency to "Module Summary Analysis" pass
llvm-svn: 292732
2017-01-21 22:09:27 +00:00
Mehdi Amini
41c8d20c82 LLVM 4.0: cherry-pick r292667 [ThinLTO] The "codegen only" path didn't honor the recently added file-based API
llvm-svn: 292731
2017-01-21 22:08:38 +00:00
Jonathan Peyton
78a501493e Merging r292349:
------------------------------------------------------------------------
r292349 | jlpeyton | 2017-01-18 01:02:21 -0600 (Wed, 18 Jan 2017) | 6 lines

Fix memory error in case of reinit using kmp_set_defaults() for lock code.

The lock tables were being reallocated if kmp_set_defaults() was called.
In the env_init code it says that the user should be able to switch between
different KMP_CONSISTENCY_CHECK values which is what this change enables.

------------------------------------------------------------------------

llvm-svn: 292678
2017-01-20 23:32:49 +00:00
Jonathan Peyton
fa88fdb8bc Merging r292348:
------------------------------------------------------------------------
r292348 | jlpeyton | 2017-01-18 00:40:19 -0600 (Wed, 18 Jan 2017) | 5 lines

Fix small memory leak regarding __kmp_nested_proc_bind

There is no corresponding free() for this expandable array.  The logic is
added in __kmp_cleanup() next to the freeing of __kmp_nested_nth.

------------------------------------------------------------------------

llvm-svn: 292677
2017-01-20 23:31:21 +00:00
Rafael Espindola
4bd9bdb3d5 Port 292512.
Create _end symbol even if a .so defines it.

The freebsd sbrk implementation uses _end to find the initial value of
brk, so it has to be defined in the main binary.

This should fix the emacs build.

llvm-svn: 292622
2017-01-20 17:40:10 +00:00
Rafael Espindola
5bebaaeb56 Port r292228.
Add a isInCurrentDSO helper. NFC.

llvm-svn: 292620
2017-01-20 17:38:03 +00:00
Diana Picus
9f1ab8e3b9 Fix wrapping in ReleaseNotes.rst. NFC.
llvm-svn: 292603
2017-01-20 11:38:10 +00:00
Diana Picus
63abf924b4 Add some release notes for ARM and AArch64
llvm-svn: 292602
2017-01-20 11:34:32 +00:00
Eric Fiselier
1caad7ce21 Merge r292582 - Still expose std::align_val_t in C++17 even if we don't have aligned new/delete.
r292564 disabled the aligned new/delete overloads on platforms without
    posix_memalign. Unfortunately that patch also disabled the  align_val_t
    definition in C++17 as well.

llvm-svn: 292586
2017-01-20 07:53:20 +00:00
Eric Fiselier
0233b48ba8 Merge r292564 - Disable aligned new/delete on Apple platforms without posix_memalign
This patch disables the aligned new/delet overloads on Apple platforms without
posix_memalign. This fixes libc++.dylib build regressions on such platforms.
This fixes http://llvm.org/PR31448.

llvm-svn: 292566
2017-01-20 01:54:53 +00:00
Eric Fiselier
9b10e0808a Merge r292560 - [NFC] Group aligned new/delete definitions together in new.cpp
llvm-svn: 292565
2017-01-20 01:52:28 +00:00
Hans Wennborg
1055f67308 Merging r292418:
------------------------------------------------------------------------
r292418 | jroelofs | 2017-01-18 10:12:39 -0800 (Wed, 18 Jan 2017) | 15 lines

Revert r286788

The Itanium ABI [1] specifies that __cxa_demangle accept either:

   1) symbol names, which start with "_Z"
   2) type manglings, which do not start with "_Z"

r286788 erroneously assumes that it should only handle symbols, so this patch
reverts it and adds a counterexample to the testcase.

1: https://mentorembedded.github.io/cxx-abi/abi.html#demangler


Reviewers: zygoloid, EricWF

------------------------------------------------------------------------

llvm-svn: 292524
2017-01-19 21:57:56 +00:00
Mehdi Amini
d2f0a38dec Merge r292420 in 4.0 Release: "[ThinLTO] Add a recursive step in Metadata lazy-loading"
llvm-svn: 292505
2017-01-19 18:48:31 +00:00
Hans Wennborg
f172e5f1d1 Merging r292254 and r292280:
------------------------------------------------------------------------
r292254 | mssimpso | 2017-01-17 12:51:39 -0800 (Tue, 17 Jan 2017) | 8 lines

[LV] Mark non-consecutive-like pointers non-uniform

If a memory instruction will be vectorized, but it's pointer operand is
non-consecutive-like, the instruction is a gather or scatter operation. Its
pointer operand will be non-uniform. This should fix PR31671.

Reference: https://llvm.org/bugs/show_bug.cgi?id=31671
Differential Revision: https://reviews.llvm.org/D28819
------------------------------------------------------------------------

------------------------------------------------------------------------
r292280 | mssimpso | 2017-01-17 14:21:33 -0800 (Tue, 17 Jan 2017) | 1 line

[LV] Add requires asserts to test case
------------------------------------------------------------------------

llvm-svn: 292503
2017-01-19 18:35:20 +00:00
Hans Wennborg
3fe39cdeea Merging r292135:
------------------------------------------------------------------------
r292135 | marshall | 2017-01-16 07:28:03 -0800 (Mon, 16 Jan 2017) | 1 line

Mark the dynamic-exception tests as unsupported under C++17, since it has no dynamic-exception specs. Also, remove a FIXME workaround from the config that allowed these tests to work under C++17. This addresses PR#31621.
------------------------------------------------------------------------

llvm-svn: 292495
2017-01-19 16:52:39 +00:00
Hans Wennborg
4c898ba628 Merging r292091:
------------------------------------------------------------------------
r292091 | marshall | 2017-01-15 19:02:10 -0800 (Sun, 15 Jan 2017) | 1 line

Implement the missing constexpr stuff in <array>. Fixes PR#31645.
------------------------------------------------------------------------

llvm-svn: 292494
2017-01-19 16:50:46 +00:00
Hans Wennborg
78b36cd282 Merging r291955:
------------------------------------------------------------------------
r291955 | rsmith | 2017-01-13 12:46:54 -0800 (Fri, 13 Jan 2017) | 3 lines

PR31606: Generalize our tentative DR resolution for inheriting copy/move
constructors to better match the pre-P0136R1 behavior.

------------------------------------------------------------------------

llvm-svn: 292463
2017-01-19 01:51:39 +00:00
Joerg Sonnenberger
0cdb18a0ff Merging r292244:
------------------------------------------------------------------------
r292244 | joerg | 2017-01-17 20:29:15 +0100 (Di, 17. Jan 2017) | 2 Zeilen

Remove an overeager assert from r288844.

------------------------------------------------------------------------

llvm-svn: 292453
2017-01-19 00:19:28 +00:00
Joerg Sonnenberger
776831911f Merging r292119:
------------------------------------------------------------------------
r292119 | joerg | 2017-01-16 15:07:24 +0100 (Mo, 16. Jan 2017) | 3 Zeilen

Ensure that clang -pthread creates the right macro. -D_POSIX_THREADS
seems to have been a C&P error from old GCC specs for OpenBSD.

------------------------------------------------------------------------

llvm-svn: 292451
2017-01-19 00:10:50 +00:00
Rafael Espindola
b98695ecbd Port r291944.
Don't add DT_INIT/DT_FINI for undef and shared symbols.

The freebsd dynamic linker doesn't check if the value is null (and it
is reasonable for it to do that). That means that producing a .so with
a null DT_INIT/DT_FINI causes the base address to be called.

This should fix the libreoffice build.

llvm-svn: 292429
2017-01-18 20:00:59 +00:00
Rafael Espindola
1fc8b50777 Port r292146.
Give priority to linker scripts over preemption.

LLD exports symbols that are also present in used shared libraries to
make sure they are preempted at runtime. That is a reasonable default,
but we must allow for it to be overwritten with linker script. If we
don't, libraries that expect to be able to hide a c++ delete operator
will fail.

This should fix the firebird build.

llvm-svn: 292370
2017-01-18 14:43:01 +00:00
Eric Fiselier
72cd787e22 Merge R292276: Fix std::string assignment ambiguity from braced initializer lists.
When support for `basic_string_view` was added to string it also
added new assignment operators from `basic_string_view`. These caused
ambiguity when assigning from a braced initializer. This patch fixes
that regression by making the basic_string_view assignment operator
rank lower in overload resolution by making it a template.

llvm-svn: 292354
2017-01-18 08:43:24 +00:00
Hans Wennborg
5476b86ed3 Merging r292013:
------------------------------------------------------------------------
r292013 | hahnfeld | 2017-01-14 03:35:15 -0800 (Sat, 14 Jan 2017) | 6 lines

Fix last_write_time tests for filesystems that don't support negative and very large times

Seems to be the case for NFS.

Original patch by Eric Fiselier!
Differential Revision: https://reviews.llvm.org/D22452
------------------------------------------------------------------------

llvm-svn: 292341
2017-01-18 05:07:58 +00:00
Hans Wennborg
f581e2cd50 Merging r291966:
------------------------------------------------------------------------
r291966 | majnemer | 2017-01-13 14:24:27 -0800 (Fri, 13 Jan 2017) | 6 lines

[LoopStrengthReduce] Don't bother rewriting PHIs in catchswitch blocks

The catchswitch instruction cannot be split, don't bother trying to
rewrite it.

This fixes PR31627.
------------------------------------------------------------------------

llvm-svn: 292340
2017-01-18 04:56:54 +00:00
Hans Wennborg
51d42e77e9 Merging r292247:
------------------------------------------------------------------------
r292247 | jbcoe | 2017-01-17 12:03:54 -0800 (Tue, 17 Jan 2017) | 14 lines

Fix Python 3 language issues and add an explicit check for Python version == 2.

Summary:
Python bindings cannot support Python 3 without work being done to fix Unicode c-string conversion.

This was attempted in https://reviews.llvm.org/D26082. That patch was reverted due to memory access issues on Linux.

This revision fixes enough language compatibility issues for the clang module to be loaded and raise an error if the Python version is not 2.

Reviewers: mgorny, MathieuDuponchelle, rengolin, compnerd

Reviewed By: compnerd

Differential Revision: https://reviews.llvm.org/D28682
------------------------------------------------------------------------

llvm-svn: 292339
2017-01-18 04:45:43 +00:00
Hans Wennborg
7dc1f85818 Merging r292183:
------------------------------------------------------------------------
r292183 | rsmith | 2017-01-16 18:14:37 -0800 (Mon, 16 Jan 2017) | 14 lines

Partial revert of r290511.

The rules around typechecking deduced template arguments during partial
ordering are not clear, and while the prior behavior does not seem to be
correct (it doesn't follow the general model of partial ordering where each
template parameter is replaced by a non-dependent but unique value), the new
behavior is also not clearly right and breaks some existing idioms.

The new behavior is retained for dealing with non-type template parameters
with 'auto' types, as without it even the most basic uses of that feature
don't work. We can revisit this once CWG has come to an agreement on how
partial ordering with 'auto' non-type template parameters is supposed to
work.

------------------------------------------------------------------------

llvm-svn: 292338
2017-01-18 04:36:52 +00:00
Hans Wennborg
4fe1712e62 Merging r292052:
------------------------------------------------------------------------
r292052 | akirtzidis | 2017-01-14 22:11:04 -0800 (Sat, 14 Jan 2017) | 1 line

[code-completion] Fix crash when trying to do postfix completion of instance member inside a static function.
------------------------------------------------------------------------

llvm-svn: 292313
2017-01-18 00:24:13 +00:00
Hans Wennborg
481bb24909 Merging r292133:
------------------------------------------------------------------------
r292133 | hfinkel | 2017-01-16 07:22:01 -0800 (Mon, 16 Jan 2017) | 10 lines

Fix use-after-free bug in AffectedValueCallbackVH::allUsesReplacedWith

When transferring affected values in the cache from an old value, identified by
the value of the current callback, to the specified new value we might need to
insert a new entry into the DenseMap which constitutes the cache. Doing so
might delete the current callback object. Move the copying logic into a new
function, a member of the assumption cache itself, so that we don't run into UB
should the callback handle itself be removed mid-copy.

Differential Revision: https://reviews.llvm.org/D28749
------------------------------------------------------------------------

llvm-svn: 292312
2017-01-18 00:21:36 +00:00
Hans Wennborg
57f962dfeb Merging r292032:
------------------------------------------------------------------------
r292032 | yrnkrn | 2017-01-14 13:12:08 -0800 (Sat, 14 Jan 2017) | 4 lines

Fix PR31644 introduced by r287138 and add a regression test.
Thanks Dimitry Andric for the report and fix!


------------------------------------------------------------------------

llvm-svn: 292311
2017-01-18 00:16:39 +00:00
Eric Fiselier
4fae7917b7 Merge r292294: Fix type_info's constructor by making it explicit again.
In recent changes type_info's private constructor was accidentally made
implicit. This patch fixes that.

llvm-svn: 292309
2017-01-18 00:14:31 +00:00
Hans Wennborg
759bf08715 Merging r291968 and r291979:
------------------------------------------------------------------------
r291968 | dannyb | 2017-01-13 14:40:01 -0800 (Fri, 13 Jan 2017) | 23 lines

NewGVN: Move leaders around properly to ensure we have a canonical dominating leader. Fixes PR 31613.

Summary:
This is a testcase where phi node cycling happens, and because we do
not order the leaders by domination or anything similar, the leader
keeps changing.

Using std::set for the members is too expensive, and we actually don't
need them sorted all the time, only at leader changes.

We could keep both a set and a vector, and keep them mostly sorted and
resort as necessary, or use a set and a fibheap, but all of this seems
premature.

After running some statistics, we are able to avoid the vast majority
of sorting by keeping a "next leader" field.  Most congruence classes only have
leader changes once or twice during GVN.

Reviewers: davide

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D28594
------------------------------------------------------------------------

------------------------------------------------------------------------
r291979 | dannyb | 2017-01-13 15:54:10 -0800 (Fri, 13 Jan 2017) | 1 line

NewGVN: Fix PR31613 test regex naming
------------------------------------------------------------------------

llvm-svn: 292307
2017-01-18 00:12:25 +00:00
Hans Wennborg
c011d30be2 Merging r292255:
------------------------------------------------------------------------
r292255 | mgorny | 2017-01-17 13:04:19 -0800 (Tue, 17 Jan 2017) | 12 lines

[cmake] Update SOVERSION for the new versioning scheme

Update SOVERSION to use just the major version number rather than
major+minor, to match the new versioning scheme where only major is used
to indicate API/ABI version.

Since two-digit SOVERSIONs were introduced post 3.9 branching, this
change does not risk any SOVERSION collisions. In the past,
two-component X.Y SOVERSIONs were shortly used but those will not
interfere with the new ones since the new versions start at 4.

Differential Revision: https://reviews.llvm.org/D28730
------------------------------------------------------------------------

llvm-svn: 292270
2017-01-17 21:47:58 +00:00
Hans Wennborg
59b7122580 Make the -fstrict-vtable-pointers link relative
llvm-svn: 292267
2017-01-17 21:33:39 +00:00
Hans Wennborg
8819de8819 Merging r292265:
------------------------------------------------------------------------
r292265 | hans | 2017-01-17 13:31:57 -0800 (Tue, 17 Jan 2017) | 1 line

UsersManual.rst: add missing newline
------------------------------------------------------------------------

llvm-svn: 292266
2017-01-17 21:32:31 +00:00
Hans Wennborg
ac7da5564c Fix -fstrict-vtable-pointers link
llvm-svn: 292264
2017-01-17 21:29:52 +00:00
Hans Wennborg
b60a8c7d6a Drop 'if you're using released version' warning
llvm-svn: 292263
2017-01-17 21:27:57 +00:00
Hans Wennborg
6e97d9762d Fix docs build
llvm-svn: 292262
2017-01-17 21:26:58 +00:00
Hans Wennborg
2c585068b7 Regenerate AttributeReference.rst
llvm-svn: 292259
2017-01-17 21:20:45 +00:00
Hans Wennborg
80e29a8301 Merging r292242:
------------------------------------------------------------------------
r292242 | bwilson | 2017-01-17 11:18:57 -0800 (Tue, 17 Jan 2017) | 5 lines

Revert r291640 change to fold X86 comparison with atomic_load_add.

Even with the fix from r291630, this still causes problems. I get
widespread assertion failures in the Swift runtime's WeakRefCount::increment()
function. I sent a reduced testcase in reply to the commit.
------------------------------------------------------------------------

llvm-svn: 292243
2017-01-17 19:29:13 +00:00
Piotr Padlewski
475150bd71 Add -fstrict-vtable-pointers to UsersManual
In order to have link from ReleaseNotes working
this needs to have -fstrict-vtable-pointers 
option.

There is also one small typo fix (overridden)
y

https://reviews.llvm.org/D28727

llvm-svn: 292113
2017-01-16 13:24:50 +00:00
Piotr Padlewski
4cd57bf3a2 Mention Devirtualization and ThinLTO in ReleaseNotes
This might require some small fixits after generating
doc

Devirtualization:
https://reviews.llvm.org/D28606

ThinLTO:
https://reviews.llvm.org/D28746

llvm-svn: 292080
2017-01-15 22:38:15 +00:00
Piotr Padlewski
17becd082c Mention ThinLTO in ReleaseNotes
https://reviews.llvm.org/D28746

llvm-svn: 292079
2017-01-15 22:33:49 +00:00
Piotr Padlewski
9a809b2316 Mention invariant.group in ReleaseNotes
https://reviews.llvm.org/D28605

llvm-svn: 292009
2017-01-14 10:03:14 +00:00
Hans Wennborg
74ffad2922 Merging r291964:
------------------------------------------------------------------------
r291964 | rsmith | 2017-01-13 14:16:41 -0800 (Fri, 13 Jan 2017) | 2 lines

PR31631: fix bad CFG (and bogus warnings) when an if-statement has an init-statement and has binary operator as its condition.

------------------------------------------------------------------------

llvm-svn: 291978
2017-01-13 23:47:08 +00:00
Hans Wennborg
aa8d52cd37 Merging r291879:
------------------------------------------------------------------------
r291879 | echristo | 2017-01-12 17:52:04 -0800 (Thu, 12 Jan 2017) | 1 line

Add a necessary newline for diagnose_if documentation.
------------------------------------------------------------------------

llvm-svn: 291952
2017-01-13 19:40:22 +00:00
Hans Wennborg
d7cde544c8 Merging r291881:
------------------------------------------------------------------------
r291881 | chandlerc | 2017-01-12 18:47:34 -0800 (Thu, 12 Jan 2017) | 3 lines

Another fix for r291850 because there are apparently targets which add
"-mllvm" flags to the CC1 invocation (notably, Hexagon seems to hit
this).
------------------------------------------------------------------------

llvm-svn: 291951
2017-01-13 19:37:35 +00:00
Hans Wennborg
33799a65b3 Merging r291907:
------------------------------------------------------------------------
r291907 | jbcoe | 2017-01-13 08:06:59 -0800 (Fri, 13 Jan 2017) | 6 lines

Revert "Support for Python 3 in libclang python bindings"

This reverts commit 4464581bb63e9789e9ee231a8c8800be5f614743.

Memory access issues on Linux were reported by Mathieu Duponchelle and
discussed here: https://reviews.llvm.org/D26082.
------------------------------------------------------------------------

llvm-svn: 291950
2017-01-13 19:33:59 +00:00
Hans Wennborg
43c1ed14b8 Merging r291875:
------------------------------------------------------------------------
r291875 | chapuni | 2017-01-12 17:13:10 -0800 (Thu, 12 Jan 2017) | 8 lines

Revert r291503, "Lift the 10-type limit for AlignedCharArrayUnion", and followings.

  r291503, "Lift the 10-type limit for AlignedCharArrayUnion"
  r291514, "Fix MSVC build of AlignedCharArrayUnion"
  r291515, "Revert the attempt to optimize the constexpr functions. MSVC does not handle this yet"
  r291519, "Try once again to fix the MSVC build of AlignedCharArrayUnion"

They has been failing on i686-linux.
------------------------------------------------------------------------

llvm-svn: 291945
2017-01-13 19:20:38 +00:00
Hans Wennborg
111f0956ca Merging r291877:
------------------------------------------------------------------------
r291877 | smeenai | 2017-01-12 17:28:34 -0800 (Thu, 12 Jan 2017) | 13 lines

[Sema] Restrict explicit instantation definition dllexport

In the case where the template class itself is already `dllexport`, the
implicit instantiation will have already emitted all members. When we
check the explicit instantiation definition, the `Specialization` will
have inherited the `dllexport` attribute, so we'll attempt to emit all
members for a second time, which causes an assertion failure. Restrict
the exporting to when the `dllexport` attribute is newly introduced by
the explicit instantiation definition.

Fixes PR31608.

Differential Revision: https://reviews.llvm.org/D28590
------------------------------------------------------------------------

llvm-svn: 291943
2017-01-13 19:11:01 +00:00
Eric Fiselier
45181d08a0 Fix merge error caused by r291922
llvm-svn: 291935
2017-01-13 18:42:41 +00:00
Eric Fiselier
8343e2ddeb Revert "Rework fix for PR19460 - Use explicit bool as an extension instead."
llvm-svn: 291922
2017-01-13 18:08:23 +00:00
Hans Wennborg
c18d03105b Merging r291863:
------------------------------------------------------------------------
r291863 | chapuni | 2017-01-12 16:17:15 -0800 (Thu, 12 Jan 2017) | 1 line

xray-account: Avoid std::errc::bad_message to appease mingw.
------------------------------------------------------------------------

llvm-svn: 291914
2017-01-13 16:57:29 +00:00
Hans Wennborg
3294e2a1a3 Merging r291871:
------------------------------------------------------------------------
r291871 | rsmith | 2017-01-12 16:57:54 -0800 (Thu, 12 Jan 2017) | 10 lines

Update C++ status pages for Clang 4 branch:

 * Update version number in DR tests from 4.0 to 4
 * Teach make_cxx_dr_status script about version numbers that don't contain a
   period.
 * Update cxx_status.html and cxx_dr_status.html to list Clang 4 features as
   "Clang 4" rather than "SVN"

Clang 4 features are still listed in yellow rather than green until release.

------------------------------------------------------------------------

llvm-svn: 291913
2017-01-13 16:52:17 +00:00
Hans Wennborg
e9b065b5e7 Merging r291865:
------------------------------------------------------------------------
r291865 | rsmith | 2017-01-12 16:43:31 -0800 (Thu, 12 Jan 2017) | 15 lines

Improve handling of instantiated thread_local variables in Itanium C++ ABI.

 * Do not initialize these variables when initializing the rest of the
   thread_locals in the TU; they have unordered initialization so they can be
   initialized by themselves.

   This fixes a rejects-valid bug: we would make the per-variable initializer
   function internal, but put it in a comdat keyed off the variable, resulting
   in link errors when the comdat is selected from a different TU (as the per
   TU TLS init function tries to call an init function that does not exist).

 * On Darwin, when we decide that we're not going to emit a thread wrapper
   function at all, demote its linkage to External. Fixes a verifier failure
   on explicit instantiation of a thread_local variable on Darwin.

------------------------------------------------------------------------

llvm-svn: 291912
2017-01-13 16:47:33 +00:00
Hans Wennborg
86db6dfb80 Merging r291850 and r291853:
------------------------------------------------------------------------
r291850 | chandlerc | 2017-01-12 14:40:13 -0800 (Thu, 12 Jan 2017) | 9 lines

Address review comments on r290392:
- Don't break using '-mllvm -disable-llvm-optzns' (yet).
- Don't add support for '-mllvm -disable-llvm-passes'.

This is important for LLVM 4 as we haven't yet really told folks this is
coming. I'll add release notes about this.

I've also added some explicit testing of this so its more obvious what
is happening here.
------------------------------------------------------------------------

------------------------------------------------------------------------
r291853 | chandlerc | 2017-01-12 14:48:28 -0800 (Thu, 12 Jan 2017) | 1 line

Fix two test cases I missed updating in r291850. Sorry for the noise.
------------------------------------------------------------------------

llvm-svn: 291860
2017-01-12 23:30:04 +00:00
Hans Wennborg
7ad09ec2f2 ReleaseNotes: remove 'if you're reading on trunk' warning
llvm-svn: 291857
2017-01-12 22:51:59 +00:00
Hans Wennborg
7cd09801c4 ReleaseNotes: remove 'if you're reading on trunk' warning
llvm-svn: 291856
2017-01-12 22:51:35 +00:00
Hans Wennborg
28e9f914ed ReleaseNotes: remove 'if you're reading on trunk' warning
llvm-svn: 291855
2017-01-12 22:51:23 +00:00
Hans Wennborg
b3e36f2704 ReleaseNotes: remove 'if you're reading on trunk' warning
llvm-svn: 291854
2017-01-12 22:51:04 +00:00
Hans Wennborg
49075460d9 Generate docs/AttributeReference.rst
llvm-svn: 291848
2017-01-12 22:26:52 +00:00
Hans Wennborg
72f564730f Drop 'svn' suffix from version.
llvm-svn: 291846
2017-01-12 22:13:19 +00:00
Hans Wennborg
8b187d55b8 Drop 'svn' suffix from version.
llvm-svn: 291845
2017-01-12 22:13:09 +00:00
Hans Wennborg
71ca167b9e Drop 'svn' suffix from version.
llvm-svn: 291844
2017-01-12 22:12:54 +00:00
Hans Wennborg
2402860537 Drop 'svn' suffix from version.
llvm-svn: 291843
2017-01-12 22:12:41 +00:00
Hans Wennborg
ca21025169 Update scripts/Xcode/build-llvm.py to use llvm/clang 4 branch
llvm-svn: 291842
2017-01-12 22:06:33 +00:00
Hans Wennborg
bfe45360b1 Creating release_40 branch off revision 291814
llvm-svn: 291827
llvm-svn: 291826
llvm-svn: 291825
llvm-svn: 291824
llvm-svn: 291823
llvm-svn: 291822
llvm-svn: 291821
llvm-svn: 291820
llvm-svn: 291819
llvm-svn: 291817
llvm-svn: 291816
2017-01-12 21:26:18 +00:00
29040 changed files with 733083 additions and 2888436 deletions

View File

@@ -1,4 +1,4 @@
{
"repository.callsign" : "CTE",
"project_id" : "clang-tools-extra",
"conduit_uri" : "https://reviews.llvm.org/"
}

View File

@@ -1,4 +1,5 @@
add_subdirectory(clang-apply-replacements)
add_subdirectory(clang-rename)
add_subdirectory(clang-reorder-fields)
add_subdirectory(modularize)
if(CLANG_ENABLE_STATIC_ANALYZER)
@@ -9,13 +10,13 @@ endif()
add_subdirectory(change-namespace)
add_subdirectory(clang-query)
add_subdirectory(clang-move)
add_subdirectory(clangd)
add_subdirectory(include-fixer)
add_subdirectory(pp-trace)
add_subdirectory(tool-template)
# Add the common testsuite after all the tools.
if(CLANG_INCLUDE_TESTS)
# TODO: Support tests with more granularity when features are off?
if(CLANG_ENABLE_STATIC_ANALYZER AND CLANG_INCLUDE_TESTS)
add_subdirectory(test)
add_subdirectory(unittests)
endif()

View File

@@ -60,4 +60,3 @@ licenses, and/or restrictions:
Program Directory
------- ---------
clang-tidy clang-tidy/cert
clang-tidy clang-tidy/hicpp

View File

@@ -28,14 +28,6 @@ joinNamespaces(const llvm::SmallVectorImpl<StringRef> &Namespaces) {
return Result;
}
// Given "a::b::c", returns {"a", "b", "c"}.
llvm::SmallVector<llvm::StringRef, 4> splitSymbolName(llvm::StringRef Name) {
llvm::SmallVector<llvm::StringRef, 4> Splitted;
Name.split(Splitted, "::", /*MaxSplit=*/-1,
/*KeepEmpty=*/false);
return Splitted;
}
SourceLocation startLocationForType(TypeLoc TLoc) {
// For elaborated types (e.g. `struct a::A`) we want the portion after the
// `struct` but including the namespace qualifier, `a::`.
@@ -76,7 +68,9 @@ const NamespaceDecl *getOuterNamespace(const NamespaceDecl *InnerNs,
return nullptr;
const auto *CurrentContext = llvm::cast<DeclContext>(InnerNs);
const auto *CurrentNs = InnerNs;
auto PartialNsNameSplitted = splitSymbolName(PartialNsName);
llvm::SmallVector<llvm::StringRef, 4> PartialNsNameSplitted;
PartialNsName.split(PartialNsNameSplitted, "::", /*MaxSplit=*/-1,
/*KeepEmpty=*/false);
while (!PartialNsNameSplitted.empty()) {
// Get the inner-most namespace in CurrentContext.
while (CurrentContext && !llvm::isa<NamespaceDecl>(CurrentContext))
@@ -202,8 +196,6 @@ tooling::Replacement createInsertion(SourceLocation Loc,
// Returns the shortest qualified name for declaration `DeclName` in the
// namespace `NsName`. For example, if `DeclName` is "a::b::X" and `NsName`
// is "a::c::d", then "b::X" will be returned.
// Note that if `DeclName` is `::b::X` and `NsName` is `::a::b`, this returns
// "::b::X" instead of "b::X" since there will be a name conflict otherwise.
// \param DeclName A fully qualified name, "::a::b::X" or "a::b::X".
// \param NsName A fully qualified name, "::a::b" or "a::b". Global namespace
// will have empty name.
@@ -214,44 +206,22 @@ std::string getShortestQualifiedNameInNamespace(llvm::StringRef DeclName,
if (DeclName.find(':') == llvm::StringRef::npos)
return DeclName;
auto NsNameSplitted = splitSymbolName(NsName);
auto DeclNsSplitted = splitSymbolName(DeclName);
llvm::StringRef UnqualifiedDeclName = DeclNsSplitted.pop_back_val();
// If the Decl is in global namespace, there is no need to shorten it.
if (DeclNsSplitted.empty())
return UnqualifiedDeclName;
// If NsName is the global namespace, we can simply use the DeclName sans
// leading "::".
if (NsNameSplitted.empty())
return DeclName;
if (NsNameSplitted.front() != DeclNsSplitted.front()) {
// The DeclName must be fully-qualified, but we still need to decide if a
// leading "::" is necessary. For example, if `NsName` is "a::b::c" and the
// `DeclName` is "b::X", then the reference must be qualified as "::b::X"
// to avoid conflict.
if (llvm::is_contained(NsNameSplitted, DeclNsSplitted.front()))
return ("::" + DeclName).str();
return DeclName;
while (!DeclName.consume_front((NsName + "::").str())) {
const auto Pos = NsName.find_last_of(':');
if (Pos == llvm::StringRef::npos)
return DeclName;
assert(Pos > 0);
NsName = NsName.substr(0, Pos - 1);
}
// Since there is already an overlap namespace, we know that `DeclName` can be
// shortened, so we reduce the longest common prefix.
auto DeclI = DeclNsSplitted.begin();
auto DeclE = DeclNsSplitted.end();
auto NsI = NsNameSplitted.begin();
auto NsE = NsNameSplitted.end();
for (; DeclI != DeclE && NsI != NsE && *DeclI == *NsI; ++DeclI, ++NsI) {
}
return (DeclI == DeclE)
? UnqualifiedDeclName.str()
: (llvm::join(DeclI, DeclE, "::") + "::" + UnqualifiedDeclName)
.str();
return DeclName;
}
std::string wrapCodeInNamespace(StringRef NestedNs, std::string Code) {
if (Code.back() != '\n')
Code += "\n";
auto NsSplitted = splitSymbolName(NestedNs);
llvm::SmallVector<StringRef, 4> NsSplitted;
NestedNs.split(NsSplitted, "::", /*MaxSplit=*/-1,
/*KeepEmpty=*/false);
while (!NsSplitted.empty()) {
// FIXME: consider code style for comments.
Code = ("namespace " + NsSplitted.back() + " {\n" + Code +
@@ -275,61 +245,27 @@ bool isNestedDeclContext(const DeclContext *D, const DeclContext *Context) {
// Returns true if \p D is visible at \p Loc with DeclContext \p DeclCtx.
bool isDeclVisibleAtLocation(const SourceManager &SM, const Decl *D,
const DeclContext *DeclCtx, SourceLocation Loc) {
SourceLocation DeclLoc = SM.getSpellingLoc(D->getLocStart());
SourceLocation DeclLoc = SM.getSpellingLoc(D->getLocation());
Loc = SM.getSpellingLoc(Loc);
return SM.isBeforeInTranslationUnit(DeclLoc, Loc) &&
(SM.getFileID(DeclLoc) == SM.getFileID(Loc) &&
isNestedDeclContext(DeclCtx, D->getDeclContext()));
}
// Given a qualified symbol name, returns true if the symbol will be
// incorrectly qualified without leading "::".
bool conflictInNamespace(llvm::StringRef QualifiedSymbol,
llvm::StringRef Namespace) {
auto SymbolSplitted = splitSymbolName(QualifiedSymbol.trim(":"));
assert(!SymbolSplitted.empty());
SymbolSplitted.pop_back(); // We are only interested in namespaces.
if (SymbolSplitted.size() > 1 && !Namespace.empty()) {
auto NsSplitted = splitSymbolName(Namespace.trim(":"));
assert(!NsSplitted.empty());
// We do not check the outermost namespace since it would not be a conflict
// if it equals to the symbol's outermost namespace and the symbol name
// would have been shortened.
for (auto I = NsSplitted.begin() + 1, E = NsSplitted.end(); I != E; ++I) {
if (*I == SymbolSplitted.front())
return true;
}
}
return false;
}
AST_MATCHER(EnumDecl, isScoped) {
return Node.isScoped();
}
bool isTemplateParameter(TypeLoc Type) {
while (!Type.isNull()) {
if (Type.getTypeLocClass() == TypeLoc::SubstTemplateTypeParm)
return true;
Type = Type.getNextTypeLoc();
}
return false;
}
} // anonymous namespace
ChangeNamespaceTool::ChangeNamespaceTool(
llvm::StringRef OldNs, llvm::StringRef NewNs, llvm::StringRef FilePattern,
llvm::ArrayRef<std::string> WhiteListedSymbolPatterns,
std::map<std::string, tooling::Replacements> *FileToReplacements,
llvm::StringRef FallbackStyle)
: FallbackStyle(FallbackStyle), FileToReplacements(*FileToReplacements),
OldNamespace(OldNs.ltrim(':')), NewNamespace(NewNs.ltrim(':')),
FilePattern(FilePattern), FilePatternRE(FilePattern) {
FileToReplacements->clear();
auto OldNsSplitted = splitSymbolName(OldNamespace);
auto NewNsSplitted = splitSymbolName(NewNamespace);
llvm::SmallVector<llvm::StringRef, 4> OldNsSplitted;
llvm::SmallVector<llvm::StringRef, 4> NewNsSplitted;
llvm::StringRef(OldNamespace).split(OldNsSplitted, "::");
llvm::StringRef(NewNamespace).split(NewNsSplitted, "::");
// Calculates `DiffOldNamespace` and `DiffNewNamespace`.
while (!OldNsSplitted.empty() && !NewNsSplitted.empty() &&
OldNsSplitted.front() == NewNsSplitted.front()) {
@@ -338,9 +274,6 @@ ChangeNamespaceTool::ChangeNamespaceTool(
}
DiffOldNamespace = joinNamespaces(OldNsSplitted);
DiffNewNamespace = joinNamespaces(NewNsSplitted);
for (const auto &Pattern : WhiteListedSymbolPatterns)
WhiteListedSymbolRegexes.emplace_back(Pattern);
}
void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
@@ -427,8 +360,7 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
unless(templateSpecializationType())))))),
hasParent(nestedNameSpecifierLoc()),
hasAncestor(isImplicit()),
hasAncestor(UsingShadowDeclInClass),
hasAncestor(functionDecl(isDefaulted())))),
hasAncestor(UsingShadowDeclInClass))),
hasAncestor(decl().bind("dc")))
.bind("type"),
this);
@@ -452,7 +384,6 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
specifiesType(hasDeclaration(DeclMatcher.bind("from_decl"))))),
unless(anyOf(hasAncestor(isImplicit()),
hasAncestor(UsingShadowDeclInClass),
hasAncestor(functionDecl(isDefaulted())),
hasAncestor(typeLoc(loc(qualType(hasDeclaration(
decl(equalsBoundNode("from_decl"))))))))))
.bind("nested_specifier_loc"),
@@ -493,17 +424,6 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
to(GlobalVarMatcher.bind("var_decl")))
.bind("var_ref"),
this);
// Handle unscoped enum constant.
auto UnscopedEnumMatcher = enumConstantDecl(hasParent(enumDecl(
hasParent(namespaceDecl()),
unless(anyOf(isScoped(), IsInMovedNs, hasAncestor(cxxRecordDecl()),
hasAncestor(namespaceDecl(isAnonymous())))))));
Finder->addMatcher(
declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")),
to(UnscopedEnumMatcher.bind("enum_const_decl")))
.bind("enum_const_ref"),
this);
}
void ChangeNamespaceTool::run(
@@ -552,10 +472,6 @@ void ChangeNamespaceTool::run(
if (Loc.getTypeLocClass() == TypeLoc::Elaborated) {
NestedNameSpecifierLoc NestedNameSpecifier =
Loc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
// This happens for friend declaration of a base class with injected class
// name.
if (!NestedNameSpecifier.getNestedNameSpecifier())
return;
const Type *SpecifierType =
NestedNameSpecifier.getNestedNameSpecifier()->getAsType();
if (SpecifierType && SpecifierType->isRecordType())
@@ -572,23 +488,6 @@ void ChangeNamespaceTool::run(
assert(Context && "Empty decl context.");
fixDeclRefExpr(Result, Context->getDeclContext(),
llvm::cast<NamedDecl>(Var), VarRef);
} else if (const auto *EnumConstRef =
Result.Nodes.getNodeAs<DeclRefExpr>("enum_const_ref")) {
// Do not rename the reference if it is already scoped by the EnumDecl name.
if (EnumConstRef->hasQualifier() &&
EnumConstRef->getQualifier()->getKind() ==
NestedNameSpecifier::SpecifierKind::TypeSpec &&
EnumConstRef->getQualifier()->getAsType()->isEnumeralType())
return;
const auto *EnumConstDecl =
Result.Nodes.getNodeAs<EnumConstantDecl>("enum_const_decl");
assert(EnumConstDecl);
const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");
assert(Context && "Empty decl context.");
// FIXME: this would qualify "ns::VALUE" as "ns::EnumValue::VALUE". Fix it
// if it turns out to be an issue.
fixDeclRefExpr(Result, Context->getDeclContext(),
llvm::cast<NamedDecl>(EnumConstDecl), EnumConstRef);
} else if (const auto *FuncRef =
Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
// If this reference has been processed as a function call, we do not
@@ -711,18 +610,19 @@ void ChangeNamespaceTool::moveClassForwardDeclaration(
const NamedDecl *FwdDecl) {
SourceLocation Start = FwdDecl->getLocStart();
SourceLocation End = FwdDecl->getLocEnd();
const SourceManager &SM = *Result.SourceManager;
SourceLocation AfterSemi = Lexer::findLocationAfterToken(
End, tok::semi, SM, Result.Context->getLangOpts(),
End, tok::semi, *Result.SourceManager, Result.Context->getLangOpts(),
/*SkipTrailingWhitespaceAndNewLine=*/true);
if (AfterSemi.isValid())
End = AfterSemi.getLocWithOffset(-1);
// Delete the forward declaration from the code to be moved.
addReplacementOrDie(Start, End, "", SM, &FileToReplacements);
addReplacementOrDie(Start, End, "", *Result.SourceManager,
&FileToReplacements);
llvm::StringRef Code = Lexer::getSourceText(
CharSourceRange::getTokenRange(SM.getSpellingLoc(Start),
SM.getSpellingLoc(End)),
SM, Result.Context->getLangOpts());
CharSourceRange::getTokenRange(
Result.SourceManager->getSpellingLoc(Start),
Result.SourceManager->getSpellingLoc(End)),
*Result.SourceManager, Result.Context->getLangOpts());
// Insert the forward declaration back into the old namespace after moving the
// code from old namespace to new namespace.
// Insertion information is stored in `InsertFwdDecls` and actual
@@ -731,9 +631,8 @@ void ChangeNamespaceTool::moveClassForwardDeclaration(
const auto *NsDecl = Result.Nodes.getNodeAs<NamespaceDecl>("ns_decl");
// The namespace contains the forward declaration, so it must not be empty.
assert(!NsDecl->decls_empty());
const auto Insertion = createInsertion(
getLocAfterNamespaceLBrace(NsDecl, SM, Result.Context->getLangOpts()),
Code, SM);
const auto Insertion = createInsertion(NsDecl->decls_begin()->getLocStart(),
Code, *Result.SourceManager);
InsertForwardDeclaration InsertFwd;
InsertFwd.InsertionOffset = Insertion.getOffset();
InsertFwd.ForwardDeclText = Insertion.getReplacementText().str();
@@ -774,10 +673,10 @@ void ChangeNamespaceTool::replaceQualifiedSymbolInDeclContext(
Result.SourceManager->getSpellingLoc(Start),
Result.SourceManager->getSpellingLoc(End)),
*Result.SourceManager, Result.Context->getLangOpts());
// If the symbol is already fully qualified, no change needs to be make.
if (NestedName.startswith("::"))
return;
std::string FromDeclName = FromDecl->getQualifiedNameAsString();
for (llvm::Regex &RE : WhiteListedSymbolRegexes)
if (RE.match(FromDeclName))
return;
std::string ReplaceName =
getShortestQualifiedNameInNamespace(FromDeclName, NewNs);
// Checks if there is any using namespace declarations that can shorten the
@@ -835,8 +734,7 @@ void ChangeNamespaceTool::replaceQualifiedSymbolInDeclContext(
if (isDeclVisibleAtLocation(*Result.SourceManager, Using, DeclCtx, Start)) {
for (const auto *UsingShadow : Using->shadows()) {
const auto *TargetDecl = UsingShadow->getTargetDecl();
if (TargetDecl->getQualifiedNameAsString() ==
FromDecl->getQualifiedNameAsString()) {
if (TargetDecl == FromDecl) {
ReplaceName = FromDecl->getNameAsString();
Matched = true;
break;
@@ -846,13 +744,11 @@ void ChangeNamespaceTool::replaceQualifiedSymbolInDeclContext(
}
// If the new nested name in the new namespace is the same as it was in the
// old namespace, we don't create replacement.
if (NestedName == ReplaceName ||
(NestedName.startswith("::") && NestedName.drop_front(2) == ReplaceName))
if (NestedName == ReplaceName)
return;
// If the reference need to be fully-qualified, add a leading "::" unless
// NewNamespace is the global namespace.
if (ReplaceName == FromDeclName && !NewNamespace.empty() &&
conflictInNamespace(ReplaceName, NewNamespace))
if (ReplaceName == FromDeclName && !NewNamespace.empty())
ReplaceName = "::" + ReplaceName;
addReplacementOrDie(Start, End, ReplaceName, *Result.SourceManager,
&FileToReplacements);
@@ -869,8 +765,6 @@ void ChangeNamespaceTool::fixTypeLoc(
// Types of CXXCtorInitializers do not need to be fixed.
if (llvm::is_contained(BaseCtorInitializerTypeLocs, Type))
return;
if (isTemplateParameter(Type))
return;
// The declaration which this TypeLoc refers to.
const auto *FromDecl = Result.Nodes.getNodeAs<NamedDecl>("from_decl");
// `hasDeclaration` gives underlying declaration, but if the type is
@@ -989,14 +883,11 @@ void ChangeNamespaceTool::onEndOfTranslationUnit() {
// Add replacements referring to the changed code to existing replacements,
// which refers to the original code.
Replaces = Replaces.merge(NewReplacements);
auto Style = format::getStyle("file", FilePath, FallbackStyle);
if (!Style) {
llvm::errs() << llvm::toString(Style.takeError()) << "\n";
continue;
}
format::FormatStyle Style =
format::getStyle("file", FilePath, FallbackStyle);
// Clean up old namespaces if there is nothing in it after moving.
auto CleanReplacements =
format::cleanupAroundReplacements(Code, Replaces, *Style);
format::cleanupAroundReplacements(Code, Replaces, Style);
if (!CleanReplacements) {
llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
continue;

View File

@@ -50,7 +50,6 @@ public:
// files matching `FilePattern`.
ChangeNamespaceTool(
llvm::StringRef OldNs, llvm::StringRef NewNs, llvm::StringRef FilePattern,
llvm::ArrayRef<std::string> WhiteListedSymbolPatterns,
std::map<std::string, tooling::Replacements> *FileToReplacements,
llvm::StringRef FallbackStyle = "LLVM");
@@ -165,9 +164,6 @@ private:
// CallExpr and one as DeclRefExpr), we record all DeclRefExpr's that have
// been processed so that we don't handle them twice.
llvm::SmallPtrSet<const clang::DeclRefExpr*, 16> ProcessedFuncRefs;
// Patterns of symbol names whose references are not expected to be updated
// when changing namespaces around them.
std::vector<llvm::Regex> WhiteListedSymbolRegexes;
};
} // namespace change_namespace

View File

@@ -8,7 +8,6 @@ add_clang_executable(clang-change-namespace
ClangChangeNamespace.cpp
)
target_link_libraries(clang-change-namespace
PRIVATE
clangAST
clangASTMatchers
clangBasic

View File

@@ -39,7 +39,6 @@
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/YAMLTraits.h"
using namespace clang;
using namespace llvm;
@@ -64,38 +63,10 @@ cl::opt<std::string> FilePattern(
cl::opt<bool> Inplace("i", cl::desc("Inplace edit <file>s, if specified."),
cl::cat(ChangeNamespaceCategory));
cl::opt<bool>
DumpYAML("dump_result",
cl::desc("Dump new file contents in YAML, if specified."),
cl::cat(ChangeNamespaceCategory));
cl::opt<std::string> Style("style",
cl::desc("The style name used for reformatting."),
cl::init("LLVM"), cl::cat(ChangeNamespaceCategory));
cl::opt<std::string> WhiteListFile(
"whitelist_file",
cl::desc("A file containing regexes of symbol names that are not expected "
"to be updated when changing namespaces around them."),
cl::init(""), cl::cat(ChangeNamespaceCategory));
llvm::ErrorOr<std::vector<std::string>> GetWhiteListedSymbolPatterns() {
std::vector<std::string> Patterns;
if (WhiteListFile.empty())
return Patterns;
llvm::SmallVector<StringRef, 8> Lines;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
llvm::MemoryBuffer::getFile(WhiteListFile);
if (!File)
return File.getError();
llvm::StringRef Content = File.get()->getBuffer();
Content.split(Lines, '\n', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
for (auto Line : Lines)
Patterns.push_back(Line.trim());
return Patterns;
}
} // anonymous namespace
int main(int argc, const char **argv) {
@@ -104,16 +75,8 @@ int main(int argc, const char **argv) {
ChangeNamespaceCategory);
const auto &Files = OptionsParser.getSourcePathList();
tooling::RefactoringTool Tool(OptionsParser.getCompilations(), Files);
llvm::ErrorOr<std::vector<std::string>> WhiteListPatterns =
GetWhiteListedSymbolPatterns();
if (!WhiteListPatterns) {
llvm::errs() << "Failed to open whitelist file " << WhiteListFile << ". "
<< WhiteListPatterns.getError().message() << "\n";
return 1;
}
change_namespace::ChangeNamespaceTool NamespaceTool(
OldNamespace, NewNamespace, FilePattern, *WhiteListPatterns,
&Tool.getReplacements(), Style);
OldNamespace, NewNamespace, FilePattern, &Tool.getReplacements(), Style);
ast_matchers::MatchFinder Finder;
NamespaceTool.registerMatchers(&Finder);
std::unique_ptr<tooling::FrontendActionFactory> Factory =
@@ -138,41 +101,14 @@ int main(int argc, const char **argv) {
if (Inplace)
return Rewrite.overwriteChangedFiles();
std::set<llvm::StringRef> ChangedFiles;
for (const auto &it : Tool.getReplacements())
ChangedFiles.insert(it.first);
if (DumpYAML) {
auto WriteToYAML = [&](llvm::raw_ostream &OS) {
OS << "[\n";
for (auto I = ChangedFiles.begin(), E = ChangedFiles.end(); I != E; ++I) {
OS << " {\n";
OS << " \"FilePath\": \"" << *I << "\",\n";
const auto *Entry = FileMgr.getFile(*I);
auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User);
std::string Content;
llvm::raw_string_ostream ContentStream(Content);
Rewrite.getEditBuffer(ID).write(ContentStream);
OS << " \"SourceText\": \""
<< llvm::yaml::escape(ContentStream.str()) << "\"\n";
OS << " }";
if (I != std::prev(E))
OS << ",\n";
}
OS << "\n]\n";
};
WriteToYAML(llvm::outs());
return 0;
}
for (const auto &File : ChangedFiles) {
for (const auto &File : Files) {
const auto *Entry = FileMgr.getFile(File);
auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User);
// FIXME: print results in parsable format, e.g. JSON.
outs() << "============== " << File << " ==============\n";
Rewrite.getEditBuffer(ID).write(llvm::outs());
outs() << "\n============================================\n";
}
return 0;
}

View File

@@ -288,12 +288,13 @@ bool mergeAndDeduplicate(const TUReplacements &TUs,
for (const tooling::Replacement &R : TU.Replacements) {
// Use the file manager to deduplicate paths. FileEntries are
// automatically canonicalized.
if (const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath())) {
GroupedReplacements[Entry].push_back(R);
} else if (Warned.insert(R.getFilePath()).second) {
errs() << "Described file '" << R.getFilePath()
<< "' doesn't exist. Ignoring...\n";
const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath());
if (!Entry && Warned.insert(R.getFilePath()).second) {
errs() << "Described file '" << R.getFilePath()
<< "' doesn't exist. Ignoring...\n";
continue;
}
GroupedReplacements[Entry].push_back(R);
}
}
@@ -313,12 +314,13 @@ bool mergeAndDeduplicate(const TUDiagnostics &TUs,
for (const tooling::Replacement &R : Fix.second) {
// Use the file manager to deduplicate paths. FileEntries are
// automatically canonicalized.
if (const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath())) {
GroupedReplacements[Entry].push_back(R);
} else if (Warned.insert(R.getFilePath()).second) {
errs() << "Described file '" << R.getFilePath()
<< "' doesn't exist. Ignoring...\n";
const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath());
if (!Entry && Warned.insert(R.getFilePath()).second) {
errs() << "Described file '" << R.getFilePath()
<< "' doesn't exist. Ignoring...\n";
continue;
}
GroupedReplacements[Entry].push_back(R);
}
}
}

View File

@@ -6,7 +6,6 @@ add_clang_executable(clang-apply-replacements
ClangApplyReplacementsMain.cpp
)
target_link_libraries(clang-apply-replacements
PRIVATE
clangApplyReplacements
clangBasic
clangFormat

View File

@@ -82,8 +82,8 @@ private:
};
} // namespace
static void printVersion(raw_ostream &OS) {
OS << "clang-apply-replacements version " CLANG_VERSION_STRING << "\n";
static void printVersion() {
outs() << "clang-apply-replacements version " CLANG_VERSION_STRING << "\n";
}
/// \brief Convenience function to get rewritten content for \c Filename from
@@ -199,7 +199,7 @@ applyFormatting(const std::vector<tooling::Replacement> &Replacements,
int main(int argc, char **argv) {
cl::HideUnrelatedOptions(makeArrayRef(VisibleCategories));
cl::SetVersionPrinter(printVersion);
cl::SetVersionPrinter(&printVersion);
cl::ParseCommandLineOptions(argc, argv);
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
@@ -208,15 +208,8 @@ int main(int argc, char **argv) {
// Determine a formatting style from options.
format::FormatStyle FormatStyle;
if (DoFormat) {
auto FormatStyleOrError =
format::getStyle(FormatStyleOpt, FormatStyleConfig, "LLVM");
if (!FormatStyleOrError) {
llvm::errs() << llvm::toString(FormatStyleOrError.takeError()) << "\n";
return 1;
}
FormatStyle = *FormatStyleOrError;
}
if (DoFormat)
FormatStyle = format::getStyle(FormatStyleOpt, FormatStyleConfig, "LLVM");
TUReplacements TURs;
TUReplacementFiles TUFiles;

View File

@@ -31,8 +31,6 @@ namespace {
// FIXME: Move to ASTMatchers.
AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
AST_MATCHER(NamedDecl, notInMacro) { return !Node.getLocation().isMacroID(); }
AST_MATCHER_P(Decl, hasOutermostEnclosingClass,
ast_matchers::internal::Matcher<Decl>, InnerMatcher) {
const auto *Context = Node.getDeclContext();
@@ -168,21 +166,6 @@ private:
ClangMoveTool *MoveTool;
};
class VarDeclarationMatch : public MatchFinder::MatchCallback {
public:
explicit VarDeclarationMatch(ClangMoveTool *MoveTool)
: MoveTool(MoveTool) {}
void run(const MatchFinder::MatchResult &Result) override {
const auto *VD = Result.Nodes.getNodeAs<clang::VarDecl>("var");
assert(VD);
MoveDeclFromOldFileToNewFile(MoveTool, VD);
}
private:
ClangMoveTool *MoveTool;
};
class TypeAliasMatch : public MatchFinder::MatchCallback {
public:
explicit TypeAliasMatch(ClangMoveTool *MoveTool)
@@ -504,11 +487,8 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
isExpansionInFile(makeAbsolutePath(Context->Spec.OldHeader));
auto InOldCC = isExpansionInFile(makeAbsolutePath(Context->Spec.OldCC));
auto InOldFiles = anyOf(InOldHeader, InOldCC);
auto classTemplateForwardDecls =
classTemplateDecl(unless(has(cxxRecordDecl(isDefinition()))));
auto ForwardClassDecls = namedDecl(
anyOf(cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition()))),
classTemplateForwardDecls));
auto ForwardDecls =
cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition())));
auto TopLevelDecl =
hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));
@@ -521,8 +501,9 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
// We consider declarations inside a class belongs to the class. So these
// declarations will be ignored.
auto AllDeclsInHeader = namedDecl(
unless(ForwardClassDecls), unless(namespaceDecl()),
unless(usingDirectiveDecl()), // using namespace decl.
unless(ForwardDecls), unless(namespaceDecl()),
unless(usingDirectiveDecl()), // using namespace decl.
unless(classTemplateDecl(has(ForwardDecls))), // template forward decl.
InOldHeader,
hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
hasDeclContext(decl(anyOf(namespaceDecl(), translationUnitDecl()))));
@@ -533,7 +514,7 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
return;
// Match forward declarations in old header.
Finder->addMatcher(namedDecl(ForwardClassDecls, InOldHeader).bind("fwd_decl"),
Finder->addMatcher(namedDecl(ForwardDecls, InOldHeader).bind("fwd_decl"),
this);
//============================================================================
@@ -544,12 +525,12 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
// Matching using decls/type alias decls which are in named/anonymous/global
// namespace, these decls are always copied to new.h/cc. Those in classes,
// functions are covered in other matchers.
Finder->addMatcher(namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
usingDirectiveDecl(IsOldCCTopLevelDecl),
typeAliasDecl(IsOldCCTopLevelDecl)),
notInMacro())
.bind("using_decl"),
this);
Finder->addMatcher(
namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
usingDirectiveDecl(IsOldCCTopLevelDecl),
typeAliasDecl(IsOldCCTopLevelDecl)))
.bind("using_decl"),
this);
// Match static functions/variable definitions which are defined in named
// namespaces.
@@ -570,22 +551,14 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
// Matchers for helper declarations in old.cc.
auto InAnonymousNS = hasParent(namespaceDecl(isAnonymous()));
auto NotInMovedClass= allOf(unless(InMovedClass), InOldCC);
auto IsOldCCHelper =
allOf(NotInMovedClass, anyOf(isStaticStorageClass(), InAnonymousNS));
auto DefinitionInOldCC = allOf(isDefinition(), unless(InMovedClass), InOldCC);
auto IsOldCCHelperDefinition =
allOf(DefinitionInOldCC, anyOf(isStaticStorageClass(), InAnonymousNS));
// Match helper classes separately with helper functions/variables since we
// want to reuse these matchers in finding helpers usage below.
//
// There could be forward declarations usage for helpers, especially for
// classes and functions. We need include these forward declarations.
//
// Forward declarations for variable helpers will be excluded as these
// declarations (with "extern") are not supposed in cpp file.
auto HelperFuncOrVar =
namedDecl(notInMacro(), anyOf(functionDecl(IsOldCCHelper),
varDecl(isDefinition(), IsOldCCHelper)));
auto HelperClasses =
cxxRecordDecl(notInMacro(), NotInMovedClass, InAnonymousNS);
auto HelperFuncOrVar = namedDecl(anyOf(functionDecl(IsOldCCHelperDefinition),
varDecl(IsOldCCHelperDefinition)));
auto HelperClasses = cxxRecordDecl(DefinitionInOldCC, InAnonymousNS);
// Save all helper declarations in old.cc.
Finder->addMatcher(
namedDecl(anyOf(HelperFuncOrVar, HelperClasses)).bind("helper_decls"),
@@ -635,11 +608,6 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
.bind("function"),
MatchCallbacks.back().get());
MatchCallbacks.push_back(llvm::make_unique<VarDeclarationMatch>(this));
Finder->addMatcher(
varDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl).bind("var"),
MatchCallbacks.back().get());
// Match enum definition in old.h. Enum helpers (which are defined in old.cc)
// will not be moved for now no matter whether they are used or not.
MatchCallbacks.push_back(llvm::make_unique<EnumDeclarationMatch>(this));
@@ -671,12 +639,13 @@ void ClangMoveTool::run(const ast_matchers::MatchFinder::MatchResult &Result) {
else
MovedDecls.push_back(FWD);
}
} else if (const auto *ND =
Result.Nodes.getNodeAs<clang::NamedDecl>("static_decls")) {
MovedDecls.push_back(ND);
} else if (const auto *ND =
Result.Nodes.getNodeAs<clang::NamedDecl>("helper_decls")) {
MovedDecls.push_back(ND);
HelperDeclarations.push_back(ND);
DEBUG(llvm::dbgs() << "Add helper : "
<< ND->getNameAsString() << " (" << ND << ")\n");
} else if (const auto *UD =
Result.Nodes.getNodeAs<clang::NamedDecl>("using_decl")) {
MovedDecls.push_back(UD);
@@ -730,12 +699,9 @@ void ClangMoveTool::removeDeclsInOldFiles() {
// We remove the helper declarations which are not used in the old.cc after
// moving the given declarations.
for (const auto *D : HelperDeclarations) {
DEBUG(llvm::dbgs() << "Check helper is used: "
<< D->getNameAsString() << " (" << D << ")\n");
if (!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(
D->getCanonicalDecl()))) {
if (!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(D))) {
DEBUG(llvm::dbgs() << "Helper removed in old.cc: "
<< D->getNameAsString() << " (" << D << ")\n");
<< D->getNameAsString() << " " << D << "\n");
RemovedDecls.push_back(D);
}
}
@@ -776,13 +742,10 @@ void ClangMoveTool::removeDeclsInOldFiles() {
// Ignore replacements for new.h/cc.
if (SI == FilePathToFileID.end()) continue;
llvm::StringRef Code = SM.getBufferData(SI->second);
auto Style = format::getStyle("file", FilePath, Context->FallbackStyle);
if (!Style) {
llvm::errs() << llvm::toString(Style.takeError()) << "\n";
continue;
}
format::FormatStyle Style =
format::getStyle("file", FilePath, Context->FallbackStyle);
auto CleanReplacements = format::cleanupAroundReplacements(
Code, Context->FileToReplacements[FilePath], *Style);
Code, Context->FileToReplacements[FilePath], Style);
if (!CleanReplacements) {
llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
@@ -811,8 +774,7 @@ void ClangMoveTool::moveDeclsToNewFiles() {
// given symbols being moved.
for (const auto *D : NewCCDecls) {
if (llvm::is_contained(HelperDeclarations, D) &&
!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(
D->getCanonicalDecl())))
!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(D)))
continue;
DEBUG(llvm::dbgs() << "Helper used in new.cc: " << D->getNameAsString()
@@ -874,20 +836,11 @@ void ClangMoveTool::onEndOfTranslationUnit() {
for (const auto *Decl : UnremovedDeclsInOldHeader) {
auto Kind = Decl->getKind();
const std::string QualifiedName = Decl->getQualifiedNameAsString();
if (Kind == Decl::Kind::Var)
Reporter->reportDeclaration(QualifiedName, "Variable");
else if (Kind == Decl::Kind::Function ||
Kind == Decl::Kind::FunctionTemplate)
if (Kind == Decl::Kind::Function || Kind == Decl::Kind::FunctionTemplate)
Reporter->reportDeclaration(QualifiedName, "Function");
else if (Kind == Decl::Kind::ClassTemplate ||
Kind == Decl::Kind::CXXRecord)
Reporter->reportDeclaration(QualifiedName, "Class");
else if (Kind == Decl::Kind::Enum)
Reporter->reportDeclaration(QualifiedName, "Enum");
else if (Kind == Decl::Kind::Typedef ||
Kind == Decl::Kind::TypeAlias ||
Kind == Decl::Kind::TypeAliasTemplate)
Reporter->reportDeclaration(QualifiedName, "TypeAlias");
}
return;
}
@@ -908,7 +861,6 @@ void ClangMoveTool::onEndOfTranslationUnit() {
case Decl::Kind::Typedef:
case Decl::Kind::TypeAlias:
case Decl::Kind::TypeAliasTemplate:
case Decl::Kind::Var:
return true;
default:
return false;

View File

@@ -10,11 +10,8 @@
#include "HelperDeclRefGraph.h"
#include "ClangMove.h"
#include "clang/AST/Decl.h"
#include "llvm/Support/Debug.h"
#include <vector>
#define DEBUG_TYPE "clang-move"
namespace clang {
namespace move {
@@ -116,19 +113,13 @@ void HelperDeclRGBuilder::run(
if (const auto *FuncRef = Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
const auto *DC = Result.Nodes.getNodeAs<Decl>("dc");
assert(DC);
DEBUG(llvm::dbgs() << "Find helper function usage: "
<< FuncRef->getDecl()->getNameAsString() << " ("
<< FuncRef->getDecl() << ")\n");
RG->addEdge(
getOutmostClassOrFunDecl(DC->getCanonicalDecl()),
getOutmostClassOrFunDecl(FuncRef->getDecl()->getCanonicalDecl()));
RG->addEdge(getOutmostClassOrFunDecl(DC->getCanonicalDecl()),
getOutmostClassOrFunDecl(FuncRef->getDecl()));
} else if (const auto *UsedClass =
Result.Nodes.getNodeAs<CXXRecordDecl>("used_class")) {
const auto *DC = Result.Nodes.getNodeAs<Decl>("dc");
assert(DC);
DEBUG(llvm::dbgs() << "Find helper class usage: "
<< UsedClass->getNameAsString() << " (" << UsedClass
<< ")\n");
RG->addEdge(getOutmostClassOrFunDecl(DC->getCanonicalDecl()), UsedClass);
}
}

View File

@@ -5,7 +5,6 @@ add_clang_executable(clang-move
)
target_link_libraries(clang-move
PRIVATE
clangAST
clangASTMatchers
clangBasic

View File

@@ -127,9 +127,10 @@ int main(int argc, const char **argv) {
move::ClangMoveContext Context{Spec, Tool.getReplacements(),
InitialDirectory.str(), Style, DumpDecls};
move::DeclarationReporter Reporter;
move::ClangMoveActionFactory Factory(&Context, &Reporter);
int CodeStatus = Tool.run(&Factory);
auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
&Context, &Reporter);
int CodeStatus = Tool.run(Factory.get());
if (CodeStatus)
return CodeStatus;

View File

@@ -97,10 +97,10 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
if (R.isValid()) {
TextDiagnostic TD(OS, AST->getASTContext().getLangOpts(),
&AST->getDiagnostics().getDiagnosticOptions());
TD.emitDiagnostic(
FullSourceLoc(R.getBegin(), AST->getSourceManager()),
DiagnosticsEngine::Note, "\"" + BI->first + "\" binds here",
CharSourceRange::getTokenRange(R), None);
TD.emitDiagnostic(R.getBegin(), DiagnosticsEngine::Note,
"\"" + BI->first + "\" binds here",
CharSourceRange::getTokenRange(R), None,
&AST->getSourceManager());
}
break;
}

View File

@@ -2,7 +2,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
add_clang_executable(clang-query ClangQuery.cpp)
target_link_libraries(clang-query
PRIVATE
clangAST
clangASTMatchers
clangBasic

View File

@@ -0,0 +1,18 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangRename
USRFinder.cpp
USRFindingAction.cpp
USRLocFinder.cpp
RenamingAction.cpp
LINK_LIBS
clangAST
clangASTMatchers
clangBasic
clangIndex
clangLex
clangToolingCore
)
add_subdirectory(tool)

View File

@@ -0,0 +1,93 @@
//===--- tools/extra/clang-rename/RenamingAction.cpp - Clang rename tool --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Provides an action to rename every symbol at a point.
///
//===----------------------------------------------------------------------===//
#include "RenamingAction.h"
#include "USRLocFinder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include <string>
#include <vector>
using namespace llvm;
namespace clang {
namespace rename {
class RenamingASTConsumer : public ASTConsumer {
public:
RenamingASTConsumer(
const std::vector<std::string> &NewNames,
const std::vector<std::string> &PrevNames,
const std::vector<std::vector<std::string>> &USRList,
std::map<std::string, tooling::Replacements> &FileToReplaces,
bool PrintLocations)
: NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
void HandleTranslationUnit(ASTContext &Context) override {
for (unsigned I = 0; I < NewNames.size(); ++I)
HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);
}
void HandleOneRename(ASTContext &Context, const std::string &NewName,
const std::string &PrevName,
const std::vector<std::string> &USRs) {
const SourceManager &SourceMgr = Context.getSourceManager();
std::vector<SourceLocation> RenamingCandidates;
std::vector<SourceLocation> NewCandidates;
NewCandidates =
getLocationsOfUSRs(USRs, PrevName, Context.getTranslationUnitDecl());
RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(),
NewCandidates.end());
unsigned PrevNameLen = PrevName.length();
for (const auto &Loc : RenamingCandidates) {
if (PrintLocations) {
FullSourceLoc FullLoc(Loc, SourceMgr);
errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc)
<< ":" << FullLoc.getSpellingLineNumber() << ":"
<< FullLoc.getSpellingColumnNumber() << "\n";
}
// FIXME: better error handling.
tooling::Replacement Replace(SourceMgr, Loc, PrevNameLen, NewName);
llvm::Error Err = FileToReplaces[Replace.getFilePath()].add(Replace);
if (Err)
llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "
<< llvm::toString(std::move(Err)) << "\n";
}
}
private:
const std::vector<std::string> &NewNames, &PrevNames;
const std::vector<std::vector<std::string>> &USRList;
std::map<std::string, tooling::Replacements> &FileToReplaces;
bool PrintLocations;
};
std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() {
return llvm::make_unique<RenamingASTConsumer>(NewNames, PrevNames, USRList,
FileToReplaces, PrintLocations);
}
} // namespace rename
} // namespace clang

View File

@@ -0,0 +1,48 @@
//===--- tools/extra/clang-rename/RenamingAction.h - Clang rename tool ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Provides an action to rename every symbol at a point.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H
#include "clang/Tooling/Refactoring.h"
namespace clang {
class ASTConsumer;
class CompilerInstance;
namespace rename {
class RenamingAction {
public:
RenamingAction(const std::vector<std::string> &NewNames,
const std::vector<std::string> &PrevNames,
const std::vector<std::vector<std::string>> &USRList,
std::map<std::string, tooling::Replacements> &FileToReplaces,
bool PrintLocations = false)
: NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
std::unique_ptr<ASTConsumer> newASTConsumer();
private:
const std::vector<std::string> &NewNames, &PrevNames;
const std::vector<std::vector<std::string>> &USRList;
std::map<std::string, tooling::Replacements> &FileToReplaces;
bool PrintLocations;
};
} // namespace rename
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H

View File

@@ -0,0 +1,212 @@
//===--- tools/extra/clang-rename/USRFinder.cpp - Clang rename tool -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file Implements a recursive AST visitor that finds the USR of a symbol at a
/// point.
///
//===----------------------------------------------------------------------===//
#include "USRFinder.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;
namespace clang {
namespace rename {
// NamedDeclFindingASTVisitor recursively visits each AST node to find the
// symbol underneath the cursor.
// FIXME: move to seperate .h/.cc file if this gets too large.
namespace {
class NamedDeclFindingASTVisitor
: public clang::RecursiveASTVisitor<NamedDeclFindingASTVisitor> {
public:
// \brief Finds the NamedDecl at a point in the source.
// \param Point the location in the source to search for the NamedDecl.
explicit NamedDeclFindingASTVisitor(const SourceLocation Point,
const ASTContext &Context)
: Result(nullptr), Point(Point), Context(Context) {}
// \brief Finds the NamedDecl for a name in the source.
// \param Name the fully qualified name.
explicit NamedDeclFindingASTVisitor(const std::string &Name,
const ASTContext &Context)
: Result(nullptr), Name(Name), Context(Context) {}
// Declaration visitors:
// \brief Checks if the point falls within the NameDecl. This covers every
// declaration of a named entity that we may come across. Usually, just
// checking if the point lies within the length of the name of the declaration
// and the start location is sufficient.
bool VisitNamedDecl(const NamedDecl *Decl) {
return dyn_cast<CXXConversionDecl>(Decl)
? true
: setResult(Decl, Decl->getLocation(),
Decl->getNameAsString().length());
}
// Expression visitors:
bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
const NamedDecl *Decl = Expr->getFoundDecl();
return setResult(Decl, Expr->getLocation(),
Decl->getNameAsString().length());
}
bool VisitMemberExpr(const MemberExpr *Expr) {
const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
return setResult(Decl, Expr->getMemberLoc(),
Decl->getNameAsString().length());
}
// Other visitors:
bool VisitTypeLoc(const TypeLoc Loc) {
const SourceLocation TypeBeginLoc = Loc.getBeginLoc();
const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(
TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
if (const auto *TemplateTypeParm =
dyn_cast<TemplateTypeParmType>(Loc.getType()))
return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
if (const auto *TemplateSpecType =
dyn_cast<TemplateSpecializationType>(Loc.getType())) {
return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
TypeBeginLoc, TypeEndLoc);
}
return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
TypeEndLoc);
}
bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
for (const auto *Initializer : ConstructorDecl->inits()) {
// Ignore implicit initializers.
if (!Initializer->isWritten())
continue;
if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
const SourceLocation InitBeginLoc = Initializer->getSourceLocation(),
InitEndLoc = Lexer::getLocForEndOfToken(
InitBeginLoc, 0, Context.getSourceManager(),
Context.getLangOpts());
if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc))
return false;
}
}
return true;
}
// Other:
const NamedDecl *getNamedDecl() { return Result; }
// \brief Determines if a namespace qualifier contains the point.
// \returns false on success and sets Result.
void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
while (NameLoc) {
const NamespaceDecl *Decl =
NameLoc.getNestedNameSpecifier()->getAsNamespace();
setResult(Decl, NameLoc.getLocalBeginLoc(), NameLoc.getLocalEndLoc());
NameLoc = NameLoc.getPrefix();
}
}
private:
// \brief Sets Result to Decl if the Point is within Start and End.
// \returns false on success.
bool setResult(const NamedDecl *Decl, SourceLocation Start,
SourceLocation End) {
if (!Decl)
return true;
if (Name.empty()) {
// Offset is used to find the declaration.
if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
!End.isFileID() || !isPointWithin(Start, End))
return true;
} else {
// Fully qualified name is used to find the declaration.
if (Name != Decl->getQualifiedNameAsString())
return true;
}
Result = Decl;
return false;
}
// \brief Sets Result to Decl if Point is within Loc and Loc + Offset.
// \returns false on success.
bool setResult(const NamedDecl *Decl, SourceLocation Loc, unsigned Offset) {
// FIXME: Add test for Offset == 0. Add test for Offset - 1 (vs -2 etc).
return Offset == 0 ||
setResult(Decl, Loc, Loc.getLocWithOffset(Offset - 1));
}
// \brief Determines if the Point is within Start and End.
bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
// FIXME: Add tests for Point == End.
return Point == Start || Point == End ||
(Context.getSourceManager().isBeforeInTranslationUnit(Start,
Point) &&
Context.getSourceManager().isBeforeInTranslationUnit(Point, End));
}
const NamedDecl *Result;
const SourceLocation Point; // The location to find the NamedDecl.
const std::string Name;
const ASTContext &Context;
};
} // namespace
const NamedDecl *getNamedDeclAt(const ASTContext &Context,
const SourceLocation Point) {
const SourceManager &SM = Context.getSourceManager();
NamedDeclFindingASTVisitor Visitor(Point, Context);
// Try to be clever about pruning down the number of top-level declarations we
// see. If both start and end is either before or after the point we're
// looking for the point cannot be inside of this decl. Don't even look at it.
for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
SourceLocation StartLoc = CurrDecl->getLocStart();
SourceLocation EndLoc = CurrDecl->getLocEnd();
if (StartLoc.isValid() && EndLoc.isValid() &&
SM.isBeforeInTranslationUnit(StartLoc, Point) !=
SM.isBeforeInTranslationUnit(EndLoc, Point))
Visitor.TraverseDecl(CurrDecl);
}
NestedNameSpecifierLocFinder Finder(const_cast<ASTContext &>(Context));
for (const auto &Location : Finder.getNestedNameSpecifierLocations())
Visitor.handleNestedNameSpecifierLoc(Location);
return Visitor.getNamedDecl();
}
const NamedDecl *getNamedDeclFor(const ASTContext &Context,
const std::string &Name) {
NamedDeclFindingASTVisitor Visitor(Name, Context);
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
return Visitor.getNamedDecl();
}
std::string getUSRForDecl(const Decl *Decl) {
llvm::SmallVector<char, 128> Buff;
// FIXME: Add test for the nullptr case.
if (Decl == nullptr || index::generateUSRForDecl(Decl, Buff))
return "";
return std::string(Buff.data(), Buff.size());
}
} // namespace rename
} // namespace clang

View File

@@ -0,0 +1,84 @@
//===--- tools/extra/clang-rename/USRFinder.h - Clang rename tool ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Methods for determining the USR of a symbol at a location in source
/// code.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <string>
#include <vector>
using namespace llvm;
using namespace clang::ast_matchers;
namespace clang {
class ASTContext;
class Decl;
class SourceLocation;
class NamedDecl;
namespace rename {
// Given an AST context and a point, returns a NamedDecl identifying the symbol
// at the point. Returns null if nothing is found at the point.
const NamedDecl *getNamedDeclAt(const ASTContext &Context,
const SourceLocation Point);
// Given an AST context and a fully qualified name, returns a NamedDecl
// identifying the symbol with a matching name. Returns null if nothing is
// found for the name.
const NamedDecl *getNamedDeclFor(const ASTContext &Context,
const std::string &Name);
// Converts a Decl into a USR.
std::string getUSRForDecl(const Decl *Decl);
// FIXME: Implement RecursiveASTVisitor<T>::VisitNestedNameSpecifier instead.
class NestedNameSpecifierLocFinder : public MatchFinder::MatchCallback {
public:
explicit NestedNameSpecifierLocFinder(ASTContext &Context)
: Context(Context) {}
std::vector<NestedNameSpecifierLoc> getNestedNameSpecifierLocations() {
addMatchers();
Finder.matchAST(Context);
return Locations;
}
private:
void addMatchers() {
const auto NestedNameSpecifierLocMatcher =
nestedNameSpecifierLoc().bind("nestedNameSpecifierLoc");
Finder.addMatcher(NestedNameSpecifierLocMatcher, this);
}
void run(const MatchFinder::MatchResult &Result) override {
const auto *NNS = Result.Nodes.getNodeAs<NestedNameSpecifierLoc>(
"nestedNameSpecifierLoc");
Locations.push_back(*NNS);
}
ASTContext &Context;
std::vector<NestedNameSpecifierLoc> Locations;
MatchFinder Finder;
};
} // namespace rename
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H

View File

@@ -0,0 +1,226 @@
//===--- tools/extra/clang-rename/USRFindingAction.cpp - Clang rename tool ===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Provides an action to find USR for the symbol at <offset>, as well as
/// all additional USRs.
///
//===----------------------------------------------------------------------===//
#include "USRFindingAction.h"
#include "USRFinder.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include <algorithm>
#include <set>
#include <string>
#include <vector>
using namespace llvm;
namespace clang {
namespace rename {
namespace {
// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
// Decl refers to class and adds USRs of all overridden methods if Decl refers
// to virtual method.
class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
public:
AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
: FoundDecl(FoundDecl), Context(Context) {}
std::vector<std::string> Find() {
// Fill OverriddenMethods and PartialSpecs storages.
TraverseDecl(Context.getTranslationUnitDecl());
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
addUSRsOfOverridenFunctions(MethodDecl);
for (const auto &OverriddenMethod : OverriddenMethods) {
if (checkIfOverriddenFunctionAscends(OverriddenMethod))
USRSet.insert(getUSRForDecl(OverriddenMethod));
}
} else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
handleCXXRecordDecl(RecordDecl);
} else if (const auto *TemplateDecl =
dyn_cast<ClassTemplateDecl>(FoundDecl)) {
handleClassTemplateDecl(TemplateDecl);
} else {
USRSet.insert(getUSRForDecl(FoundDecl));
}
return std::vector<std::string>(USRSet.begin(), USRSet.end());
}
bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
if (MethodDecl->isVirtual())
OverriddenMethods.push_back(MethodDecl);
return true;
}
bool VisitClassTemplatePartialSpecializationDecl(
const ClassTemplatePartialSpecializationDecl *PartialSpec) {
PartialSpecs.push_back(PartialSpec);
return true;
}
private:
void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
RecordDecl = RecordDecl->getDefinition();
if (const auto *ClassTemplateSpecDecl =
dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl))
handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
addUSRsOfCtorDtors(RecordDecl);
}
void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
for (const auto *Specialization : TemplateDecl->specializations())
addUSRsOfCtorDtors(Specialization);
for (const auto *PartialSpec : PartialSpecs) {
if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
addUSRsOfCtorDtors(PartialSpec);
}
addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
}
void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
RecordDecl = RecordDecl->getDefinition();
for (const auto *CtorDecl : RecordDecl->ctors())
USRSet.insert(getUSRForDecl(CtorDecl));
USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
USRSet.insert(getUSRForDecl(RecordDecl));
}
void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) {
USRSet.insert(getUSRForDecl(MethodDecl));
// Recursively visit each OverridenMethod.
for (const auto &OverriddenMethod : MethodDecl->overridden_methods())
addUSRsOfOverridenFunctions(OverriddenMethod);
}
bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
return true;
return checkIfOverriddenFunctionAscends(OverriddenMethod);
}
return false;
}
const Decl *FoundDecl;
ASTContext &Context;
std::set<std::string> USRSet;
std::vector<const CXXMethodDecl *> OverriddenMethods;
std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs;
};
} // namespace
class NamedDeclFindingConsumer : public ASTConsumer {
public:
NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
ArrayRef<std::string> QualifiedNames,
std::vector<std::string> &SpellingNames,
std::vector<std::vector<std::string>> &USRList,
bool &ErrorOccurred)
: SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
SpellingNames(SpellingNames), USRList(USRList),
ErrorOccurred(ErrorOccurred) {}
private:
bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr,
unsigned SymbolOffset, const std::string &QualifiedName) {
DiagnosticsEngine &Engine = Context.getDiagnostics();
const FileID MainFileID = SourceMgr.getMainFileID();
if (SymbolOffset >= SourceMgr.getFileIDSize(MainFileID)) {
ErrorOccurred = true;
unsigned InvalidOffset = Engine.getCustomDiagID(
DiagnosticsEngine::Error,
"SourceLocation in file %0 at offset %1 is invalid");
Engine.Report(SourceLocation(), InvalidOffset)
<< SourceMgr.getFileEntryForID(MainFileID)->getName() << SymbolOffset;
return false;
}
const SourceLocation Point = SourceMgr.getLocForStartOfFile(MainFileID)
.getLocWithOffset(SymbolOffset);
const NamedDecl *FoundDecl = QualifiedName.empty()
? getNamedDeclAt(Context, Point)
: getNamedDeclFor(Context, QualifiedName);
if (FoundDecl == nullptr) {
if (QualifiedName.empty()) {
FullSourceLoc FullLoc(Point, SourceMgr);
unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID(
DiagnosticsEngine::Error,
"clang-rename could not find symbol (offset %0)");
Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset;
ErrorOccurred = true;
return false;
}
unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
Engine.Report(CouldNotFindSymbolNamed) << QualifiedName;
ErrorOccurred = true;
return false;
}
// If FoundDecl is a constructor or destructor, we want to instead take
// the Decl of the corresponding class.
if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
FoundDecl = CtorDecl->getParent();
else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
FoundDecl = DtorDecl->getParent();
SpellingNames.push_back(FoundDecl->getNameAsString());
AdditionalUSRFinder Finder(FoundDecl, Context);
USRList.push_back(Finder.Find());
return true;
}
void HandleTranslationUnit(ASTContext &Context) override {
const SourceManager &SourceMgr = Context.getSourceManager();
for (unsigned Offset : SymbolOffsets) {
if (!FindSymbol(Context, SourceMgr, Offset, ""))
return;
}
for (const std::string &QualifiedName : QualifiedNames) {
if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))
return;
}
}
ArrayRef<unsigned> SymbolOffsets;
ArrayRef<std::string> QualifiedNames;
std::vector<std::string> &SpellingNames;
std::vector<std::vector<std::string>> &USRList;
bool &ErrorOccurred;
};
std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() {
return llvm::make_unique<NamedDeclFindingConsumer>(
SymbolOffsets, QualifiedNames, SpellingNames, USRList, ErrorOccurred);
}
} // namespace rename
} // namespace clang

View File

@@ -0,0 +1,53 @@
//===--- tools/extra/clang-rename/USRFindingAction.h - Clang rename tool --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Provides an action to find all relevant USRs at a point.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include <string>
#include <vector>
namespace clang {
class ASTConsumer;
class CompilerInstance;
class NamedDecl;
namespace rename {
struct USRFindingAction {
USRFindingAction(ArrayRef<unsigned> SymbolOffsets,
ArrayRef<std::string> QualifiedNames)
: SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
ErrorOccurred(false) {}
std::unique_ptr<ASTConsumer> newASTConsumer();
ArrayRef<std::string> getUSRSpellings() { return SpellingNames; }
ArrayRef<std::vector<std::string>> getUSRList() { return USRList; }
bool errorOccurred() { return ErrorOccurred; }
private:
std::vector<unsigned> SymbolOffsets;
std::vector<std::string> QualifiedNames;
std::vector<std::string> SpellingNames;
std::vector<std::vector<std::string>> USRList;
bool ErrorOccurred;
};
} // namespace rename
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H

View File

@@ -0,0 +1,167 @@
//===--- tools/extra/clang-rename/USRLocFinder.cpp - Clang rename tool ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Mehtods for finding all instances of a USR. Our strategy is very
/// simple; we just compare the USR at every relevant AST node with the one
/// provided.
///
//===----------------------------------------------------------------------===//
#include "USRLocFinder.h"
#include "USRFinder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include <cstddef>
#include <set>
#include <string>
#include <vector>
using namespace llvm;
namespace clang {
namespace rename {
namespace {
// \brief This visitor recursively searches for all instances of a USR in a
// translation unit and stores them for later usage.
class USRLocFindingASTVisitor
: public clang::RecursiveASTVisitor<USRLocFindingASTVisitor> {
public:
explicit USRLocFindingASTVisitor(const std::vector<std::string> &USRs,
StringRef PrevName,
const ASTContext &Context)
: USRSet(USRs.begin(), USRs.end()), PrevName(PrevName), Context(Context) {
}
// Declaration visitors:
bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) {
for (const auto *Initializer : ConstructorDecl->inits()) {
// Ignore implicit initializers.
if (!Initializer->isWritten())
continue;
if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) {
if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end())
LocationsFound.push_back(Initializer->getSourceLocation());
}
}
return true;
}
bool VisitNamedDecl(const NamedDecl *Decl) {
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
checkAndAddLocation(Decl->getLocation());
return true;
}
// Expression visitors:
bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
const NamedDecl *Decl = Expr->getFoundDecl();
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
const SourceManager &Manager = Decl->getASTContext().getSourceManager();
SourceLocation Location = Manager.getSpellingLoc(Expr->getLocation());
checkAndAddLocation(Location);
}
return true;
}
bool VisitMemberExpr(const MemberExpr *Expr) {
const NamedDecl *Decl = Expr->getFoundDecl().getDecl();
if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) {
const SourceManager &Manager = Decl->getASTContext().getSourceManager();
SourceLocation Location = Manager.getSpellingLoc(Expr->getMemberLoc());
checkAndAddLocation(Location);
}
return true;
}
// Other visitors:
bool VisitTypeLoc(const TypeLoc Loc) {
if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) !=
USRSet.end())
checkAndAddLocation(Loc.getBeginLoc());
if (const auto *TemplateTypeParm =
dyn_cast<TemplateTypeParmType>(Loc.getType())) {
if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) !=
USRSet.end())
checkAndAddLocation(Loc.getBeginLoc());
}
return true;
}
// Non-visitors:
// \brief Returns a list of unique locations. Duplicate or overlapping
// locations are erroneous and should be reported!
const std::vector<clang::SourceLocation> &getLocationsFound() const {
return LocationsFound;
}
// Namespace traversal:
void handleNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
while (NameLoc) {
const NamespaceDecl *Decl =
NameLoc.getNestedNameSpecifier()->getAsNamespace();
if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end())
checkAndAddLocation(NameLoc.getLocalBeginLoc());
NameLoc = NameLoc.getPrefix();
}
}
private:
void checkAndAddLocation(SourceLocation Loc) {
const SourceLocation BeginLoc = Loc;
const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
BeginLoc, 0, Context.getSourceManager(), Context.getLangOpts());
StringRef TokenName =
Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
Context.getSourceManager(), Context.getLangOpts());
size_t Offset = TokenName.find(PrevName);
// The token of the source location we find actually has the old
// name.
if (Offset != StringRef::npos)
LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
}
const std::set<std::string> USRSet;
const std::string PrevName;
std::vector<clang::SourceLocation> LocationsFound;
const ASTContext &Context;
};
} // namespace
std::vector<SourceLocation>
getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef PrevName,
Decl *Decl) {
USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
Visitor.TraverseDecl(Decl);
NestedNameSpecifierLocFinder Finder(Decl->getASTContext());
for (const auto &Location : Finder.getNestedNameSpecifierLocations())
Visitor.handleNestedNameSpecifierLoc(Location);
return Visitor.getLocationsFound();
}
} // namespace rename
} // namespace clang

View File

@@ -0,0 +1,35 @@
//===--- tools/extra/clang-rename/USRLocFinder.h - Clang rename tool ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Provides functionality for finding all instances of a USR in a given
/// AST.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H
#include "clang/AST/AST.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <vector>
namespace clang {
namespace rename {
// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
std::vector<SourceLocation>
getLocationsOfUSRs(const std::vector<std::string> &USRs,
llvm::StringRef PrevName, Decl *Decl);
} // namespace rename
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H

View File

@@ -0,0 +1,19 @@
add_clang_executable(clang-rename ClangRename.cpp)
target_link_libraries(clang-rename
clangBasic
clangFrontend
clangRename
clangRewrite
clangTooling
clangToolingCore
)
install(TARGETS clang-rename RUNTIME DESTINATION bin)
install(PROGRAMS clang-rename.py
DESTINATION share/clang
COMPONENT clang-rename)
install(PROGRAMS clang-rename.el
DESTINATION share/clang
COMPONENT clang-rename)

View File

@@ -13,6 +13,8 @@
///
//===----------------------------------------------------------------------===//
#include "../RenamingAction.h"
#include "../USRFindingAction.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
@@ -24,8 +26,6 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h"
#include "clang/Tooling/ReplacementsYaml.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -33,6 +33,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <string>
#include <system_error>
@@ -94,9 +95,6 @@ static cl::opt<std::string>
static cl::opt<std::string>
Input("input", cl::desc("YAML file to load oldname-newname pairs from."),
cl::Optional, cl::cat(ClangRenameOptions));
static cl::opt<bool> Force("force",
cl::desc("Ignore nonexistent qualified names."),
cl::cat(ClangRenameOptions));
int main(int argc, const char **argv) {
tooling::CommonOptionsParser OP(argc, argv, ClangRenameOptions);
@@ -126,25 +124,25 @@ int main(int argc, const char **argv) {
// Check the arguments for correctness.
if (NewNames.empty()) {
errs() << "clang-rename: -new-name must be specified.\n\n";
return 1;
exit(1);
}
if (SymbolOffsets.empty() == QualifiedNames.empty()) {
errs() << "clang-rename: -offset and -qualified-name can't be present at "
"the same time.\n";
return 1;
exit(1);
}
// Check if NewNames is a valid identifier in C++17.
LangOptions Options;
Options.CPlusPlus = true;
Options.CPlusPlus17 = true;
Options.CPlusPlus1z = true;
IdentifierTable Table(Options);
for (const auto &NewName : NewNames) {
auto NewNameTokKind = Table.get(NewName).getTokenID();
if (!tok::isAnyIdentifier(NewNameTokKind)) {
errs() << "ERROR: new name is not a valid identifier in C++17.\n\n";
return 1;
exit(1);
}
}
@@ -154,12 +152,12 @@ int main(int argc, const char **argv) {
<< ") must be equal to number of new names(" << NewNames.size()
<< ").\n\n";
cl::PrintHelpMessage();
return 1;
exit(1);
}
auto Files = OP.getSourcePathList();
tooling::RefactoringTool Tool(OP.getCompilations(), Files);
tooling::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames, Force);
rename::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames);
Tool.run(tooling::newFrontendActionFactory(&FindingAction).get());
const std::vector<std::vector<std::string>> &USRList =
FindingAction.getUSRList();
@@ -172,12 +170,12 @@ int main(int argc, const char **argv) {
if (FindingAction.errorOccurred()) {
// Diagnostics are already issued at this point.
return 1;
exit(1);
}
// Perform the renaming.
tooling::RenamingAction RenameAction(NewNames, PrevNames, USRList,
Tool.getReplacements(), PrintLocations);
rename::RenamingAction RenameAction(NewNames, PrevNames, USRList,
Tool.getReplacements(), PrintLocations);
std::unique_ptr<tooling::FrontendActionFactory> Factory =
tooling::newFrontendActionFactory(&RenameAction);
int ExitCode;
@@ -192,7 +190,7 @@ int main(int argc, const char **argv) {
llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None);
if (EC) {
llvm::errs() << "Error opening output file: " << EC.message() << '\n';
return 1;
exit(1);
}
// Export replacements.
@@ -205,7 +203,7 @@ int main(int argc, const char **argv) {
yaml::Output YAML(OS);
YAML << TUR;
OS.close();
return 0;
exit(0);
}
// Write every file to stdout. Right now we just barf the files without any
@@ -229,5 +227,5 @@ int main(int argc, const char **argv) {
}
}
return ExitCode;
exit(ExitCode);
}

View File

@@ -22,23 +22,21 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/Refactoring.h"
#include "llvm/ADT/SetVector.h"
#include <algorithm>
#include <string>
namespace clang {
namespace reorder_fields {
using namespace clang::ast_matchers;
using llvm::SmallSetVector;
/// \brief Finds the definition of a record by name.
///
/// \returns nullptr if the name is ambiguous or not found.
static const RecordDecl *findDefinition(StringRef RecordName,
ASTContext &Context) {
auto Results =
match(recordDecl(hasName(RecordName), isDefinition()).bind("recordDecl"),
Context);
static const CXXRecordDecl *findDefinition(StringRef RecordName,
ASTContext &Context) {
auto Results = match(
recordDecl(hasName(RecordName), isDefinition()).bind("cxxRecordDecl"),
Context);
if (Results.empty()) {
llvm::errs() << "Definition of " << RecordName << " not found\n";
return nullptr;
@@ -48,14 +46,14 @@ static const RecordDecl *findDefinition(StringRef RecordName,
<< " is ambiguous, several definitions found\n";
return nullptr;
}
return selectFirst<RecordDecl>("recordDecl", Results);
return selectFirst<CXXRecordDecl>("cxxRecordDecl", Results);
}
/// \brief Calculates the new order of fields.
///
/// \returns empty vector if the list of fields doesn't match the definition.
static SmallVector<unsigned, 4>
getNewFieldsOrder(const RecordDecl *Definition,
getNewFieldsOrder(const CXXRecordDecl *Definition,
ArrayRef<std::string> DesiredFieldsOrder) {
assert(Definition && "Definition is null");
@@ -93,35 +91,13 @@ addReplacement(SourceRange Old, SourceRange New, const ASTContext &Context,
consumeError(Replacements[R.getFilePath()].add(R));
}
/// \brief Find all member fields used in the given init-list initializer expr
/// that belong to the same record
///
/// \returns a set of field declarations, empty if none were present
static SmallSetVector<FieldDecl *, 1>
findMembersUsedInInitExpr(const CXXCtorInitializer *Initializer,
ASTContext &Context) {
SmallSetVector<FieldDecl *, 1> Results;
// Note that this does not pick up member fields of base classes since
// for those accesses Sema::PerformObjectMemberConversion always inserts an
// UncheckedDerivedToBase ImplicitCastExpr between the this expr and the
// object expression
auto FoundExprs =
match(findAll(memberExpr(hasObjectExpression(cxxThisExpr())).bind("ME")),
*Initializer->getInit(), Context);
for (BoundNodes &BN : FoundExprs)
if (auto *MemExpr = BN.getNodeAs<MemberExpr>("ME"))
if (auto *FD = dyn_cast<FieldDecl>(MemExpr->getMemberDecl()))
Results.insert(FD);
return Results;
}
/// \brief Reorders fields in the definition of a struct/class.
///
/// At the moment reodering of fields with
/// different accesses (public/protected/private) is not supported.
/// \returns true on success.
static bool reorderFieldsInDefinition(
const RecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
const CXXRecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
const ASTContext &Context,
std::map<std::string, tooling::Replacements> &Replacements) {
assert(Definition && "Definition is null");
@@ -153,12 +129,11 @@ static bool reorderFieldsInDefinition(
/// \brief Reorders initializers in a C++ struct/class constructor.
///
/// A constructor can have initializers for an arbitrary subset of the class's
/// fields. Thus, we need to ensure that we reorder just the initializers that
/// are present.
/// A constructor can have initializers for an arbitrary subset of the class's fields.
/// Thus, we need to ensure that we reorder just the initializers that are present.
static void reorderFieldsInConstructor(
const CXXConstructorDecl *CtorDecl, ArrayRef<unsigned> NewFieldsOrder,
ASTContext &Context,
const ASTContext &Context,
std::map<std::string, tooling::Replacements> &Replacements) {
assert(CtorDecl && "Constructor declaration is null");
if (CtorDecl->isImplicit() || CtorDecl->getNumCtorInitializers() <= 1)
@@ -176,26 +151,8 @@ static void reorderFieldsInConstructor(
SmallVector<const CXXCtorInitializer *, 10> OldWrittenInitializersOrder;
SmallVector<const CXXCtorInitializer *, 10> NewWrittenInitializersOrder;
for (const auto *Initializer : CtorDecl->inits()) {
if (!Initializer->isMemberInitializer() || !Initializer->isWritten())
if (!Initializer->isWritten())
continue;
// Warn if this reordering violates initialization expr dependencies.
const FieldDecl *ThisM = Initializer->getMember();
const auto UsedMembers = findMembersUsedInInitExpr(Initializer, Context);
for (const FieldDecl *UM : UsedMembers) {
if (NewFieldsPositions[UM->getFieldIndex()] >
NewFieldsPositions[ThisM->getFieldIndex()]) {
DiagnosticsEngine &DiagEngine = Context.getDiagnostics();
auto Description = ("reordering field " + UM->getName() + " after " +
ThisM->getName() + " makes " + UM->getName() +
" uninitialized when used in init expression")
.str();
unsigned ID = DiagEngine.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Warning, Description);
DiagEngine.Report(Initializer->getSourceLocation(), ID);
}
}
OldWrittenInitializersOrder.push_back(Initializer);
NewWrittenInitializersOrder.push_back(Initializer);
}
@@ -225,12 +182,12 @@ static bool reorderFieldsInInitListExpr(
const ASTContext &Context,
std::map<std::string, tooling::Replacements> &Replacements) {
assert(InitListEx && "Init list expression is null");
// We care only about InitListExprs which originate from source code.
// We care only about InitListExprs which originate from source code.
// Implicit InitListExprs are created by the semantic analyzer.
if (!InitListEx->isExplicit())
return true;
// The method InitListExpr::getSyntacticForm may return nullptr indicating
// that the current initializer list also serves as its syntactic form.
// The method InitListExpr::getSyntacticForm may return nullptr indicating that
// the current initializer list also serves as its syntactic form.
if (const auto *SyntacticForm = InitListEx->getSyntacticForm())
InitListEx = SyntacticForm;
// If there are no initializers we do not need to change anything.
@@ -242,9 +199,10 @@ static bool reorderFieldsInInitListExpr(
}
for (unsigned i = 0, e = InitListEx->getNumInits(); i < e; ++i)
if (i != NewFieldsOrder[i])
addReplacement(InitListEx->getInit(i)->getSourceRange(),
InitListEx->getInit(NewFieldsOrder[i])->getSourceRange(),
Context, Replacements);
addReplacement(
InitListEx->getInit(i)->getSourceRange(),
InitListEx->getInit(NewFieldsOrder[i])->getSourceRange(), Context,
Replacements);
return true;
}
@@ -265,7 +223,7 @@ public:
ReorderingConsumer &operator=(const ReorderingConsumer &) = delete;
void HandleTranslationUnit(ASTContext &Context) override {
const RecordDecl *RD = findDefinition(RecordName, Context);
const CXXRecordDecl *RD = findDefinition(RecordName, Context);
if (!RD)
return;
SmallVector<unsigned, 4> NewFieldsOrder =
@@ -274,21 +232,16 @@ public:
return;
if (!reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements))
return;
for (const auto *C : RD->ctors())
if (const auto *D = dyn_cast<CXXConstructorDecl>(C->getDefinition()))
reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
NewFieldsOrder, Context, Replacements);
// CXXRD will be nullptr if C code (not C++) is being processed.
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
if (CXXRD)
for (const auto *C : CXXRD->ctors())
if (const auto *D = dyn_cast<CXXConstructorDecl>(C->getDefinition()))
reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
NewFieldsOrder, Context, Replacements);
// We only need to reorder init list expressions for
// plain C structs or C++ aggregate types.
// We only need to reorder init list expressions for aggregate types.
// For other types the order of constructor parameters is used,
// which we don't change at the moment.
// Now (v0) partial initialization is not supported.
if (!CXXRD || CXXRD->isAggregate())
if (RD->isAggregate())
for (auto Result :
match(initListExpr(hasType(equalsNode(RD))).bind("initListExpr"),
Context))

View File

@@ -1,7 +1,6 @@
add_clang_tool(clang-reorder-fields ClangReorderFields.cpp)
add_clang_executable(clang-reorder-fields ClangReorderFields.cpp)
target_link_libraries(clang-reorder-fields
PRIVATE
clangBasic
clangFrontend
clangReorderFields
@@ -9,3 +8,5 @@ target_link_libraries(clang-reorder-fields
clangTooling
clangToolingCore
)
install(TARGETS clang-reorder-fields RUNTIME DESTINATION bin)

View File

@@ -26,21 +26,16 @@ add_clang_library(clangTidy
clangToolingCore
)
add_subdirectory(android)
add_subdirectory(tool)
add_subdirectory(plugin)
add_subdirectory(boost)
add_subdirectory(bugprone)
add_subdirectory(cert)
add_subdirectory(cppcoreguidelines)
add_subdirectory(fuchsia)
add_subdirectory(google)
add_subdirectory(hicpp)
add_subdirectory(llvm)
add_subdirectory(cppcoreguidelines)
add_subdirectory(google)
add_subdirectory(misc)
add_subdirectory(modernize)
add_subdirectory(mpi)
add_subdirectory(objc)
add_subdirectory(performance)
add_subdirectory(plugin)
add_subdirectory(readability)
add_subdirectory(tool)
add_subdirectory(utils)

View File

@@ -89,13 +89,13 @@ private:
class ErrorReporter {
public:
ErrorReporter(ClangTidyContext &Context, bool ApplyFixes)
ErrorReporter(bool ApplyFixes, StringRef FormatStyle)
: Files(FileSystemOptions()), DiagOpts(new DiagnosticOptions()),
DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), &*DiagOpts)),
Diags(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts,
DiagPrinter),
SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes),
TotalFixes(0), AppliedFixes(0), WarningsAsErrors(0) {
SourceMgr(Diags, Files), ApplyFixes(ApplyFixes), TotalFixes(0),
AppliedFixes(0), WarningsAsErrors(0), FormatStyle(FormatStyle) {
DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors();
DiagPrinter->BeginSourceFile(LangOpts);
}
@@ -183,6 +183,7 @@ public:
}
void Finish() {
// FIXME: Run clang-format on changes.
if (ApplyFixes && TotalFixes > 0) {
Rewriter Rewrite(SourceMgr, LangOpts);
for (const auto &FileAndReplacements : FileReplacements) {
@@ -196,29 +197,15 @@ public:
continue;
}
StringRef Code = Buffer.get()->getBuffer();
auto Style = format::getStyle(
*Context.getOptionsForFile(File).FormatStyle, File, "none");
if (!Style) {
llvm::errs() << llvm::toString(Style.takeError()) << "\n";
continue;
}
llvm::Expected<tooling::Replacements> Replacements =
format::FormatStyle Style = format::getStyle("file", File, FormatStyle);
llvm::Expected<Replacements> CleanReplacements =
format::cleanupAroundReplacements(Code, FileAndReplacements.second,
*Style);
if (!Replacements) {
llvm::errs() << llvm::toString(Replacements.takeError()) << "\n";
Style);
if (!CleanReplacements) {
llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
continue;
}
if (llvm::Expected<tooling::Replacements> FormattedReplacements =
format::formatReplacements(Code, *Replacements, *Style)) {
Replacements = std::move(FormattedReplacements);
if (!Replacements)
llvm_unreachable("!Replacements");
} else {
llvm::errs() << llvm::toString(FormattedReplacements.takeError())
<< ". Skipping formatting.\n";
}
if (!tooling::applyAllReplacements(Replacements.get(), Rewrite)) {
if (!tooling::applyAllReplacements(CleanReplacements.get(), Rewrite)) {
llvm::errs() << "Can't apply replacements for file " << File << "\n";
}
}
@@ -239,7 +226,7 @@ private:
return SourceLocation();
const FileEntry *File = SourceMgr.getFileManager().getFile(FilePath);
FileID ID = SourceMgr.getOrCreateFileID(File, SrcMgr::C_User);
FileID ID = SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User);
return SourceMgr.getLocForStartOfFile(ID).getLocWithOffset(Offset);
}
@@ -256,11 +243,11 @@ private:
DiagnosticsEngine Diags;
SourceManager SourceMgr;
llvm::StringMap<Replacements> FileReplacements;
ClangTidyContext &Context;
bool ApplyFixes;
unsigned TotalFixes;
unsigned AppliedFixes;
unsigned WarningsAsErrors;
StringRef FormatStyle;
};
class ClangTidyASTConsumer : public MultiplexConsumer {
@@ -302,7 +289,7 @@ static void setStaticAnalyzerCheckerOpts(const ClangTidyOptions &Opts,
typedef std::vector<std::pair<std::string, bool>> CheckersList;
static CheckersList getCheckersControlList(ClangTidyContext &Context) {
static CheckersList getCheckersControlList(GlobList &Filter) {
CheckersList List;
const auto &RegisteredCheckers =
@@ -310,7 +297,7 @@ static CheckersList getCheckersControlList(ClangTidyContext &Context) {
bool AnalyzerChecksEnabled = false;
for (StringRef CheckName : RegisteredCheckers) {
std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
AnalyzerChecksEnabled |= Context.isCheckEnabled(ClangTidyCheckName);
AnalyzerChecksEnabled |= Filter.contains(ClangTidyCheckName);
}
if (!AnalyzerChecksEnabled)
@@ -324,10 +311,8 @@ static CheckersList getCheckersControlList(ClangTidyContext &Context) {
for (StringRef CheckName : RegisteredCheckers) {
std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str());
if (CheckName.startswith("core") ||
Context.isCheckEnabled(ClangTidyCheckName)) {
if (CheckName.startswith("core") || Filter.contains(ClangTidyCheckName))
List.emplace_back(CheckName, true);
}
}
return List;
}
@@ -373,7 +358,8 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
AnalyzerOptions->Config["cfg-temporary-dtors"] =
Context.getOptions().AnalyzeTemporaryDtors ? "true" : "false";
AnalyzerOptions->CheckersControlList = getCheckersControlList(Context);
GlobList &Filter = Context.getChecksFilter();
AnalyzerOptions->CheckersControlList = getCheckersControlList(Filter);
if (!AnalyzerOptions->CheckersControlList.empty()) {
setStaticAnalyzerCheckerOpts(Context.getOptions(), AnalyzerOptions);
AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
@@ -392,12 +378,13 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
std::vector<std::string> CheckNames;
GlobList &Filter = Context.getChecksFilter();
for (const auto &CheckFactory : *CheckFactories) {
if (Context.isCheckEnabled(CheckFactory.first))
if (Filter.contains(CheckFactory.first))
CheckNames.push_back(CheckFactory.first);
}
for (const auto &AnalyzerCheck : getCheckersControlList(Context))
for (const auto &AnalyzerCheck : getCheckersControlList(Filter))
CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first);
std::sort(CheckNames.begin(), CheckNames.end());
@@ -472,10 +459,13 @@ ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options) {
return Factory.getCheckOptions();
}
void runClangTidy(clang::tidy::ClangTidyContext &Context,
const CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles, ProfileData *Profile) {
ClangTidyStats
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
const CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
std::vector<ClangTidyError> *Errors, ProfileData *Profile) {
ClangTool Tool(Compilations, InputFiles);
clang::tidy::ClangTidyContext Context(std::move(OptionsProvider));
// Add extra arguments passed by the clang-tidy command-line.
ArgumentsAdjuster PerFileExtraArgumentsInserter =
@@ -497,7 +487,7 @@ void runClangTidy(clang::tidy::ClangTidyContext &Context,
// Remove plugins arguments.
ArgumentsAdjuster PluginArgumentsRemover =
[](const CommandLineArguments &Args, StringRef Filename) {
[&Context](const CommandLineArguments &Args, StringRef Filename) {
CommandLineArguments AdjustedArgs;
for (size_t I = 0, E = Args.size(); I < E; ++I) {
if (I + 4 < Args.size() && Args[I] == "-Xclang" &&
@@ -543,18 +533,20 @@ void runClangTidy(clang::tidy::ClangTidyContext &Context,
ActionFactory Factory(Context);
Tool.run(&Factory);
*Errors = Context.getErrors();
return Context.getStats();
}
void handleErrors(ClangTidyContext &Context, bool Fix,
unsigned &WarningsAsErrorsCount) {
ErrorReporter Reporter(Context, Fix);
void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix,
StringRef FormatStyle, unsigned &WarningsAsErrorsCount) {
ErrorReporter Reporter(Fix, FormatStyle);
vfs::FileSystem &FileSystem =
*Reporter.getSourceManager().getFileManager().getVirtualFileSystem();
auto InitialWorkingDir = FileSystem.getCurrentWorkingDirectory();
if (!InitialWorkingDir)
llvm::report_fatal_error("Cannot get current working path.");
for (const ClangTidyError &Error : Context.getErrors()) {
for (const ClangTidyError &Error : Errors) {
if (!Error.BuildDirectory.empty()) {
// By default, the working directory of file system is the current
// clang-tidy running directory.

View File

@@ -224,10 +224,12 @@ ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options);
///
/// \param Profile if provided, it enables check profile collection in
/// MatchFinder, and will contain the result of the profile.
void runClangTidy(clang::tidy::ClangTidyContext &Context,
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
ProfileData *Profile = nullptr);
ClangTidyStats
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
std::vector<ClangTidyError> *Errors,
ProfileData *Profile = nullptr);
// FIXME: This interface will need to be significantly extended to be useful.
// FIXME: Implement confidence levels for displaying/fixing errors.
@@ -235,8 +237,8 @@ void runClangTidy(clang::tidy::ClangTidyContext &Context,
/// \brief Displays the found \p Errors to the users. If \p Fix is true, \p
/// Errors containing fixes are automatically applied and reformatted. If no
/// clang-format configuration file is found, the given \P FormatStyle is used.
void handleErrors(ClangTidyContext &Context, bool Fix,
unsigned &WarningsAsErrorsCount);
void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix,
StringRef FormatStyle, unsigned &WarningsAsErrorsCount);
/// \brief Serializes replacements into YAML and writes them to the specified
/// output stream.

View File

@@ -21,7 +21,6 @@
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/DiagnosticRenderer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include <tuple>
#include <vector>
@@ -37,9 +36,10 @@ public:
: DiagnosticRenderer(LangOpts, DiagOpts), Error(Error) {}
protected:
void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, StringRef Message,
ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag Info) override {
// Remove check name from the message.
// FIXME: Remove this once there's a better way to pass check names than
@@ -49,10 +49,9 @@ protected:
if (Message.endswith(CheckNameInMessage))
Message = Message.substr(0, Message.size() - CheckNameInMessage.size());
auto TidyMessage =
Loc.isValid()
? tooling::DiagnosticMessage(Message, Loc.getManager(), Loc)
: tooling::DiagnosticMessage(Message);
auto TidyMessage = Loc.isValid()
? tooling::DiagnosticMessage(Message, *SM, Loc)
: tooling::DiagnosticMessage(Message);
if (Level == DiagnosticsEngine::Note) {
Error.Notes.push_back(TidyMessage);
return;
@@ -61,13 +60,15 @@ protected:
Error.Message = TidyMessage;
}
void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges) override {}
ArrayRef<CharSourceRange> Ranges,
const SourceManager &SM) override {}
void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange> &Ranges,
ArrayRef<FixItHint> Hints) override {
ArrayRef<FixItHint> Hints,
const SourceManager &SM) override {
assert(Loc.isValid());
for (const auto &FixIt : Hints) {
CharSourceRange Range = FixIt.RemoveRange;
@@ -76,8 +77,7 @@ protected:
assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() &&
"Only file locations supported in fix-it hints.");
tooling::Replacement Replacement(Loc.getManager(), Range,
FixIt.CodeToInsert);
tooling::Replacement Replacement(SM, Range, FixIt.CodeToInsert);
llvm::Error Err = Error.Fix[Replacement.getFilePath()].add(Replacement);
// FIXME: better error handling (at least, don't let other replacements be
// applied).
@@ -89,13 +89,16 @@ protected:
}
}
void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override {}
void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
const SourceManager &SM) override {}
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
StringRef ModuleName) override {}
void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
StringRef ModuleName,
const SourceManager &SM) override {}
void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
StringRef ModuleName) override {}
void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
StringRef ModuleName,
const SourceManager &SM) override {}
void endDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) override {
@@ -116,7 +119,6 @@ ClangTidyError::ClangTidyError(StringRef CheckName,
// Returns true if GlobList starts with the negative indicator ('-'), removes it
// from the GlobList.
static bool ConsumeNegativeIndicator(StringRef &GlobList) {
GlobList = GlobList.trim(" \r\n");
if (GlobList.startswith("-")) {
GlobList = GlobList.substr(1);
return true;
@@ -126,9 +128,8 @@ static bool ConsumeNegativeIndicator(StringRef &GlobList) {
// Converts first glob from the comma-separated list of globs to Regex and
// removes it and the trailing comma from the GlobList.
static llvm::Regex ConsumeGlob(StringRef &GlobList) {
StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(','));
StringRef Glob = UntrimmedGlob.trim(' ');
GlobList = GlobList.substr(UntrimmedGlob.size() + 1);
StringRef Glob = GlobList.substr(0, GlobList.find(',')).trim();
GlobList = GlobList.substr(Glob.size() + 1);
SmallString<128> RegexText("^");
StringRef MetaChars("()^$|*+?.[]\\{}");
for (char C : Glob) {
@@ -155,27 +156,6 @@ bool GlobList::contains(StringRef S, bool Contains) {
return Contains;
}
class ClangTidyContext::CachedGlobList {
public:
CachedGlobList(StringRef Globs) : Globs(Globs) {}
bool contains(StringRef S) {
switch (auto &Result = Cache[S]) {
case Yes: return true;
case No: return false;
case None:
Result = Globs.contains(S) ? Yes : No;
return Result == Yes;
}
llvm_unreachable("invalid enum");
}
private:
GlobList Globs;
enum Tristate { None, Yes, No };
llvm::StringMap<Tristate> Cache;
};
ClangTidyContext::ClangTidyContext(
std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider)
: DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),
@@ -185,8 +165,6 @@ ClangTidyContext::ClangTidyContext(
setCurrentFile("");
}
ClangTidyContext::~ClangTidyContext() = default;
DiagnosticBuilder ClangTidyContext::diag(
StringRef CheckName, SourceLocation Loc, StringRef Description,
DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
@@ -208,9 +186,8 @@ void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
void ClangTidyContext::setCurrentFile(StringRef File) {
CurrentFile = File;
CurrentOptions = getOptionsForFile(CurrentFile);
CheckFilter = llvm::make_unique<CachedGlobList>(*getOptions().Checks);
WarningAsErrorFilter =
llvm::make_unique<CachedGlobList>(*getOptions().WarningsAsErrors);
CheckFilter.reset(new GlobList(*getOptions().Checks));
WarningAsErrorFilter.reset(new GlobList(*getOptions().WarningsAsErrors));
}
void ClangTidyContext::setASTContext(ASTContext *Context) {
@@ -235,14 +212,14 @@ ClangTidyOptions ClangTidyContext::getOptionsForFile(StringRef File) const {
void ClangTidyContext::setCheckProfileData(ProfileData *P) { Profile = P; }
bool ClangTidyContext::isCheckEnabled(StringRef CheckName) const {
GlobList &ClangTidyContext::getChecksFilter() {
assert(CheckFilter != nullptr);
return CheckFilter->contains(CheckName);
return *CheckFilter;
}
bool ClangTidyContext::treatAsError(StringRef CheckName) const {
GlobList &ClangTidyContext::getWarningAsErrorFilter() {
assert(WarningAsErrorFilter != nullptr);
return WarningAsErrorFilter->contains(CheckName);
return *WarningAsErrorFilter;
}
/// \brief Store a \c ClangTidyError.
@@ -258,22 +235,20 @@ StringRef ClangTidyContext::getCheckName(unsigned DiagnosticID) const {
return "";
}
ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
ClangTidyContext &Ctx, bool RemoveIncompatibleErrors)
: Context(Ctx), RemoveIncompatibleErrors(RemoveIncompatibleErrors),
LastErrorRelatesToUserCode(false), LastErrorPassesLineFilter(false),
LastErrorWasIgnored(false) {
ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)
: Context(Ctx), LastErrorRelatesToUserCode(false),
LastErrorPassesLineFilter(false), LastErrorWasIgnored(false) {
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
Diags = llvm::make_unique<DiagnosticsEngine>(
Diags.reset(new DiagnosticsEngine(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,
/*ShouldOwnClient=*/false);
/*ShouldOwnClient=*/false));
Context.setDiagnosticsEngine(Diags.get());
}
void ClangTidyDiagnosticConsumer::finalizeLastError() {
if (!Errors.empty()) {
ClangTidyError &Error = Errors.back();
if (!Context.isCheckEnabled(Error.DiagnosticName) &&
if (!Context.getChecksFilter().contains(Error.DiagnosticName) &&
Error.DiagLevel != ClangTidyError::Error) {
++Context.Stats.ErrorsIgnoredCheckFilter;
Errors.pop_back();
@@ -291,86 +266,26 @@ void ClangTidyDiagnosticConsumer::finalizeLastError() {
LastErrorPassesLineFilter = false;
}
static bool IsNOLINTFound(StringRef NolintDirectiveText, StringRef Line,
unsigned DiagID, const ClangTidyContext &Context) {
const size_t NolintIndex = Line.find(NolintDirectiveText);
if (NolintIndex == StringRef::npos)
return false;
size_t BracketIndex = NolintIndex + NolintDirectiveText.size();
// Check if the specific checks are specified in brackets.
if (BracketIndex < Line.size() && Line[BracketIndex] == '(') {
++BracketIndex;
const size_t BracketEndIndex = Line.find(')', BracketIndex);
if (BracketEndIndex != StringRef::npos) {
StringRef ChecksStr =
Line.substr(BracketIndex, BracketEndIndex - BracketIndex);
// Allow disabling all the checks with "*".
if (ChecksStr != "*") {
StringRef CheckName = Context.getCheckName(DiagID);
// Allow specifying a few check names, delimited with comma.
SmallVector<StringRef, 1> Checks;
ChecksStr.split(Checks, ',', -1, false);
llvm::transform(Checks, Checks.begin(),
[](StringRef S) { return S.trim(); });
return llvm::find(Checks, CheckName) != Checks.end();
}
}
}
return true;
}
static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc,
unsigned DiagID,
const ClangTidyContext &Context) {
static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) {
bool Invalid;
const char *CharacterData = SM.getCharacterData(Loc, &Invalid);
if (Invalid)
return false;
// Check if there's a NOLINT on this line.
const char *P = CharacterData;
while (*P != '\0' && *P != '\r' && *P != '\n')
++P;
StringRef RestOfLine(CharacterData, P - CharacterData + 1);
if (IsNOLINTFound("NOLINT", RestOfLine, DiagID, Context))
return true;
// Check if there's a NOLINTNEXTLINE on the previous line.
const char *BufBegin =
SM.getCharacterData(SM.getLocForStartOfFile(SM.getFileID(Loc)), &Invalid);
if (Invalid || P == BufBegin)
return false;
// Scan backwards over the current line.
P = CharacterData;
while (P != BufBegin && *P != '\n')
--P;
// If we reached the begin of the file there is no line before it.
if (P == BufBegin)
return false;
// Skip over the newline.
--P;
const char *LineEnd = P;
// Now we're on the previous line. Skip to the beginning of it.
while (P != BufBegin && *P != '\n')
--P;
RestOfLine = StringRef(P, LineEnd - P + 1);
if (IsNOLINTFound("NOLINTNEXTLINE", RestOfLine, DiagID, Context))
return true;
if (!Invalid) {
const char *P = CharacterData;
while (*P != '\0' && *P != '\r' && *P != '\n')
++P;
StringRef RestOfLine(CharacterData, P - CharacterData + 1);
// FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
if (RestOfLine.find("NOLINT") != StringRef::npos) {
return true;
}
}
return false;
}
static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM, SourceLocation Loc,
unsigned DiagID,
const ClangTidyContext &Context) {
static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM,
SourceLocation Loc) {
while (true) {
if (LineIsMarkedWithNOLINT(SM, Loc, DiagID, Context))
if (LineIsMarkedWithNOLINT(SM, Loc))
return true;
if (!Loc.isMacroID())
return false;
@@ -387,8 +302,7 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic(
if (Info.getLocation().isValid() && DiagLevel != DiagnosticsEngine::Error &&
DiagLevel != DiagnosticsEngine::Fatal &&
LineIsMarkedWithNOLINTinMacro(Diags->getSourceManager(),
Info.getLocation(), Info.getID(),
Context)) {
Info.getLocation())) {
++Context.Stats.ErrorsIgnoredNOLINT;
// Ignored a warning, should ignore related notes as well
LastErrorWasIgnored = true;
@@ -437,8 +351,9 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic(
LastErrorRelatesToUserCode = true;
LastErrorPassesLineFilter = true;
}
bool IsWarningAsError = DiagLevel == DiagnosticsEngine::Warning &&
Context.treatAsError(CheckName);
bool IsWarningAsError =
DiagLevel == DiagnosticsEngine::Warning &&
Context.getWarningAsErrorFilter().contains(CheckName);
Errors.emplace_back(CheckName, Level, Context.getCurrentBuildDirectory(),
IsWarningAsError);
}
@@ -448,12 +363,11 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic(
Errors.back());
SmallString<100> Message;
Info.FormatDiagnostic(Message);
FullSourceLoc Loc =
(Info.getLocation().isInvalid())
? FullSourceLoc()
: FullSourceLoc(Info.getLocation(), Info.getSourceManager());
Converter.emitDiagnostic(Loc, DiagLevel, Message, Info.getRanges(),
Info.getFixItHints());
SourceManager *Sources = nullptr;
if (Info.hasSourceManager())
Sources = &Info.getSourceManager();
Converter.emitDiagnostic(Info.getLocation(), DiagLevel, Message,
Info.getRanges(), Info.getFixItHints(), Sources);
checkFilters(Info.getLocation());
}
@@ -515,8 +429,8 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location) {
llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
if (!HeaderFilter)
HeaderFilter =
llvm::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
HeaderFilter.reset(
new llvm::Regex(*Context.getOptions().HeaderFilterRegex));
return HeaderFilter.get();
}
@@ -666,9 +580,7 @@ void ClangTidyDiagnosticConsumer::finish() {
std::sort(Errors.begin(), Errors.end(), LessClangTidyError());
Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()),
Errors.end());
if (RemoveIncompatibleErrors)
removeIncompatibleErrors(Errors);
removeIncompatibleErrors(Errors);
for (const ClangTidyError &Error : Errors)
Context.storeError(Error);

View File

@@ -106,8 +106,6 @@ public:
/// \brief Initializes \c ClangTidyContext instance.
ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider);
~ClangTidyContext();
/// \brief Report any errors detected using this method.
///
/// This is still under heavy development and will likely change towards using
@@ -138,14 +136,14 @@ public:
/// diagnostic ID.
StringRef getCheckName(unsigned DiagnosticID) const;
/// \brief Returns \c true if the check is enabled for the \c CurrentFile.
/// \brief Returns check filter for the \c CurrentFile.
///
/// The \c CurrentFile can be changed using \c setCurrentFile.
bool isCheckEnabled(StringRef CheckName) const;
GlobList &getChecksFilter();
/// \brief Returns \c true if the check should be upgraded to error for the
/// \c CurrentFile.
bool treatAsError(StringRef CheckName) const;
/// \brief Returns check filter for the \c CurrentFile which
/// selects checks for upgrade to error.
GlobList &getWarningAsErrorFilter();
/// \brief Returns global options.
const ClangTidyGlobalOptions &getGlobalOptions() const;
@@ -164,7 +162,7 @@ public:
const ClangTidyStats &getStats() const { return Stats; }
/// \brief Returns all collected errors.
ArrayRef<ClangTidyError> getErrors() const { return Errors; }
const std::vector<ClangTidyError> &getErrors() const { return Errors; }
/// \brief Clears collected errors.
void clearErrors() { Errors.clear(); }
@@ -204,9 +202,8 @@ private:
std::string CurrentFile;
ClangTidyOptions CurrentOptions;
class CachedGlobList;
std::unique_ptr<CachedGlobList> CheckFilter;
std::unique_ptr<CachedGlobList> WarningAsErrorFilter;
std::unique_ptr<GlobList> CheckFilter;
std::unique_ptr<GlobList> WarningAsErrorFilter;
LangOptions LangOpts;
@@ -226,8 +223,7 @@ private:
// implementation file.
class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
public:
ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx,
bool RemoveIncompatibleErrors = true);
ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx);
// FIXME: The concept of converting between FixItHints and Replacements is
// more generic and should be pulled out into a more useful Diagnostics
@@ -253,7 +249,6 @@ private:
bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
ClangTidyContext &Context;
bool RemoveIncompatibleErrors;
std::unique_ptr<DiagnosticsEngine> Diags;
SmallVector<ClangTidyError, 8> Errors;
std::unique_ptr<llvm::Regex> HeaderFilter;

View File

@@ -24,8 +24,9 @@ void ClangTidyCheckFactories::registerCheckFactory(StringRef Name,
void ClangTidyCheckFactories::createChecks(
ClangTidyContext *Context,
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks) {
GlobList &Filter = Context->getChecksFilter();
for (const auto &Factory : Factories) {
if (Context->isCheckEnabled(Factory.first))
if (Filter.contains(Factory.first))
Checks.emplace_back(Factory.second(Factory.first, Context));
}
}

View File

@@ -27,6 +27,8 @@ using OptionsSource = clang::tidy::ClangTidyOptionsProvider::OptionsSource;
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
LLVM_YAML_IS_SEQUENCE_VECTOR(ClangTidyOptions::StringPair)
LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)
namespace llvm {
namespace yaml {
@@ -87,7 +89,6 @@ template <> struct MappingTraits<ClangTidyOptions> {
IO.mapOptional("WarningsAsErrors", Options.WarningsAsErrors);
IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors);
IO.mapOptional("FormatStyle", Options.FormatStyle);
IO.mapOptional("User", Options.User);
IO.mapOptional("CheckOptions", NOpts->Options);
IO.mapOptional("ExtraArgs", Options.ExtraArgs);
@@ -108,7 +109,6 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
Options.HeaderFilterRegex = "";
Options.SystemHeaders = false;
Options.AnalyzeTemporaryDtors = false;
Options.FormatStyle = "none";
Options.User = llvm::None;
for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
E = ClangTidyModuleRegistry::end();
@@ -148,7 +148,6 @@ ClangTidyOptions::mergeWith(const ClangTidyOptions &Other) const {
overrideValue(Result.HeaderFilterRegex, Other.HeaderFilterRegex);
overrideValue(Result.SystemHeaders, Other.SystemHeaders);
overrideValue(Result.AnalyzeTemporaryDtors, Other.AnalyzeTemporaryDtors);
overrideValue(Result.FormatStyle, Other.FormatStyle);
overrideValue(Result.User, Other.User);
mergeVectors(Result.ExtraArgs, Other.ExtraArgs);
mergeVectors(Result.ExtraArgsBefore, Other.ExtraArgsBefore);

View File

@@ -75,20 +75,6 @@ struct ClangTidyOptions {
/// \brief Turns on temporary destructor-based analysis.
llvm::Optional<bool> AnalyzeTemporaryDtors;
/// \brief Format code around applied fixes with clang-format using this
/// style.
///
/// Can be one of:
/// * 'none' - don't format code around applied fixes;
/// * 'llvm', 'google', 'mozilla' or other predefined clang-format style
/// names;
/// * 'file' - use the .clang-format file in the closest parent directory of
/// each source file;
/// * '{inline-formatting-style-in-yaml-format}'.
///
/// See clang-format documentation for more about configuring format style.
llvm::Optional<std::string> FormatStyle;
/// \brief Specifies the name or e-mail of the user running clang-tidy.
///
/// This option is used, for example, to place the correct user name in TODO()

View File

@@ -51,7 +51,7 @@ def write_header(module_path, module, check_name, check_name_camel):
print('Creating %s...' % filename)
with open(filename, 'wb') as f:
header_guard = ('LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_' + module.upper() + '_'
+ check_name_camel.upper() + '_H')
+ check_name.upper().replace('-', '_') + '_H')
f.write('//===--- ')
f.write(os.path.basename(filename))
f.write(' - clang-tidy')
@@ -189,37 +189,6 @@ def adapt_module(module_path, module, check_name, check_name_camel):
f.write(line)
# Adds a release notes entry.
def add_release_notes(module_path, module, check_name):
check_name_dashes = module + '-' + check_name
filename = os.path.normpath(os.path.join(module_path,
'../../docs/ReleaseNotes.rst'))
with open(filename, 'r') as f:
lines = f.readlines()
print('Updating %s...' % filename)
with open(filename, 'wb') as f:
note_added = False
header_found = False
for line in lines:
if not note_added:
match = re.search('Improvements to clang-tidy', line)
if match:
header_found = True
elif header_found:
if not line.startswith('----'):
f.write("""
- New `%s
<http://clang.llvm.org/extra/clang-tidy/checks/%s.html>`_ check
FIXME: add release notes.
""" % (check_name_dashes, check_name_dashes))
note_added = True
f.write(line)
# Adds a test for the check.
def write_test(module_path, module, check_name):
check_name_dashes = module + '-' + check_name
@@ -331,7 +300,6 @@ documentation files."""
write_header(module_path, module, check_name, check_name_camel)
write_implementation(module_path, module, check_name_camel)
adapt_module(module_path, module, check_name, check_name_camel)
add_release_notes(module_path, module, check_name)
write_test(module_path, module, check_name)
write_docs(module_path, module, check_name)
update_checks_list(clang_tidy_path)

View File

@@ -1,67 +0,0 @@
//===--- AndroidTidyModule.cpp - clang-tidy--------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "CloexecAccept4Check.h"
#include "CloexecAcceptCheck.h"
#include "CloexecCreatCheck.h"
#include "CloexecEpollCreate1Check.h"
#include "CloexecEpollCreateCheck.h"
#include "CloexecDupCheck.h"
#include "CloexecFopenCheck.h"
#include "CloexecInotifyInit1Check.h"
#include "CloexecInotifyInitCheck.h"
#include "CloexecMemfdCreateCheck.h"
#include "CloexecOpenCheck.h"
#include "CloexecSocketCheck.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
/// This module is for Android specific checks.
class AndroidModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<CloexecAccept4Check>("android-cloexec-accept4");
CheckFactories.registerCheck<CloexecAcceptCheck>("android-cloexec-accept");
CheckFactories.registerCheck<CloexecCreatCheck>("android-cloexec-creat");
CheckFactories.registerCheck<CloexecEpollCreate1Check>(
"android-cloexec-epoll-create1");
CheckFactories.registerCheck<CloexecEpollCreateCheck>(
"android-cloexec-epoll-create");
CheckFactories.registerCheck<CloexecDupCheck>("android-cloexec-dup");
CheckFactories.registerCheck<CloexecFopenCheck>("android-cloexec-fopen");
CheckFactories.registerCheck<CloexecInotifyInitCheck>(
"android-cloexec-inotify-init");
CheckFactories.registerCheck<CloexecInotifyInit1Check>(
"android-cloexec-inotify-init1");
CheckFactories.registerCheck<CloexecMemfdCreateCheck>(
"android-cloexec-memfd-create");
CheckFactories.registerCheck<CloexecOpenCheck>("android-cloexec-open");
CheckFactories.registerCheck<CloexecSocketCheck>("android-cloexec-socket");
}
};
// Register the AndroidTidyModule using this statically initialized variable.
static ClangTidyModuleRegistry::Add<AndroidModule>
X("android-module", "Adds Android platform checks.");
} // namespace android
// This anchor is used to force the linker to link in the generated object file
// and thus register the AndroidModule.
volatile int AndroidModuleAnchorSource = 0;
} // namespace tidy
} // namespace clang

View File

@@ -1,26 +0,0 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyAndroidModule
AndroidTidyModule.cpp
CloexecAccept4Check.cpp
CloexecAcceptCheck.cpp
CloexecCheck.cpp
CloexecCreatCheck.cpp
CloexecEpollCreate1Check.cpp
CloexecEpollCreateCheck.cpp
CloexecDupCheck.cpp
CloexecFopenCheck.cpp
CloexecInotifyInit1Check.cpp
CloexecInotifyInitCheck.cpp
CloexecMemfdCreateCheck.cpp
CloexecOpenCheck.cpp
CloexecSocketCheck.cpp
LINK_LIBS
clangAST
clangASTMatchers
clangBasic
clangLex
clangTidy
clangTidyUtils
)

View File

@@ -1,40 +0,0 @@
//===--- CloexecAccept4Check.cpp - clang-tidy------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecAccept4Check.h"
#include "../utils/ASTUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecAccept4Check::registerMatchers(MatchFinder *Finder) {
auto SockAddrPointerType =
hasType(pointsTo(recordDecl(isStruct(), hasName("sockaddr"))));
auto SockLenPointerType = hasType(pointsTo(namedDecl(hasName("socklen_t"))));
registerMatchersImpl(Finder,
functionDecl(returns(isInteger()), hasName("accept4"),
hasParameter(0, hasType(isInteger())),
hasParameter(1, SockAddrPointerType),
hasParameter(2, SockLenPointerType),
hasParameter(3, hasType(isInteger()))));
}
void CloexecAccept4Check::check(const MatchFinder::MatchResult &Result) {
insertMacroFlag(Result, /*MarcoFlag=*/"SOCK_CLOEXEC", /*ArgPos=*/3);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecAccept4Check.h - clang-tidy----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT4_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT4_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// Finds code that uses accept4() without using the SOCK_CLOEXEC flag.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-accept4.html
class CloexecAccept4Check : public CloexecCheck {
public:
CloexecAccept4Check(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT4_H

View File

@@ -1,47 +0,0 @@
//===--- CloexecAcceptCheck.cpp - clang-tidy-------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecAcceptCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecAcceptCheck::registerMatchers(MatchFinder *Finder) {
auto SockAddrPointerType =
hasType(pointsTo(recordDecl(isStruct(), hasName("sockaddr"))));
auto SockLenPointerType = hasType(pointsTo(namedDecl(hasName("socklen_t"))));
registerMatchersImpl(Finder,
functionDecl(returns(isInteger()), hasName("accept"),
hasParameter(0, hasType(isInteger())),
hasParameter(1, SockAddrPointerType),
hasParameter(2, SockLenPointerType)));
}
void CloexecAcceptCheck::check(const MatchFinder::MatchResult &Result) {
const std::string &ReplacementText =
(Twine("accept4(") + getSpellingArg(Result, 0) + ", " +
getSpellingArg(Result, 1) + ", " + getSpellingArg(Result, 2) +
", SOCK_CLOEXEC)")
.str();
replaceFunc(
Result,
"prefer accept4() to accept() because accept4() allows SOCK_CLOEXEC",
ReplacementText);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecAcceptCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// accept() is better to be replaced by accept4().
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-accept.html
class CloexecAcceptCheck : public CloexecCheck {
public:
CloexecAcceptCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_ACCEPT_H

View File

@@ -1,114 +0,0 @@
//===--- CloexecCheck.cpp - clang-tidy-------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecCheck.h"
#include "../utils/ASTUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
namespace {
// Helper function to form the correct string mode for Type3.
// Build the replace text. If it's string constant, add <Mode> directly in the
// end of the string. Else, add <Mode>.
std::string buildFixMsgForStringFlag(const Expr *Arg, const SourceManager &SM,
const LangOptions &LangOpts, char Mode) {
if (Arg->getLocStart().isMacroID())
return (Lexer::getSourceText(
CharSourceRange::getTokenRange(Arg->getSourceRange()), SM,
LangOpts) +
" \"" + Twine(Mode) + "\"")
.str();
StringRef SR = cast<StringLiteral>(Arg->IgnoreParenCasts())->getString();
return ("\"" + SR + Twine(Mode) + "\"").str();
}
} // namespace
const char *CloexecCheck::FuncDeclBindingStr = "funcDecl";
const char *CloexecCheck::FuncBindingStr ="func";
void CloexecCheck::registerMatchersImpl(
MatchFinder *Finder, internal::Matcher<FunctionDecl> Function) {
// We assume all the checked APIs are C functions.
Finder->addMatcher(
callExpr(
callee(functionDecl(isExternC(), Function).bind(FuncDeclBindingStr)))
.bind(FuncBindingStr),
this);
}
void CloexecCheck::insertMacroFlag(const MatchFinder::MatchResult &Result,
StringRef MacroFlag, int ArgPos) {
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
const auto *FlagArg = MatchedCall->getArg(ArgPos);
const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr);
SourceManager &SM = *Result.SourceManager;
if (utils::exprHasBitFlagWithSpelling(FlagArg->IgnoreParenCasts(), SM,
Result.Context->getLangOpts(),
MacroFlag))
return;
SourceLocation EndLoc =
Lexer::getLocForEndOfToken(SM.getFileLoc(FlagArg->getLocEnd()), 0, SM,
Result.Context->getLangOpts());
diag(EndLoc, "%0 should use %1 where possible")
<< FD << MacroFlag
<< FixItHint::CreateInsertion(EndLoc, (Twine(" | ") + MacroFlag).str());
}
void CloexecCheck::replaceFunc(const MatchFinder::MatchResult &Result,
StringRef WarningMsg, StringRef FixMsg) {
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
diag(MatchedCall->getLocStart(), WarningMsg)
<< FixItHint::CreateReplacement(MatchedCall->getSourceRange(), FixMsg);
}
void CloexecCheck::insertStringFlag(
const ast_matchers::MatchFinder::MatchResult &Result, const char Mode,
const int ArgPos) {
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr);
const auto *ModeArg = MatchedCall->getArg(ArgPos);
// Check if the <Mode> may be in the mode string.
const auto *ModeStr = dyn_cast<StringLiteral>(ModeArg->IgnoreParenCasts());
if (!ModeStr || (ModeStr->getString().find(Mode) != StringRef::npos))
return;
const std::string &ReplacementText = buildFixMsgForStringFlag(
ModeArg, *Result.SourceManager, Result.Context->getLangOpts(), Mode);
diag(ModeArg->getLocStart(), "use %0 mode '%1' to set O_CLOEXEC")
<< FD << std::string(1, Mode)
<< FixItHint::CreateReplacement(ModeArg->getSourceRange(),
ReplacementText);
}
StringRef CloexecCheck::getSpellingArg(const MatchFinder::MatchResult &Result,
int N) const {
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(FuncBindingStr);
const SourceManager &SM = *Result.SourceManager;
return Lexer::getSourceText(
CharSourceRange::getTokenRange(MatchedCall->getArg(N)->getSourceRange()),
SM, Result.Context->getLangOpts());
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,105 +0,0 @@
//===--- CloexecCheck.h - clang-tidy-----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declaration of the CloexecCheck class, which is the
/// base class for all of the close-on-exec checks in Android module.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace android {
/// \brief The base class for all close-on-exec checks in Android module.
/// To be specific, there are some functions that need the close-on-exec flag to
/// prevent the file descriptor leakage on fork+exec and this class provides
/// utilities to identify and fix these C functions.
class CloexecCheck : public ClangTidyCheck {
public:
CloexecCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
protected:
void
registerMatchersImpl(ast_matchers::MatchFinder *Finder,
ast_matchers::internal::Matcher<FunctionDecl> Function);
/// Currently, we have three types of fixes.
///
/// Type1 is to insert the necessary macro flag in the flag argument. For
/// example, 'O_CLOEXEC' is required in function 'open()', so
/// \code
/// open(file, O_RDONLY);
/// \endcode
/// should be
/// \code
/// open(file, O_RDONLY | O_CLOEXE);
/// \endcode
///
/// \param [out] Result MatchResult from AST matcher.
/// \param MacroFlag The macro name of the flag.
/// \param ArgPos The 0-based position of the flag argument.
void insertMacroFlag(const ast_matchers::MatchFinder::MatchResult &Result,
StringRef MacroFlag, int ArgPos);
/// Type2 is to replace the API to another function that has required the
/// ability. For example:
/// \code
/// creat(path, mode);
/// \endcode
/// should be
/// \code
/// open(path, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, mode)
/// \endcode
///
/// \param [out] Result MatchResult from AST matcher.
/// \param WarningMsg The warning message.
/// \param FixMsg The fix message.
void replaceFunc(const ast_matchers::MatchFinder::MatchResult &Result,
StringRef WarningMsg, StringRef FixMsg);
/// Type3 is also to add a flag to the corresponding argument, but this time,
/// the flag is some string and each char represents a mode rather than a
/// macro. For example, 'fopen' needs char 'e' in its mode argument string, so
/// \code
/// fopen(in_file, "r");
/// \endcode
/// should be
/// \code
/// fopen(in_file, "re");
/// \endcode
///
/// \param [out] Result MatchResult from AST matcher.
/// \param Mode The required mode char.
/// \param ArgPos The 0-based position of the flag argument.
void insertStringFlag(const ast_matchers::MatchFinder::MatchResult &Result,
const char Mode, const int ArgPos);
/// Helper function to get the spelling of a particular argument.
StringRef getSpellingArg(const ast_matchers::MatchFinder::MatchResult &Result,
int N) const;
/// Binding name of the FuncDecl of a function call.
static const char *FuncDeclBindingStr;
/// Binding name of the function call expression.
static const char *FuncBindingStr;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_H

View File

@@ -1,43 +0,0 @@
//===--- CloexecCreatCheck.cpp - clang-tidy--------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecCreatCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecCreatCheck::registerMatchers(MatchFinder *Finder) {
auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
auto MODETType = hasType(namedDecl(hasName("mode_t")));
registerMatchersImpl(Finder,
functionDecl(isExternC(), returns(isInteger()),
hasName("creat"),
hasParameter(0, CharPointerType),
hasParameter(1, MODETType)));
}
void CloexecCreatCheck::check(const MatchFinder::MatchResult &Result) {
const std::string &ReplacementText =
(Twine("open (") + getSpellingArg(Result, 0) +
", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, " +
getSpellingArg(Result, 1) + ")")
.str();
replaceFunc(Result,
"prefer open() to creat() because open() allows O_CLOEXEC",
ReplacementText);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecCreatCheck.h - clang-tidy------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_CREAT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_CREAT_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// creat() is better to be replaced by open().
/// Find the usage of creat() and redirect user to use open().
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-creat.html
class CloexecCreatCheck : public CloexecCheck {
public:
CloexecCreatCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_CREAT_H

View File

@@ -1,38 +0,0 @@
//===--- CloexecDupCheck.cpp - clang-tidy----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecDupCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecDupCheck::registerMatchers(MatchFinder *Finder) {
registerMatchersImpl(Finder,
functionDecl(returns(isInteger()), hasName("dup"),
hasParameter(0, hasType(isInteger()))));
}
void CloexecDupCheck::check(const MatchFinder::MatchResult &Result) {
const std::string &ReplacementText =
(Twine("fcntl(") + getSpellingArg(Result, 0) + ", F_DUPFD_CLOEXEC)")
.str();
replaceFunc(Result,
"prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC",
ReplacementText);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,36 +0,0 @@
//===--- CloexecDupCheck.h - clang-tidy-------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_DUP_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_DUP_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// dup() is better to be replaced by fcntl(), which has close-on-exec flag.
/// Find the usage of dup() and redirect user to use fcntl().
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-dup.html
class CloexecDupCheck : public CloexecCheck {
public:
CloexecDupCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_DUP_H

View File

@@ -1,33 +0,0 @@
//===--- CloexecEpollCreate1Check.cpp - clang-tidy-------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecEpollCreate1Check.h"
#include "../utils/ASTUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecEpollCreate1Check::registerMatchers(MatchFinder *Finder) {
registerMatchersImpl(
Finder, functionDecl(returns(isInteger()), hasName("epoll_create1"),
hasParameter(0, hasType(isInteger()))));
}
void CloexecEpollCreate1Check::check(const MatchFinder::MatchResult &Result) {
insertMacroFlag(Result, /*MarcoFlag=*/"EPOLL_CLOEXEC", /*ArgPos=*/0);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecEpollCreate1Check.h - clang-tidy-----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// Finds code that uses epoll_create1() without using the EPOLL_CLOEXEC flag.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create1.html
class CloexecEpollCreate1Check : public CloexecCheck {
public:
CloexecEpollCreate1Check(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE1_H

View File

@@ -1,36 +0,0 @@
//===--- CloexecEpollCreateCheck.cpp - clang-tidy--------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecEpollCreateCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecEpollCreateCheck::registerMatchers(MatchFinder *Finder) {
registerMatchersImpl(
Finder, functionDecl(returns(isInteger()), hasName("epoll_create"),
hasParameter(0, hasType(isInteger()))));
}
void CloexecEpollCreateCheck::check(const MatchFinder::MatchResult &Result) {
replaceFunc(Result,
"prefer epoll_create() to epoll_create1() "
"because epoll_create1() allows "
"EPOLL_CLOEXEC",
"epoll_create1(EPOLL_CLOEXEC)");
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecEpollCreateCheck.h - clang-tidy------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// epoll_create() is better to be replaced by epoll_create1().
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-epoll-create.html
class CloexecEpollCreateCheck : public CloexecCheck {
public:
CloexecEpollCreateCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_EPOLL_CREATE_H

View File

@@ -1,36 +0,0 @@
//===--- CloexecFopenCheck.cpp - clang-tidy--------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details. //
//===----------------------------------------------------------------------===//
#include "CloexecFopenCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecFopenCheck::registerMatchers(MatchFinder *Finder) {
auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
registerMatchersImpl(Finder,
functionDecl(isExternC(), returns(asString("FILE *")),
hasName("fopen"),
hasParameter(0, CharPointerType),
hasParameter(1, CharPointerType)));
}
void CloexecFopenCheck::check(const MatchFinder::MatchResult &Result) {
insertStringFlag(Result, /*Mode=*/'e', /*ArgPos=*/1);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,38 +0,0 @@
//===--- CloexecFopenCheck.h - clang-tidy------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_FOPEN_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_FOPEN_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// fopen() is suggested to include "e" in their mode string; like "re" would be
/// better than "r".
///
/// This check only works when corresponding argument is StringLiteral. No
/// constant propagation.
///
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-fopen.html
class CloexecFopenCheck : public CloexecCheck {
public:
CloexecFopenCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_FOPEN_H

View File

@@ -1,33 +0,0 @@
//===--- CloexecInotifyInit1Check.cpp - clang-tidy-------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecInotifyInit1Check.h"
#include "../utils/ASTUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecInotifyInit1Check::registerMatchers(MatchFinder *Finder) {
registerMatchersImpl(
Finder, functionDecl(returns(isInteger()), hasName("inotify_init1"),
hasParameter(0, hasType(isInteger()))));
}
void CloexecInotifyInit1Check::check(const MatchFinder::MatchResult &Result) {
insertMacroFlag(Result, /*MarcoFlag=*/"IN_CLOEXEC", /*ArgPos=*/0);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecInotifyInit1Check.h - clang-tidy-----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT1_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT1_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// Finds code that uses inotify_init1() without using the IN_CLOEXEC flag.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-inotify-init1.html
class CloexecInotifyInit1Check : public CloexecCheck {
public:
CloexecInotifyInit1Check(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT1_H

View File

@@ -1,34 +0,0 @@
//===--- CloexecInotifyInitCheck.cpp - clang-tidy--------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecInotifyInitCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecInotifyInitCheck::registerMatchers(MatchFinder *Finder) {
registerMatchersImpl(
Finder, functionDecl(returns(isInteger()), hasName("inotify_init")));
}
void CloexecInotifyInitCheck::check(const MatchFinder::MatchResult &Result) {
replaceFunc(Result, /*WarningMsg=*/
"prefer inotify_init() to inotify_init1() "
"because inotify_init1() allows IN_CLOEXEC",
/*FixMsg=*/"inotify_init1(IN_CLOEXEC)");
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecInotifyInitCheck.h - clang-tidy------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// inotify_init() is better to be replaced by inotify_init1().
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-inotify-init.html
class CloexecInotifyInitCheck : public CloexecCheck {
public:
CloexecInotifyInitCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_INOTIFY_INIT_H

View File

@@ -1,32 +0,0 @@
//===--- CloexecMemfdCreateCheck.cpp - clang-tidy--------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecMemfdCreateCheck.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecMemfdCreateCheck::registerMatchers(MatchFinder *Finder) {
auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
registerMatchersImpl(
Finder, functionDecl(returns(isInteger()), hasName("memfd_create"),
hasParameter(0, CharPointerType),
hasParameter(1, hasType(isInteger()))));
}
void CloexecMemfdCreateCheck::check(const MatchFinder::MatchResult &Result) {
insertMacroFlag(Result, "MFD_CLOEXEC", /*ArgPos=*/1);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecMemfdCreateCheck.h - clang-tidy-----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_MEMFD_CREATE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_MEMFD_CREATE_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// Finds code that uses memfd_create() without using the MFD_CLOEXEC flag.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-memfd-create.html
class CloexecMemfdCreateCheck : public CloexecCheck {
public:
CloexecMemfdCreateCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_MEMFD_CREATE_H

View File

@@ -1,44 +0,0 @@
//===--- CloexecOpenCheck.cpp - clang-tidy---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecOpenCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecOpenCheck::registerMatchers(MatchFinder *Finder) {
auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
registerMatchersImpl(Finder,
functionDecl(isExternC(), returns(isInteger()),
hasAnyName("open", "open64"),
hasParameter(0, CharPointerType),
hasParameter(1, hasType(isInteger()))));
registerMatchersImpl(Finder,
functionDecl(isExternC(), returns(isInteger()),
hasName("openat"),
hasParameter(0, hasType(isInteger())),
hasParameter(1, CharPointerType),
hasParameter(2, hasType(isInteger()))));
}
void CloexecOpenCheck::check(const MatchFinder::MatchResult &Result) {
const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>(FuncDeclBindingStr);
assert(FD->param_size() > 1);
int ArgPos = (FD->param_size() > 2) ? 2 : 1;
insertMacroFlag(Result, /*MarcoFlag=*/"O_CLOEXEC", ArgPos);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,40 +0,0 @@
//===--- CloexecOpenCheck.h - clang-tidy-----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_OPEN_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_OPEN_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// Finds code that opens file without using the O_CLOEXEC flag.
///
/// open(), openat(), and open64() had better to include O_CLOEXEC in their
/// flags argument. Only consider simple cases that the corresponding argument
/// is constant or binary operation OR among constants like 'O_CLOEXEC' or
/// 'O_CLOEXEC | O_RDONLY'. No constant propagation is performed.
///
/// Only the symbolic 'O_CLOEXEC' macro definition is checked, not the concrete
/// value.
class CloexecOpenCheck : public CloexecCheck {
public:
CloexecOpenCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_OPEN_H

View File

@@ -1,35 +0,0 @@
//===--- CloexecSocketCheck.cpp - clang-tidy-------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CloexecSocketCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace android {
void CloexecSocketCheck::registerMatchers(MatchFinder *Finder) {
registerMatchersImpl(Finder,
functionDecl(isExternC(), returns(isInteger()),
hasName("socket"),
hasParameter(0, hasType(isInteger())),
hasParameter(1, hasType(isInteger())),
hasParameter(2, hasType(isInteger()))));
}
void CloexecSocketCheck::check(const MatchFinder::MatchResult &Result) {
insertMacroFlag(Result, /*MarcoFlag=*/"SOCK_CLOEXEC", /*ArgPos=*/1);
}
} // namespace android
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- CloexecSocketCheck.h - clang-tidy-----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_SOCKET_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_SOCKET_H
#include "CloexecCheck.h"
namespace clang {
namespace tidy {
namespace android {
/// Finds code that uses socket() without using the SOCK_CLOEXEC flag.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-socket.html
class CloexecSocketCheck : public CloexecCheck {
public:
CloexecSocketCheck(StringRef Name, ClangTidyContext *Context)
: CloexecCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace android
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ANDROID_CLOEXEC_SOCKET_H

View File

@@ -1,308 +0,0 @@
//===--- ArgumentCommentCheck.cpp - clang-tidy ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ArgumentCommentCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Token.h"
#include "../utils/LexerUtils.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
ArgumentCommentCheck::ArgumentCommentCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
StrictMode(Options.getLocalOrGlobal("StrictMode", 0) != 0),
IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
void ArgumentCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "StrictMode", StrictMode);
}
void ArgumentCommentCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
callExpr(unless(cxxOperatorCallExpr()),
// NewCallback's arguments relate to the pointed function, don't
// check them against NewCallback's parameter names.
// FIXME: Make this configurable.
unless(hasDeclaration(functionDecl(
hasAnyName("NewCallback", "NewPermanentCallback")))))
.bind("expr"),
this);
Finder->addMatcher(cxxConstructExpr().bind("expr"), this);
}
static std::vector<std::pair<SourceLocation, StringRef>>
getCommentsInRange(ASTContext *Ctx, CharSourceRange Range) {
std::vector<std::pair<SourceLocation, StringRef>> Comments;
auto &SM = Ctx->getSourceManager();
std::pair<FileID, unsigned> BeginLoc = SM.getDecomposedLoc(Range.getBegin()),
EndLoc = SM.getDecomposedLoc(Range.getEnd());
if (BeginLoc.first != EndLoc.first)
return Comments;
bool Invalid = false;
StringRef Buffer = SM.getBufferData(BeginLoc.first, &Invalid);
if (Invalid)
return Comments;
const char *StrData = Buffer.data() + BeginLoc.second;
Lexer TheLexer(SM.getLocForStartOfFile(BeginLoc.first), Ctx->getLangOpts(),
Buffer.begin(), StrData, Buffer.end());
TheLexer.SetCommentRetentionState(true);
while (true) {
Token Tok;
if (TheLexer.LexFromRawLexer(Tok))
break;
if (Tok.getLocation() == Range.getEnd() || Tok.is(tok::eof))
break;
if (Tok.is(tok::comment)) {
std::pair<FileID, unsigned> CommentLoc =
SM.getDecomposedLoc(Tok.getLocation());
assert(CommentLoc.first == BeginLoc.first);
Comments.emplace_back(
Tok.getLocation(),
StringRef(Buffer.begin() + CommentLoc.second, Tok.getLength()));
} else {
// Clear comments found before the different token, e.g. comma.
Comments.clear();
}
}
return Comments;
}
static std::vector<std::pair<SourceLocation, StringRef>>
getCommentsBeforeLoc(ASTContext *Ctx, SourceLocation Loc) {
std::vector<std::pair<SourceLocation, StringRef>> Comments;
while (Loc.isValid()) {
clang::Token Tok =
utils::lexer::getPreviousToken(*Ctx, Loc, /*SkipComments=*/false);
if (Tok.isNot(tok::comment))
break;
Loc = Tok.getLocation();
Comments.emplace_back(
Loc,
Lexer::getSourceText(CharSourceRange::getCharRange(
Loc, Loc.getLocWithOffset(Tok.getLength())),
Ctx->getSourceManager(), Ctx->getLangOpts()));
}
return Comments;
}
static bool isLikelyTypo(llvm::ArrayRef<ParmVarDecl *> Params,
StringRef ArgName, unsigned ArgIndex) {
std::string ArgNameLowerStr = ArgName.lower();
StringRef ArgNameLower = ArgNameLowerStr;
// The threshold is arbitrary.
unsigned UpperBound = (ArgName.size() + 2) / 3 + 1;
unsigned ThisED = ArgNameLower.edit_distance(
Params[ArgIndex]->getIdentifier()->getName().lower(),
/*AllowReplacements=*/true, UpperBound);
if (ThisED >= UpperBound)
return false;
for (unsigned I = 0, E = Params.size(); I != E; ++I) {
if (I == ArgIndex)
continue;
IdentifierInfo *II = Params[I]->getIdentifier();
if (!II)
continue;
const unsigned Threshold = 2;
// Other parameters must be an edit distance at least Threshold more away
// from this parameter. This gives us greater confidence that this is a typo
// of this parameter and not one with a similar name.
unsigned OtherED = ArgNameLower.edit_distance(II->getName().lower(),
/*AllowReplacements=*/true,
ThisED + Threshold);
if (OtherED < ThisED + Threshold)
return false;
}
return true;
}
static bool sameName(StringRef InComment, StringRef InDecl, bool StrictMode) {
if (StrictMode)
return InComment == InDecl;
InComment = InComment.trim('_');
InDecl = InDecl.trim('_');
// FIXME: compare_lower only works for ASCII.
return InComment.compare_lower(InDecl) == 0;
}
static bool looksLikeExpectMethod(const CXXMethodDecl *Expect) {
return Expect != nullptr && Expect->getLocation().isMacroID() &&
Expect->getNameInfo().getName().isIdentifier() &&
Expect->getName().startswith("gmock_");
}
static bool areMockAndExpectMethods(const CXXMethodDecl *Mock,
const CXXMethodDecl *Expect) {
assert(looksLikeExpectMethod(Expect));
return Mock != nullptr && Mock->getNextDeclInContext() == Expect &&
Mock->getNumParams() == Expect->getNumParams() &&
Mock->getLocation().isMacroID() &&
Mock->getNameInfo().getName().isIdentifier() &&
Mock->getName() == Expect->getName().substr(strlen("gmock_"));
}
// This uses implementation details of MOCK_METHODx_ macros: for each mocked
// method M it defines M() with appropriate signature and a method used to set
// up expectations - gmock_M() - with each argument's type changed the
// corresponding matcher. This function returns M when given either M or
// gmock_M.
static const CXXMethodDecl *findMockedMethod(const CXXMethodDecl *Method) {
if (looksLikeExpectMethod(Method)) {
const DeclContext *Ctx = Method->getDeclContext();
if (Ctx == nullptr || !Ctx->isRecord())
return nullptr;
for (const auto *D : Ctx->decls()) {
if (D->getNextDeclInContext() == Method) {
const auto *Previous = dyn_cast<CXXMethodDecl>(D);
return areMockAndExpectMethods(Previous, Method) ? Previous : nullptr;
}
}
return nullptr;
}
if (const auto *Next = dyn_cast_or_null<CXXMethodDecl>(
Method->getNextDeclInContext())) {
if (looksLikeExpectMethod(Next) && areMockAndExpectMethods(Method, Next))
return Method;
}
return nullptr;
}
// For gmock expectation builder method (the target of the call generated by
// `EXPECT_CALL(obj, Method(...))`) tries to find the real method being mocked
// (returns nullptr, if the mock method doesn't override anything). For other
// functions returns the function itself.
static const FunctionDecl *resolveMocks(const FunctionDecl *Func) {
if (const auto *Method = dyn_cast<CXXMethodDecl>(Func)) {
if (const auto *MockedMethod = findMockedMethod(Method)) {
// If mocked method overrides the real one, we can use its parameter
// names, otherwise we're out of luck.
if (MockedMethod->size_overridden_methods() > 0) {
return *MockedMethod->begin_overridden_methods();
}
return nullptr;
}
}
return Func;
}
void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
const FunctionDecl *OriginalCallee,
SourceLocation ArgBeginLoc,
llvm::ArrayRef<const Expr *> Args) {
const FunctionDecl *Callee = resolveMocks(OriginalCallee);
if (!Callee)
return;
Callee = Callee->getFirstDecl();
unsigned NumArgs = std::min<unsigned>(Args.size(), Callee->getNumParams());
if (NumArgs == 0)
return;
auto makeFileCharRange = [Ctx](SourceLocation Begin, SourceLocation End) {
return Lexer::makeFileCharRange(CharSourceRange::getCharRange(Begin, End),
Ctx->getSourceManager(),
Ctx->getLangOpts());
};
for (unsigned I = 0; I < NumArgs; ++I) {
const ParmVarDecl *PVD = Callee->getParamDecl(I);
IdentifierInfo *II = PVD->getIdentifier();
if (!II)
continue;
if (auto Template = Callee->getTemplateInstantiationPattern()) {
// Don't warn on arguments for parameters instantiated from template
// parameter packs. If we find more arguments than the template
// definition has, it also means that they correspond to a parameter
// pack.
if (Template->getNumParams() <= I ||
Template->getParamDecl(I)->isParameterPack()) {
continue;
}
}
CharSourceRange BeforeArgument =
makeFileCharRange(ArgBeginLoc, Args[I]->getLocStart());
ArgBeginLoc = Args[I]->getLocEnd();
std::vector<std::pair<SourceLocation, StringRef>> Comments;
if (BeforeArgument.isValid()) {
Comments = getCommentsInRange(Ctx, BeforeArgument);
} else {
// Fall back to parsing back from the start of the argument.
CharSourceRange ArgsRange = makeFileCharRange(
Args[I]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
Comments = getCommentsBeforeLoc(Ctx, ArgsRange.getBegin());
}
for (auto Comment : Comments) {
llvm::SmallVector<StringRef, 2> Matches;
if (IdentRE.match(Comment.second, &Matches) &&
!sameName(Matches[2], II->getName(), StrictMode)) {
{
DiagnosticBuilder Diag =
diag(Comment.first, "argument name '%0' in comment does not "
"match parameter name %1")
<< Matches[2] << II;
if (isLikelyTypo(Callee->parameters(), Matches[2], I)) {
Diag << FixItHint::CreateReplacement(
Comment.first, (Matches[1] + II->getName() + Matches[3]).str());
}
}
diag(PVD->getLocation(), "%0 declared here", DiagnosticIDs::Note) << II;
if (OriginalCallee != Callee) {
diag(OriginalCallee->getLocation(),
"actual callee (%0) is declared here", DiagnosticIDs::Note)
<< OriginalCallee;
}
}
}
}
}
void ArgumentCommentCheck::check(const MatchFinder::MatchResult &Result) {
const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
if (const auto *Call = dyn_cast<CallExpr>(E)) {
const FunctionDecl *Callee = Call->getDirectCallee();
if (!Callee)
return;
checkCallArgs(Result.Context, Callee, Call->getCallee()->getLocEnd(),
llvm::makeArrayRef(Call->getArgs(), Call->getNumArgs()));
} else {
const auto *Construct = cast<CXXConstructExpr>(E);
if (Construct->getNumArgs() == 1 &&
Construct->getArg(0)->getSourceRange() == Construct->getSourceRange()) {
// Ignore implicit construction.
return;
}
checkCallArgs(
Result.Context, Construct->getConstructor(),
Construct->getParenOrBraceRange().getBegin(),
llvm::makeArrayRef(Construct->getArgs(), Construct->getNumArgs()));
}
}
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@@ -1,86 +0,0 @@
//===--- BugproneTidyModule.cpp - clang-tidy ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "ArgumentCommentCheck.h"
#include "AssertSideEffectCheck.h"
#include "BoolPointerImplicitConversionCheck.h"
#include "CopyConstructorInitCheck.h"
#include "DanglingHandleCheck.h"
#include "FoldInitTypeCheck.h"
#include "ForwardDeclarationNamespaceCheck.h"
#include "InaccurateEraseCheck.h"
#include "IntegerDivisionCheck.h"
#include "MisplacedOperatorInStrlenInAllocCheck.h"
#include "MoveForwardingReferenceCheck.h"
#include "MultipleStatementMacroCheck.h"
#include "StringConstructorCheck.h"
#include "SuspiciousMemsetUsageCheck.h"
#include "UndefinedMemoryManipulationCheck.h"
#include "UseAfterMoveCheck.h"
#include "VirtualNearMissCheck.h"
namespace clang {
namespace tidy {
namespace bugprone {
class BugproneModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<ArgumentCommentCheck>(
"bugprone-argument-comment");
CheckFactories.registerCheck<AssertSideEffectCheck>(
"bugprone-assert-side-effect");
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
"bugprone-bool-pointer-implicit-conversion");
CheckFactories.registerCheck<CopyConstructorInitCheck>(
"bugprone-copy-constructor-init");
CheckFactories.registerCheck<DanglingHandleCheck>(
"bugprone-dangling-handle");
CheckFactories.registerCheck<FoldInitTypeCheck>(
"bugprone-fold-init-type");
CheckFactories.registerCheck<ForwardDeclarationNamespaceCheck>(
"bugprone-forward-declaration-namespace");
CheckFactories.registerCheck<InaccurateEraseCheck>(
"bugprone-inaccurate-erase");
CheckFactories.registerCheck<IntegerDivisionCheck>(
"bugprone-integer-division");
CheckFactories.registerCheck<MisplacedOperatorInStrlenInAllocCheck>(
"bugprone-misplaced-operator-in-strlen-in-alloc");
CheckFactories.registerCheck<MoveForwardingReferenceCheck>(
"bugprone-move-forwarding-reference");
CheckFactories.registerCheck<MultipleStatementMacroCheck>(
"bugprone-multiple-statement-macro");
CheckFactories.registerCheck<StringConstructorCheck>(
"bugprone-string-constructor");
CheckFactories.registerCheck<SuspiciousMemsetUsageCheck>(
"bugprone-suspicious-memset-usage");
CheckFactories.registerCheck<UndefinedMemoryManipulationCheck>(
"bugprone-undefined-memory-manipulation");
CheckFactories.registerCheck<UseAfterMoveCheck>(
"bugprone-use-after-move");
CheckFactories.registerCheck<VirtualNearMissCheck>(
"bugprone-virtual-near-miss");
}
};
} // namespace bugprone
// Register the BugproneTidyModule using this statically initialized variable.
static ClangTidyModuleRegistry::Add<bugprone::BugproneModule>
X("bugprone-module", "Adds checks for bugprone code constructs.");
// This anchor is used to force the linker to link in the generated object file
// and thus register the BugproneModule.
volatile int BugproneModuleAnchorSource = 0;
} // namespace tidy
} // namespace clang

View File

@@ -1,32 +0,0 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyBugproneModule
ArgumentCommentCheck.cpp
AssertSideEffectCheck.cpp
BoolPointerImplicitConversionCheck.cpp
BugproneTidyModule.cpp
CopyConstructorInitCheck.cpp
DanglingHandleCheck.cpp
FoldInitTypeCheck.cpp
ForwardDeclarationNamespaceCheck.cpp
InaccurateEraseCheck.cpp
IntegerDivisionCheck.cpp
MisplacedOperatorInStrlenInAllocCheck.cpp
MoveForwardingReferenceCheck.cpp
MultipleStatementMacroCheck.cpp
StringConstructorCheck.cpp
SuspiciousMemsetUsageCheck.cpp
UndefinedMemoryManipulationCheck.cpp
UseAfterMoveCheck.cpp
VirtualNearMissCheck.cpp
LINK_LIBS
clangAnalysis
clangAST
clangASTMatchers
clangBasic
clangLex
clangTidy
clangTidyUtils
clangTooling
)

View File

@@ -1,121 +0,0 @@
//===--- CopyConstructorInitCheck.cpp - clang-tidy-------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CopyConstructorInitCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
void CopyConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
// In the future this might be extended to move constructors?
Finder->addMatcher(
cxxConstructorDecl(
isCopyConstructor(),
hasAnyConstructorInitializer(cxxCtorInitializer(
isBaseInitializer(),
withInitializer(cxxConstructExpr(hasDeclaration(
cxxConstructorDecl(isDefaultConstructor())))))),
unless(isInstantiated()))
.bind("ctor"),
this);
}
void CopyConstructorInitCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
std::string ParamName = Ctor->getParamDecl(0)->getNameAsString();
// We want only one warning (and FixIt) for each ctor.
std::string FixItInitList;
bool HasRelevantBaseInit = false;
bool ShouldNotDoFixit = false;
bool HasWrittenInitializer = false;
SmallVector<FixItHint, 2> SafeFixIts;
for (const auto *Init : Ctor->inits()) {
bool CtorInitIsWritten = Init->isWritten();
HasWrittenInitializer = HasWrittenInitializer || CtorInitIsWritten;
if (!Init->isBaseInitializer())
continue;
const Type *BaseType = Init->getBaseClass();
// Do not do fixits if there is a type alias involved or one of the bases
// are explicitly initialized. In the latter case we not do fixits to avoid
// -Wreorder warnings.
if (const auto *TempSpecTy = dyn_cast<TemplateSpecializationType>(BaseType))
ShouldNotDoFixit = ShouldNotDoFixit || TempSpecTy->isTypeAlias();
ShouldNotDoFixit = ShouldNotDoFixit || isa<TypedefType>(BaseType);
ShouldNotDoFixit = ShouldNotDoFixit || CtorInitIsWritten;
const CXXRecordDecl *BaseClass =
BaseType->getAsCXXRecordDecl()->getDefinition();
if (BaseClass->field_empty() &&
BaseClass->forallBases(
[](const CXXRecordDecl *Class) { return Class->field_empty(); }))
continue;
bool NonCopyableBase = false;
for (const auto *Ctor : BaseClass->ctors()) {
if (Ctor->isCopyConstructor() &&
(Ctor->getAccess() == AS_private || Ctor->isDeleted())) {
NonCopyableBase = true;
break;
}
}
if (NonCopyableBase)
continue;
const auto *CExpr = dyn_cast<CXXConstructExpr>(Init->getInit());
if (!CExpr || !CExpr->getConstructor()->isDefaultConstructor())
continue;
HasRelevantBaseInit = true;
if (CtorInitIsWritten) {
if (!ParamName.empty())
SafeFixIts.push_back(
FixItHint::CreateInsertion(CExpr->getLocEnd(), ParamName));
} else {
if (Init->getSourceLocation().isMacroID() ||
Ctor->getLocation().isMacroID() || ShouldNotDoFixit)
break;
FixItInitList += BaseClass->getNameAsString();
FixItInitList += "(" + ParamName + "), ";
}
}
if (!HasRelevantBaseInit)
return;
auto Diag = diag(Ctor->getLocation(),
"calling a base constructor other than the copy constructor")
<< SafeFixIts;
if (FixItInitList.empty() || ParamName.empty() || ShouldNotDoFixit)
return;
std::string FixItMsg{FixItInitList.substr(0, FixItInitList.size() - 2)};
SourceLocation FixItLoc;
// There is no initialization list in this constructor.
if (!HasWrittenInitializer) {
FixItLoc = Ctor->getBody()->getLocStart();
FixItMsg = " : " + FixItMsg;
} else {
// We apply the missing ctors at the beginning of the initialization list.
FixItLoc = (*Ctor->init_begin())->getSourceLocation();
FixItMsg += ',';
}
FixItMsg += ' ';
Diag << FixItHint::CreateInsertion(FixItLoc, FixItMsg);
} // namespace misc
} // namespace misc
} // namespace tidy
} // namespace clang

View File

@@ -1,36 +0,0 @@
//===--- CopyConstructorInitCheck.h - clang-tidy--------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Finds copy constructors where the ctor don't call the copy constructor of
/// the base class.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc-copy-constructor-init.html
class CopyConstructorInitCheck : public ClangTidyCheck {
public:
CopyConstructorInitCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace misc
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H

View File

@@ -1,81 +0,0 @@
//===--- InaccurateEraseCheck.cpp - clang-tidy-----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "InaccurateEraseCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
namespace {
AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
}
void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
// Only register the matchers for C++; the functionality currently does not
// provide any benefit to other languages, despite being benign.
if (!getLangOpts().CPlusPlus)
return;
const auto EndCall =
callExpr(
callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))),
hasArgument(
1,
anyOf(cxxConstructExpr(has(ignoringImplicit(
cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
.bind("end")))),
anything())))
.bind("alg");
const auto DeclInStd = type(hasUnqualifiedDesugaredType(
tagType(hasDeclaration(decl(isInStdNamespace())))));
Finder->addMatcher(
cxxMemberCallExpr(
on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
hasArgument(0, has(ignoringImplicit(
anyOf(EndCall, has(ignoringImplicit(EndCall)))))),
unless(isInTemplateInstantiation()))
.bind("erase"),
this);
}
void InaccurateEraseCheck::check(const MatchFinder::MatchResult &Result) {
const auto *MemberCall =
Result.Nodes.getNodeAs<CXXMemberCallExpr>("erase");
const auto *EndExpr =
Result.Nodes.getNodeAs<CXXMemberCallExpr>("end");
const SourceLocation Loc = MemberCall->getLocStart();
FixItHint Hint;
if (!Loc.isMacroID() && EndExpr) {
const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("alg");
std::string ReplacementText = Lexer::getSourceText(
CharSourceRange::getTokenRange(EndExpr->getSourceRange()),
*Result.SourceManager, getLangOpts());
const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
AlgCall->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
Hint = FixItHint::CreateInsertion(EndLoc, ", " + ReplacementText);
}
diag(Loc, "this call will remove at most one item even when multiple items "
"should be removed")
<< Hint;
}
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@@ -1,57 +0,0 @@
//===--- IntegerDivisionCheck.cpp - clang-tidy-----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "IntegerDivisionCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
void IntegerDivisionCheck::registerMatchers(MatchFinder *Finder) {
const auto IntType = hasType(isInteger());
const auto BinaryOperators = binaryOperator(anyOf(
hasOperatorName("%"), hasOperatorName("<<"), hasOperatorName(">>"),
hasOperatorName("<<"), hasOperatorName("^"), hasOperatorName("|"),
hasOperatorName("&"), hasOperatorName("||"), hasOperatorName("&&"),
hasOperatorName("<"), hasOperatorName(">"), hasOperatorName("<="),
hasOperatorName(">="), hasOperatorName("=="), hasOperatorName("!=")));
const auto UnaryOperators =
unaryOperator(anyOf(hasOperatorName("~"), hasOperatorName("!")));
const auto Exceptions =
anyOf(BinaryOperators, conditionalOperator(), binaryConditionalOperator(),
callExpr(IntType), explicitCastExpr(IntType), UnaryOperators);
Finder->addMatcher(
binaryOperator(
hasOperatorName("/"), hasLHS(expr(IntType)), hasRHS(expr(IntType)),
hasAncestor(
castExpr(hasCastKind(CK_IntegralToFloating)).bind("FloatCast")),
unless(hasAncestor(
expr(Exceptions,
hasAncestor(castExpr(equalsBoundNode("FloatCast")))))))
.bind("IntDiv"),
this);
}
void IntegerDivisionCheck::check(const MatchFinder::MatchResult &Result) {
const auto *IntDiv = Result.Nodes.getNodeAs<BinaryOperator>("IntDiv");
diag(IntDiv->getLocStart(), "result of integer division used in a floating "
"point context; possible loss of precision");
}
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@@ -1,36 +0,0 @@
//===--- IntegerDivisionCheck.h - clang-tidy---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Finds cases where integer division in a floating point context is likely to
/// cause unintended loss of precision.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-integer-division.html
class IntegerDivisionCheck : public ClangTidyCheck {
public:
IntegerDivisionCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H

View File

@@ -1,112 +0,0 @@
//===--- MisplacedOperatorInStrlenInAllocCheck.cpp - clang-tidy------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MisplacedOperatorInStrlenInAllocCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
void MisplacedOperatorInStrlenInAllocCheck::registerMatchers(
MatchFinder *Finder) {
const auto StrLenFunc = functionDecl(anyOf(
hasName("::strlen"), hasName("::std::strlen"), hasName("::strnlen"),
hasName("::std::strnlen"), hasName("::strnlen_s"),
hasName("::std::strnlen_s"), hasName("::wcslen"),
hasName("::std::wcslen"), hasName("::wcsnlen"), hasName("::std::wcsnlen"),
hasName("::wcsnlen_s"), hasName("std::wcsnlen_s")));
const auto BadUse =
callExpr(callee(StrLenFunc),
hasAnyArgument(ignoringImpCasts(
binaryOperator(allOf(hasOperatorName("+"),
hasRHS(ignoringParenImpCasts(
integerLiteral(equals(1))))))
.bind("BinOp"))))
.bind("StrLen");
const auto BadArg = anyOf(
allOf(hasDescendant(BadUse),
unless(binaryOperator(allOf(
hasOperatorName("+"), hasLHS(BadUse),
hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))))),
BadUse);
const auto Alloc0Func =
functionDecl(anyOf(hasName("::malloc"), hasName("std::malloc"),
hasName("::alloca"), hasName("std::alloca")));
const auto Alloc1Func =
functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"),
hasName("::realloc"), hasName("std::realloc")));
const auto Alloc0FuncPtr =
varDecl(hasType(isConstQualified()),
hasInitializer(ignoringParenImpCasts(
declRefExpr(hasDeclaration(Alloc0Func)))));
const auto Alloc1FuncPtr =
varDecl(hasType(isConstQualified()),
hasInitializer(ignoringParenImpCasts(
declRefExpr(hasDeclaration(Alloc1Func)))));
Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))),
hasArgument(0, BadArg))
.bind("Alloc"),
this);
Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))),
hasArgument(1, BadArg))
.bind("Alloc"),
this);
Finder->addMatcher(
cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this);
}
void MisplacedOperatorInStrlenInAllocCheck::check(
const MatchFinder::MatchResult &Result) {
const Expr *Alloc = Result.Nodes.getNodeAs<CallExpr>("Alloc");
if (!Alloc)
Alloc = Result.Nodes.getNodeAs<CXXNewExpr>("Alloc");
assert(Alloc && "Matched node bound by 'Alloc' shoud be either 'CallExpr'"
" or 'CXXNewExpr'");
const auto *StrLen = Result.Nodes.getNodeAs<CallExpr>("StrLen");
const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("BinOp");
const StringRef StrLenText = Lexer::getSourceText(
CharSourceRange::getTokenRange(StrLen->getSourceRange()),
*Result.SourceManager, getLangOpts());
const StringRef Arg0Text = Lexer::getSourceText(
CharSourceRange::getTokenRange(StrLen->getArg(0)->getSourceRange()),
*Result.SourceManager, getLangOpts());
const StringRef StrLenBegin = StrLenText.substr(0, StrLenText.find(Arg0Text));
const StringRef StrLenEnd = StrLenText.substr(
StrLenText.find(Arg0Text) + Arg0Text.size(), StrLenText.size());
const StringRef LHSText = Lexer::getSourceText(
CharSourceRange::getTokenRange(BinOp->getLHS()->getSourceRange()),
*Result.SourceManager, getLangOpts());
const StringRef RHSText = Lexer::getSourceText(
CharSourceRange::getTokenRange(BinOp->getRHS()->getSourceRange()),
*Result.SourceManager, getLangOpts());
auto Hint = FixItHint::CreateReplacement(
StrLen->getSourceRange(),
(StrLenBegin + LHSText + StrLenEnd + " + " + RHSText).str());
diag(Alloc->getLocStart(),
"addition operator is applied to the argument of %0 instead of its "
"result") << StrLen->getDirectCallee()->getName() << Hint;
}
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@@ -1,37 +0,0 @@
//===--- MisplacedOperatorInStrlenInAllocCheck.h - clang-tidy----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Finds cases where ``1`` is added to the string in the argument to a function
/// in the ``strlen()`` family instead of the result and value is used as an
/// argument to a memory allocation function.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-misplaced-operator-in-strlen-in-alloc.html
class MisplacedOperatorInStrlenInAllocCheck : public ClangTidyCheck {
public:
MisplacedOperatorInStrlenInAllocCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H

View File

@@ -1,37 +0,0 @@
//===--- MultipleStatementMacroCheck.h - clang-tidy--------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Detect multiple statement macros that are used in unbraced conditionals.
/// Only the first statement of the macro will be inside the conditional and the
/// other ones will be executed unconditionally.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-multiple-statement-macro.html
class MultipleStatementMacroCheck : public ClangTidyCheck {
public:
MultipleStatementMacroCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H

View File

@@ -1,39 +0,0 @@
//===--- StringConstructorCheck.h - clang-tidy-------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Finds suspicious string constructor and check their parameters.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-string-constructor.html
class StringConstructorCheck : public ClangTidyCheck {
public:
StringConstructorCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
const bool WarnOnLargeLength;
const unsigned int LargeLengthThreshold;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H

View File

@@ -1,127 +0,0 @@
//===--- SuspiciousMemsetUsageCheck.cpp - clang-tidy-----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "SuspiciousMemsetUsageCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/FixIt.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
void SuspiciousMemsetUsageCheck::registerMatchers(MatchFinder *Finder) {
// Note: void *memset(void *buffer, int fill_char, size_t byte_count);
// Look for memset(x, '0', z). Probably memset(x, 0, z) was intended.
Finder->addMatcher(
callExpr(
callee(functionDecl(hasName("::memset"))),
hasArgument(1, characterLiteral(equals(static_cast<unsigned>('0')))
.bind("char-zero-fill")),
unless(
eachOf(hasArgument(0, anyOf(hasType(pointsTo(isAnyCharacter())),
hasType(arrayType(hasElementType(
isAnyCharacter()))))),
isInTemplateInstantiation()))),
this);
// Look for memset with an integer literal in its fill_char argument.
// Will check if it gets truncated.
Finder->addMatcher(callExpr(callee(functionDecl(hasName("::memset"))),
hasArgument(1, integerLiteral().bind("num-fill")),
unless(isInTemplateInstantiation())),
this);
// Look for memset(x, y, 0) as that is most likely an argument swap.
Finder->addMatcher(
callExpr(callee(functionDecl(hasName("::memset"))),
unless(hasArgument(1, anyOf(characterLiteral(equals(
static_cast<unsigned>('0'))),
integerLiteral()))),
unless(isInTemplateInstantiation()))
.bind("call"),
this);
}
void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) {
if (const auto *CharZeroFill =
Result.Nodes.getNodeAs<CharacterLiteral>("char-zero-fill")) {
// Case 1: fill_char of memset() is a character '0'. Probably an
// integer zero was intended.
SourceRange CharRange = CharZeroFill->getSourceRange();
auto Diag =
diag(CharZeroFill->getLocStart(), "memset fill value is char '0', "
"potentially mistaken for int 0");
// Only suggest a fix if no macros are involved.
if (CharRange.getBegin().isMacroID())
return;
Diag << FixItHint::CreateReplacement(
CharSourceRange::getTokenRange(CharRange), "0");
}
else if (const auto *NumFill =
Result.Nodes.getNodeAs<IntegerLiteral>("num-fill")) {
// Case 2: fill_char of memset() is larger in size than an unsigned char
// so it gets truncated during conversion.
llvm::APSInt NumValue;
const auto UCharMax = (1 << Result.Context->getCharWidth()) - 1;
if (!NumFill->EvaluateAsInt(NumValue, *Result.Context) ||
(NumValue >= 0 && NumValue <= UCharMax))
return;
diag(NumFill->getLocStart(), "memset fill value is out of unsigned "
"character range, gets truncated");
}
else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call")) {
// Case 3: byte_count of memset() is zero. This is most likely an
// argument swap.
const Expr *FillChar = Call->getArg(1);
const Expr *ByteCount = Call->getArg(2);
// Return if `byte_count` is not zero at compile time.
llvm::APSInt Value1, Value2;
if (ByteCount->isValueDependent() ||
!ByteCount->EvaluateAsInt(Value2, *Result.Context) || Value2 != 0)
return;
// Return if `fill_char` is known to be zero or negative at compile
// time. In these cases, swapping the args would be a nop, or
// introduce a definite bug. The code is likely correct.
if (!FillChar->isValueDependent() &&
FillChar->EvaluateAsInt(Value1, *Result.Context) &&
(Value1 == 0 || Value1.isNegative()))
return;
// `byte_count` is known to be zero at compile time, and `fill_char` is
// either not known or known to be a positive integer. Emit a warning
// and fix-its to swap the arguments.
auto D = diag(Call->getLocStart(),
"memset of size zero, potentially swapped arguments");
StringRef RHSString = tooling::fixit::getText(*ByteCount, *Result.Context);
StringRef LHSString = tooling::fixit::getText(*FillChar, *Result.Context);
if (LHSString.empty() || RHSString.empty())
return;
D << tooling::fixit::createReplacement(*FillChar, RHSString)
<< tooling::fixit::createReplacement(*ByteCount, LHSString);
}
}
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- SuspiciousMemsetUsageCheck.h - clang-tidy---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Finds memset calls with potential mistakes in their arguments.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-suspicious-memset-usage.html
class SuspiciousMemsetUsageCheck : public ClangTidyCheck {
public:
SuspiciousMemsetUsageCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H

View File

@@ -1,71 +0,0 @@
//===--- UndefinedMemoryManipulationCheck.cpp - clang-tidy-----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "UndefinedMemoryManipulationCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
namespace {
AST_MATCHER(CXXRecordDecl, isNotTriviallyCopyable) {
// For incomplete types, assume they are TriviallyCopyable.
return Node.hasDefinition() ? !Node.isTriviallyCopyable() : false;
}
} // namespace
void UndefinedMemoryManipulationCheck::registerMatchers(MatchFinder *Finder) {
const auto NotTriviallyCopyableObject =
hasType(ast_matchers::hasCanonicalType(
pointsTo(cxxRecordDecl(isNotTriviallyCopyable()))));
// Check whether destination object is not TriviallyCopyable.
// Applicable to all three memory manipulation functions.
Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
"::memset", "::memcpy", "::memmove"))),
hasArgument(0, NotTriviallyCopyableObject))
.bind("dest"),
this);
// Check whether source object is not TriviallyCopyable.
// Only applicable to memcpy() and memmove().
Finder->addMatcher(
callExpr(callee(functionDecl(hasAnyName("::memcpy", "::memmove"))),
hasArgument(1, NotTriviallyCopyableObject))
.bind("src"),
this);
}
void UndefinedMemoryManipulationCheck::check(
const MatchFinder::MatchResult &Result) {
if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("dest")) {
QualType DestType = Call->getArg(0)->IgnoreImplicit()->getType();
if (!DestType->getPointeeType().isNull())
DestType = DestType->getPointeeType();
diag(Call->getLocStart(), "undefined behavior, destination object type %0 "
"is not TriviallyCopyable")
<< DestType;
}
if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("src")) {
QualType SourceType = Call->getArg(1)->IgnoreImplicit()->getType();
if (!SourceType->getPointeeType().isNull())
SourceType = SourceType->getPointeeType();
diag(Call->getLocStart(),
"undefined behavior, source object type %0 is not TriviallyCopyable")
<< SourceType;
}
}
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@@ -1,37 +0,0 @@
//===--- UndefinedMemoryManipulationCheck.h - clang-tidy---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Finds calls of memory manipulation functions ``memset()``, ``memcpy()`` and
/// ``memmove()`` on not TriviallyCopyable objects resulting in undefined
/// behavior.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-undefined-memory-manipulation.html
class UndefinedMemoryManipulationCheck : public ClangTidyCheck {
public:
UndefinedMemoryManipulationCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H

View File

@@ -1,36 +0,0 @@
//===--- UseAfterMoveCheck.h - clang-tidy ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// The check warns if an object is used after it has been moved, without an
/// intervening reinitialization.
///
/// For details, see the user-facing documentation:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-use-after-move.html
class UseAfterMoveCheck : public ClangTidyCheck {
public:
UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_USEAFTERMOVECHECK_H

View File

@@ -11,16 +11,14 @@
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "../google/UnnamedNamespaceInHeaderCheck.h"
#include "../misc/MoveConstructorInitCheck.h"
#include "../misc/NewDeleteOverloadsCheck.h"
#include "../misc/NonCopyableObjects.h"
#include "../misc/StaticAssertCheck.h"
#include "../misc/ThrowByValueCatchByReferenceCheck.h"
#include "../performance/MoveConstructorInitCheck.h"
#include "CommandProcessorCheck.h"
#include "DontModifyStdNamespaceCheck.h"
#include "FloatLoopCounter.h"
#include "LimitedRandomnessCheck.h"
#include "PostfixOperatorCheck.h"
#include "SetLongJmpCheck.h"
#include "StaticObjectExceptionCheck.h"
#include "StrToNumCheck.h"
@@ -36,17 +34,13 @@ public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
// C++ checkers
// DCL
CheckFactories.registerCheck<PostfixOperatorCheck>(
"cert-dcl21-cpp");
CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
"cert-dcl54-cpp");
CheckFactories.registerCheck<DontModifyStdNamespaceCheck>(
"cert-dcl58-cpp");
CheckFactories.registerCheck<google::build::UnnamedNamespaceInHeaderCheck>(
"cert-dcl59-cpp");
// OOP
CheckFactories.registerCheck<performance::MoveConstructorInitCheck>(
CheckFactories.registerCheck<misc::MoveConstructorInitCheck>(
"cert-oop11-cpp");
// ERR
CheckFactories.registerCheck<misc::ThrowByValueCatchByReferenceCheck>(

View File

@@ -3,10 +3,8 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyCERTModule
CERTTidyModule.cpp
CommandProcessorCheck.cpp
DontModifyStdNamespaceCheck.cpp
FloatLoopCounter.cpp
LimitedRandomnessCheck.cpp
PostfixOperatorCheck.cpp
SetLongJmpCheck.cpp
StaticObjectExceptionCheck.cpp
StrToNumCheck.cpp
@@ -22,6 +20,5 @@ add_clang_library(clangTidyCERTModule
clangTidy
clangTidyGoogleModule
clangTidyMiscModule
clangTidyPerformanceModule
clangTidyUtils
)

View File

@@ -1,49 +0,0 @@
//===--- DontModifyStdNamespaceCheck.cpp - clang-tidy----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DontModifyStdNamespaceCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void DontModifyStdNamespaceCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
Finder->addMatcher(
namespaceDecl(unless(isExpansionInSystemHeader()),
anyOf(hasName("std"), hasName("posix")),
has(decl(unless(anyOf(
functionDecl(isExplicitTemplateSpecialization()),
cxxRecordDecl(isExplicitTemplateSpecialization()))))))
.bind("nmspc"),
this);
}
void DontModifyStdNamespaceCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *N = Result.Nodes.getNodeAs<NamespaceDecl>("nmspc");
// Only consider top level namespaces.
if (N->getParent() != Result.Context->getTranslationUnitDecl())
return;
diag(N->getLocation(),
"modification of %0 namespace can result in undefined behavior")
<< N;
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@@ -1,36 +0,0 @@
//===--- DontModifyStdNamespaceCheck.h - clang-tidy--------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Modification of the std or posix namespace can result in undefined behavior.
/// This check warns for such modifications.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-msc53-cpp.html
class DontModifyStdNamespaceCheck : public ClangTidyCheck {
public:
DontModifyStdNamespaceCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H

View File

@@ -1,88 +0,0 @@
//===--- PostfixOperatorCheck.cpp - clang-tidy-----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PostfixOperatorCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace cert {
void PostfixOperatorCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
Finder->addMatcher(functionDecl(anyOf(hasOverloadedOperatorName("++"),
hasOverloadedOperatorName("--")))
.bind("decl"),
this);
}
void PostfixOperatorCheck::check(const MatchFinder::MatchResult &Result) {
const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
bool HasThis = false;
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
HasThis = MethodDecl->isInstance();
// Check if the operator is a postfix one.
if (FuncDecl->getNumParams() != (HasThis ? 1 : 2))
return;
SourceRange ReturnRange = FuncDecl->getReturnTypeSourceRange();
SourceLocation Location = ReturnRange.getBegin();
if (!Location.isValid())
return;
QualType ReturnType = FuncDecl->getReturnType();
// Warn when the operators return a reference.
if (const auto *RefType = ReturnType->getAs<ReferenceType>()) {
auto Diag = diag(Location, "overloaded %0 returns a reference instead of a "
"constant object type")
<< FuncDecl;
if (Location.isMacroID() || ReturnType->getAs<TypedefType>() ||
RefType->getPointeeTypeAsWritten()->getAs<TypedefType>())
return;
QualType ReplaceType =
ReturnType.getNonReferenceType().getLocalUnqualifiedType();
// The getReturnTypeSourceRange omits the qualifiers. We do not want to
// duplicate the const.
if (!ReturnType->getPointeeType().isConstQualified())
ReplaceType.addConst();
Diag << FixItHint::CreateReplacement(
ReturnRange,
ReplaceType.getAsString(Result.Context->getPrintingPolicy()) + " ");
return;
}
if (ReturnType.isConstQualified() || ReturnType->isBuiltinType() ||
ReturnType->isPointerType())
return;
auto Diag =
diag(Location, "overloaded %0 returns a non-constant object instead of a "
"constant object type")
<< FuncDecl;
if (!Location.isMacroID() && !ReturnType->getAs<TypedefType>())
Diag << FixItHint::CreateInsertion(Location, "const ");
}
} // namespace cert
} // namespace tidy
} // namespace clang

View File

@@ -1,36 +0,0 @@
//===--- PostfixOperatorCheck.h - clang-tidy---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cert {
/// Checks if the overloaded postfix ++ and -- operator return a constant
/// object.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cert-postfix-operator.html
class PostfixOperatorCheck : public ClangTidyCheck {
public:
PostfixOperatorCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace cert
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_POSTFIX_OPERATOR_H

View File

@@ -19,7 +19,7 @@ namespace tidy {
namespace cert {
void StaticObjectExceptionCheck::registerMatchers(MatchFinder *Finder) {
if ((!getLangOpts().CPlusPlus) || (!getLangOpts().CXXExceptions))
if (!getLangOpts().CPlusPlus)
return;
// Match any static or thread_local variable declaration that has an

View File

@@ -4,7 +4,6 @@ add_clang_library(clangTidyCppCoreGuidelinesModule
CppCoreGuidelinesTidyModule.cpp
InterfacesGlobalInitCheck.cpp
NoMallocCheck.cpp
OwningMemoryCheck.cpp
ProBoundsArrayToPointerDecayCheck.cpp
ProBoundsConstantArrayIndexCheck.cpp
ProBoundsPointerArithmeticCheck.cpp

View File

@@ -13,7 +13,6 @@
#include "../misc/UnconventionalAssignOperatorCheck.h"
#include "InterfacesGlobalInitCheck.h"
#include "NoMallocCheck.h"
#include "OwningMemoryCheck.h"
#include "ProBoundsArrayToPointerDecayCheck.h"
#include "ProBoundsConstantArrayIndexCheck.h"
#include "ProBoundsPointerArithmeticCheck.h"
@@ -38,8 +37,6 @@ public:
CheckFactories.registerCheck<InterfacesGlobalInitCheck>(
"cppcoreguidelines-interfaces-global-init");
CheckFactories.registerCheck<NoMallocCheck>("cppcoreguidelines-no-malloc");
CheckFactories.registerCheck<OwningMemoryCheck>(
"cppcoreguidelines-owning-memory");
CheckFactories.registerCheck<ProBoundsArrayToPointerDecayCheck>(
"cppcoreguidelines-pro-bounds-array-to-pointer-decay");
CheckFactories.registerCheck<ProBoundsConstantArrayIndexCheck>(

View File

@@ -8,63 +8,43 @@
//===----------------------------------------------------------------------===//
#include "NoMallocCheck.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace clang::ast_matchers;
using namespace clang::ast_matchers::internal;
namespace clang {
namespace tidy {
namespace cppcoreguidelines {
namespace {
Matcher<FunctionDecl> hasAnyListedName(const std::string &FunctionNames) {
const std::vector<std::string> NameList =
utils::options::parseStringList(FunctionNames);
return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end()));
}
} // namespace
void NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "Allocations", AllocList);
Options.store(Opts, "Reallocations", ReallocList);
Options.store(Opts, "Deallocations", DeallocList);
}
void NoMallocCheck::registerMatchers(MatchFinder *Finder) {
// C-style memory management is only problematic in C++.
if (!getLangOpts().CPlusPlus)
return;
// Registering malloc, will suggest RAII.
Finder->addMatcher(callExpr(callee(functionDecl(hasAnyListedName(AllocList))))
.bind("allocation"),
this);
Finder->addMatcher(
callExpr(callee(functionDecl(hasAnyName("::malloc", "::calloc"))))
.bind("aquisition"),
this);
// Registering realloc calls, suggest std::vector or std::string.
Finder->addMatcher(
callExpr(callee(functionDecl(hasAnyListedName(ReallocList))))
.bind("realloc"),
callExpr(callee(functionDecl(hasName("::realloc")))).bind("realloc"),
this);
// Registering free calls, will suggest RAII instead.
Finder->addMatcher(
callExpr(callee(functionDecl(hasAnyListedName(DeallocList))))
.bind("free"),
this);
callExpr(callee(functionDecl(hasName("::free")))).bind("free"), this);
}
void NoMallocCheck::check(const MatchFinder::MatchResult &Result) {
const CallExpr *Call = nullptr;
StringRef Recommendation;
if ((Call = Result.Nodes.getNodeAs<CallExpr>("allocation")))
if ((Call = Result.Nodes.getNodeAs<CallExpr>("aquisition")))
Recommendation = "consider a container or a smart pointer";
else if ((Call = Result.Nodes.getNodeAs<CallExpr>("realloc")))
Recommendation = "consider std::vector or std::string";

View File

@@ -27,32 +27,14 @@ namespace cppcoreguidelines {
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-no-malloc.html
class NoMallocCheck : public ClangTidyCheck {
public:
/// Construct Checker and read in configuration for function names.
NoMallocCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
AllocList(Options.get("Allocations", "::malloc;::calloc")),
ReallocList(Options.get("Reallocations", "::realloc")),
DeallocList(Options.get("Deallocations", "::free")) {}
/// Make configuration of checker discoverable.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
: ClangTidyCheck(Name, Context) {}
/// Registering for malloc, calloc, realloc and free calls.
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
/// Checks matched function calls and gives suggestion to modernize the code.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
/// Semicolon-separated list of fully qualified names of memory allocation
/// functions the check warns about. Defaults to `::malloc;::calloc`.
const std::string AllocList;
/// Semicolon-separated list of fully qualified names of memory reallocation
/// functions the check warns about. Defaults to `::realloc`.
const std::string ReallocList;
/// Semicolon-separated list of fully qualified names of memory deallocation
/// functions the check warns about. Defaults to `::free`.
const std::string DeallocList;
};
} // namespace cppcoreguidelines

View File

@@ -1,394 +0,0 @@
//===--- OwningMemoryCheck.cpp - clang-tidy--------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "OwningMemoryCheck.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <string>
#include <vector>
using namespace clang::ast_matchers;
using namespace clang::ast_matchers::internal;
namespace clang {
namespace tidy {
namespace cppcoreguidelines {
// FIXME: Copied from 'NoMallocCheck.cpp'. Has to be refactored into 'util' or
// something like that.
namespace {
Matcher<FunctionDecl> hasAnyListedName(const std::string &FunctionNames) {
const std::vector<std::string> NameList =
utils::options::parseStringList(FunctionNames);
return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end()));
}
} // namespace
void OwningMemoryCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "LegacyResourceProducers", LegacyResourceProducers);
Options.store(Opts, "LegacyResourceConsumers", LegacyResourceConsumers);
}
/// Match common cases, where the owner semantic is relevant, like function
/// calls, delete expressions and others.
void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus11)
return;
const auto OwnerDecl = typeAliasTemplateDecl(hasName("::gsl::owner"));
const auto IsOwnerType = hasType(OwnerDecl);
const auto LegacyCreatorFunctions = hasAnyListedName(LegacyResourceProducers);
const auto LegacyConsumerFunctions =
hasAnyListedName(LegacyResourceConsumers);
// Legacy functions that are use for resource management but cannot be
// updated to use `gsl::owner<>`, like standard C memory management.
const auto CreatesLegacyOwner =
callExpr(callee(functionDecl(LegacyCreatorFunctions)));
// C-style functions like `::malloc()` sometimes create owners as void*
// which is expected to be cast to the correct type in C++. This case
// must be catched explicitly.
const auto LegacyOwnerCast =
castExpr(hasSourceExpression(CreatesLegacyOwner));
// Functions that do manual resource management but cannot be updated to use
// owner. Best example is `::free()`.
const auto LegacyOwnerConsumers = functionDecl(LegacyConsumerFunctions);
const auto CreatesOwner =
anyOf(cxxNewExpr(),
callExpr(callee(
functionDecl(returns(qualType(hasDeclaration(OwnerDecl)))))),
CreatesLegacyOwner, LegacyOwnerCast);
const auto ConsideredOwner = eachOf(IsOwnerType, CreatesOwner);
// Find delete expressions that delete non-owners.
Finder->addMatcher(
cxxDeleteExpr(
hasDescendant(
declRefExpr(unless(ConsideredOwner)).bind("deleted_variable")))
.bind("delete_expr"),
this);
// Ignoring the implicit casts is vital because the legacy owners do not work
// with the 'owner<>' annotation and therefore always implicitly cast to the
// legacy type (even 'void *').
//
// Furthermore, legacy owner functions are assumed to use raw pointers for
// resources. This check assumes that all pointer arguments of a legacy
// functions shall be 'gsl::owner<>'.
Finder->addMatcher(
callExpr(
allOf(callee(LegacyOwnerConsumers),
hasAnyArgument(allOf(unless(ignoringImpCasts(ConsideredOwner)),
hasType(pointerType())))))
.bind("legacy_consumer"),
this);
// Matching assignment to owners, with the rhs not being an owner nor creating
// one.
Finder->addMatcher(binaryOperator(allOf(matchers::isAssignmentOperator(),
hasLHS(IsOwnerType),
hasRHS(unless(ConsideredOwner))))
.bind("owner_assignment"),
this);
// Matching initialization of owners with non-owners, nor creating owners.
Finder->addMatcher(
namedDecl(
varDecl(allOf(hasInitializer(unless(ConsideredOwner)), IsOwnerType))
.bind("owner_initialization")),
this);
const auto HasConstructorInitializerForOwner =
has(cxxConstructorDecl(forEachConstructorInitializer(
cxxCtorInitializer(allOf(isMemberInitializer(), forField(IsOwnerType),
withInitializer(
// Avoid templatesdeclaration with
// excluding parenListExpr.
allOf(unless(ConsideredOwner),
unless(parenListExpr())))))
.bind("owner_member_initializer"))));
// Match class member initialization that expects owners, but does not get
// them.
Finder->addMatcher(cxxRecordDecl(HasConstructorInitializerForOwner), this);
// Matching on assignment operations where the RHS is a newly created owner,
// but the LHS is not an owner.
Finder->addMatcher(
binaryOperator(allOf(matchers::isAssignmentOperator(),
hasLHS(unless(IsOwnerType)), hasRHS(CreatesOwner)))
.bind("bad_owner_creation_assignment"),
this);
// Matching on initialization operations where the initial value is a newly
// created owner, but the LHS is not an owner.
Finder->addMatcher(
namedDecl(varDecl(eachOf(allOf(hasInitializer(CreatesOwner),
unless(IsOwnerType)),
allOf(hasInitializer(ConsideredOwner),
hasType(autoType().bind("deduced_type")))))
.bind("bad_owner_creation_variable")),
this);
// Match on all function calls that expect owners as arguments, but didn't
// get them.
Finder->addMatcher(
callExpr(forEachArgumentWithParam(
expr(unless(ConsideredOwner)).bind("expected_owner_argument"),
parmVarDecl(IsOwnerType))),
this);
// Matching for function calls where one argument is a created owner, but the
// parameter type is not an owner.
Finder->addMatcher(callExpr(forEachArgumentWithParam(
expr(CreatesOwner).bind("bad_owner_creation_argument"),
parmVarDecl(unless(IsOwnerType))
.bind("bad_owner_creation_parameter"))),
this);
// Matching on functions, that return an owner/resource, but don't declare
// their return type as owner.
Finder->addMatcher(
functionDecl(
allOf(hasDescendant(returnStmt(hasReturnValue(ConsideredOwner))
.bind("bad_owner_return")),
unless(returns(qualType(hasDeclaration(OwnerDecl))))))
.bind("function_decl"),
this);
// Match on classes that have an owner as member, but don't declare a
// destructor to properly release the owner.
Finder->addMatcher(
cxxRecordDecl(
allOf(
has(fieldDecl(IsOwnerType).bind("undestructed_owner_member")),
anyOf(unless(has(cxxDestructorDecl())),
has(cxxDestructorDecl(anyOf(isDefaulted(), isDeleted()))))))
.bind("non_destructor_class"),
this);
}
void OwningMemoryCheck::check(const MatchFinder::MatchResult &Result) {
const auto &Nodes = Result.Nodes;
bool CheckExecuted = false;
CheckExecuted |= handleDeletion(Nodes);
CheckExecuted |= handleLegacyConsumers(Nodes);
CheckExecuted |= handleExpectedOwner(Nodes);
CheckExecuted |= handleAssignmentAndInit(Nodes);
CheckExecuted |= handleAssignmentFromNewOwner(Nodes);
CheckExecuted |= handleReturnValues(Nodes);
CheckExecuted |= handleOwnerMembers(Nodes);
assert(CheckExecuted &&
"None of the subroutines executed, logic error in matcher!");
}
bool OwningMemoryCheck::handleDeletion(const BoundNodes &Nodes) {
// Result of delete matchers.
const auto *DeleteStmt = Nodes.getNodeAs<CXXDeleteExpr>("delete_expr");
const auto *DeletedVariable =
Nodes.getNodeAs<DeclRefExpr>("deleted_variable");
// Deletion of non-owners, with `delete variable;`
if (DeleteStmt) {
diag(DeleteStmt->getLocStart(),
"deleting a pointer through a type that is "
"not marked 'gsl::owner<>'; consider using a "
"smart pointer instead")
<< DeletedVariable->getSourceRange();
// FIXME: The declaration of the variable that was deleted can be
// rewritten.
const ValueDecl *Decl = DeletedVariable->getDecl();
diag(Decl->getLocStart(), "variable declared here", DiagnosticIDs::Note)
<< Decl->getSourceRange();
return true;
}
return false;
}
bool OwningMemoryCheck::handleLegacyConsumers(const BoundNodes &Nodes) {
// Result of matching for legacy consumer-functions like `::free()`.
const auto *LegacyConsumer = Nodes.getNodeAs<CallExpr>("legacy_consumer");
// FIXME: `freopen` should be handled seperately because it takes the filename
// as a pointer, which should not be an owner. The argument that is an owner
// is known and the false positive coming from the filename can be avoided.
if (LegacyConsumer) {
diag(LegacyConsumer->getLocStart(),
"calling legacy resource function without passing a 'gsl::owner<>'")
<< LegacyConsumer->getSourceRange();
return true;
}
return false;
}
bool OwningMemoryCheck::handleExpectedOwner(const BoundNodes &Nodes) {
// Result of function call matchers.
const auto *ExpectedOwner = Nodes.getNodeAs<Expr>("expected_owner_argument");
// Expected function argument to be owner.
if (ExpectedOwner) {
diag(ExpectedOwner->getLocStart(),
"expected argument of type 'gsl::owner<>'; got %0")
<< ExpectedOwner->getType() << ExpectedOwner->getSourceRange();
return true;
}
return false;
}
/// Assignment and initialization of owner variables.
bool OwningMemoryCheck::handleAssignmentAndInit(const BoundNodes &Nodes) {
const auto *OwnerAssignment =
Nodes.getNodeAs<BinaryOperator>("owner_assignment");
const auto *OwnerInitialization =
Nodes.getNodeAs<VarDecl>("owner_initialization");
const auto *OwnerInitializer =
Nodes.getNodeAs<CXXCtorInitializer>("owner_member_initializer");
// Assignments to owners.
if (OwnerAssignment) {
diag(OwnerAssignment->getLocStart(),
"expected assignment source to be of type 'gsl::owner<>'; got %0")
<< OwnerAssignment->getRHS()->getType()
<< OwnerAssignment->getSourceRange();
return true;
}
// Initialization of owners.
if (OwnerInitialization) {
diag(OwnerInitialization->getLocStart(),
"expected initialization with value of type 'gsl::owner<>'; got %0")
<< OwnerInitialization->getAnyInitializer()->getType()
<< OwnerInitialization->getSourceRange();
return true;
}
// Initializer of class constructors that initialize owners.
if (OwnerInitializer) {
diag(OwnerInitializer->getSourceLocation(),
"expected initialization of owner member variable with value of type "
"'gsl::owner<>'; got %0")
// FIXME: the expression from getInit has type 'void', but the type
// of the supplied argument would be of interest.
<< OwnerInitializer->getInit()->getType()
<< OwnerInitializer->getSourceRange();
return true;
}
return false;
}
/// Problematic assignment and initializations, since the assigned value is a
/// newly created owner.
bool OwningMemoryCheck::handleAssignmentFromNewOwner(const BoundNodes &Nodes) {
const auto *BadOwnerAssignment =
Nodes.getNodeAs<BinaryOperator>("bad_owner_creation_assignment");
const auto *BadOwnerInitialization =
Nodes.getNodeAs<VarDecl>("bad_owner_creation_variable");
const auto *BadOwnerArgument =
Nodes.getNodeAs<Expr>("bad_owner_creation_argument");
const auto *BadOwnerParameter =
Nodes.getNodeAs<ParmVarDecl>("bad_owner_creation_parameter");
// Bad assignments to non-owners, where the RHS is a newly created owner.
if (BadOwnerAssignment) {
diag(BadOwnerAssignment->getLocStart(),
"assigning newly created 'gsl::owner<>' to non-owner %0")
<< BadOwnerAssignment->getLHS()->getType()
<< BadOwnerAssignment->getSourceRange();
return true;
}
// Bad initialization of non-owners, where the RHS is a newly created owner.
if (BadOwnerInitialization) {
diag(BadOwnerInitialization->getLocStart(),
"initializing non-owner %0 with a newly created 'gsl::owner<>'")
<< BadOwnerInitialization->getType()
<< BadOwnerInitialization->getSourceRange();
// FIXME: FixitHint to rewrite the type of the initialized variable
// as 'gsl::owner<OriginalType>'
// If the type of the variable was deduced, the wrapping owner typedef is
// eliminated, therefore the check emits a special note for that case.
if (Nodes.getNodeAs<AutoType>("deduced_type")) {
diag(BadOwnerInitialization->getLocStart(),
"type deduction did not result in an owner", DiagnosticIDs::Note);
}
return true;
}
// Function call, where one arguments is a newly created owner, but the
// parameter type is not.
if (BadOwnerArgument) {
assert(BadOwnerParameter &&
"parameter for the problematic argument not found");
diag(BadOwnerArgument->getLocStart(), "initializing non-owner argument of "
"type %0 with a newly created "
"'gsl::owner<>'")
<< BadOwnerParameter->getType() << BadOwnerArgument->getSourceRange();
return true;
}
return false;
}
bool OwningMemoryCheck::handleReturnValues(const BoundNodes &Nodes) {
// Function return statements, that are owners/resources, but the function
// declaration does not declare its return value as owner.
const auto *BadReturnType = Nodes.getNodeAs<ReturnStmt>("bad_owner_return");
const auto *Function = Nodes.getNodeAs<FunctionDecl>("function_decl");
// Function return values, that should be owners but aren't.
if (BadReturnType) {
// The returned value is a resource or variable that was not annotated with
// owner<> and the function return type is not owner<>.
diag(BadReturnType->getLocStart(),
"returning a newly created resource of "
"type %0 or 'gsl::owner<>' from a "
"function whose return type is not 'gsl::owner<>'")
<< Function->getReturnType() << BadReturnType->getSourceRange();
// FIXME: Rewrite the return type as 'gsl::owner<OriginalType>'
return true;
}
return false;
}
bool OwningMemoryCheck::handleOwnerMembers(const BoundNodes &Nodes) {
// Classes, that have owners as member, but do not declare destructors
// accordingly.
const auto *BadClass = Nodes.getNodeAs<CXXRecordDecl>("non_destructor_class");
// Classes, that contains owners, but do not declare destructors.
if (BadClass) {
const auto *DeclaredOwnerMember =
Nodes.getNodeAs<FieldDecl>("undestructed_owner_member");
assert(DeclaredOwnerMember &&
"match on class with bad destructor but without a declared owner");
diag(DeclaredOwnerMember->getLocStart(),
"member variable of type 'gsl::owner<>' requires the class %0 to "
"implement a destructor to release the owned resource")
<< BadClass;
return true;
}
return false;
}
} // namespace cppcoreguidelines
} // namespace tidy
} // namespace clang

View File

@@ -1,63 +0,0 @@
//===--- OwningMemoryCheck.h - clang-tidy------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_OWNING_MEMORY_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_OWNING_MEMORY_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace cppcoreguidelines {
/// Checks for common use cases for gsl::owner and enforces the unique owner
/// nature of it whenever possible.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-owning-memory.html
class OwningMemoryCheck : public ClangTidyCheck {
public:
OwningMemoryCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
LegacyResourceProducers(Options.get(
"LegacyResourceProducers", "::malloc;::aligned_alloc;::realloc;"
"::calloc;::fopen;::freopen;::tmpfile")),
LegacyResourceConsumers(Options.get(
"LegacyResourceConsumers", "::free;::realloc;::freopen;::fclose")) {
}
/// Make configuration of checker discoverable.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
bool handleDeletion(const ast_matchers::BoundNodes &Nodes);
bool handleLegacyConsumers(const ast_matchers::BoundNodes &Nodes);
bool handleExpectedOwner(const ast_matchers::BoundNodes &Nodes);
bool handleAssignmentAndInit(const ast_matchers::BoundNodes &Nodes);
bool handleAssignmentFromNewOwner(const ast_matchers::BoundNodes &Nodes);
bool handleReturnValues(const ast_matchers::BoundNodes &Nodes);
bool handleOwnerMembers(const ast_matchers::BoundNodes &Nodes);
/// List of old C-style functions that create resources.
/// Defaults to
/// `::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile`.
const std::string LegacyResourceProducers;
/// List of old C-style functions that consume or release resources.
/// Defaults to `::free;::realloc;::freopen;::fclose`.
const std::string LegacyResourceConsumers;
};
} // namespace cppcoreguidelines
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_OWNING_MEMORY_H

View File

@@ -23,7 +23,7 @@ ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")),
IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
Options.getLocalOrGlobal("IncludeStyle", "llvm"))) {}
Options.get("IncludeStyle", "llvm"))) {}
void ProBoundsConstantArrayIndexCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {

View File

@@ -32,16 +32,22 @@ AST_MATCHER(CXXRecordDecl, hasDefaultConstructor) {
}
// Iterate over all the fields in a record type, both direct and indirect (e.g.
// if the record contains an anonmyous struct).
// if the record contains an anonmyous struct). If OneFieldPerUnion is true and
// the record type (or indirect field) is a union, forEachField will stop after
// the first field.
template <typename T, typename Func>
void forEachField(const RecordDecl &Record, const T &Fields, Func &&Fn) {
void forEachField(const RecordDecl &Record, const T &Fields,
bool OneFieldPerUnion, Func &&Fn) {
for (const FieldDecl *F : Fields) {
if (F->isAnonymousStructOrUnion()) {
if (const CXXRecordDecl *R = F->getType()->getAsCXXRecordDecl())
forEachField(*R, R->fields(), Fn);
forEachField(*R, R->fields(), OneFieldPerUnion, Fn);
} else {
Fn(F);
}
if (OneFieldPerUnion && Record.isUnion())
break;
}
}
@@ -119,12 +125,12 @@ struct IntializerInsertion {
SourceLocation Location;
switch (Placement) {
case InitializerPlacement::New:
Location = utils::lexer::getPreviousToken(
Location = utils::lexer::getPreviousNonCommentToken(
Context, Constructor.getBody()->getLocStart())
.getLocation();
break;
case InitializerPlacement::Before:
Location = utils::lexer::getPreviousToken(
Location = utils::lexer::getPreviousNonCommentToken(
Context, Where->getSourceRange().getBegin())
.getLocation();
break;
@@ -221,7 +227,7 @@ void getInitializationsInOrder(const CXXRecordDecl &ClassDecl,
Decls.emplace_back(Decl);
}
}
forEachField(ClassDecl, ClassDecl.fields(),
forEachField(ClassDecl, ClassDecl.fields(), false,
[&](const FieldDecl *F) { Decls.push_back(F); });
}
@@ -347,7 +353,7 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer(
// Gather all fields (direct and indirect) that need to be initialized.
SmallPtrSet<const FieldDecl *, 16> FieldsToInit;
forEachField(ClassDecl, ClassDecl.fields(), [&](const FieldDecl *F) {
forEachField(ClassDecl, ClassDecl.fields(), false, [&](const FieldDecl *F) {
if (!F->hasInClassInitializer() &&
utils::type_traits::isTriviallyDefaultConstructible(F->getType(),
Context) &&
@@ -373,12 +379,12 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer(
// Collect all fields in order, both direct fields and indirect fields from
// anonmyous record types.
SmallVector<const FieldDecl *, 16> OrderedFields;
forEachField(ClassDecl, ClassDecl.fields(),
forEachField(ClassDecl, ClassDecl.fields(), false,
[&](const FieldDecl *F) { OrderedFields.push_back(F); });
// Collect all the fields we need to initialize, including indirect fields.
SmallPtrSet<const FieldDecl *, 16> AllFieldsToInit;
forEachField(ClassDecl, FieldsToInit,
forEachField(ClassDecl, FieldsToInit, false,
[&](const FieldDecl *F) { AllFieldsToInit.insert(F); });
if (AllFieldsToInit.empty())
return;
@@ -398,16 +404,11 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer(
// Collect all fields but only suggest a fix for the first member of unions,
// as initializing more than one union member is an error.
SmallPtrSet<const FieldDecl *, 16> FieldsToFix;
SmallPtrSet<const RecordDecl *, 4> UnionsSeen;
forEachField(ClassDecl, OrderedFields, [&](const FieldDecl *F) {
if (!FieldsToInit.count(F))
return;
forEachField(ClassDecl, FieldsToInit, true, [&](const FieldDecl *F) {
// Don't suggest fixes for enums because we don't know a good default.
// Don't suggest fixes for bitfields because in-class initialization is not
// possible.
if (F->getType()->isEnumeralType() || F->isBitField())
return;
if (!F->getParent()->isUnion() || UnionsSeen.insert(F->getParent()).second)
if (!F->getType()->isEnumeralType() && !F->isBitField())
FieldsToFix.insert(F);
});
if (FieldsToFix.empty())
@@ -448,9 +449,6 @@ void ProTypeMemberInitCheck::checkMissingBaseClassInitializer(
// Remove any bases that were explicitly written in the initializer list.
if (Ctor) {
if (Ctor->isImplicit())
return;
for (const CXXCtorInitializer *Init : Ctor->inits()) {
if (Init->isBaseInitializer() && Init->isWritten())
BasesToInit.erase(Init->getBaseClass()->getAsCXXRecordDecl());

Some files were not shown because too many files have changed in this diff Show More