Compare commits

...

262 Commits

Author SHA1 Message Date
Tom Stellard
8d2c8a6d22 Merging r230694:
------------------------------------------------------------------------
r230694 | chaoren | 2015-02-26 14:15:16 -0800 (Thu, 26 Feb 2015) | 16 lines

Fix Bug 20400

Summary:
http://llvm.org/bugs/show_bug.cgi?id=20400

The default triple of i686-pc-linux-gnu for 32 bit linux targets is compatible
but not necessarily identical to the inferior binaries.

Applying Azat Khuzhin's solution of using ArchSpec::IsCompatibleMatch() instead
of ArchSpec::IsExactMatch() when comparing ObjectFile and Modules architecture.

Reviewers: vharron

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D7897
------------------------------------------------------------------------

llvm-svn: 232574
2015-03-18 00:37:37 +00:00
Tom Stellard
e0cba6fbc2 Merging r214336:
------------------------------------------------------------------------
r214336 | rafael.espindola | 2014-07-30 17:04:00 -0400 (Wed, 30 Jul 2014) | 9 lines

SimplifyCFG: Avoid miscompilations due to removed lifetime intrinsics.

The lifetime intrinsics need some work in order to make it clear which
optimizations are or are not valid.

For now dropping this optimization avoids a miscompilation.

Patch by Björn Steinbrink.

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

llvm-svn: 232544
2015-03-17 20:42:08 +00:00
Tom Stellard
a3a80c717d Merging r229352:
------------------------------------------------------------------------
r229352 | david.majnemer | 2015-02-15 23:02:09 -0500 (Sun, 15 Feb 2015) | 9 lines

IR: Properly return nullptr when getAggregateElement is out-of-bounds

We didn't properly handle the out-of-bounds case for
ConstantAggregateZero and UndefValue.  This would manifest as a crash
when the constant folder was asked to fold a load of a constant global
whose struct type has no operands.

This fixes PR22595.

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

llvm-svn: 232512
2015-03-17 18:09:58 +00:00
Daniel Sanders
4dbd3c9853 Added MIPS changes to release notes for 3.5.2.
llvm-svn: 232369
2015-03-16 10:40:59 +00:00
Daniel Sanders
b9f83dd2e7 Try to make AsmPrinter vtable compatible with previous shared library.
r232083 added AsmPrinter::emitInlineAsmStart() before
AsmPrinter::emitInlineAsmEnd(), changing the vtable in an incompatible way.
This patch swaps the declaration order so that the new vtable entry is at the
end of the vtable.

llvm-svn: 232162
2015-03-13 11:54:32 +00:00
Daniel Sanders
4351822ac5 Merging r225521:
------------------------------------------------------------------------
r225521 | tomatabacu | 2015-01-09 15:00:30 +0000 (Fri, 09 Jan 2015) | 1 line

[mips] Add comment which explains why we need to change the assembler options before and after inline asm blocks. NFC.
------------------------------------------------------------------------

llvm-svn: 232084
2015-03-12 19:21:16 +00:00
Daniel Sanders
60d1be210d Merging r224425:
------------------------------------------------------------------------
r224425 | tomatabacu | 2014-12-17 10:56:16 +0000 (Wed, 17 Dec 2014) | 17 lines

[mips] Set GCC-compatible MIPS asssembler options before inline asm blocks.

Summary:
When generating MIPS assembly, LLVM always overrides the default assembler options by emitting the '.set noreorder', '.set nomacro' and '.set noat' directives,
while GCC uses the default options if an assembly-level function contains inline assembly code.

This becomes a problem when the code generated by LLVM is interleaved with inline assembly which assumes GCC-like assembler options (from Linux, for example).

This patch fixes these conflicts by setting the appropriate assembler options at the beginning of an inline asm block and popping them at the end.

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6637
------------------------------------------------------------------------

llvm-svn: 232083
2015-03-12 19:17:32 +00:00
Daniel Sanders
af61ee821b Merging r217432:
------------------------------------------------------------------------
r217432 | tomatabacu | 2014-09-09 11:15:38 +0100 (Tue, 09 Sep 2014) | 12 lines

[mips] Add assembler support for .set push/pop directive.

Summary:
These directives are used to save the current assembler options (in the case of ".set push") and restore the previously saved options (in the case of ".set pop").

Contains work done by Matheus Almeida.

Reviewers: dsanders

Reviewed By: dsanders

Differential Revision: http://reviews.llvm.org/D4821
------------------------------------------------------------------------

llvm-svn: 232082
2015-03-12 19:12:54 +00:00
Daniel Sanders
fedffd766d Merging r217254:
------------------------------------------------------------------------
r217254 | tomatabacu | 2014-09-05 16:43:21 +0100 (Fri, 05 Sep 2014) | 9 lines

[mips] Rename data members and member functions in MipsAssemblerOptions.

Summary: Use the naming convention from the LLVM Coding Standards.

Reviewers: dsanders

Reviewed By: dsanders

Differential Revision: http://reviews.llvm.org/D4972
------------------------------------------------------------------------

llvm-svn: 232054
2015-03-12 16:23:09 +00:00
Daniel Sanders
101b70d6d1 Merging r230235:
------------------------------------------------------------------------
r230235 | dsanders | 2015-02-23 17:22:16 +0000 (Mon, 23 Feb 2015) | 16 lines

[mips] Honour -mno-odd-spreg for vector insert/extract when MSA is enabled.

Summary:
-mno-odd-spreg prohibits the use of odd-numbered single-precision floating
point registers. However, vector insert/extract was still using them when
manipulating the subregisters of an MSA register. Fixed this by ensuring
that insertion/extraction is only performed on even-numbered vector
registers when -mno-odd-spreg is given.

Reviewers: vmedic, sstankovic

Reviewed By: sstankovic

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D7672
------------------------------------------------------------------------

llvm-svn: 231472
2015-03-06 13:24:18 +00:00
Daniel Sanders
77105d9817 Merging r227089:
------------------------------------------------------------------------
r227089 | vkalintiris | 2015-01-26 12:33:22 +0000 (Mon, 26 Jan 2015) | 15 lines

[mips] Enable arithmetic and binary operations for the i128 data type.

Summary:
This patch adds support for some operations that were missing from
128-bit integer types (add/sub/mul/sdiv/udiv... etc.). With these
changes we can support the __int128_t and __uint128_t data types
from C/C++.

Depends on D7125

Reviewers: dsanders

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D7143
------------------------------------------------------------------------

llvm-svn: 231471
2015-03-06 13:19:44 +00:00
Daniel Sanders
2a764cb0b8 Merging r227087:
Except for the MIPS-II and MIPS-III cases since these targets were not
supported in 3.5.1.
------------------------------------------------------------------------
r227087 | vkalintiris | 2015-01-26 12:04:40 +0000 (Mon, 26 Jan 2015) | 7 lines

[mips] Add tests for bitwise binary and integer arithmetic operators.

Reviewers: dsanders

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D7125
------------------------------------------------------------------------

llvm-svn: 231469
2015-03-06 13:09:25 +00:00
Daniel Sanders
a35f06ccc7 Partially merging r221686:
Only the testcase minus the MIPS-II and MIPS-IV cases have been merged.
They are required to cleanly apply a subsequent patch.
------------------------------------------------------------------------
r221686 | vkalintiris | 2014-11-11 11:43:55 +0000 (Tue, 11 Nov 2014) | 16 lines

[mips] Add preliminary support for the MIPS II target.

Summary:
This patch enables code generation for the MIPS II target. Pre-Mips32
targets don't have the MUL instruction, so we add the correspondent
pattern that uses the MULT/MFLO combination in order to retrieve the
product.

This is WIP as we don't support code generation for select nodes due to
the lack of conditional-move instructions.

Reviewers: dsanders

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6150
------------------------------------------------------------------------

llvm-svn: 231468
2015-03-06 12:51:21 +00:00
Daniel Sanders
ecdc943a5a Merging r226171:
------------------------------------------------------------------------
r226171 | dsanders | 2015-01-15 15:41:03 +0000 (Thu, 15 Jan 2015) | 11 lines

[mips] Fix a typo in the compare patterns for MIPS32r6/MIPS64r6.

Summary: The patterns intended for the SETLE node were actually matching the SETLT node.

Reviewers: atanasyan, sstankovic, vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6997
------------------------------------------------------------------------

llvm-svn: 231467
2015-03-06 12:38:41 +00:00
Daniel Sanders
c0ab938bba Merging r225529:
------------------------------------------------------------------------
r225529 | dsanders | 2015-01-09 17:21:30 +0000 (Fri, 09 Jan 2015) | 18 lines

[mips] Add support for accessing $gp as a named register.

Summary:
Mips Linux uses $gp to hold a pointer to thread info structure and accesses it
with a named register. This makes this work for LLVM.

The N32 ABI doesn't quite work yet since the frontend generates incorrect IR
for this case. It neglects to truncate the 64-bit GPR to a 32-bit value before
converting to a pointer. Given correct IR (as in the testcase in this patch),
it works correctly.

Reviewers: sstankovic, vmedic, atanasyan

Reviewed By: atanasyan

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6893
------------------------------------------------------------------------

llvm-svn: 231466
2015-03-06 12:34:10 +00:00
Daniel Sanders
81155380be Revert r231463 and r231462.
The build fails after merging them due to two missing functions.

llvm-svn: 231464
2015-03-06 11:47:54 +00:00
Daniel Sanders
8f20452cf2 Merging r225521:
------------------------------------------------------------------------
r225521 | tomatabacu | 2015-01-09 15:00:30 +0000 (Fri, 09 Jan 2015) | 1 line

[mips] Add comment which explains why we need to change the assembler options before and after inline asm blocks. NFC.
------------------------------------------------------------------------

llvm-svn: 231463
2015-03-06 11:40:28 +00:00
Daniel Sanders
84bc83fd78 Merging r224425:
------------------------------------------------------------------------
r224425 | tomatabacu | 2014-12-17 10:56:16 +0000 (Wed, 17 Dec 2014) | 17 lines

[mips] Set GCC-compatible MIPS asssembler options before inline asm blocks.

Summary:
When generating MIPS assembly, LLVM always overrides the default assembler options by emitting the '.set noreorder', '.set nomacro' and '.set noat' directives,
while GCC uses the default options if an assembly-level function contains inline assembly code.

This becomes a problem when the code generated by LLVM is interleaved with inline assembly which assumes GCC-like assembler options (from Linux, for example).

This patch fixes these conflicts by setting the appropriate assembler options at the beginning of an inline asm block and popping them at the end.

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6637
------------------------------------------------------------------------

llvm-svn: 231462
2015-03-06 11:39:52 +00:00
Tom Stellard
ea32d3a23d Bump version to 3.5.2
llvm-svn: 225916
2015-01-14 01:21:39 +00:00
David Majnemer
385d0dd52d Merging r222856:
------------------------------------------------------------------------
r222856 | majnemer | 2014-11-26 15:00:38 -0800 (Wed, 26 Nov 2014) | 8 lines

Revert "Added inst combine transforms for single bit tests from Chris's note"

This reverts commit r210006, it miscompiled libapr which is used in who
knows how many projects.

A test has been added to ensure that we don't regress again.

I'll work on a rewrite of what the optimization was trying to do later.
------------------------------------------------------------------------

llvm-svn: 225255
2015-01-06 08:51:50 +00:00
Tom Stellard
6ad55e925a Creating a 3.5 branch, which is compatible with LLVM 3.5
This branch will probably not be mantained.  Its purpose is to mark
the last commit that is compatible with LLVM 3.5.

llvm-svn: 225040
2014-12-31 14:56:56 +00:00
Daniel Sanders
30a0597a0d Merging r224333:
------------------------------------------------------------------------
r224333 | dsanders | 2014-12-16 11:21:58 +0000 (Tue, 16 Dec 2014) | 3 lines

[mips] Fix arguments-struct.ll for Windows and OSX hosts.


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

llvm-svn: 224510
2014-12-18 10:43:48 +00:00
Hans Wennborg
f2f09fb329 Merging r220117:
------------------------------------------------------------------------
r220117 | rsmith | 2014-10-17 17:56:31 -0700 (Fri, 17 Oct 2014) | 6 lines

Hardcode the list of ELF targets here rather than using a glob.

The code was making non-portable assumptions about the exact string returned by
the glob (possibly by the shell?); this is more robust and matches what is done
everywhere else.

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

llvm-svn: 224364
2014-12-16 20:39:02 +00:00
Hal Finkel
e354bf82ba Fixup backport of r223318
TM.getSubtargetImpl()->getRegisterInfo() needs to be TM.getRegisterInfo() in 3.5.

llvm-svn: 223749
2014-12-09 02:43:05 +00:00
Hal Finkel
651925a496 Merging r223708:
------------------------------------------------------------------------
r223708 | hfinkel | 2014-12-08 22:54:22 +0000 (Mon, 08 Dec 2014) | 13 lines

[PowerPC] Don't use a non-allocatable register to implement the 'cc' alias

GCC accepts 'cc' as an alias for 'cr0', and we need to do the same when
processing inline asm constraints. This had previously been implemented using a
non-allocatable register, named 'cc', that was listed as an alias of 'cr0', but
the infrastructure does not seem to support this properly (neither the register
allocator nor the scheduler properly accounts for the alias). Instead, we can
just process this as a naming alias inside of the inline asm
constraint-processing code, so we'll do that instead.

There are two regression tests, one where the post-RA scheduler did the wrong
thing with the non-allocatable alias, and one where the register allocator did
the wrong thing. Fixes PR21742.
------------------------------------------------------------------------

llvm-svn: 223748
2014-12-09 02:37:53 +00:00
Hal Finkel
628944dbd8 Merging r223328:
------------------------------------------------------------------------
r223328 | hfinkel | 2014-12-04 00:46:20 +0000 (Thu, 04 Dec 2014) | 8 lines

[PowerPC] 'cc' should be an alias only to 'cr0'

We had mistakenly believed that GCC's 'cc' referred to the entire
condition-code register (cr0 through cr7) -- and implemented this in r205630 to
fix PR19326, but 'cc' is actually an alias only to 'cr0'. This is causing LLVM
to clobber too much with legacy code with inline asm using the 'cc' clobber.

Fixes PR21451.
------------------------------------------------------------------------

llvm-svn: 223747
2014-12-09 02:37:11 +00:00
Hal Finkel
4e4e391da8 Merging r223318:
------------------------------------------------------------------------
r223318 | hfinkel | 2014-12-03 23:40:13 +0000 (Wed, 03 Dec 2014) | 12 lines

[PowerPC] Fix inline asm memory operands not to use r0

On PowerPC, inline asm memory operands might be expanded as 0($r), where $r is
a register containing the address. As a result, this register cannot be r0, and
we need to enforce this register subclass constraint to prevent miscompiling
the code (we'd get this constraint for free with the usual instruction
definitions, but that scheme has no knowledge of how we end up printing inline
asm memory operands, and so here we need to do it 'by hand'). We can accomplish
this within the current address-mode selection framework by introducing an
explicit COPY_TO_REGCLASS node.

Fixes PR21443.
------------------------------------------------------------------------

llvm-svn: 223746
2014-12-09 02:36:22 +00:00
Hal Finkel
b6574c9047 Merging r223220:
------------------------------------------------------------------------
r223220 | hfinkel | 2014-12-03 09:37:50 +0000 (Wed, 03 Dec 2014) | 23 lines

[PowerPC] Print all inline-asm consts as signed numbers

Almost all immediates in PowerPC assembly (both 32-bit and 64-bit) are signed
numbers, and it is important that we print them as such. To make sure that
happens, we change PPCTargetLowering::LowerAsmOperandForConstraint so that it
does all intermediate checks on a signed-extended int64_t value, and then
creates the resulting target constant using MVT::i64. This will ensure that all
negative values are printed as negative values (mirroring what is done in other
backends to achieve the same sign-extension effect).

This came up in the context of inline assembly like this:
  "add%I2   %0,%0,%2", ..., "Ir"(-1ll)
where we used to print:
  addi   3,3,4294967295
and gcc would print:
  addi   3,3,-1
and gas accepts both forms, but our builtin assembler (correctly) does not. Now
we print -1 like gcc does.

While here, I replaced a bunch of custom integer checks with isInt<16> and
friends from MathExtras.h.

Thanks to Paul Hargrove for the bug report.
------------------------------------------------------------------------

llvm-svn: 223745
2014-12-09 02:35:44 +00:00
Hal Finkel
be4dc0e165 Merging r222996:
------------------------------------------------------------------------
r222996 | foad | 2014-12-01 09:42:32 +0000 (Mon, 01 Dec 2014) | 19 lines

[PowerPC] Fix unwind info with dynamic stack realignment

Summary:
PowerPC DWARF unwind info defined CFA as SP + offset even in a function
where the stack had been dynamically realigned. This clearly doesn't
work because the offset from SP to CFA is not a constant. Fix it by
defining CFA as BP instead.

This was causing the AddressSanitizer null_deref test to fail 50% of
the time, depending on whether SP happened to be 32-byte aligned on
entry to a particular function or not.

Reviewers: willschm, uweigand, hfinkel

Reviewed By: hfinkel

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6410
------------------------------------------------------------------------

llvm-svn: 223744
2014-12-09 02:33:41 +00:00
Hal Finkel
6a9d7718ed Merging r222672:
------------------------------------------------------------------------
r222672 | uweigand | 2014-11-24 18:09:47 +0000 (Mon, 24 Nov 2014) | 10 lines

[PowerPC] Fix PR 21652 - copy st_other bits on symbol assignment

When processing an assignment in the integrated assembler that sets
a symbol to the value of another symbol, we need to copy the st_other
bits that encode the local entry point offset.

Modeled after MipsTargetELFStreamer::emitAssignment handling of the
ELF::STO_MIPS_MICROMIPS flag.


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

llvm-svn: 223743
2014-12-09 02:30:53 +00:00
Hal Finkel
fa81086df9 Merging r221703:
------------------------------------------------------------------------
r221703 | wschmidt | 2014-11-11 20:44:09 +0000 (Tue, 11 Nov 2014) | 48 lines

[PowerPC] Replace foul hackery with real calls to __tls_get_addr

My original support for the general dynamic and local dynamic TLS
models contained some fairly obtuse hacks to generate calls to
__tls_get_addr when lowering a TargetGlobalAddress.  Rather than
generating real calls, special GET_TLS_ADDR nodes were used to wrap
the calls and only reveal them at assembly time.  I attempted to
provide correct parameter and return values by chaining CopyToReg and
CopyFromReg nodes onto the GET_TLS_ADDR nodes, but this was also not
fully correct.  Problems were seen with two back-to-back stores to TLS
variables, where the call sequences ended up overlapping with unhappy
results.  Additionally, since these weren't real calls, the proper
register side effects of a call were not recorded, so clobbered values
were kept live across the calls.

The proper thing to do is to lower these into calls in the first
place.  This is relatively straightforward; see the changes to
PPCTargetLowering::LowerGlobalTLSAddress() in PPCISelLowering.cpp.
The changes here are standard call lowering, except that we need to
track the fact that these calls will require a relocation.  This is
done by adding a machine operand flag of MO_TLSLD or MO_TLSGD to the
TargetGlobalAddress operand that appears earlier in the sequence.

The calls to LowerCallTo() eventually find their way to
LowerCall_64SVR4() or LowerCall_32SVR4(), which call FinishCall(),
which calls PrepareCall().  In PrepareCall(), we detect the calls to
__tls_get_addr and immediately snag the TargetGlobalTLSAddress with
the annotated relocation information.  This becomes an extra operand
on the call following the callee, which is expected for nodes of type
tlscall.  We change the call opcode to CALL_TLS for this case.  Back
in FinishCall(), we change it again to CALL_NOP_TLS for 64-bit only,
since we require a TOC-restore nop following the call for the 64-bit
ABIs.

During selection, patterns in PPCInstrInfo.td and PPCInstr64Bit.td
convert the CALL_TLS nodes into BL_TLS nodes, and convert the
CALL_NOP_TLS nodes into BL8_NOP_TLS nodes.  This replaces the code
removed from PPCAsmPrinter.cpp, as the BL_TLS or BL8_NOP_TLS
nodes can now be emitted normally using their patterns and the
associated printTLSCall print method.

Finally, as a result of these changes, all references to get-tls-addr
in its various guises are no longer used, so they have been removed.

There are existing TLS tests to verify the changes haven't messed
anything up).  I've added one new test that verifies that the problem
with the original code has been fixed.

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

llvm-svn: 223742
2014-12-09 02:28:44 +00:00
Hal Finkel
6c5819e34b Merging rr220959:
------------------------------------------------------------------------
r220959 | uweigand | 2014-10-31 10:33:14 +0000 (Fri, 31 Oct 2014) | 13 lines

[PowerPC] Load BlockAddress values from the TOC in 64-bit SVR4 code

Since block address values can be larger than 2GB in 64-bit code, they
cannot be loaded simply using an @l / @ha pair, but instead must be
loaded from the TOC, just like GlobalAddress, ConstantPool, and
JumpTable values are.

The commit also fixes a bug in PPCLinuxAsmPrinter::doFinalization where
temporary labels could not be used as TOC values, since code would
attempt (and fail) to use GetOrCreateSymbol to create a symbol of the
same name as the temporary label.


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

llvm-svn: 223741
2014-12-09 02:26:40 +00:00
Hal Finkel
07f06bbd97 Merging r219441:
------------------------------------------------------------------------
r219441 | sfantao | 2014-10-09 20:42:56 +0000 (Thu, 09 Oct 2014) | 3 lines

Fix bug in GPR to FPR moves in PPC64LE.

The current implementation of GPR->FPR register moves uses a stack slot. This mechanism writes a double word and reads a word. In big-endian the load address must be displaced by 4-bytes in order to get the right value. In little endian this is no longer required. This patch fixes the issue and adds LE regression tests to fast-isel-conversion which currently expose this problem.
------------------------------------------------------------------------

llvm-svn: 223740
2014-12-09 02:23:59 +00:00
Hal Finkel
9b24c0ffae Merging r217993:
------------------------------------------------------------------------
r217993 | sfantao | 2014-09-17 23:25:06 +0000 (Wed, 17 Sep 2014) | 5 lines

Fix FastISel bug in boolean returns for PowerPC.

For PPC targets, FastISel does not take the sign extension information into account when selecting return instructions whose operands are constants. A consequence of this is that the return of boolean values is not correct. This patch fixes the problem by evaluating the sign extension information also for constants, forwarding this information to PPCMaterializeInt which takes this information to drive the sign extension during the materialization. 


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

llvm-svn: 223739
2014-12-09 02:21:12 +00:00
Hal Finkel
9abeb69615 Merging r216917:
------------------------------------------------------------------------
r216917 | samsonov | 2014-09-02 17:38:34 +0000 (Tue, 02 Sep 2014) | 4 lines

Fix signed integer overflow in PPCInstPrinter.

This bug was reported by UBSan.

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

llvm-svn: 223738
2014-12-09 02:18:38 +00:00
Hal Finkel
39ba7e0552 Merging r214517:
------------------------------------------------------------------------
r214517 | uweigand | 2014-08-01 14:35:58 +0000 (Fri, 01 Aug 2014) | 8 lines

[PowerPC] PR20280 - Slots for byval parameters are not immutable

Found by inspection while looking at PR20280: code would mark slots
in the parameter save area where a byval parameter is passed as
"immutable".  This is not correct since code is allowed to modify
byval parameters in place in the parameter save area.


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

llvm-svn: 223736
2014-12-09 02:09:06 +00:00
Hal Finkel
d31f4c6106 Merging r215793:
------------------------------------------------------------------------
r215793 | hfinkel | 2014-08-16 00:16:29 +0000 (Sat, 16 Aug 2014) | 9 lines

[PowerPC] Darwin byval arguments are not immutable

On PPC/Darwin, byval arguments occur at fixed stack offsets in the callee's
frame, but are not immutable -- the pointer value is directly available to the
higher-level code as the address of the argument, and the value of the byval
argument can be modified at the IR level.

This is necessary, but not sufficient, to fix PR20280. When PR20280 is fixed in
a follow-up commit, its test case will cover this change.
------------------------------------------------------------------------

llvm-svn: 223735
2014-12-09 01:56:18 +00:00
Hal Finkel
ea9e182ade Merging r213960:
------------------------------------------------------------------------
r213960 | hfinkel | 2014-07-25 17:47:22 +0000 (Fri, 25 Jul 2014) | 3 lines

[PowerPC] Support TLS on PPC32/ELF

Patch by Justin Hibbits!
------------------------------------------------------------------------

llvm-svn: 223734
2014-12-09 01:53:54 +00:00
Tom Stellard
dffdec69e1 Merging r221832:
------------------------------------------------------------------------
r221832 | richard-llvm | 2014-11-12 18:38:38 -0500 (Wed, 12 Nov 2014) | 5 lines

PR19372: Keep checking template arguments after we see an argument pack
expansion into a parameter pack; we know that we're still filling in that
parameter's arguments. Previously, if we hit this case for an alias template,
we'd try to substitute using non-canonical template arguments.

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

llvm-svn: 223719
2014-12-08 23:38:47 +00:00
Tom Stellard
f03c72a577 Merging r221748:
------------------------------------------------------------------------
r221748 | richard-llvm | 2014-11-11 20:43:45 -0500 (Tue, 11 Nov 2014) | 4 lines

PR21536: Fix a corner case where we'd get confused by a pack expanding into the
penultimate parameter of a template parameter list, where the last parameter is
itself a pack, and build a bogus empty final pack argument.

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

llvm-svn: 223718
2014-12-08 23:38:45 +00:00
Duncan P. N. Exon Smith
28be27a04e Merging r223500 (this time for real):
------------------------------------------------------------------------
r223500 | dexonsmith | 2014-12-05 11:13:42 -0800 (Fri, 05 Dec 2014) | 9 lines

BFI: Saturate when combining edges to a successor

When a loop gets bundled up, its outgoing edges are quite large, and can
just barely overflow 64-bits.  If one successor has multiple incoming
edges -- and that successor is getting all the incoming mass --
combining just its edges can overflow.  Handle that by saturating rather
than asserting.

This fixes PR21622.
------------------------------------------------------------------------

llvm-svn: 223716
2014-12-08 23:29:14 +00:00
Duncan P. N. Exon Smith
92215b0dd0 Reverting r223712; apparently I don't understand SVN
llvm-svn: 223713
2014-12-08 23:22:11 +00:00
Duncan P. N. Exon Smith
9ef730ae0a Merging r223500:
------------------------------------------------------------------------
r223500 | dexonsmith | 2014-12-05 11:13:42 -0800 (Fri, 05 Dec 2014) | 9 lines

BFI: Saturate when combining edges to a successor

When a loop gets bundled up, its outgoing edges are quite large, and can
just barely overflow 64-bits.  If one successor has multiple incoming
edges -- and that successor is getting all the incoming mass --
combining just its edges can overflow.  Handle that by saturating rather
than asserting.

This fixes PR21622.
------------------------------------------------------------------------

llvm-svn: 223712
2014-12-08 23:18:00 +00:00
David Majnemer
2d9a3bee4c Merging r217104:
------------------------------------------------------------------------
r217104 | majnemer | 2014-09-03 16:20:58 -0700 (Wed, 03 Sep 2014) | 1 line

Adjust test to handle fallout from r217102.
------------------------------------------------------------------------

llvm-svn: 223703
2014-12-08 22:26:56 +00:00
David Majnemer
ef1c6718fd Merging r221318:
------------------------------------------------------------------------
r221318 | majnemer | 2014-11-04 15:49:08 -0800 (Tue, 04 Nov 2014) | 10 lines

Analysis: Make isSafeToSpeculativelyExecute fire less for divides

Divides and remainder operations do not behave like other operations
when they are given poison: they turn into undefined behavior.

It's really hard to know if the operands going into a div are or are not
poison.  Because of this, we should only choose to speculate if there
are constant operands which we can easily reason about.

This fixes PR21412.
------------------------------------------------------------------------

llvm-svn: 223647
2014-12-08 09:16:46 +00:00
David Majnemer
b20996e713 I did not intend to merge these in.
llvm-svn: 223646
2014-12-08 09:15:41 +00:00
David Majnemer
e228322c1c Merging r215818:
------------------------------------------------------------------------
r215818 | majnemer | 2014-08-16 02:23:42 -0700 (Sat, 16 Aug 2014) | 12 lines

InstCombine: Fix a potential bug in 0 - (X sdiv C)  -> (X sdiv -C)

While *most* (X sdiv 1) operations will get caught by InstSimplify, it
is still possible for a sdiv to appear in the worklist which hasn't been
simplified yet.

This means that it is possible for 0 - (X sdiv 1) to get transformed
into (X sdiv -1); dividing by -1 can make the transform produce undef
values instead of the proper result.

Sorry for the lack of testcase, it's a bit problematic because it relies
on the exact order of operations in the worklist.
------------------------------------------------------------------------

llvm-svn: 223645
2014-12-08 09:11:48 +00:00
David Majnemer
4c9e37fcc4 Merging r214385:
------------------------------------------------------------------------
r214385 | majnemer | 2014-07-30 21:49:29 -0700 (Wed, 30 Jul 2014) | 9 lines

InstCombine: Correctly propagate NSW/NUW for x-(-A) -> x+A

We can only propagate the nsw bits if both subtraction instructions are
marked with the appropriate bit.

N.B.  We only propagate the nsw bit in InstCombine because the nuw case
is already handled in InstSimplify.

This fixes PR20189.
------------------------------------------------------------------------

llvm-svn: 223644
2014-12-08 09:11:36 +00:00
David Majnemer
9ed146d6a8 Fix merge conflict & minor test output differences
llvm-svn: 223643
2014-12-08 09:10:57 +00:00
David Majnemer
7a61678035 Merging r222500:
------------------------------------------------------------------------
r222500 | majnemer | 2014-11-20 18:37:38 -0800 (Thu, 20 Nov 2014) | 1 line

This Reassociate change unintentionally slipped in r222499
------------------------------------------------------------------------

llvm-svn: 223640
2014-12-08 08:54:39 +00:00
David Majnemer
64e66b01b2 Merging r216891:
------------------------------------------------------------------------
r216891 | majnemer | 2014-09-01 14:20:14 -0700 (Mon, 01 Sep 2014) | 12 lines

SROA: Don't insert instructions before a PHI

SROA may decide that it needs to insert a bitcast and would set it's
insertion point before a PHI.  This will create an invalid module
right quick.

Instead, choose the first insertion point in the basic block that holds
our PHI.

This fixes PR20822.

Differential Revision: http://reviews.llvm.org/D5141
------------------------------------------------------------------------

llvm-svn: 223639
2014-12-08 08:53:47 +00:00
David Majnemer
6e3c56e785 Merging r217115:
------------------------------------------------------------------------
r217115 | majnemer | 2014-09-03 17:23:13 -0700 (Wed, 03 Sep 2014) | 3 lines

IndVarSimplify: Address review comments for r217102

No functional change intended, just some cleanups and comments added.
------------------------------------------------------------------------

llvm-svn: 223638
2014-12-08 08:50:39 +00:00
David Majnemer
37c07a6294 Merging rr217102:
------------------------------------------------------------------------
r217102 | majnemer | 2014-09-03 16:03:18 -0700 (Wed, 03 Sep 2014) | 11 lines

IndVarSimplify: Don't let LFTR compare against a poison value

LinearFunctionTestReplace tries to use the *next* indvar to compare
against when possible.  However, it may be the case that the calculation
for the next indvar has NUW/NSW flags and that it may only be safely
used inside the loop.  Using it in a comparison to calculate the exit
condition could result in observing poison.

This fixes PR20680.

Differential Revision: http://reviews.llvm.org/D5174
------------------------------------------------------------------------

llvm-svn: 223637
2014-12-08 08:50:22 +00:00
David Majnemer
085abb5d1d Merging rr221501:
------------------------------------------------------------------------
r221501 | majnemer | 2014-11-06 16:31:14 -0800 (Thu, 06 Nov 2014) | 7 lines

LoopVectorize: Don't assume pointees are sized

A pointer's pointee might not be sized: the pointee could be a function.

Report this as IK_NoInduction when calculating isInductionVariable.

This fixes PR21508.
------------------------------------------------------------------------

llvm-svn: 223636
2014-12-08 08:49:20 +00:00
David Majnemer
92f45d1333 Merging rr222376:
------------------------------------------------------------------------
r222376 | majnemer | 2014-11-19 11:36:18 -0800 (Wed, 19 Nov 2014) | 3 lines

AliasSet: Simplify mergeSetIn

No functional change intended.
------------------------------------------------------------------------

llvm-svn: 223635
2014-12-08 08:48:58 +00:00
David Majnemer
7e841d753b Merging r222338:
------------------------------------------------------------------------
r222338 | majnemer | 2014-11-19 01:41:05 -0800 (Wed, 19 Nov 2014) | 16 lines

AliasSetTracker: UnknownInsts should contribute to the refcount

AliasSetTracker::addUnknown may create an AliasSet devoid of pointers
just to contain an instruction if no suitable AliasSet already exists.
It will then AliasSet::addUnknownInst and we will be done.

However, it's possible for addUnknown to choose an existing AliasSet to
addUnknownInst.
If this were to occur, we are in a bit of a pickle: removing pointers
from the AliasSet can cause the entire AliasSet to become destroyed,
taking our unknown instructions out with them.

Instead, keep track whether or not our AliasSet has any unknown
instructions.

This fixes PR21582.
------------------------------------------------------------------------

llvm-svn: 223627
2014-12-08 08:48:09 +00:00
Daniel Sanders
18bc2ed14a Merging r215169:
------------------------------------------------------------------------
r215169 | ghoflehner | 2014-08-08 00:19:55 +0100 (Fri, 08 Aug 2014) | 2 lines

Fix for multi-line comment warning

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

llvm-svn: 223582
2014-12-06 10:34:51 +00:00
Daniel Sanders
93e02253d6 Merging r220360:
------------------------------------------------------------------------
r220360 | filcab | 2014-10-22 03:16:06 +0100 (Wed, 22 Oct 2014) | 5 lines

Silence gcc's -Wcomment

gcc's (4.7, I think) -Wcomment warning is not "as smart" as clang's and
warns even if the line right after the backslash-newline sequence only has
a line comment that starts at the beginning of the line.
------------------------------------------------------------------------

llvm-svn: 223581
2014-12-06 10:34:24 +00:00
Michael Zolotukhin
973b3c6f29 Merging r223171:
PR21302. Vectorize only bottom-tested loops.

rdar://problem/18886083

llvm-svn: 223535
2014-12-05 22:31:29 +00:00
Michael Zolotukhin
1d2a9aa20d Merging r223170:
Apply loop-rotate to several vectorizer tests.

Such loops shouldn't be vectorized due to the loops form.
After applying loop-rotate (+simplifycfg) the tests again start to check
what they are intended to check.

llvm-svn: 223534
2014-12-05 22:29:16 +00:00
Michael Zolotukhin
f0625368ba Merging r221009:
Correctly update dom-tree after loop vectorizer.

llvm-svn: 223531
2014-12-05 22:17:26 +00:00
Daniel Sanders
50c62001ca Add the big-endian O32 small structures bugfix to the Mips release notes.
llvm-svn: 223459
2014-12-05 11:06:13 +00:00
Daniel Sanders
e4301bee75 Merging r223148:
------------------------------------------------------------------------
r223148 | dsanders | 2014-12-02 20:40:27 +0000 (Tue, 02 Dec 2014) | 17 lines

[mips] Fix passing of small structures for big-endian O32.

Summary:
Like N32/N64, they must be passed in the upper bits of the register.

The new code could be merged with the existing if-statements but I've
refrained from doing this since it will make porting the O32 implementation
to tablegen harder later.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

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

llvm-svn: 223457
2014-12-05 10:20:37 +00:00
Tim Northover
8cdf2c90f0 Merging r223055:
ARM: lower tail calls correctly when using GHC calling convention.

Patch by Ben Gamari.

llvm-svn: 223406
2014-12-04 22:59:55 +00:00
Duncan P. N. Exon Smith
b29f5b907f Merging r223163:
------------------------------------------------------------------------
r223163 | cmatthews | 2014-12-02 14:19:21 -0800 (Tue, 02 Dec 2014) | 5 lines

Give lit a --xunit-xml-output option for saving results in xunit format
  
  --xunit-xml-output saves test results to disk in JUnit's xml format. This will allow Jenkins to report the details of a lit run.
  
  Based on a patch by David Chisnall.
------------------------------------------------------------------------

llvm-svn: 223250
2014-12-03 18:17:15 +00:00
Daniel Sanders
8f588dd56e Moved [ASZ]ExtUpper to the end of the CCValAssign::LocInfo enum.
This makes the 3.5.1 version of libLLVM-3.5.so compatible with the 3.5.0 version.

llvm-svn: 223242
2014-12-03 17:21:26 +00:00
Daniel Sanders
4be2d4c3af Added release notes for the Mips target.
llvm-svn: 223231
2014-12-03 13:43:39 +00:00
Daniel Sanders
f10332cab5 Merged from r221604:
[mips] Fix sret arguments for N32/N64 which were accidentally broken in r221534.

llvm-svn: 223070
2014-12-01 19:38:20 +00:00
Daniel Sanders
bb8359ff25 Merged from r221534:
[mips] Promote i32 arguments to i64 for the N32/N64 ABI and fix <64-bit structs...

Summary:
... and after all that refactoring, it's possible to distinguish softfloat
floating point values from integers so this patch no longer breaks softfloat to
do it.

Remove direct handling of i32's in the N32/N64 ABI by promoting them to
i64. This more closely reflects the ABI documentation and also fixes
problems with stack arguments on big-endian targets.

We now rely on signext/zeroext annotations (already generated by clang) and
the Assert[SZ]ext nodes to avoid the introduction of unnecessary sign/zero
extends.

It was not possible to convert three tests to use signext/zeroext. These tests
are bswap.ll, ctlz-v.ll, ctlz-v.ll. It's not possible to put signext on a
vector type so we just accept the sign extends here for now. These tests don't
pass the vectors the same way clang does (clang puts multiple elements in the
same argument, these map 1 element to 1 argument) so we don't need to worry too
much about it.

With this patch, all known N32/N64 bugs should be fixed and we now pass the
first 10,000 tests generated by ABITestGen.py.

Subscribers: llvm-commits

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

llvm-svn: 223069
2014-12-01 19:33:33 +00:00
Daniel Sanders
d8ce57ff2f Merged from r221529:
[mips] Removed the remainder of MipsCC. NFC.

Summary:
One of the calls to AllocateStack (the one in LowerCall) doesn't look like
it should be there but it was there before and removing it breaks the
frame size calculation.

Reviewers: vmedic, theraven

Reviewed By: theraven

Subscribers: llvm-commits

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

llvm-svn: 223065
2014-12-01 19:02:59 +00:00
Daniel Sanders
7585cbd858 Merged from r221528:
[mips] Remove MipsCC::reservedArgArea() in favour of MipsABIInfo::GetCalleeAllocdArgSizeInBytes(). NFC.

Summary:

Reviewers: theraven, vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223063
2014-12-01 18:57:45 +00:00
Daniel Sanders
8340bdc9d2 Merged from r221527:
MipsCCState.h: Use LLVM_DELETED_FUNCTION for msc17.

llvm-svn: 223062
2014-12-01 18:52:41 +00:00
Daniel Sanders
e6401e289e Merged from r221525:
[mips] Move MipsCCState to a separate file and clang-formatted it.

Summary:

Reviewers: theraven, vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223061
2014-12-01 18:48:22 +00:00
Daniel Sanders
75d716d345 Merged from r221522:
[mips] Fix unused variable warnings introduced in r221521

llvm-svn: 223058
2014-12-01 18:43:35 +00:00
Daniel Sanders
df22cb2bc3 Merged from r221521:
[mips] Remove remaining use of MipsCC::intArgRegs() in favour of MipsABIInfo::GetByValArgRegs() and MipsABIInfo::GetVarArgRegs()

Summary:

Reviewers: theraven, vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223053
2014-12-01 17:14:37 +00:00
Daniel Sanders
40ddbe66df Merged from r221519:
[mips] Remove MipsCC::getRegVT(). NFC

Summary: It's no longer used.

Reviewers: vmedic, theraven

Reviewed By: theraven

Subscribers: llvm-commits

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

llvm-svn: 223052
2014-12-01 17:12:32 +00:00
Daniel Sanders
901f3d19d8 Merged from r221518:
[mips] Remove MipsCC::analyzeCallOperands in favour of CCState::AnalyzeCallOperands. NFC

Summary:
In addition to the usual f128 workaround, it was also necessary to provide
a means of accessing ArgListEntry::IsFixed.

Reviewers: theraven, vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223048
2014-12-01 17:05:38 +00:00
Daniel Sanders
e4565b26dc Merged from r221517:
[mips] Move SpecialCallingConv to MipsCCState and use it from tablegen-erated code. NFC

Summary:
In the long run, it should probably become a calling convention in its own
right but for now just move it out of
MipsISelLowering::analyzeCallOperands() so that we can drop this function
in favour of CCState::AnalyzeCallOperands().

Subscribers: llvm-commits

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

llvm-svn: 223047
2014-12-01 17:02:26 +00:00
Daniel Sanders
30d2ca75b2 Merged from r221516:
[mips] Removed IsVarArg from MipsISelLowering::analyzeCallOperands(). NFC.

Summary:
CCState objects already carry this information in their isVarArg() method.

Subscribers: llvm-commits

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

llvm-svn: 223045
2014-12-01 16:35:35 +00:00
Daniel Sanders
84a7df7eaf Merged from r221463:
[mips] Removed IsSoftFloat from MipsISelLowering::analyzeCallOperands(). NFC

Summary:
It isn't used anymore.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223044
2014-12-01 16:33:17 +00:00
Daniel Sanders
2234ce5751 Merged from r221461:
[mips] Removed MipsISelLowering::analyzeFormalArguments() in favour of CCState::AnalyzeFormalArguments()

Summary:
As with returns, we must be able to identify f128 arguments despite them
being lowered away. We do this with a pre-analyze step that builds a
vector and then we use this vector from the tablegen-erated code.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223042
2014-12-01 16:32:03 +00:00
Daniel Sanders
88c94367bf Merged from r221146:
[mips] Remove unused prototype and variable. NFC.

llvm-svn: 223041
2014-12-01 16:30:07 +00:00
Daniel Sanders
81624a1b81 Merged from r221081 and r221102:
-------------------------------------------------------------------------------
Revert r221056 and others, "[mips] Move F128 argument handling into MipsCCState as we did for returns. NFC."

  r221056 "[mips] Move F128 argument handling into MipsCCState as we did for returns. NFC."
  r221058 "[mips] Fix unused variable warning introduced in r221056"
  r221059 "[mips] Move all ByVal handling into CCState and tablegen-erated code. NFC."
  r221061 "Renamed CCState members that appear to misspell 'Processed' as 'Proceed'. NFC."

It caused an undefined behavior in LLVM :: CodeGen/Mips/return-vector.ll.

-------------------------------------------------------------------------------
Re-commit r221056 and others with fix, "[mips] Move F128 argument handling into MipsCCState as we did for returns. NFC."

sret arguments can never originate from an f128 argument so we detect
sret arguments and push false into OriginalArgWasF128.

llvm-svn: 223040
2014-12-01 16:26:48 +00:00
Daniel Sanders
55bcb7bea7 Merged from r221061:
Renamed CCState members that appear to misspell
 'Processed' as 'Proceed'. NFC.

Reviewers: rnk

Reviewed By: rnk

Subscribers: rnk, llvm-commits

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

llvm-svn: 223039
2014-12-01 16:05:07 +00:00
Daniel Sanders
6b412de086 Merged from r221059:
[mips] Move all ByVal handling into CCState and tablegen-erated code. NFC.

Summary:
CCState already contains a byval implementation that is very similar to the
Mips custom code. This patch merges the custom code into the existing
common code and tablegen-erated code.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: rnk, llvm-commits

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

llvm-svn: 223037
2014-12-01 15:50:46 +00:00
Daniel Sanders
5cf014d867 Merged from r221058:
[mips] Fix unused variable warning introduced in r221056

llvm-svn: 223036
2014-12-01 15:37:28 +00:00
Daniel Sanders
9d2aa79b33 Merged from r221057:
[mips] Remove ByValArgInfo::Address in favour of CCValAssign::getMemLocOffset(). NFC.

Summary: ByValArgInfo is practically the same as CCState::ByValInfo now.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223035
2014-12-01 15:28:54 +00:00
Daniel Sanders
0dae6cdb69 Merged from r221056:
[mips] Move F128 argument handling into MipsCCState as we did for returns. NFC.

Summary:
There are a couple more changes to make before analyzeFormalArguments can
be merged into the standard AnalyzeFormalArguments. I've had to temporarily
poke a couple holes in MipsCCState's encapsulation to save having to make
all the required changes for this merge all at once*. These will be removed
shortly.

* We must merge our ByVal argument handling with the implementation in CCState.
  This will be done over the next three patches, then the fourth will merge
  analyzeFormalArguments with AnalyzeFormalArguments.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223034
2014-12-01 15:24:14 +00:00
Daniel Sanders
6d4022f7f6 Merged from r221054:
[mips] Remove MipsCC::CCInfo. NFC.

Summary:
It's now passed in as an argument to functions that need it. Eventually
this argument will be replaced by the 'this' pointer for a MipsCCState
object.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223033
2014-12-01 15:15:59 +00:00
Daniel Sanders
372b086a97 Merged from r221053:
[mips] Removed MipsCC::fixedArgFn(). NFC

Summary:
There is one remaining trace of it in MipsCC::analyzeCallOperands() where
Mips16 might override the calling convention. This will moved into
tablegen-erated code later.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223032
2014-12-01 15:14:34 +00:00
Daniel Sanders
1486635524 [tablegen] Add CustomCallingConv and use it to tablegen-erate the outermost parts of the Mips O32 implementation
Summary:
CustomCallingConv is simply a CallingConv that tablegen should not generate the
implementation for. It allows regular CallingConv's to delegate to these custom
functions. This is (currently) necessary for Mips and we cannot use CCCustom
without having to adapt to the different API that CCCustom uses.

This brings us a bit closer to being able to remove
MipsCC::analyzeCallOperands and MipsCC::analyzeFormalArguments in favour of
the common implementation.

No functional change to the targets.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: vmedic, llvm-commits

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

llvm-svn: 223031
2014-12-01 15:13:16 +00:00
Daniel Sanders
728f55c9ac Added file that should have been in r223022.
I forgot to 'svn add' it.

llvm-svn: 223030
2014-12-01 15:10:11 +00:00
Daniel Sanders
5ef6392a23 Add file that should have been in r223027
llvm-svn: 223028
2014-12-01 14:43:25 +00:00
Daniel Sanders
de7b942bde Merged from r220568:
[mips] Replace MipsABIEnum with a MipsABIInfo class.

Summary:
No functional change yet, it's just an object replacement for an enum.
It will allow us to gather ABI information in a single place so that we can
start testing for properties of the ABI's instead of the ABI itself.

For example we will eventually be able to use:
  ABI.MinStackAlignmentInBytes()
instead of:
  (isABI_N32() || isABI_N64()) ? 16 : 8
which is clearer and more maintainable.

Reviewers: matheusalmeida

Reviewed By: matheusalmeida

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

llvm-svn: 223027
2014-12-01 14:30:22 +00:00
Daniel Sanders
639afbbbf9 Merged from r220564:
[mips] Fix >80-column line

llvm-svn: 223026
2014-12-01 14:28:19 +00:00
Daniel Sanders
7ed3d6575a Merged from r220561:
[mips] Remove redundant code in RetCC_MipsN. NFC.

Summary:
i32 is always promoted to i64 so it no longer makes sense to assign i32 to
registers.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223025
2014-12-01 14:26:43 +00:00
Daniel Sanders
685924c788 Merged from r220556:
[mips] For N32/N64, structs must be passed in the upper bits of a register.

Summary:
Most structs were fixed by r218451 but those of between >32-bits and
<64-bits remained broken since they were not marked with [ASZ]ExtUpper.
This patch fixes the remaining cases by using
CCPromoteToUpperBitsInType<i64> on i64's in addition to i32 and smaller.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223024
2014-12-01 14:17:47 +00:00
Daniel Sanders
b2d7415042 Merged from r219931:
[mips] Account for endianess when expanding BuildPairF64/ExtractElementF64 nodes.

Summary:
In order to support big endian targets for the BuildPairF64 nodes we
just need to swap the low/high pair registers. Additionally, for the
ExtractElementF64 nodes we have to calculate the correct stack offset
with respect to the node's register/operand that we want to extract.

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: llvm-commits

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

llvm-svn: 223023
2014-12-01 14:16:14 +00:00
Daniel Sanders
08c8744ae8 Merged from r219196:
[mips] Return {f128} correctly for N32/N64.

Summary:
According to the ABI documentation, f128 and {f128} should both be returned
in $f0 and $f2. However, this doesn't match GCC's behaviour which is to
return f128 in $f0 and $f2, but {f128} in $f0 and $f1.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223022
2014-12-01 14:15:05 +00:00
Daniel Sanders
f5bcfc4fc2 Merging r218452:
------------------------------------------------------------------------
r218452 | dsanders | 2014-09-25 14:08:51 +0100 (Thu, 25 Sep 2014) | 3 lines

Add llvm_unreachables() for [ASZ]ExtUpper to X86FastISel.cpp to appease the buildbots.


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

llvm-svn: 223021
2014-12-01 14:10:48 +00:00
Daniel Sanders
d2d30b50c1 Merged from r218510:
Fix unused variable warning added in r218509

llvm-svn: 223020
2014-12-01 13:58:19 +00:00
Daniel Sanders
d51f07da55 Merged from r218509:
[mips] Generalize the handling of f128 return values to support f128 arguments.

Summary:
This will allow us to handle f128 arguments without duplicating code from
CCState::AnalyzeFormalArguments() or CCState::AnalyzeCallOperands().

No functional change.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223019
2014-12-01 13:55:59 +00:00
Daniel Sanders
08d315f5c5 Merged from r218451:
[mips] Add CCValAssign::[ASZ]ExtUpper and CCPromoteToUpperBitsInType and handle struct's correctly on big-endian N32/N64 return values.

Summary:
The N32/N64 ABI's require that structs passed in registers are laid out
such that spilling the register with 'sd' places the struct at the lowest
address. For little endian this is trivial but for big-endian it requires
that structs are shifted into the upper bits of the register.

We also require that structs passed in registers have the 'inreg'
attribute for big-endian N32/N64 to work correctly. This is because the
tablegen-erated calling convention implementation only has access to the
lowered form of struct arguments (one or more integers of up to 64-bits
each) and is unable to determine the original type.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223018
2014-12-01 13:46:55 +00:00
Daniel Sanders
e9f61a123a Merged from r218036:
[mips] Remove custom versions of CCState::AnalyzeReturn() and CCState::AnalyzeCallReturn().

Summary:
The N32/N64 ABI's return f128 values in $f0 and $f2 for hard-float and $v0 and
$a0 for soft-float. The registers used in the soft-float case differ from the
usual $v0, and $v1 specified for return values.

Both cases were previously handled by duplicating the CCState::AnalyzeReturn()
and CCState::AnalyzeCallReturn() functions and modifying them to delegate to
a different assignment function for f128 and further replace the register type
for the hard-float case. There is a simpler way to do both of these.

We now use the common functions and select an initial assignment function based
on whether the original type is f128 or not. We then handle the hard-float case
using CCBitConvertToType<>.

No functional change.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223017
2014-12-01 13:34:51 +00:00
Daniel Sanders
f6bf66347d Merged from r217494:
[mips] Remove inverted predicates from MipsSubtarget that were only used by MipsCallingConv.td

Summary: No functional change

Reviewers: echristo, vmedic

Reviewed By: echristo, vmedic

Subscribers: echristo, llvm-commits

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

llvm-svn: 223016
2014-12-01 13:25:44 +00:00
Daniel Sanders
2646c1259d Merged from r217485:
[mips] Return an ArrayRef from MipsCC::intArgRegs() and remove MipsCC::numIntArgRegs()

Summary: No functional change.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223015
2014-12-01 13:18:25 +00:00
Daniel Sanders
cc13b7042d Merged from r217436:
[mips] Move MipsTargetLowering::MipsCC::regSize() to MipsSubtarget::getGPRSizeInBytes()

Summary:
The GPR size is more a property of the subtarget than that of the ABI so move
this information to the MipsSubtarget.

No functional change.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223014
2014-12-01 13:17:00 +00:00
Daniel Sanders
64f980a01b Merged from r217434:
[mips] Don't cache IsO32 and IsFP64 in MipsTargetLowering::MipsCC

Summary:
Use a MipsSubtarget reference instead.

No functional change.

Reviewers: vmedic

Reviewed By: vmedic

Subscribers: llvm-commits

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

llvm-svn: 223013
2014-12-01 13:15:04 +00:00
Daniel Sanders
3f173e827a Merged from r215640:
[mips] Improve robustness of some tests.

Summary:
This is done by removing some hardcoded registers like $at or expecting a single digit register to be selected.

Contains work done by Matheus Almeida.

Reviewers: matheusalmeida, dsanders

Reviewed By: dsanders

Subscribers: tomatabacu

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

llvm-svn: 223012
2014-12-01 11:43:13 +00:00
Daniel Sanders
7863d07ace Merged from r215211:
[mips] Invert the abicalls feature bit to be noabicalls so that it's possible for -mno-abicalls to take effect.

Also added the testcase that should have been in r215194.

This behaviour has surprised me a few times now. The problem is that the
generated MipsSubtarget::ParseSubtargetFeatures() contains code like this:

   if ((Bits & Mips::FeatureABICalls) != 0) IsABICalls = true;

so '-abicalls' means 'leave it at the default' and '+abicalls' means 'set it to
true'. In this case, (and the similar -modd-spreg case) I'd like the code to be

  IsABICalls = (Bits & Mips::FeatureABICalls) != 0;

or possibly:

   if ((Bits & Mips::FeatureABICalls) != 0)
     IsABICalls = true;
   else
     IsABICalls = false;

and preferably arrange for 'Bits & Mips::FeatureABICalls' to be true by default
(on some triples).

llvm-svn: 223011
2014-12-01 11:38:38 +00:00
Daniel Sanders
24b3307b8a Merged from r215194:
[mips] Initial implementation of -mabicalls/-mno-abicalls.

This patch implements the main rules for -mno-abicalls such as reserving $gp,
and emitting the correct .option directive.

Patch by Matheus Almeida and Toma Tabacu

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

llvm-svn: 223009
2014-12-01 11:32:07 +00:00
Daniel Sanders
b16d386b54 Merged from r214578:
llvm/test/CodeGen/Mips/cconv/arguments-varargs.ll: Add explicit -mtriple=(mips|mipsel)-linux on 4 lines.

llvm-svn: 223008
2014-12-01 11:23:40 +00:00
Daniel Sanders
4feb6fe3a3 Merged from r214493:
[mips][PR19612] Fix va_arg for big-endian mode.

Summary:
Big-endian mode was not correctly adjusting the offset for types smaller
than an ABI slot.

Fixes PR19612

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: sstankovic, llvm-commits

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

llvm-svn: 223007
2014-12-01 11:22:34 +00:00
Daniel Sanders
2c03fbfd18 Merged from r222339*:
Please note that there is a significant change to the test compared to r222339.
This is because this branch generates different code compared to the trunk.
The code on this branch appears to be equivalent so the test has been updated
accordingly.
-------------------------------------------------------------------------------
Allow EmitVAArg() to promote types and use this to fix some N32/N64 vararg issues for Mips.

Summary:
With this patch, passing a va_list to another function and reading 10 int's from
it works correctly on a big-endian target.

Based on a pair of patches by David Chisnall, one of which I've reworked
for the current trunk.

Reviewers: theraven, atanasyan

Reviewed By: theraven, atanasyan

Subscribers: cfe-commits

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

llvm-svn: 223005
2014-12-01 10:45:46 +00:00
Daniel Sanders
a33f8c9ee0 Merged from r220566:
[mips] Mark aggregate arguments passed in registers with the inreg attribute

Summary:
This allows us to easily identify them in the backend which in turn allows us
to handle them correctly for big-endian targets (where they must be shifted
into the upper bits of the register).

Depends on D5961

Reviewers: atanasyan

Reviewed By: atanasyan

Subscribers: cfe-commits, theraven

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

llvm-svn: 223004
2014-12-01 10:32:00 +00:00
Daniel Sanders
2a46c56ee9 Merged from r220563:
[mips] Promote all integral/enumeration types to the GPR width

Summary:
Ensure all integral/enumeration types are appropriately annotated with
signext/zeroext. In particular, i32 now has these attributes when using the
N32/N64 ABI. This paves the way for accurately representing the way the
N32/N64 ABI's promotes integer arguments to i64.

Reviewers: atanasyan

Reviewed By: atanasyan

Subscribers: cfe-commits, theraven

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

llvm-svn: 223003
2014-12-01 10:26:16 +00:00
Daniel Sanders
492e5db50e Merged from r218298:
[mips] Fix r218248's testcase to use -O1 instead of -O3.

llvm-svn: 223002
2014-12-01 10:18:49 +00:00
Daniel Sanders
a90d20129d Merged from r218260:
Fix test/CodeGen/mips-varargs.c to use %clang_cc1

Only tests under test/Driver should use %clang, and test/CodeGen in
particular must always use %clang_cc1.

llvm-svn: 223001
2014-12-01 10:17:46 +00:00
Daniel Sanders
6c9c1dcd65 Merged from r218256:
clang/test/CodeGen/mips-varargs.c: Fixup for -Asserts.

llvm-svn: 223000
2014-12-01 10:16:19 +00:00
Daniel Sanders
6f9000213b Merged from r218248:
[mips] Correct alignment of vectors passed in varargs for the O32 ABI.

Summary:
Vectors are normally 16-byte aligned, however the O32 ABI enforces a
maximum alignment of 8-bytes since the base of the stack is 8-byte aligned.
Previously, this was enforced on the caller side, but not on the callee side.

This fixes the output of OpenCL's printf when given vectors.

Reviewers: atanasyan

Reviewed By: atanasyan

Subscribers: llvm-commits, pekka.jaaskelainen

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

llvm-svn: 222999
2014-12-01 10:14:30 +00:00
Daniel Sanders
4ce9a1a5f5 Merging r217160:
[mips] Mark aggregates returned in registers with the 'inreg' attribute.

Summary:
This allows us to easily find them in the backend after the aggregates have
been lowered to other types. This is important on big-endian targets using
the N32/N64 ABI's since these ABI's must shift small structures into the
upper bits of the register.

Reviewers: atanasyan

Reviewed By: atanasyan

Subscribers: llvm-commits

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

llvm-svn: 222998
2014-12-01 10:07:55 +00:00
Daniel Sanders
942a2456ac Merging r217257:
------------------------------------------------------------------------
r217257 | tomatabacu | 2014-09-05 17:32:09 +0100 (Fri, 05 Sep 2014) | 9 lines

[mips] Change Feature-related types from unsigned to uint64_t in MipsAsmParser. No functional changes.

Summary: Found a couple of cases where unsigned was still being used. These two should be the last ones in the (entire) Mips backend.

Reviewers: dsanders

Reviewed By: dsanders

Differential Revision: http://reviews.llvm.org/D5028
------------------------------------------------------------------------

llvm-svn: 222875
2014-11-27 10:55:46 +00:00
Daniel Sanders
3449325506 Merging r213769:
------------------------------------------------------------------------
r213769 | askrobov | 2014-07-23 18:09:26 +0100 (Wed, 23 Jul 2014) | 6 lines

Fix test/Driver/cl-x86-flags.c by providing explicit --target

This isn't very neat, but we haven't found any better ways to
make this test work with non-X86 default target.


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

llvm-svn: 222815
2014-11-26 10:16:56 +00:00
Daniel Sanders
2bace4c6ed Merging r218745:
------------------------------------------------------------------------
r218745 | dsanders | 2014-10-01 09:26:55 +0100 (Wed, 01 Oct 2014) | 7 lines

[mips] Fix disassembly of [ls][wd]c[23], cache, and pref                          
                                                                                  
Fixes PR21015, and PR20993.                                                       
                                                                                  
Patch by Jun Koi


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

llvm-svn: 222696
2014-11-24 21:47:34 +00:00
Daniel Sanders
55b9030c31 Merging r216262:
------------------------------------------------------------------------
r216262 | sstankovic | 2014-08-22 10:23:22 +0100 (Fri, 22 Aug 2014) | 5 lines

[mips] Don't use odd-numbered float registers for double arguments for fastcc
calling convention if FP is 64-bit and +nooddspreg is used.

Differential Revision: http://reviews.llvm.org/D4981.diff

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

llvm-svn: 222695
2014-11-24 21:47:07 +00:00
Daniel Sanders
0cb1d7aac0 Merging r221453:
------------------------------------------------------------------------
r221453 | tomatabacu | 2014-11-06 14:25:42 +0000 (Thu, 06 Nov 2014) | 17 lines

[mips] Tolerate the use of the %z inline asm operand modifier with non-immediates.

Summary:
Currently, we give an error if %z is used with non-immediates, instead of continuing as if the %z isn't there.

For example, you use the %z operand modifier along with the "Jr" constraints ("r" makes the operand a register, and "J" makes it an immediate, but only if its value is 0). 
In this case, you want the compiler to print "$0" if the inline asm input operand turns out to be an immediate zero and you want it to print the register containing the operand, if it's not.

We give an error in the latter case, and we shouldn't (GCC also doesn't).

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6023
------------------------------------------------------------------------

llvm-svn: 222693
2014-11-24 21:42:40 +00:00
Daniel Sanders
3915840558 Merging r221408:
------------------------------------------------------------------------
r221408 | petarj | 2014-11-05 22:42:31 +0000 (Wed, 05 Nov 2014) | 9 lines

[mips64] Fix MIPS64 exception personality encoding

Remove dynamic relocations of __gxx_personality_v0 from the .eh_frame.
The MIPS64 follow-up of the MIPS32 fix (rL209907).

Patch by Vladimir Stefanovic.

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

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

llvm-svn: 222692
2014-11-24 21:37:42 +00:00
Daniel Sanders
e222c9e1a4 Merging r216920:
------------------------------------------------------------------------
r216920 | samsonov | 2014-09-02 18:49:16 +0100 (Tue, 02 Sep 2014) | 4 lines

Fix left shifts of negative values in MipsDisassembler.

This bug was reported by UBSan.

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

llvm-svn: 222691
2014-11-24 21:37:18 +00:00
Daniel Sanders
a5166ef900 Merging r217147:
------------------------------------------------------------------------
r217147 | dsanders | 2014-09-04 14:28:14 +0100 (Thu, 04 Sep 2014) | 18 lines

[mips] Zero-sized structs cannot be ignored in MipsABIInfo::classifyReturnType() for O32

Summary:
They are returned indirectly which causes the other arguments to move to
the next argument slot.

With this, utils/ABITest does not discover any failing cases in the first
500 attempts on big/little endian for O32. Previously some of these failed.
Also tested N32/N64 little endian (big endian has other known issues) with
no issues.

Reviewers: atanasyan

Reviewed By: atanasyan

Subscribers: atanasyan, cfe-commits

Differential Revision: http://reviews.llvm.org/D4811
------------------------------------------------------------------------

llvm-svn: 222690
2014-11-24 21:30:06 +00:00
Daniel Sanders
98def3001e Merging r214662:
------------------------------------------------------------------------
r214662 | atanasyan | 2014-08-03 17:11:05 +0100 (Sun, 03 Aug 2014) | 2 lines

[Mips] Add the `mips64-linux-gnu` target to the test case to check `in128`
type handling.
------------------------------------------------------------------------

llvm-svn: 222689
2014-11-24 21:24:31 +00:00
Daniel Sanders
1c81157a21 Merging r214025:
------------------------------------------------------------------------
r214025 | atanasyan | 2014-07-26 10:52:21 +0100 (Sat, 26 Jul 2014) | 4 lines

[Driver][Mips] Check output of -dynamic-linker arguments by the Clang driver
for a couple of MIPS toolchains.

No functional changes.
------------------------------------------------------------------------

llvm-svn: 222686
2014-11-24 21:18:01 +00:00
Tom Stellard
322fcb0c9b Merging r220148:
------------------------------------------------------------------------
r220148 | me | 2014-10-18 19:36:12 -0400 (Sat, 18 Oct 2014) | 6 lines

New round of fixes for "Always compile debuginfo-tests for the host triple"

clang tests were breaking, at least when compiling clang only, from an
installed llvm. Make the lit.cfg script deal with the case when we don't
have a host_triple available.

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

llvm-svn: 221618
2014-11-10 18:19:09 +00:00
Tom Stellard
aacbb87535 Merging r220112:
------------------------------------------------------------------------
r220112 | me | 2014-10-17 19:50:47 -0400 (Fri, 17 Oct 2014) | 2 lines

Fix makefile for debuginfo-tests execution.

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

llvm-svn: 221617
2014-11-10 18:19:08 +00:00
Tom Stellard
06d5a61a5d Merging r219989:
------------------------------------------------------------------------
r219989 | me | 2014-10-16 19:41:40 -0400 (Thu, 16 Oct 2014) | 2 lines

Added %itanium_abi_host_triple to fix debuginfo-tests when clang is a cross-compiler by default

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

llvm-svn: 221616
2014-11-10 18:19:05 +00:00
Tom Stellard
971e92b417 Merging r220401:
------------------------------------------------------------------------
r220401 | mail | 2014-10-22 14:18:54 -0400 (Wed, 22 Oct 2014) | 6 lines

test: Make this test runnable in directories with @ in their names

Jenkins likes to use directories with names involving the '@'
character, which breaks the sed expression in this test. Switch to use
'|' on the assumption that it's less likely to show up in a path.

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

llvm-svn: 221390
2014-11-05 20:14:56 +00:00
Hans Wennborg
4b156f75c9 Merging r220874:
------------------------------------------------------------------------
r220874 | hans | 2014-10-29 14:20:57 -0700 (Wed, 29 Oct 2014) | 3 lines

Follow-up to r216619: use isCXXCLassMember() instead of trying to
check the context ourselves when selectively allowing late-added
dll attributes on unused free functions and variables (PR20746)
------------------------------------------------------------------------

llvm-svn: 221253
2014-11-04 09:47:45 +00:00
Tom Stellard
a49d21edfb Bump version to 3.5.1
llvm-svn: 220990
2014-10-31 19:33:25 +00:00
Hans Wennborg
2bf62cbd91 Merging r216619:
------------------------------------------------------------------------
r216619 | hans | 2014-08-27 14:27:40 -0700 (Wed, 27 Aug 2014) | 7 lines

Allow adding dll attributes on certain redecls with a warning if the decl hasn't been used yet (PR20746)

This shouldn't really be allowed, but it comes up in real code (see PR). As
long as the decl hasn't been used there's no technical difficulty in supporting
it, so downgrade the error to a warning.

Differential Revision: http://reviews.llvm.org/D5087
------------------------------------------------------------------------

llvm-svn: 218644
2014-09-29 23:33:05 +00:00
Dan Liew
484f12f661 Merging r217490:
------------------------------------------------------------------------
r217490 | delcypher | 2014-09-10 12:09:23 +0100 (Wed, 10 Sep 2014) | 4 lines

Don't attempt to run llvm-config in cmake/modules/Makefile when doing
``make clean`` because it won't be available.

This is an attempt to unbreak buildbots broken by r217484.
------------------------------------------------------------------------

llvm-svn: 217640
2014-09-11 23:00:09 +00:00
Dan Liew
f015491478 Merging r217484:
------------------------------------------------------------------------
r217484 | delcypher | 2014-09-10 11:18:59 +0100 (Wed, 10 Sep 2014) | 13 lines

Attempt to fix PR20884

This fixes the generation of broken LLVMExports.cmake file by
the Autoconf/Makefile build system when --enable-shared is passed to
configure.

When --enable_shared is passed the Makefile.rules does not set the
LLVMConfigLibs variable which cmake/modules/Makefile previously relied
on. Now it runs the llvm-config command itself to get the library names.

This still isn't perfect because the generated LLVM targets refer to the
static libraries and not the shared library but that is much larger
problem to fix.
------------------------------------------------------------------------

llvm-svn: 217638
2014-09-11 22:56:28 +00:00
Bill Wendling
fc44467537 Update PowerPC target information.
llvm-svn: 217304
2014-09-06 03:26:11 +00:00
Bill Wendling
c740b0f251 Update ReleaseNotes to remove empty sections.
llvm-svn: 217216
2014-09-05 01:16:32 +00:00
Bill Wendling
d355b771d6 Update docs.
llvm-svn: 216954
2014-09-02 21:29:19 +00:00
Bill Wendling
08cbe67bbf Update release notes.
llvm-svn: 216951
2014-09-02 21:22:28 +00:00
Bill Wendling
3b19a92b75 Update lang ref.
llvm-svn: 216950
2014-09-02 21:21:48 +00:00
Richard Smith
40a62e6d56 Some Clang 3.5 release note updates.
llvm-svn: 216835
2014-08-31 03:54:48 +00:00
Bill Wendling
42bd5807a3 Include blurb about Likely. By Josh Klontz.
llvm-svn: 216762
2014-08-29 20:00:59 +00:00
Bill Wendling
85e644f424 Update to include ISPC. By Dmitry Babokin.
llvm-svn: 216760
2014-08-29 19:57:40 +00:00
Bill Wendling
83f8b92b34 Merging r216572:
------------------------------------------------------------------------
r216572 | chandlerc | 2014-08-27 11:21:27 -0700 (Wed, 27 Aug 2014) | 3 lines

Fix PR20773 which I introduced with a silly edit mistake in r216531.
Trivial fix, and I've made the gentoo tests more representative. With
the changes, they would have caught this failure.
------------------------------------------------------------------------

llvm-svn: 216588
2014-08-27 20:07:31 +00:00
Bill Wendling
d2cd7c5902 Merging r216531:
------------------------------------------------------------------------
r216531 | chandlerc | 2014-08-27 01:41:41 -0700 (Wed, 27 Aug 2014) | 22 lines

Significantly fix Clang's header search for Ubuntu (and possibly other
modern Debian-based distributions) due to on-going multiarch madness.

It appears that when the multiarch heeader search support went into the
clang driver, it went in in a quite bad state. The order of includes
completely failed to match the order exhibited by GCC, and in a specific
case -- when the GCC triple and the multiarch triple don't match as with
i686-linux-gnu and i386-linux-gnu -- we would absolutely fail to find
the libstdc++ target-specific header files.

I assume that folks who have been using Clang on Ubuntu 32-bit systems
have been applying weird patches to hack around this. I can't imagine
how else it could have worked. This was originally reported by a 64-bit
operating system user who had a 32-bit crosscompiler installed. We tried
to use that rather than the bi-arch support of the 64-bit compiler, but
failed due to the triple differences.

I've corrected all the wrong orderings in the existing tests and added
a specific test for the multiarch triple strings that are different in
a significant way. This should significantly improve the usability of
Clang when checked out vanilla from upstream onto Ubuntu machines with
an i686 GCC installation for whatever reason.
------------------------------------------------------------------------

llvm-svn: 216587
2014-08-27 20:07:13 +00:00
Michael Wong
76d2581450 updated with clang openmp notes by Michael Wong
llvm-svn: 216578
2014-08-27 19:22:48 +00:00
Bill Wendling
13225a76de Use C++14 flags.
llvm-svn: 216287
2014-08-22 20:54:39 +00:00
Bill Wendling
368a2bed7b Merging r216064:
------------------------------------------------------------------------
r216064 | kongyi | 2014-08-20 03:40:20 -0700 (Wed, 20 Aug 2014) | 9 lines

ARM: Fix codegen for rbit intrinsic

LLVM generates illegal `rbit r0, #352` instruction for rbit intrinsic.
According to ARM ARM, rbit only takes register as argument, not immediate.
The correct instruction should be rbit <Rd>, <Rm>.

The bug was originally introduced in r211057.

Differential Revision: http://reviews.llvm.org/D4980
------------------------------------------------------------------------

llvm-svn: 216089
2014-08-20 17:42:35 +00:00
Bill Wendling
95959916e7 It fixes a regression with multiple address spaces in
OpenCL and blocks.

Patch by Pekka.

llvm-svn: 216049
2014-08-20 07:39:19 +00:00
Bill Wendling
7370495d29 Make 3.5 branch.
llvm-svn: 216046
2014-08-20 07:27:19 +00:00
Renato Golin
813999532a Merging r215295:
------------------------------------------------------------------------
r215295 | compnerd | 2014-08-09 21:17:37 +0100 (Sat, 09 Aug 2014) | 10 lines

builtins: correct __umodsi3, __udivsi3 on ARM

When building the builtins for a modern CPU (idiv support), __umodsi3 was
completely incorrect as it would behave as __udivmosi3, which takes a tertiary
parameter which is a pointer.

__udivsi3 was also incorrect, returning the remainder in r1.  Although this
would not result in any crash or invalid behaviour as r1 is a caller saved
register in AAPCS, this is unnecessary.  Simply perform the division ignoring
the remainder.
------------------------------------------------------------------------

llvm-svn: 216035
2014-08-19 23:30:32 +00:00
Bill Wendling
4c7a06eb9c Merging r215609:
------------------------------------------------------------------------
r215609 | majnemer | 2014-08-13 17:49:23 -0700 (Wed, 13 Aug 2014) | 3 lines

Sema: Permit nullptr template args in MSVC compat mode

This fixes a regression I caused back in r211766.
------------------------------------------------------------------------

llvm-svn: 215881
2014-08-18 05:18:35 +00:00
Bill Wendling
61c4ba945c Merging r215618:
------------------------------------------------------------------------
r215618 | majnemer | 2014-08-13 23:35:08 -0700 (Wed, 13 Aug 2014) | 7 lines

Parse: Don't attempt to act on #pragma init_seg when not targeting MSVC

It doesn't really make sense to try and do stuff with #pragma init_seg
when targeting non-Microsoft platforms; notions like library vs user
initializers don't exist for other targets.

This fixes PR20639.
------------------------------------------------------------------------

llvm-svn: 215880
2014-08-18 05:18:12 +00:00
Bill Wendling
562712ae80 Merging r215711:
------------------------------------------------------------------------
r215711 | wschmidt | 2014-08-15 06:51:57 -0700 (Fri, 15 Aug 2014) | 8 lines

[PPC64] Add test case for r215685.

I had deferred adding this test case until I could get it down to a
reasonable size.  That's done now.

Thanks,
Bill

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

llvm-svn: 215879
2014-08-18 05:16:58 +00:00
Bill Wendling
ef492f7c44 Merging r215685:
------------------------------------------------------------------------
r215685 | wschmidt | 2014-08-14 18:25:26 -0700 (Thu, 14 Aug 2014) | 69 lines

[PPC64] Add missing dependency on X2 to LDinto_toc.

The LDinto_toc pattern has been part of 64-bit PowerPC for a long
time, and represents loading from a memory location into the TOC
register (X2).  However, this pattern doesn't explicitly record that
it modifies that register.  This patch adds the missing dependency.

It was very surprising to me that this has never shown up as a problem
in the past, and that we only saw this problem recently in a single
scenario when building a self-hosted clang.  It turns out that in most
cases we have another dependency present that keeps the LDinto_toc
instruction tied in place.  LDinto_toc is used for TOC restore
following a call site, so this is a typical sequence:

   BCTRL8 <regmask>, %CTR8<imp-use>, %RM<imp-use>, %X3<imp-use>, %X12<imp-use>, %X1<imp-def>, ...
   LDinto_toc 24, %X1
   ADJCALLSTACKUP 96, 0, %R1<imp-def>, %R1<imp-use>

Because the LDinto_toc is inserted prior to the ADJCALLSTACKUP, there
is a natural anti-dependency between the two that keeps it in place.

Therefore we don't usually see a problem.  However, in one particular
case, one call is followed immediately by another call, and the second
call requires a parameter that is a TOC-relative address.  This is the
code sequence:

  BCTRL8 <regmask>, %CTR8<imp-use>, %RM<imp-use>, %X3<imp-use>, %X4<imp-use>, %X5<imp-use>, %X12<imp-use>, %X1<imp-def>, ...
  LDinto_toc 24, %X1
  ADJCALLSTACKUP 96, 0, %R1<imp-def>, %R1<imp-use>
  ADJCALLSTACKDOWN 96, %R1<imp-def>, %R1<imp-use>
  %vreg39<def> = ADDIStocHA %X2, <ga:@.str>; G8RC_and_G8RC_NOX0:%vreg39
  %vreg40<def> = ADDItocL %vreg39<kill>, <ga:@.str>; G8RC:%vreg40 G8RC_and_G8RC_NOX0:%vreg39

Note that the back-to-back stack adjustments are the same size!  The
back end is smart enough to recognize this and optimize them away:

  BCTRL8 <regmask>, %CTR8<imp-use>, %RM<imp-use>, %X3<imp-use>, %X4<imp-use>, %X5<imp-use>, %X12<imp-use>, %X1<imp-def>, ...
  LDinto_toc 24, %X1
  %vreg39<def> = ADDIStocHA %X2, <ga:@.str>; G8RC_and_G8RC_NOX0:%vreg39
  %vreg40<def> = ADDItocL %vreg39<kill>, <ga:@.str>; G8RC:%vreg40 G8RC_and_G8RC_NOX0:%vreg39

Now there is nothing to prevent the ADDIStocHA instruction from moving
ahead of the LDinto_toc instruction, and because of the longest-path
heuristic, this is what happens.

With the accompanying patch, %X2 is represented as an implicit def:

  BCTRL8 <regmask>, %CTR8<imp-use>, %RM<imp-use>, %X3<imp-use>, %X4<imp-use>, %X5<imp-use>, %X12<imp-use>, %X1<imp-def>, ...
  LDinto_toc 24, %X1, %X2<imp-def,dead>
  ADJCALLSTACKUP 96, 0, %R1<imp-def,dead>, %R1<imp-use>
  ADJCALLSTACKDOWN 96, %R1<imp-def,dead>, %R1<imp-use>
  %vreg39<def> = ADDIStocHA %X2, <ga:@.str>; G8RC_and_G8RC_NOX0:%vreg39
  %vreg40<def> = ADDItocL %vreg39<kill>, <ga:@.str>; G8RC:%vreg40 G8RC_and_G8RC_NOX0:%vreg39

So now when the two stack adjustments are removed, ADDIStocHA is
prevented from being moved above LDinto_toc.

I have not yet created a test case for this, because the original
failure occurs on a relatively large function that needs reduction.
However, this is a fairly serious bug, despite its infrequency, and I
wanted to get this patch onto the list as soon as possible so that it
can be considered for a 3.5 backport.  I'll work on whittling down a
test case.

Have we missed the boat for 3.5 at this point?

Thanks,
Bill

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

llvm-svn: 215878
2014-08-18 05:16:33 +00:00
Bill Wendling
3c78fb290a Merging r215808:
------------------------------------------------------------------------
r215808 | nicholas | 2014-08-15 19:14:37 -0700 (Fri, 15 Aug 2014) | 2 lines

Clarify.

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

llvm-svn: 215877
2014-08-18 05:15:34 +00:00
Bill Wendling
4262851e1b Merging r215807:
------------------------------------------------------------------------
r215807 | nicholas | 2014-08-15 19:11:54 -0700 (Fri, 15 Aug 2014) | 2 lines

Try indenting to put all the text inside the block.

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

llvm-svn: 215876
2014-08-18 05:15:18 +00:00
Bill Wendling
ff38e3da85 Merging r215806:
------------------------------------------------------------------------
r215806 | nicholas | 2014-08-15 19:09:42 -0700 (Fri, 15 Aug 2014) | 2 lines

Document what's experimental about __attribute__((enable_if)). PR20392

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

llvm-svn: 215875
2014-08-18 05:15:02 +00:00
Bill Wendling
6bdbb229c0 Merging r215806:
------------------------------------------------------------------------

llvm-svn: 215874
2014-08-18 05:14:39 +00:00
Sylvestre Ledru
fcd989333f Fix the build. Match the declaration in trunk. Use clang::diag::Flavor::WarningOrError
llvm-svn: 215833
2014-08-17 11:59:37 +00:00
Sylvestre Ledru
e82b3c8f5f Document -Wabsolute-value with example
llvm-svn: 215652
2014-08-14 16:10:10 +00:00
Sylvestre Ledru
bc626ae563 Document -Wtautological-pointer-compare & -Wtautological-undefined-compare with example
llvm-svn: 215651
2014-08-14 16:09:45 +00:00
Sylvestre Ledru
4de5839c99 Document the new warning -Wabsolute-value
llvm-svn: 215525
2014-08-13 07:41:41 +00:00
Bill Wendling
5ba548388f Merging r214679:
------------------------------------------------------------------------
r214679 | chandlerc | 2014-08-03 17:54:28 -0700 (Sun, 03 Aug 2014) | 10 lines

[x86] Fix the test case added in r214670 and tweaked in r214674 further.

Fundamentally, there isn't a really portable way to test the constant
pool contents. Instead, pin this test to the bare-metal triple. This
also makes it a 64-bit triple which allows us to only match a single
constant pool rather than two. It can also just hard code the '.' prefix
as the format should be stable now that it has a fixed triple. Finally,
I've switched it to use CHECK-NEXT to be more precise in the instruction
sequence expected and to use variables rather than hard coding decisions
by the register allocator.
------------------------------------------------------------------------

llvm-svn: 215430
2014-08-12 05:41:35 +00:00
Bill Wendling
6036ee499c Merging r214674:
------------------------------------------------------------------------
r214674 | spatel | 2014-08-03 16:20:16 -0700 (Sun, 03 Aug 2014) | 2 lines

Account for possible leading '.' in label string.

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

llvm-svn: 215429
2014-08-12 05:41:22 +00:00
Bill Wendling
0ee1c0452b Merging r214670:
------------------------------------------------------------------------
r214670 | spatel | 2014-08-03 15:48:23 -0700 (Sun, 03 Aug 2014) | 8 lines

fix for PR20354 - Miscompile of fabs due to vectorization

This is intended to be the minimal change needed to fix PR20354 ( http://llvm.org/bugs/show_bug.cgi?id=20354 ). The check for a vector operation was wrong; we need to check that the fabs itself is not a vector operation.

This patch will not generate the optimal code. A constant pool load and 'and' op will be generated instead of just returning a value that we can calculate in advance (as we do for the scalar case). I've put a 'TODO' comment for that here and expect to have that patch ready soon.

There is a very similar optimization that we can do in visitFNEG, so I've put another 'TODO' there and expect to have another patch for that too.

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

llvm-svn: 215428
2014-08-12 05:41:11 +00:00
Bill Wendling
5a09dfa964 Merging r215229:
------------------------------------------------------------------------
r215229 | sylvestre | 2014-08-08 10:15:13 -0700 (Fri, 08 Aug 2014) | 11 lines

Fix a bug when scan-build is used in a cross-compilation environment with
the --use-cc option.

Instead, we will search in the PATH
For example:
 scan-build --use-cc=arm-none-eabi-gcc -o out make -e

Initially reported as a Debian Bug:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=748777


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

llvm-svn: 215427
2014-08-12 05:38:53 +00:00
Bill Wendling
668c2339e1 Revert r.215058.
llvm-svn: 215426
2014-08-12 05:35:26 +00:00
Bill Wendling
2ffe33d726 Fix lldb build for 3.5 release. Patcy by Sylvestre Ladru.
llvm-svn: 215425
2014-08-12 05:32:50 +00:00
Sylvestre Ledru
3f0867ead3 Also describe the new check 'alpha.core.TestAfterDivZero'
llvm-svn: 215314
2014-08-10 12:41:40 +00:00
Sylvestre Ledru
c76f4b6602 Update of the release notes: '-z' is also forwarded to the linker
llvm-svn: 215313
2014-08-10 12:38:46 +00:00
Bob Wilson
28e01d94e1 Merge r215245: Change __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ for versions > 10.9.
llvm-svn: 215254
2014-08-08 22:59:37 +00:00
Sylvestre Ledru
192e2e2ca9 Fixed the build broken by the r215046 (same patch as abidh in trunk)
llvm-svn: 215130
2014-08-07 18:51:43 +00:00
Jim Cownie
c25f426db2 Update Branch3_5 to include new Cmake code and PowerPC64 buld fixes.
Branch_35 will then be the same as Rev 215093 on the trunk.

llvm-svn: 215098
2014-08-07 11:16:59 +00:00
Pekka Jaaskelainen
66671a5b81 Added pocl and TCE to the list of projects that work with Clang/LLVM 3.5.
llvm-svn: 215090
2014-08-07 09:06:53 +00:00
Bill Wendling
21bac108cf Merging r214481:
------------------------------------------------------------------------
r214481 | hfinkel | 2014-07-31 22:20:41 -0700 (Thu, 31 Jul 2014) | 38 lines

[PowerPC] Generate unaligned vector loads using intrinsics instead of regular loads

Altivec vector loads on PowerPC have an interesting property: They always load
from an aligned address (by rounding down the address actually provided if
necessary). In order to generate an actual unaligned load, you can generate two
load instructions, one with the original address, one offset by one vector
length, and use a special permutation to extract the bytes desired.

When this was originally implemented, I generated these two loads using regular
ISD::LOAD nodes, now marked as aligned. Unfortunately, there is a problem with
this:

The alignment of a load does not contribute to its identity, and SDNodes
are uniqued. So, imagine that we have some unaligned load, L1, that is not
aligned. The routine will create two loads, L1(aligned) and (L1+16)(aligned).
Further imagine that there had already existed a load (L1+16)(unaligned) with
the same chain operand as the load L1. When (L1+16)(aligned) is created as part
of the lowering of L1, this load *is* also the (L1+16)(unaligned) node, just
now marked as aligned (because the new alignment overwrites the old). But the
original users of (L1+16)(unaligned) now get the data intended for the
permutation yielding the data for L1, and (L1+16)(unaligned) no longer exists
to get its own permutation-based expansion. This was PR19991.

A second potential problem has to do with the MMOs on these loads, which can be
used by AA during instruction scheduling to break chain-based dependencies. If
the new "aligned" loads get the MMO from the original unaligned load, this does
not represent the fact that it will load data from below the original address.
Normally, this would not matter, but this load might be combined with another
load pair for a previous vector, and then the dependency on the otherwise-
ignored lower bytes can matter.

To fix both problems, instead of generating the necessary loads using regular
ISD::LOAD instructions, ppc_altivec_lvx intrinsics are used instead. These are
provided with MMOs with a conservative address range.

Unfortunately, I no longer have a failing test case (since PR19991 was
reported, other changes in CodeGen have forced this bug back into hiding it
again). Nevertheless, this should fix the underlying problem.
------------------------------------------------------------------------

llvm-svn: 215058
2014-08-07 04:52:45 +00:00
Bill Wendling
b625dc1f9e Merging r215046:
------------------------------------------------------------------------
r215046 | rsmith | 2014-08-06 17:24:21 -0700 (Wed, 06 Aug 2014) | 19 lines

Use -Rblah, not -Wblah, to control remark diagnostics. This was always the
intent when we added remark support, but was never implemented in the general
case, because the first -R flags didn't need it. (-Rpass= had special handling
to accomodate its argument.)

-Rno-foo, -Reverything, and -Rno-everything can be used to turn off a remark,
or to turn on or off all remarks. Per discussion on cfe-commits, -Weverything
does not affect remarks, and -Reverything does not affect warnings or errors.

The only "real" -R flag we have right now is -Rmodule-build; that flag is
effectively renamed from -Wmodule-build to -Rmodule-build by this change.

-Wpass and -Wno-pass (and their friends) are also renamed to -Rpass and
-Rno-pass by this change; it's not completely clear whether we intended to have
a -Rpass (with no =pattern), but that is unchanged by this commit, other than
the flag name. The default pattern is effectively one which matches no passes.
In future, we may want to make the default pattern be .*, so that -Reverything
works for -Rpass properly.

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

llvm-svn: 215057
2014-08-07 04:51:51 +00:00
Bill Schmidt
ca6c6b95d5 Correct faulty merge of r214923 due to echristo's subversion changes in trunk
llvm-svn: 214927
2014-08-05 21:15:38 +00:00
Bill Schmidt
b2459060c8 Merging r214923:
------------------------------------------------------------------------
r214923 | wschmidt | 2014-08-05 15:47:25 -0500 (Tue, 05 Aug 2014) | 12 lines

[PowerPC] Swap arguments and adjust shift count for vsldoi on little endian

Commits r213915 and r214718 fix recognition of shuffle masks for vmrg*
and vpku*um instructions for a little-endian target, by swapping the
input arguments.  The vsldoi instruction requires similar treatment,
and also needs its shift count adjusted for little endian.

Reviewed by Ulrich Weigand.

This is a bug fix candidate for release 3.5 (and hopefully the last of
those for PowerPC).

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

llvm-svn: 214926
2014-08-05 20:59:06 +00:00
Tom Stellard
0abd0b2d75 Merging r214865:
------------------------------------------------------------------------
r214865 | thomas.stellard | 2014-08-05 10:40:52 -0400 (Tue, 05 Aug 2014) | 5 lines

R600/SI: Avoid generating REGISTER_LOAD instructions.

SI doesn't use REGISTER_LOAD anymore, but it was still hitting this code
path for 8-bit and 16-bit private loads.

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

llvm-svn: 214895
2014-08-05 17:38:25 +00:00
Tom Stellard
3e548d31e8 Merging r214463:
------------------------------------------------------------------------
r214463 | thomas.stellard | 2014-07-31 20:32:28 -0400 (Thu, 31 Jul 2014) | 7 lines

R600/SI: Fix incorrect commute operation in shrink instructions pass

We were commuting the instruction by still shrinking it using the
original opcode.

NOTE: This is a candidate for the 3.5 branch.

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

llvm-svn: 214894
2014-08-05 17:38:23 +00:00
Bill Wendling
f48d9e60c0 Add blurb about LDC.
llvm-svn: 214842
2014-08-05 05:23:26 +00:00
Bill Wendling
904a8f6ac8 Merging r213799:
------------------------------------------------------------------------
r213799 | grosbach | 2014-07-23 13:41:38 -0700 (Wed, 23 Jul 2014) | 5 lines

X86: restrict combine to when type sizes are safe.

The folding of unary operations through a vector compare and mask operation
is only safe if the unary operation result is of the same size as its input.
For example, it's not safe for [su]itofp from v4i32 to v4f64.
------------------------------------------------------------------------

llvm-svn: 214841
2014-08-05 05:20:22 +00:00
Bill Wendling
20b8eb19ee Merging r214735:
------------------------------------------------------------------------
r214735 | ogoffart | 2014-08-04 10:28:11 -0700 (Mon, 04 Aug 2014) | 1 line

Fix crash when accessing a property of an invalid interface
------------------------------------------------------------------------

llvm-svn: 214840
2014-08-05 05:19:37 +00:00
Bill Wendling
13b8dc2040 Merging r214734:
------------------------------------------------------------------------
r214734 | ogoffart | 2014-08-04 10:28:05 -0700 (Mon, 04 Aug 2014) | 7 lines

Fix crash when assiging to a property with an invalid type

This is a regression from clang 3.4

Set the result to ExprError and returns true, rather than simply
returns false because errors have been reported already and returning
false show a confusing error
------------------------------------------------------------------------

llvm-svn: 214839
2014-08-05 05:19:17 +00:00
Bill Schmidt
6a183487cc Merging r214801:
------------------------------------------------------------------------
r214801 | wschmidt | 2014-08-04 18:21:26 -0500 (Mon, 04 Aug 2014) | 19 lines

[PPC64LE] Fix wrong IR for vec_sld and vec_vsldoi

My original LE implementation of the vsldoi instruction, with its
altivec.h interfaces vec_sld and vec_vsldoi, produces incorrect
shufflevector operations in the LLVM IR.  Correct code is generated
because the back end handles the incorrect shufflevector in a
consistent manner.

This patch and a companion patch for LLVM correct this problem by
removing the fixup from altivec.h and the corresponding fixup from the
PowerPC back end.  Several test cases are also modified to reflect the
now-correct LLVM IR.

The vec_sums and vec_vsumsws interfaces in altivec.h are also fixed,
because they used vec_perm calls intended to be recognized as vsldoi
instructions.  These vec_perm calls are now replaced with code that
more clearly shows the intent of the transformation.


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

llvm-svn: 214823
2014-08-04 23:48:10 +00:00
Bill Schmidt
869abd3c4a Fix incorrectly resolved merge conflict
llvm-svn: 214822
2014-08-04 23:47:21 +00:00
Bill Schmidt
d7eab8630c Merging r214800:
------------------------------------------------------------------------
r214800 | wschmidt | 2014-08-04 18:21:01 -0500 (Mon, 04 Aug 2014) | 13 lines

[PPC64LE] Fix wrong IR for vec_sld and vec_vsldoi

My original LE implementation of the vsldoi instruction, with its
altivec.h interfaces vec_sld and vec_vsldoi, produces incorrect
shufflevector operations in the LLVM IR.  Correct code is generated
because the back end handles the incorrect shufflevector in a
consistent manner.

This patch and a companion patch for Clang correct this problem by
removing the fixup from altivec.h and the corresponding fixup from the
PowerPC back end.  Several test cases are also modified to reflect the
now-correct LLVM IR.

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

llvm-svn: 214821
2014-08-04 23:44:59 +00:00
Bill Schmidt
3df9c41538 Merging r214721:
------------------------------------------------------------------------
r214721 | uweigand | 2014-08-04 09:55:26 -0500 (Mon, 04 Aug 2014) | 4 lines

[PowerPC] Add target triple to vec_urem_const.ll test case

This should hopefully fix build bots on other architectures.

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

llvm-svn: 214820
2014-08-04 23:43:34 +00:00
Bill Schmidt
8338208af2 Merging r214718:
------------------------------------------------------------------------
r214718 | uweigand | 2014-08-04 08:53:40 -0500 (Mon, 04 Aug 2014) | 12 lines

[PowerPC] Swap arguments to vpkuhum/vpkuwum on little-endian

In commit r213915, Bill fixed little-endian usage of vmrgh* and vmrgl*
by swapping the input arguments.  As it turns out, the exact same fix
is also required for the vpkuhum/vpkuwum patterns.

This fixes another regression in llvmpipe when vector support is
enabled.

Reviewed by Bill Schmidt.


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

llvm-svn: 214819
2014-08-04 23:42:09 +00:00
Bill Schmidt
b33695227a Merging r214716:
------------------------------------------------------------------------
r214716 | uweigand | 2014-08-04 08:27:12 -0500 (Mon, 04 Aug 2014) | 9 lines

[PowerPC] MULHU/MULHS are not legal for vector types

I ran into some test failures where common code changed vector division
by constant into a multiply-high operation (MULHU).  But these are not
implemented by the back-end, so we failed to recognize the insn.

Fixed by marking MULHU/MULHS as Expand for vector types.


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

llvm-svn: 214818
2014-08-04 23:41:27 +00:00
Bill Schmidt
444a522e5d Merging r214714:
------------------------------------------------------------------------
r214714 | uweigand | 2014-08-04 08:13:57 -0500 (Mon, 04 Aug 2014) | 19 lines

[PowerPC] Fix and improve vector comparisons

This patch refactors code generation of vector comparisons.

This fixes a wrong code-gen bug for ISD::SETGE for floating-point types,
and improves generated code for vector comparisons in general.

Specifically, the patch moves all logic deciding how to implement vector
comparisons into getVCmpInst, which gets two extra boolean outputs
indicating to its caller whether its needs to swap the input operands
and/or negate the result of the comparison.  Apart from implementing
these two modifications as directed by getVCmpInst, there is no need
to ever implement vector comparisons in any other manner; in particular,
there is never a need to perform two separate comparisons (e.g. one for
equal and one for greater-than, as code used to do before this patch).

Reviewed by Bill Schmidt.


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

llvm-svn: 214817
2014-08-04 23:37:33 +00:00
Hans Wennborg
9b74891142 Merging r214777:
Excluding the /Zp option, because that was added after the 3.5 branch.

------------------------------------------------------------------------
r214777 | hans | 2014-08-04 14:07:58 -0700 (Mon, 04 Aug 2014) | 1 line

UsersManual: update clang-cl options
------------------------------------------------------------------------

llvm-svn: 214778
2014-08-04 21:11:53 +00:00
Bill Wendling
5f262c819d Merging r214291:
------------------------------------------------------------------------
r214291 | sylvestre | 2014-07-30 01:33:21 -0700 (Wed, 30 Jul 2014) | 11 lines

Use __linux__ macro throughout, instead of ocasional __linux.

__linux is not universally defined across all standards versions, compilers and architectures. Specifically at C99 and up, it's not defined in GCC on powerpc platform.

See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=28314

Bugzilla: http://llvm.org/bugs/show_bug.cgi?id=20380

Patch by Dimitri John Ledkov <dimitri.ledkov@canonical.com>


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

llvm-svn: 214766
2014-08-04 20:01:31 +00:00
Bill Wendling
569deba640 Merging r214060:
------------------------------------------------------------------------
r214060 | brad | 2014-07-27 18:57:32 -0700 (Sun, 27 Jul 2014) | 2 lines

Add missing override keyword to OpenBSD IsIntegratedAssemblerDefault().

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

llvm-svn: 214765
2014-08-04 19:58:38 +00:00
Bill Wendling
2c74c29d92 Merging r214060:
------------------------------------------------------------------------

llvm-svn: 214764
2014-08-04 19:58:16 +00:00
Bill Wendling
c369220352 Merging r213834:
------------------------------------------------------------------------
r213834 | rsmith | 2014-07-23 19:27:39 -0700 (Wed, 23 Jul 2014) | 4 lines

Take the canonical type when forming a canonical template argument with
'nullptr' value. Fixes profiling of such template arguments to always give the
same value.

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

llvm-svn: 214751
2014-08-04 18:38:09 +00:00
Bill Wendling
001a4b73cd Merging r213913:
------------------------------------------------------------------------
r213913 | rsmith | 2014-07-24 18:12:44 -0700 (Thu, 24 Jul 2014) | 4 lines

PR20445: Properly transform the initializer in a CXXNewExpr rather than running
it through the normal TreeTransform logic for Exprs (which will strip off
implicit parts of the initialization and never re-create them).

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

llvm-svn: 214750
2014-08-04 18:37:31 +00:00
Bill Wendling
405f701d60 Merging r213966:
------------------------------------------------------------------------
r213966 | brad | 2014-07-25 12:28:44 -0700 (Fri, 25 Jul 2014) | 4 lines

Fix arc4random detection.

Patch by Pascal Stumpf.

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

llvm-svn: 214749
2014-08-04 18:36:56 +00:00
Bill Wendling
dfb3dabbf1 Merging r213999:
------------------------------------------------------------------------
r213999 | tstellar | 2014-07-25 18:05:20 -0700 (Fri, 25 Jul 2014) | 1 line

R600: Add processor type for Mullins
------------------------------------------------------------------------

llvm-svn: 214748
2014-08-04 18:36:16 +00:00
Bill Wendling
c326e800f2 Merging r213999:
------------------------------------------------------------------------

llvm-svn: 214747
2014-08-04 18:35:56 +00:00
Bill Wendling
e3b981281d Merging r214119:
------------------------------------------------------------------------
r214119 | joerg | 2014-07-28 14:06:22 -0700 (Mon, 28 Jul 2014) | 7 lines

Change __INTx_TYPE__ to be always signed. This changes the value for
char-based types from "char" to "signed char". Adjust stdint.h to use
__INTx_TYPE__ directly without prefixing it with signed and to use
__UINTx_TYPE__ for unsigned ones.

The value of __INTx_TYPE__ now matches GCC.

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

llvm-svn: 214746
2014-08-04 18:34:05 +00:00
Bill Wendling
12646940aa Merging r214222:
------------------------------------------------------------------------
r214222 | rsmith | 2014-07-29 14:20:12 -0700 (Tue, 29 Jul 2014) | 4 lines

PR20473: Don't "deduplicate" string literals with the same value but different
lengths! In passing, simplify string literal deduplication by relying on LLVM
to deduplicate the underlying constant values.

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

llvm-svn: 214745
2014-08-04 18:33:13 +00:00
Bill Wendling
fe62b2b0a7 ------------------------------------------------------------------------
llvm-svn: 214744
2014-08-04 18:31:55 +00:00
Bill Wendling
f6c040eca0 Merging r214369:
------------------------------------------------------------------------
r214369 | rsmith | 2014-07-30 17:22:56 -0700 (Wed, 30 Jul 2014) | 2 lines

Rename this test so that it actually runs, and fix it so that it passes.

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

llvm-svn: 214743
2014-08-04 18:28:36 +00:00
Bill Wendling
317fbe2805 Merging r214050:
------------------------------------------------------------------------
r214050 | rsmith | 2014-07-26 22:12:49 -0700 (Sat, 26 Jul 2014) | 7 lines

When looking for temporary dtors while building the CFG, do not walk into
lambda expressions (other than their capture initializers) nor blocks. Do walk
into default argument expressions and default initializer expressions.

These bugs were causing us to produce broken CFGs whenever a lambda expression
was used to initialize a libstdc++ std::function object!

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

llvm-svn: 214742
2014-08-04 18:19:14 +00:00
Bill Wendling
fe82a366df Merging r214471:
------------------------------------------------------------------------
r214471 | rtrieu | 2014-07-31 18:42:01 -0700 (Thu, 31 Jul 2014) | 5 lines

Remove this pointer that is converted to bool.  In well-defined contexts, the
this pointer is always non-null.  If the this pointer is null, it is undefined
and the compiler may optimize it away by assuming it is non-null.  The null
checks are pushed into the callers.

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

llvm-svn: 214741
2014-08-04 18:18:40 +00:00
Bill Wendling
75c7375ee8 Merging r214008:
------------------------------------------------------------------------
r214008 | rtrieu | 2014-07-25 19:10:52 -0700 (Fri, 25 Jul 2014) | 3 lines

If a template argument is non-evaluable expression, use the profile ID to see
if the two arguments are equal.

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

llvm-svn: 214696
2014-08-04 04:36:40 +00:00
Bill Wendling
ec68271f06 Merging r213912:
------------------------------------------------------------------------
r213912 | rtrieu | 2014-07-24 17:24:02 -0700 (Thu, 24 Jul 2014) | 4 lines

Pass the PrintingPolicy when converting types to strings in template type
diffing.  This removes extra "struct"/"class" in the type names and gives
"bool" instead of "_Bool" for booleans.

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

llvm-svn: 214695
2014-08-04 04:36:15 +00:00
Bill Wendling
4bd3da119e Merging r213902:
------------------------------------------------------------------------
r213902 | rtrieu | 2014-07-24 16:14:16 -0700 (Thu, 24 Jul 2014) | 3 lines

Print "(default)" for default template template arguments to match the
printing of other types.

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

llvm-svn: 214694
2014-08-04 04:35:58 +00:00
Bill Wendling
009ef32ff2 Merging r213840:
------------------------------------------------------------------------
r213840 | rtrieu | 2014-07-23 21:24:50 -0700 (Wed, 23 Jul 2014) | 2 lines

Add support for nullptr template arguments to template type diffing.

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

llvm-svn: 214693
2014-08-04 04:35:31 +00:00
Bill Wendling
3869e6a789 Merging r213613:
------------------------------------------------------------------------
r213613 | rtrieu | 2014-07-21 21:42:15 -0700 (Mon, 21 Jul 2014) | 2 lines

Fix '&' printing for template arguments in parentheses in template diffing.

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

llvm-svn: 214692
2014-08-04 04:35:10 +00:00
Bill Wendling
d8f7f82712 Merging r213611:
------------------------------------------------------------------------
r213611 | rtrieu | 2014-07-21 21:06:54 -0700 (Mon, 21 Jul 2014) | 2 lines

More gracefully handle parentheses in templare arguments in template diffing.

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

llvm-svn: 214691
2014-08-04 04:34:53 +00:00
Bill Wendling
aa124fa230 Merging r213609:
------------------------------------------------------------------------
r213609 | rtrieu | 2014-07-21 20:33:01 -0700 (Mon, 21 Jul 2014) | 3 lines

Fix a template diffing problem were an '&' is unexpectedly printed in
a template argument.

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

llvm-svn: 214690
2014-08-04 04:34:27 +00:00
Bill Wendling
23513f4039 Merging r213665:
------------------------------------------------------------------------
r213665 | tnorthover | 2014-07-22 08:47:09 -0700 (Tue, 22 Jul 2014) | 11 lines

X86: drop relocations on __eh_frame sections globally.

Without this, we produce non-extern relocations when targeting older OS X
versions that ld64 can't cope with in the particular context of __eh_frame
sections (who'd want generic relocation-processing anyway?).

This means that an updated linker (ld64 from Xcode 3.2.6 or later) may be
needed when targeting such platforms with a modern version of LLVM, but this is
probably the case anyway and a reasonable requirement.

PR20212, rdar://problem/17544795
------------------------------------------------------------------------

llvm-svn: 214689
2014-08-04 04:29:47 +00:00
Bill Wendling
54f837917c Merging r213726:
------------------------------------------------------------------------
r213726 | nicholas | 2014-07-22 23:24:49 -0700 (Tue, 22 Jul 2014) | 2 lines

We may visit a call that uses an alloca multiple times in callUsesLocalStack, sometimes with IsNocapture true and sometimes with IsNocapture false. We accidentally skipped work we needed to do in the IsNocapture=false case if we were called with IsNocapture=true the first time. Fixes PR20405!

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

llvm-svn: 214688
2014-08-04 04:28:45 +00:00
Bill Wendling
800eae7e0b Merging r213896:
------------------------------------------------------------------------
r213896 | compnerd | 2014-07-24 15:09:06 -0700 (Thu, 24 Jul 2014) | 6 lines

Target: invert condition for Windows

The Microsoft ABI and MSVCRT are considered the canonical C runtime and ABI.
The long double routines are not part of this environment.  However, cygwin and
MinGW both provide supplementary implementations.  Change the condition to
reflect this reality.
------------------------------------------------------------------------

llvm-svn: 214687
2014-08-04 04:28:05 +00:00
Bill Wendling
cdd225435f Merging r213883:
------------------------------------------------------------------------
r213883 | compnerd | 2014-07-24 10:46:36 -0700 (Thu, 24 Jul 2014) | 5 lines

X86: correct library call setup for Windows itanium

This target is identical to the Windows MSVC (and follows Microsoft ABI for C).
Correct the library call setup for this target.  The same set of library calls
are missing on this environment.
------------------------------------------------------------------------

llvm-svn: 214686
2014-08-04 04:27:37 +00:00
Bill Wendling
cd8406104c Merging r213899:
------------------------------------------------------------------------
r213899 | joerg | 2014-07-24 15:20:10 -0700 (Thu, 24 Jul 2014) | 2 lines

Don't use 128bit functions on PPC32.

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

llvm-svn: 214685
2014-08-04 04:25:53 +00:00
Bill Wendling
87d61cf9aa Merging r214423:
------------------------------------------------------------------------
r214423 | hfinkel | 2014-07-31 12:13:38 -0700 (Thu, 31 Jul 2014) | 9 lines

Fix ScalarEvolutionExpander when creating a PHI in a block with duplicate predecessors

It seems that when I fixed this, almost exactly a year ago, I did not quite do
it correctly. When we have duplicate block predecessors, we can indeed not have
different incoming values for the same block, but we *must* have duplicate
entries. So, instead of skipping the duplicates, we explicitly add the
duplicate incoming values.

Fixes PR20442.
------------------------------------------------------------------------

llvm-svn: 214684
2014-08-04 04:22:44 +00:00
Bill Wendling
0e9a6b6dc0 Merging r214429:
------------------------------------------------------------------------
r214429 | willschm | 2014-07-31 12:50:53 -0700 (Thu, 31 Jul 2014) | 29 lines

Disable IsSub subregister assert.  pr18663.

This is a follow-up to the activity in the bug at
http://llvm.org/bugs/show_bug.cgi?id=18663 .  The underlying issue has
to do with how the KILL pseudo-instruction is handled.  I defer to
Hal/Jakob/Uli for additional details and background.

This will disable the (bad?) assert, add an associated fixme comment,
and add a pair of tests.

The code change and the pr18663-2.ll test are copied from the referenced
bug.  That test does not immediately fail in my environment, but I have
added the pr18663.ll test which does.

(Comment from Hal)
to provide everyone else with some context, this assert was not bad when
it was written. At that time, we only generated KILL pseudo instructions
around subregister copies. This logic, unfortunately, had its own problems.
In r199797, the relevant logic in MachineCopyPropagation was replaced to
generate KILLs for other kinds of copies too. This change in semantics broke
this now-problematic assumption in AggressiveAntiDepBreaker. The
AggressiveAntiDepBreaker really needs a proper cleanup to deal with the
change, but removing the assert (which just allows the function to return
false) is a safe conservative behavior, and should do for the time being.





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

llvm-svn: 214683
2014-08-04 04:22:18 +00:00
Bill Wendling
832d6a68de Merging r214519:
------------------------------------------------------------------------
r214519 | rafael | 2014-08-01 07:57:05 -0700 (Fri, 01 Aug 2014) | 3 lines

Remove lto_codegen_set_attr.

It was never exported, so no functionality change.
------------------------------------------------------------------------

llvm-svn: 214682
2014-08-04 04:21:04 +00:00
Eric Fiselier
b0ca78fb51 [libcxx] Remove use of default function template parameters in type traits. Fixes DR20484
Summary: This patch moves the SFINAE for __is_destructor_welformed out of the function template parameters. type_traits must compile in c++03 mode since it is included in c++03 headers. 

Test Plan: No tests have been added.

Reviewers: danalbert, mclow.lists

Reviewed By: danalbert

Subscribers: K-ballo, cfe-commits

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

llvm-svn: 214427
2014-07-31 19:35:37 +00:00
Bill Wendling
fc546f8627 Merging r213798:
------------------------------------------------------------------------
r213798 | grosbach | 2014-07-23 13:41:31 -0700 (Wed, 23 Jul 2014) | 7 lines

DAG: fp->int conversion for non-splat constants.

Constant fold the lanes of the input constant build_vector individually
so we correctly handle when the vector elements are not all the same
constant value.

PR20394
------------------------------------------------------------------------

llvm-svn: 214413
2014-07-31 18:17:04 +00:00
Justin Bogner
6b823ba449 Merging r214331:
------------------------------------------------------------------------
r214331 | arphaman | 2014-07-30 13:30:11 -0700 (Wed, 30 Jul 2014) | 4 lines

docs: update the command guide documentation for llvm-profdata.

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

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

llvm-svn: 214353
2014-07-30 22:43:59 +00:00
Justin Holewinski
9a45867caf Merging r213793:
------------------------------------------------------------------------
r213793 | jholewinski | 2014-07-23 16:23:47 -0400 (Wed, 23 Jul 2014) | 4 lines

[NVPTX] Silence a GCC warning found by the buildbots

The cast to NVPTXTargetLowering was missing a 'const', but let's
just access the right pointer through the subtarget anyway.
------------------------------------------------------------------------

llvm-svn: 214310
2014-07-30 14:53:00 +00:00
Justin Holewinski
94f35ea76f Merging r213773:
------------------------------------------------------------------------
r213773 | jholewinski | 2014-07-23 13:40:45 -0400 (Wed, 23 Jul 2014) | 5 lines

[NVPTX] Make sure we do not generate MULWIDE ISD nodes when optimizations are disabled

With optimizations disabled, we disable the isel patterns for mul.wide; but we
were still generating MULWIDE ISD nodes.  Now, we only try to generate MULWIDE
ISD nodes in DAGCombine if the optimization level is not zero.
------------------------------------------------------------------------

llvm-svn: 214309
2014-07-30 14:49:09 +00:00
Daniel Sanders
014e7b834f Merging r214180:
------------------------------------------------------------------------
r214180 | sstankovic | 2014-07-29 15:39:24 +0100 (Tue, 29 Jul 2014) | 5 lines

[mips] Don't use odd-numbered single precision registers for fastcc calling
convention if -mno-odd-spreg is used.

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

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

llvm-svn: 214304
2014-07-30 12:39:37 +00:00
Bill Wendling
0cec800e8d Merging r214287:
------------------------------------------------------------------------
r214287 | chandlerc | 2014-07-29 22:44:04 -0700 (Tue, 29 Jul 2014) | 9 lines

Don't manually (and forcibly) run the verifier on the entire module from
the jump instruction table pass. First, the verifier is already built
into all the tools. The test case is adapted to just run llvm-as
demonstrating that we still catch the broken module. Second, the
verifier is *extremely* slow. This was responsible for very significant
compile time regressions.

If you have deployed a Clang binary anywhere from r210280 to this
commit, you really want to re-deploy.
------------------------------------------------------------------------

llvm-svn: 214288
2014-07-30 06:21:43 +00:00
Bob Wilson
6323faf644 Merging r213993,213998:
llvm-svn: 214262
2014-07-30 00:07:54 +00:00
Hans Wennborg
d180cc9112 Merging r214129:
------------------------------------------------------------------------
r214129 | echristo | 2014-07-28 15:00:44 -0700 (Mon, 28 Jul 2014) | 2 lines

Regenerate autoconf, previous updates to the configury haven't
been updating configure.
------------------------------------------------------------------------

llvm-svn: 214261
2014-07-30 00:07:21 +00:00
Bob Wilson
81d4e6005c Merging r214208:
llvm-svn: 214257
2014-07-29 23:48:32 +00:00
Hans Wennborg
062184f19b Merging r213895:
------------------------------------------------------------------------
r213895 | mren | 2014-07-24 14:13:20 -0700 (Thu, 24 Jul 2014) | 2 lines

Feedback from Hans on r213815. No functionaility change.

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

llvm-svn: 214254
2014-07-29 23:42:01 +00:00
Hans Wennborg
b3ff622079 Merging r213884:
------------------------------------------------------------------------
r213884 | mren | 2014-07-24 10:57:09 -0700 (Thu, 24 Jul 2014) | 1 line

Try to fix the bots again by moving test to X86 directory.
------------------------------------------------------------------------

llvm-svn: 214253
2014-07-29 23:40:11 +00:00
Hans Wennborg
6207270016 Merging r213880:
------------------------------------------------------------------------
r213880 | mren | 2014-07-24 10:18:33 -0700 (Thu, 24 Jul 2014) | 1 line

Try to fix the bots. If this does not work, I am going to move it to X86 directory.
------------------------------------------------------------------------

llvm-svn: 214252
2014-07-29 23:39:40 +00:00
Hans Wennborg
c7bfb6d36a Merging r213815:
------------------------------------------------------------------------
r213815 | mren | 2014-07-23 16:13:23 -0700 (Wed, 23 Jul 2014) | 17 lines

SimplifyCFG: fix a bug in switch to table conversion

We use gep to access the global array "switch.table", and the table index
should be treated as unsigned. When the highest bit is 1, this commit
zero-extends the index to an integer type with larger size.

For a switch on i2, we used to generate:
%switch.tableidx = sub i2 %0, -2
getelementptr inbounds [4 x i64]* @switch.table, i32 0, i2 %switch.tableidx

It is incorrect when %switch.tableidx is 2 or 3. The fix is to generate
%switch.tableidx = sub i2 %0, -2
%switch.tableidx.zext = zext i2 %switch.tableidx to i3
getelementptr inbounds [4 x i64]* @switch.table, i32 0, i3 %switch.tableidx.zext

rdar://17735071

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

llvm-svn: 214251
2014-07-29 23:38:58 +00:00
Hans Wennborg
60c15ed5ff Merging r213894:
------------------------------------------------------------------------
r213894 | hans | 2014-07-24 14:09:45 -0700 (Thu, 24 Jul 2014) | 4 lines

Windows: Don't wildcard expand /? or -?

Even if there's a file called c:\a, we want /? to be preserved as
an option, not expanded to a filename.
------------------------------------------------------------------------

llvm-svn: 214248
2014-07-29 23:27:06 +00:00
Renato Golin
5975e88f88 Merging r213714:
------------------------------------------------------------------------
r213714 | compnerd | 2014-07-23 02:32:32 +0100 (Wed, 23 Jul 2014) | 4 lines

test: add an explicit target triple

Now that we support WoA, this test fails on ARM build bots as __va_start has a
different signature on different architectures.
------------------------------------------------------------------------

llvm-svn: 214110
2014-07-28 18:27:07 +00:00
Dan Liew
b8f0391a7c Add information about new CMake interface to LLVM and note
deprecation of llvm_map_components_to_libraries()

llvm-svn: 214083
2014-07-28 14:04:39 +00:00
Dan Liew
dddf67f5d5 Merging r214078:
------------------------------------------------------------------------
r214078 | delcypher | 2014-07-28 14:36:50 +0100 (Mon, 28 Jul 2014) | 6 lines

Emit a warning if llvm_map_components_to_libraries() is used noting that its
use is deprecated in favour of llvm_map_components_to_libnames()

Although message(DEPRECATION "msg") would probably be a better fit this
does nothing if CMAKE_ERROR_DEPRECATED and CMAKE_WARNING_DEPRECATED are
both off, which is the default.
------------------------------------------------------------------------

llvm-svn: 214080
2014-07-28 13:39:56 +00:00
Dan Liew
3c89b2c953 Merging r214077:
------------------------------------------------------------------------
r214077 | delcypher | 2014-07-28 14:36:37 +0100 (Mon, 28 Jul 2014) | 2 lines

Document the new LLVM CMake interface for building against LLVM
libraries. With many contributions from Brad King.
------------------------------------------------------------------------

llvm-svn: 214079
2014-07-28 13:39:33 +00:00
Dan Liew
ffd65c839c Document building Sphinx documentation in release notes.
llvm-svn: 214068
2014-07-28 11:47:23 +00:00
Dan Liew
aa9583d2ed Merging r213660:
------------------------------------------------------------------------
r213660 | delcypher | 2014-07-22 15:59:38 +0100 (Tue, 22 Jul 2014) | 1 line

Fix Sphinx warning.
------------------------------------------------------------------------

llvm-svn: 214066
2014-07-28 11:15:25 +00:00
Simon Atanasyan
5b15c0f87d Merging r213937:
------------------------------------------------------------------------
r213937 | atanasyan | 2014-07-25 15:20:21 +0400 (Fri, 25 Jul 2014) | 3 lines

[Driver][Mips] Remove "fp64" directories from the mips-mti-linux-gnu toolchain
directories description. Released version of this toolchain has not separate
libraries for -mfp64 command line option.
------------------------------------------------------------------------

llvm-svn: 214053
2014-07-27 09:19:33 +00:00
Bill Wendling
2fbdb127ea Merging r213915:
------------------------------------------------------------------------
r213915 | wschmidt | 2014-07-24 18:55:55 -0700 (Thu, 24 Jul 2014) | 21 lines

[PATCH][PPC64LE] Correct little-endian usage of vmrgh* and vmrgl*.

Because the PowerPC vmrgh* and vmrgl* instructions have a built-in
big-endian bias, it is necessary to swap their inputs in little-endian
mode when using them to implement a vector shuffle.  This was
previously missed in the vector LE implementation.

There was already logic to distinguish between unary and "normal"
vmrg* vector shuffles, so this patch extends that logic to use a third
option:  "swapped" vmrg* vector shuffles that are used for little
endian in place of the "normal" ones.

I've updated the vec-shuffle-le.ll test to check for the expected
register ordering on the generated instructions.

This bug was discovered when testing the LE and ELFv2 patches for
safety if they were backported to 3.4.  A different vectorization
decision was made in 3.4 than on mainline trunk, and that exposed the
problem.  I've verified this fix takes care of that issue.


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

llvm-svn: 213961
2014-07-25 17:47:30 +00:00
Tim Northover
6b7ac2a98c [3.5] AArch64: docuemnt merge in release notes
llvm-svn: 213939
2014-07-25 11:51:48 +00:00
Sylvestre Ledru
e1dceeca1a Fix the version in the doc generation
llvm-svn: 213934
2014-07-25 10:16:56 +00:00
Filipe Cabecinhas
00cc493db6 Merge r213826
------------------------------------------------------------------------
r213826 | filcab | 2014-07-23 18:28:21 -0700 (Wed, 23 Jul 2014) | 7 lines

Fixed PR20411 - bug in getINSERTPS()

When we had a vector_shuffle where we had an input from each vector, we
could miscompile it because we were assuming the input from V2 wouldn't
be moved from where it was on the vector.

Added a test case.

llvm-svn: 213911
2014-07-25 00:00:11 +00:00
Daniel Sanders
9149bf6772 Merging r213749:
------------------------------------------------------------------------
r213749 | dsanders | 2014-07-23 13:59:26 +0100 (Wed, 23 Jul 2014) | 3 lines

Added release notes for MIPS.


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

llvm-svn: 213849
2014-07-24 09:52:28 +00:00
Daniel Sanders
b4a2b91353 Merging r213847:
------------------------------------------------------------------------
r213847 | dsanders | 2014-07-24 10:47:14 +0100 (Thu, 24 Jul 2014) | 8 lines

[mips] Fix ll and sc instructions

Summary: The ll and sc instructions for r6 and non-r6 are misplaced. This patch fixes that.

Patch by Jyun-Yan You

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

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

llvm-svn: 213848
2014-07-24 09:48:54 +00:00
Yi Kong
2cabf384c2 Merging r213733:
------------------------------------------------------------------------
r213733 | kongyi | 2014-07-23 10:25:02 +0100 (Wed, 23 Jul 2014) | 5 lines

ARM: Add doc for ACLE memory barrier intrinsics

Add documentations for ACLE memory barrier intrinsics, describing their motion
barrier characteristics.

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

llvm-svn: 213787
2014-07-23 19:55:09 +00:00
Dan Liew
a0911d3f03 Merging r213674:
------------------------------------------------------------------------
r213674 | delcypher | 2014-07-22 18:48:51 +0100 (Tue, 22 Jul 2014) | 5 lines

Add LLVM_TOOLS_BINARY_DIR variable to LLVMConfig.cmake so clients
of LLVM using CMake can easily find the tools directory.

LLVM_BUILD_TOOLS_BINARY_DIR was removed because it is now
superfluous.
------------------------------------------------------------------------

llvm-svn: 213766
2014-07-23 15:21:22 +00:00
Dan Liew
98ab17b1b3 Merging r213664:
------------------------------------------------------------------------
r213664 | delcypher | 2014-07-22 16:41:33 +0100 (Tue, 22 Jul 2014) | 3 lines

Export LLVM_ENABLE_RTTI and LLVM_ENABLE_EH in LLVMConfig.cmake so
clients of LLVM know if RTTI and/or EH were enabled in the build of
LLVM they are trying to link against.
------------------------------------------------------------------------

llvm-svn: 213765
2014-07-23 15:20:44 +00:00
Dan Liew
b79ae58145 Merging r213663:
------------------------------------------------------------------------
r213663 | delcypher | 2014-07-22 16:41:18 +0100 (Tue, 22 Jul 2014) | 4 lines

Added LLVM_ENABLE_RTTI and LLVM_ENABLE_EH options that allow RTTI and EH
to globally be controlled. Individual targets (e.g.  ExceptionDemo) can
still override this by using LLVM_REQUIRE_RTTI and LLVM_REQUIRE_EH if
they need to be compiled with RTTI or exception handling respectively.
------------------------------------------------------------------------

llvm-svn: 213764
2014-07-23 15:19:01 +00:00
Daniel Sanders
6e814ffb39 Merging r213653:
------------------------------------------------------------------------
r213653 | sstankovic | 2014-07-22 14:36:02 +0100 (Tue, 22 Jul 2014) | 7 lines

[mips] Fix two patterns that select i32's (for MIPS32r6) / i64's (for MIPS64r6)
from setne comparison with an i32.

The patterns that are fixed:
  * (select (i32 (setne i32, immZExt16)), i32, i32) (for MIPS32r6)
  * (select (i32 (setne i32, immZExt16)), i64, i64) (for MIPS64r6)

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

llvm-svn: 213746
2014-07-23 12:45:33 +00:00
Daniel Sanders
e25ce394b0 Merging r213741:
------------------------------------------------------------------------
r213741 | dsanders | 2014-07-23 13:06:13 +0100 (Wed, 23 Jul 2014) | 5 lines

[mips] -mno-shared should only be given to the assembler when -fPIC/-fpic/-fPIE/-fpie is not in effect.

This fixes compiler recursion on MIPS32r2.


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

llvm-svn: 213742
2014-07-23 12:11:45 +00:00
Bill Wendling
93c80e5bff Creating release_35 branch
llvm-svn: 213607
llvm-svn: 213606
llvm-svn: 213605
llvm-svn: 213604
llvm-svn: 213603
llvm-svn: 213602
llvm-svn: 213601
llvm-svn: 213598
llvm-svn: 213597
2014-07-22 03:16:41 +00:00
19020 changed files with 294844 additions and 1339393 deletions

View File

@@ -1,6 +1,5 @@
add_subdirectory(clang-apply-replacements)
add_subdirectory(clang-modernize)
add_subdirectory(clang-rename)
add_subdirectory(modularize)
add_subdirectory(module-map-checker)
add_subdirectory(remove-cstr-calls)

View File

@@ -13,8 +13,8 @@ include $(CLANG_LEVEL)/../../Makefile.config
PARALLEL_DIRS := remove-cstr-calls tool-template modularize \
module-map-checker pp-trace
DIRS := clang-apply-replacements clang-modernize clang-rename clang-tidy \
clang-query unittests
DIRS := clang-apply-replacements clang-modernize clang-tidy clang-query \
unittests
include $(CLANG_LEVEL)/Makefile

View File

@@ -6,10 +6,9 @@ add_clang_library(clangApplyReplacements
lib/Tooling/ApplyReplacements.cpp
LINK_LIBS
clangAST
clangBasic
clangRewrite
clangToolingCore
clangTooling
)
include_directories(

View File

@@ -45,9 +45,8 @@ TUReplacements;
typedef std::vector<std::string> TUReplacementFiles;
/// \brief Map mapping file name to Replacements targeting that file.
typedef llvm::DenseMap<const clang::FileEntry *,
std::vector<clang::tooling::Replacement>>
FileToReplacementsMap;
typedef llvm::StringMap<std::vector<clang::tooling::Replacement> >
FileToReplacementsMap;
/// \brief Recursively descends through a directory structure rooted at \p
/// Directory and attempts to deserialize *.yaml files as

View File

@@ -98,26 +98,29 @@ static void reportConflict(
// FIXME: Output something a little more user-friendly (e.g. unified diff?)
errs() << "The following changes conflict:\n";
for (const tooling::Replacement &R : ConflictingReplacements) {
if (R.getLength() == 0) {
errs() << " Insert at " << SM.getLineNumber(FID, R.getOffset()) << ":"
<< SM.getColumnNumber(FID, R.getOffset()) << " "
<< R.getReplacementText() << "\n";
for (const tooling::Replacement *I = ConflictingReplacements.begin(),
*E = ConflictingReplacements.end();
I != E; ++I) {
if (I->getLength() == 0) {
errs() << " Insert at " << SM.getLineNumber(FID, I->getOffset()) << ":"
<< SM.getColumnNumber(FID, I->getOffset()) << " "
<< I->getReplacementText() << "\n";
} else {
if (R.getReplacementText().empty())
if (I->getReplacementText().empty())
errs() << " Remove ";
else
errs() << " Replace ";
errs() << SM.getLineNumber(FID, R.getOffset()) << ":"
<< SM.getColumnNumber(FID, R.getOffset()) << "-"
<< SM.getLineNumber(FID, R.getOffset() + R.getLength() - 1) << ":"
<< SM.getColumnNumber(FID, R.getOffset() + R.getLength() - 1);
errs() << SM.getLineNumber(FID, I->getOffset()) << ":"
<< SM.getColumnNumber(FID, I->getOffset()) << "-"
<< SM.getLineNumber(FID, I->getOffset() + I->getLength() - 1)
<< ":"
<< SM.getColumnNumber(FID, I->getOffset() + I->getLength() - 1);
if (R.getReplacementText().empty())
if (I->getReplacementText().empty())
errs() << "\n";
else
errs() << " with \"" << R.getReplacementText() << "\"\n";
errs() << " with \"" << I->getReplacementText() << "\"\n";
}
}
}
@@ -137,24 +140,33 @@ static bool deduplicateAndDetectConflicts(FileToReplacementsMap &Replacements,
SourceManager &SM) {
bool conflictsFound = false;
for (auto &FileAndReplacements : Replacements) {
const FileEntry *Entry = FileAndReplacements.first;
auto &Replacements = FileAndReplacements.second;
assert(Entry != nullptr && "No file entry!");
for (FileToReplacementsMap::iterator I = Replacements.begin(),
E = Replacements.end();
I != E; ++I) {
const FileEntry *Entry = SM.getFileManager().getFile(I->getKey());
if (!Entry) {
errs() << "Described file '" << I->getKey()
<< "' doesn't exist. Ignoring...\n";
continue;
}
std::vector<tooling::Range> Conflicts;
tooling::deduplicate(FileAndReplacements.second, Conflicts);
tooling::deduplicate(I->getValue(), Conflicts);
if (Conflicts.empty())
continue;
conflictsFound = true;
errs() << "There are conflicting changes to " << Entry->getName() << ":\n";
errs() << "There are conflicting changes to " << I->getKey() << ":\n";
for (const tooling::Range &Conflict : Conflicts) {
auto ConflictingReplacements = llvm::makeArrayRef(
&Replacements[Conflict.getOffset()], Conflict.getLength());
for (std::vector<tooling::Range>::const_iterator
ConflictI = Conflicts.begin(),
ConflictE = Conflicts.end();
ConflictI != ConflictE; ++ConflictI) {
ArrayRef<tooling::Replacement> ConflictingReplacements(
&I->getValue()[ConflictI->getOffset()], ConflictI->getLength());
reportConflict(Entry, ConflictingReplacements, SM);
}
}
@@ -167,20 +179,14 @@ bool mergeAndDeduplicate(const TUReplacements &TUs,
clang::SourceManager &SM) {
// Group all replacements by target file.
std::set<StringRef> Warned;
for (const auto &TU : TUs) {
for (const tooling::Replacement &R : TU.Replacements) {
// Use the file manager to deduplicate paths. FileEntries are
// automatically canonicalized.
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);
}
}
for (TUReplacements::const_iterator TUI = TUs.begin(), TUE = TUs.end();
TUI != TUE; ++TUI)
for (std::vector<tooling::Replacement>::const_iterator
RI = TUI->Replacements.begin(),
RE = TUI->Replacements.end();
RI != RE; ++RI)
GroupedReplacements[RI->getFilePath()].push_back(*RI);
// Ask clang to deduplicate and report conflicts.
if (deduplicateAndDetectConflicts(GroupedReplacements, SM))
@@ -198,8 +204,10 @@ bool applyReplacements(const FileToReplacementsMap &GroupedReplacements,
// data structure for applying replacements. Rewriter certainly doesn't care.
// However, until we nail down the design of ReplacementGroups, might as well
// leave this as is.
for (const auto &FileAndReplacements : GroupedReplacements) {
if (!tooling::applyAllReplacements(FileAndReplacements.second, Rewrites))
for (FileToReplacementsMap::const_iterator I = GroupedReplacements.begin(),
E = GroupedReplacements.end();
I != E; ++I) {
if (!tooling::applyAllReplacements(I->getValue(), Rewrites))
return false;
}
@@ -215,7 +223,11 @@ RangeVector calculateChangedRanges(
// NOTE: This is O(n^2) in the number of replacements. If this starts to
// become a problem inline shiftedCodePosition() here and do shifts in a
// single run through this loop.
for (const tooling::Replacement &R : Replaces) {
for (std::vector<clang::tooling::Replacement>::const_iterator
I = Replaces.begin(),
E = Replaces.end();
I != E; ++I) {
const tooling::Replacement &R = *I;
unsigned Offset = tooling::shiftedCodePosition(Replaces, R.getOffset());
unsigned Length = R.getReplacementText().size();
@@ -233,10 +245,11 @@ bool writeFiles(const clang::Rewriter &Rewrites) {
const char *FileName =
Rewrites.getSourceMgr().getFileEntryForID(BufferI->first)->getName();
std::error_code EC;
llvm::raw_fd_ostream FileStream(FileName, EC, llvm::sys::fs::F_Text);
if (EC) {
errs() << "Warning: Could not write to " << EC.message() << "\n";
std::string ErrorInfo;
llvm::raw_fd_ostream FileStream(FileName, ErrorInfo, llvm::sys::fs::F_Text);
if (!ErrorInfo.empty()) {
errs() << "Warning: Could not write to " << FileName << "\n";
continue;
}
BufferI->second.write(FileStream);
@@ -248,12 +261,13 @@ bool writeFiles(const clang::Rewriter &Rewrites) {
bool deleteReplacementFiles(const TUReplacementFiles &Files,
clang::DiagnosticsEngine &Diagnostics) {
bool Success = true;
for (const auto &Filename : Files) {
std::error_code Error = llvm::sys::fs::remove(Filename);
for (TUReplacementFiles::const_iterator I = Files.begin(), E = Files.end();
I != E; ++I) {
std::error_code Error = llvm::sys::fs::remove(*I);
if (Error) {
Success = false;
// FIXME: Use Diagnostics for outputting errors.
errs() << "Error deleting file: " << Filename << "\n";
errs() << "Error deleting file: " << *I << "\n";
errs() << Error.message() << "\n";
errs() << "Please delete the file manually\n";
}

View File

@@ -10,7 +10,7 @@ target_link_libraries(clang-apply-replacements
clangBasic
clangFormat
clangRewrite
clangToolingCore
clangTooling
)
install(TARGETS clang-apply-replacements

View File

@@ -199,10 +199,11 @@ int main(int argc, char **argv) {
// Only include our options in -help output.
StringMap<cl::Option*> OptMap;
cl::getRegisteredOptions(OptMap);
const char **EndOpts = std::end(OptionsToShow);
for (const auto &Opt : OptMap) {
if (std::find(OptionsToShow, EndOpts, Opt.getKey()) == EndOpts)
Opt.getValue()->setHiddenFlag(cl::ReallyHidden);
const char **EndOpts = OptionsToShow + array_lengthof(OptionsToShow);
for (StringMap<cl::Option *>::iterator I = OptMap.begin(), E = OptMap.end();
I != E; ++I) {
if (std::find(OptionsToShow, EndOpts, I->getKey()) == EndOpts)
I->getValue()->setHiddenFlag(cl::ReallyHidden);
}
cl::SetVersionPrinter(&printVersion);
@@ -245,34 +246,36 @@ int main(int argc, char **argv) {
Rewriter ReplacementsRewriter(SM, LangOptions());
for (const auto &FileAndReplacements : GroupedReplacements) {
// This shouldn't happen but if a file somehow has no replacements skip to
// next file.
if (FileAndReplacements.second.empty())
continue;
for (FileToReplacementsMap::const_iterator I = GroupedReplacements.begin(),
E = GroupedReplacements.end();
I != E; ++I) {
std::string NewFileData;
const char *FileName = FileAndReplacements.first->getName();
if (!applyReplacements(FileAndReplacements.second, NewFileData,
Diagnostics)) {
errs() << "Failed to apply replacements to " << FileName << "\n";
// This shouldn't happen but if a file somehow has no replacements skip to
// next file.
if (I->getValue().empty())
continue;
if (!applyReplacements(I->getValue(), NewFileData, Diagnostics)) {
errs() << "Failed to apply replacements to " << I->getKey() << "\n";
continue;
}
// Apply formatting if requested.
if (DoFormat &&
!applyFormatting(FileAndReplacements.second, NewFileData, NewFileData,
FormatStyle, Diagnostics)) {
errs() << "Failed to apply reformatting replacements for " << FileName
if (DoFormat && !applyFormatting(I->getValue(), NewFileData, NewFileData,
FormatStyle, Diagnostics)) {
errs() << "Failed to apply reformatting replacements for " << I->getKey()
<< "\n";
continue;
}
// Write new file to disk
std::error_code EC;
llvm::raw_fd_ostream FileStream(FileName, EC, llvm::sys::fs::F_None);
if (EC) {
llvm::errs() << "Could not open " << FileName << " for writing\n";
std::string ErrorInfo;
llvm::raw_fd_ostream FileStream(I->getKey().str().c_str(), ErrorInfo,
llvm::sys::fs::F_Text);
if (!ErrorInfo.empty()) {
llvm::errs() << "Could not open " << I->getKey() << " for writing\n";
continue;
}

View File

@@ -18,8 +18,7 @@ TOOL_NO_EXPORTS = 1
SOURCES = ClangApplyReplacementsMain.cpp
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option
USEDLIBS = clangApplyReplacements.a clangFormat.a \
clangTooling.a clangToolingCore.a clangFrontend.a \
USEDLIBS = clangApplyReplacements.a clangFormat.a clangTooling.a clangFrontend.a \
clangSerialization.a clangDriver.a clangRewriteFrontend.a \
clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a

View File

@@ -40,7 +40,7 @@ int AddOverrideTransform::apply(const CompilationDatabase &Database,
// Make Fixer available to handleBeginSource().
this->Fixer = &Fixer;
if (int result = AddOverrideTool.run(createActionFactory(Finder).get())) {
if (int result = AddOverrideTool.run(createActionFactory(Finder))) {
llvm::errs() << "Error encountered during translation.\n";
return result;
}

View File

@@ -15,5 +15,4 @@ add_clang_library(modernizeCore
clangFrontend
clangLex
clangTooling
clangToolingCore
)

View File

@@ -60,9 +60,9 @@ class IncludeDirectivesPPCallback : public clang::PPCallbacks {
public:
IncludeDirectivesPPCallback(IncludeDirectives *Self)
: Self(Self), Guard(nullptr) {}
virtual ~IncludeDirectivesPPCallback() {}
private:
virtual ~IncludeDirectivesPPCallback() {}
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
@@ -116,8 +116,7 @@ private:
// checking for equality because it can also be part of the preamble if the
// preamble is the whole file.
unsigned Preamble =
Lexer::ComputePreamble(SM.getBuffer(Guard.FID)->getBuffer(), LangOpts)
.first;
Lexer::ComputePreamble(SM.getBuffer(Guard.FID), LangOpts).first;
unsigned IfndefOffset = SM.getFileOffset(Guard.IfndefLoc);
if (IfndefOffset > (Preamble + 1))
return;
@@ -178,7 +177,7 @@ private:
}
}
void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
Guard->Count++;
// If it's the #endif corresponding to the top-most #ifndef
@@ -220,7 +219,7 @@ private:
const MacroDirective *) override {
Guard->Count++;
}
void Else(SourceLocation, SourceLocation) override {
virtual void Else(SourceLocation, SourceLocation) override {
Guard->Count++;
}
@@ -311,8 +310,7 @@ static std::pair<unsigned, bool> findDirectiveEnd(SourceLocation HashLoc,
IncludeDirectives::IncludeDirectives(clang::CompilerInstance &CI)
: CI(CI), Sources(CI.getSourceManager()) {
// addPPCallbacks takes ownership of the callback
CI.getPreprocessor().addPPCallbacks(
llvm::make_unique<IncludeDirectivesPPCallback>(this));
CI.getPreprocessor().addPPCallbacks(new IncludeDirectivesPPCallback(this));
}
bool IncludeDirectives::lookForInclude(const FileEntry *File,

View File

@@ -50,8 +50,9 @@ void writePerfDataJSON(
SS << DirectoryName << "/" << static_cast<int>(T.getWallTime()) << "_" << Pid
<< ".json";
std::error_code EC;
llvm::raw_fd_ostream FileStream(SS.str(), EC, llvm::sys::fs::F_Text);
std::string ErrorInfo;
llvm::raw_fd_ostream FileStream(SS.str().c_str(), ErrorInfo,
llvm::sys::fs::F_Text);
FileStream << "{\n";
FileStream << " \"Sources\" : [\n";
for (SourcePerfData::const_iterator I = TimingResults.begin(),

View File

@@ -25,12 +25,11 @@ using namespace llvm::sys;
using namespace clang::tooling;
bool ReplacementHandling::findClangApplyReplacements(const char *Argv0) {
ErrorOr<std::string> CARPathOrErr =
findProgramByName("clang-apply-replacements");
if (!CARPathOrErr)
CARPath = FindProgramByName("clang-apply-replacements");
if (!CARPath.empty())
return true;
CARPath = *CARPathOrErr;
static int StaticSymbol;
std::string ClangModernizePath = fs::getMainExecutable(Argv0, &StaticSymbol);
SmallString<128> TestPath = path::parent_path(ClangModernizePath);
@@ -73,10 +72,11 @@ bool ReplacementHandling::serializeReplacements(
continue;
}
std::error_code EC;
raw_fd_ostream ReplacementsFile(ReplacementsFileName, EC, fs::F_None);
if (EC) {
errs() << "Error opening file: " << EC.message() << "\n";
std::string ErrorInfo;
raw_fd_ostream ReplacementsFile(ReplacementsFileName.c_str(), ErrorInfo,
fs::F_None);
if (!ErrorInfo.empty()) {
errs() << "Error opening file: " << ErrorInfo << "\n";
Errors = true;
continue;
}

View File

@@ -39,7 +39,7 @@ public:
ActionFactory(MatchFinder &Finder, Transform &Owner)
: Finder(Finder), Owner(Owner) {}
FrontendAction *create() override {
virtual FrontendAction *create() override {
return new FactoryAdaptor(Finder, Owner);
}
@@ -49,8 +49,7 @@ private:
FactoryAdaptor(MatchFinder &Finder, Transform &Owner)
: Finder(Finder), Owner(Owner) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &,
StringRef) override {
ASTConsumer *CreateASTConsumer(CompilerInstance &, StringRef) {
return Finder.newASTConsumer();
}
@@ -62,7 +61,7 @@ private:
return Owner.handleBeginSource(CI, Filename);
}
void EndSourceFileAction() override {
virtual void EndSourceFileAction() override {
Owner.handleEndSource();
return ASTFrontendAction::EndSourceFileAction();
}
@@ -129,9 +128,8 @@ Transform::addReplacementForCurrentTU(const clang::tooling::Replacement &R) {
return true;
}
std::unique_ptr<FrontendActionFactory>
Transform::createActionFactory(MatchFinder &Finder) {
return llvm::make_unique<ActionFactory>(Finder, /*Owner=*/*this);
FrontendActionFactory *Transform::createActionFactory(MatchFinder &Finder) {
return new ActionFactory(Finder, /*Owner=*/ *this);
}
Version Version::getFromString(llvm::StringRef VersionStr) {

View File

@@ -208,8 +208,8 @@ protected:
///
/// The factory returned by this function is responsible for calling back to
/// Transform to call handleBeginSource() and handleEndSource().
std::unique_ptr<clang::tooling::FrontendActionFactory>
createActionFactory(clang::ast_matchers::MatchFinder &Finder);
clang::tooling::FrontendActionFactory *
createActionFactory(clang::ast_matchers::MatchFinder &Finder);
private:
const std::string Name;

View File

@@ -48,7 +48,7 @@ int LoopConvertTransform::apply(const CompilationDatabase &Database,
LFK_PseudoArray, /*Owner=*/ *this);
Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer);
if (int result = LoopTool.run(createActionFactory(Finder).get())) {
if (int result = LoopTool.run(createActionFactory(Finder))) {
llvm::errs() << "Error encountered during translation.\n";
return result;
}

View File

@@ -35,7 +35,7 @@ int PassByValueTransform::apply(const tooling::CompilationDatabase &Database,
// make the replacer available to handleBeginSource()
this->Replacer = &Replacer;
if (Tool.run(createActionFactory(Finder).get())) {
if (Tool.run(createActionFactory(Finder))) {
llvm::errs() << "Error encountered during translation.\n";
return 1;
}

View File

@@ -34,7 +34,7 @@ ReplaceAutoPtrTransform::apply(const CompilationDatabase &Database,
Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer);
Finder.addMatcher(makeTransferOwnershipExprMatcher(), &Fixer);
if (Tool.run(createActionFactory(Finder).get())) {
if (Tool.run(createActionFactory(Finder))) {
llvm::errs() << "Error encountered during translation.\n";
return 1;
}

View File

@@ -36,7 +36,7 @@ int UseAutoTransform::apply(const clang::tooling::CompilationDatabase &Database,
Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
if (int Result = UseAutoTool.run(createActionFactory(Finder).get())) {
if (int Result = UseAutoTool.run(createActionFactory(Finder))) {
llvm::errs() << "Error encountered during translation.\n";
return Result;
}

View File

@@ -383,27 +383,27 @@ private:
assert(MacroLoc.isFileID());
do {
const auto &Parents = Context.getParents(Start);
ASTContext::ParentVector Parents = Context.getParents(Start);
if (Parents.empty())
return false;
assert(Parents.size() == 1 &&
"Found an ancestor with more than one parent!");
const ast_type_traits::DynTypedNode &Parent = Parents[0];
ASTContext::ParentVector::const_iterator I = Parents.begin();
SourceLocation Loc;
if (const Decl *D = Parent.get<Decl>())
if (const Decl *D = I->get<Decl>())
Loc = D->getLocStart();
else if (const Stmt *S = Parent.get<Stmt>())
else if (const Stmt *S = I->get<Stmt>())
Loc = S->getLocStart();
else
llvm_unreachable("Expected to find Decl or Stmt containing ancestor");
if (!expandsFrom(Loc, MacroLoc)) {
Result = Parent;
Result = *I;
return true;
}
Start = Parent;
Start = *I;
} while (1);
llvm_unreachable("findContainingAncestor");

View File

@@ -46,7 +46,8 @@ int UseNullptrTransform::apply(const CompilationDatabase &Database,
NullptrFixer Fixer(AcceptedChanges, MacroNames, /*Owner=*/ *this);
Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
if (int result = UseNullptrTool.run(createActionFactory(Finder).get())) {
if (int result = UseNullptrTool.run(createActionFactory(Finder))) {
llvm::errs() << "Error encountered during translation.\n";
return result;
}

View File

@@ -41,7 +41,6 @@ target_link_libraries(clang-modernize
clangFrontend
clangLex
clangTooling
clangToolingCore
modernizeCore
)

View File

@@ -248,15 +248,14 @@ static CompilerVersions handleSupportedCompilers(const char *ProgName,
return RequiredVersions;
}
std::unique_ptr<CompilationDatabase>
autoDetectCompilations(std::string &ErrorMessage) {
CompilationDatabase *autoDetectCompilations(std::string &ErrorMessage) {
// Auto-detect a compilation database from BuildPath.
if (BuildPath.getNumOccurrences() > 0)
return CompilationDatabase::autoDetectFromDirectory(BuildPath,
ErrorMessage);
// Try to auto-detect a compilation database from the first source.
if (!SourcePaths.empty()) {
if (std::unique_ptr<CompilationDatabase> Compilations =
if (CompilationDatabase *Compilations =
CompilationDatabase::autoDetectFromSource(SourcePaths[0],
ErrorMessage)) {
// FIXME: just pass SourcePaths[0] once getCompileCommands supports
@@ -276,7 +275,7 @@ autoDetectCompilations(std::string &ErrorMessage) {
// If no compilation database can be detected from source then we create a
// fixed compilation database with c++11 support.
std::string CommandLine[] = { "-std=c++11" };
return llvm::make_unique<FixedCompilationDatabase>(".", CommandLine);
return new FixedCompilationDatabase(".", CommandLine);
}
ErrorMessage = "Could not determine sources to transform";
@@ -335,7 +334,7 @@ int main(int argc, const char **argv) {
if (!Compilations) {
std::string ErrorMessage;
Compilations = autoDetectCompilations(ErrorMessage);
Compilations.reset(autoDetectCompilations(ErrorMessage));
if (!Compilations) {
llvm::errs() << llvm::sys::path::filename(argv[0]) << ": " << ErrorMessage
<< "\n";

View File

@@ -36,8 +36,7 @@ SOURCES += $(addprefix ../ReplaceAutoPtr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/..
BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option
USEDLIBS = modernizeCore.a clangFormat.a \
clangTooling.a clangToolingCore.a clangFrontend.a \
USEDLIBS = modernizeCore.a clangFormat.a clangTooling.a clangFrontend.a \
clangSerialization.a clangDriver.a clangRewriteFrontend.a \
clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a

View File

@@ -92,8 +92,8 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const {
TD.emitDiagnostic(
R.getBegin(), DiagnosticsEngine::Note,
"\"" + BI->first + "\" binds here",
CharSourceRange::getTokenRange(R),
None, &AST->getSourceManager());
ArrayRef<CharSourceRange>(CharSourceRange::getTokenRange(R)),
ArrayRef<FixItHint>(), &AST->getSourceManager());
}
break;
}

View File

@@ -157,12 +157,23 @@ QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
return new InvalidQuery(OS.str());
}
class QuerySessionSema : public Parser::RegistrySema {
public:
QuerySessionSema(const QuerySession &QS) : QS(QS) {}
ast_matchers::dynamic::VariantValue getNamedValue(StringRef Name) override {
return QS.NamedValues.lookup(Name);
}
private:
const QuerySession &QS;
};
} // namespace
QueryRef QueryParser::completeMatcherExpression() {
std::vector<MatcherCompletion> Comps = Parser::completeExpression(
StringRef(Begin, End - Begin), CompletionPos - Begin, nullptr,
&QS.NamedValues);
StringRef(Begin, End - Begin), CompletionPos - Begin);
for (std::vector<MatcherCompletion>::iterator I = Comps.begin(),
E = Comps.end();
I != E; ++I) {
@@ -183,6 +194,8 @@ QueryRef QueryParser::doParse() {
.Case("unlet", PQK_Unlet)
.Default(PQK_Invalid);
QuerySessionSema S(QS);
switch (QKind) {
case PQK_NoOp:
return new NoOpQuery;
@@ -201,8 +214,8 @@ QueryRef QueryParser::doParse() {
Diagnostics Diag;
ast_matchers::dynamic::VariantValue Value;
if (!Parser::parseExpression(StringRef(Begin, End - Begin), nullptr,
&QS.NamedValues, &Value, &Diag)) {
if (!Parser::parseExpression(StringRef(Begin, End - Begin), &S, &Value,
&Diag)) {
return makeInvalidQueryFromDiagnostics(Diag);
}
@@ -215,7 +228,7 @@ QueryRef QueryParser::doParse() {
Diagnostics Diag;
Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
StringRef(Begin, End - Begin), nullptr, &QS.NamedValues, &Diag);
StringRef(Begin, End - Begin), &S, &Diag);
if (!Matcher) {
return makeInvalidQueryFromDiagnostics(Diag);
}

View File

@@ -30,7 +30,7 @@
#include "QueryParser.h"
#include "QuerySession.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/LineEditor/LineEditor.h"
#include "llvm/Support/CommandLine.h"
@@ -46,30 +46,45 @@ using namespace clang::query;
using namespace clang::tooling;
using namespace llvm;
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
static cl::OptionCategory ClangQueryCategory("clang-query options");
static cl::opt<std::string> BuildPath("b", cl::desc("Specify build path"),
cl::value_desc("<path>"));
static cl::list<std::string> Commands("c", cl::desc("Specify command to run"),
cl::value_desc("command"),
cl::cat(ClangQueryCategory));
cl::value_desc("<command>"));
static cl::list<std::string> CommandFiles("f",
cl::desc("Read commands from file"),
cl::value_desc("file"),
cl::cat(ClangQueryCategory));
cl::value_desc("<file>"));
static cl::list<std::string> SourcePaths(cl::Positional,
cl::desc("<source0> [... <sourceN>]"),
cl::OneOrMore);
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
CommonOptionsParser OptionsParser(argc, argv, ClangQueryCategory);
cl::ParseCommandLineOptions(argc, argv);
if (!Commands.empty() && !CommandFiles.empty()) {
llvm::errs() << argv[0] << ": cannot specify both -c and -f\n";
return 1;
}
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
std::unique_ptr<CompilationDatabase> Compilations(
FixedCompilationDatabase::loadFromCommandLine(argc, argv));
if (!Compilations) { // Couldn't find a compilation DB from the command line
std::string ErrorMessage;
Compilations.reset(
!BuildPath.empty() ?
CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage) :
CompilationDatabase::autoDetectFromSource(SourcePaths[0], ErrorMessage)
);
// Still no compilation DB? - bail.
if (!Compilations)
llvm::report_fatal_error(ErrorMessage);
}
ClangTool Tool(*Compilations, SourcePaths);
std::vector<std::unique_ptr<ASTUnit>> ASTs;
if (Tool.buildASTs(ASTs) != 0)
return 1;

View File

@@ -1,16 +0,0 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangRename
USRFinder.cpp
USRFindingAction.cpp
USRLocFinder.cpp
RenamingAction.cpp
LINK_LIBS
clangAST
clangBasic
clangIndex
clangToolingCore
)
add_subdirectory(tool)

View File

@@ -1,16 +0,0 @@
##===- tools/extra/clang-rename/Makefile -------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ../../..
LIBRARYNAME = clangRename
include $(CLANG_LEVEL)/../../Makefile.config
DIRS = tool
include $(CLANG_LEVEL)/Makefile

View File

@@ -1,90 +0,0 @@
//===--- 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/Preprocessor.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string>
#include <vector>
using namespace llvm;
namespace clang {
namespace rename {
class RenamingASTConsumer : public ASTConsumer {
public:
RenamingASTConsumer(const std::string &NewName,
const std::string &PrevName,
const std::vector<std::string> &USRs,
tooling::Replacements &Replaces,
bool PrintLocations)
: NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces),
PrintLocations(PrintLocations) {
}
void HandleTranslationUnit(ASTContext &Context) override {
const auto &SourceMgr = Context.getSourceManager();
std::vector<SourceLocation> RenamingCandidates;
std::vector<SourceLocation> NewCandidates;
for (const auto &USR : USRs) {
NewCandidates = getLocationsOfUSR(USR, Context.getTranslationUnitDecl());
RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(),
NewCandidates.end());
NewCandidates.clear();
}
auto PrevNameLen = PrevName.length();
if (PrintLocations)
for (const auto &Loc : RenamingCandidates) {
FullSourceLoc FullLoc(Loc, SourceMgr);
errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc)
<< ":" << FullLoc.getSpellingLineNumber() << ":"
<< FullLoc.getSpellingColumnNumber() << "\n";
Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen,
NewName));
}
else
for (const auto &Loc : RenamingCandidates)
Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen,
NewName));
}
private:
const std::string &NewName, &PrevName;
const std::vector<std::string> &USRs;
tooling::Replacements &Replaces;
bool PrintLocations;
};
std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() {
return llvm::make_unique<RenamingASTConsumer>(NewName, PrevName, USRs,
Replaces, PrintLocations);
}
}
}

View File

@@ -1,47 +0,0 @@
//===--- 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::string &NewName, const std::string &PrevName,
const std::vector<std::string> &USRs,
tooling::Replacements &Replaces, bool PrintLocations = false)
: NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces),
PrintLocations(PrintLocations) {
}
std::unique_ptr<ASTConsumer> newASTConsumer();
private:
const std::string &NewName, &PrevName;
const std::vector<std::string> &USRs;
tooling::Replacements &Replaces;
bool PrintLocations;
};
}
}
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H_

View File

@@ -1,162 +0,0 @@
//===--- 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/Lex/Lexer.h"
#include "clang/Index/USRGeneration.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 SourceManager &SourceMgr,
const SourceLocation Point)
: Result(nullptr), SourceMgr(SourceMgr),
Point(Point) {
}
// 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 setResult(Decl, Decl->getLocation(),
Decl->getNameAsString().length());
}
// Expression visitors:
bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
// Check the namespace specifier first.
if (!checkNestedNameSpecifierLoc(Expr->getQualifierLoc()))
return false;
const auto *Decl = Expr->getFoundDecl();
return setResult(Decl, Expr->getLocation(),
Decl->getNameAsString().length());
}
bool VisitMemberExpr(const MemberExpr *Expr) {
const auto *Decl = Expr->getFoundDecl().getDecl();
return setResult(Decl, Expr->getMemberLoc(),
Decl->getNameAsString().length());
}
// Other:
const NamedDecl *getNamedDecl() {
return Result;
}
private:
// \brief Determines if a namespace qualifier contains the point.
// \returns false on success and sets Result.
bool checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
while (NameLoc) {
const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace();
if (Decl && !setResult(Decl, NameLoc.getLocalBeginLoc(),
Decl->getNameAsString().length()))
return false;
NameLoc = NameLoc.getPrefix();
}
return true;
}
// \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 (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
!End.isFileID() || !isPointWithin(Start, End)) {
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 ||
(SourceMgr.isBeforeInTranslationUnit(Start, Point) &&
SourceMgr.isBeforeInTranslationUnit(Point, End));
}
const NamedDecl *Result;
const SourceManager &SourceMgr;
const SourceLocation Point; // The location to find the NamedDecl.
};
}
const NamedDecl *getNamedDeclAt(const ASTContext &Context,
const SourceLocation Point) {
const auto &SourceMgr = Context.getSourceManager();
const auto SearchFile = SourceMgr.getFilename(Point);
NamedDeclFindingASTVisitor Visitor(SourceMgr, Point);
// We only want to search the decls that exist in the same file as the point.
auto Decls = Context.getTranslationUnitDecl()->decls();
for (auto &CurrDecl : Decls) {
const auto FileLoc = CurrDecl->getLocStart();
const auto FileName = SourceMgr.getFilename(FileLoc);
// FIXME: Add test.
if (FileName == SearchFile) {
Visitor.TraverseDecl(CurrDecl);
if (const NamedDecl *Result = Visitor.getNamedDecl()) {
return Result;
}
}
}
return nullptr;
}
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 clang
} // namespace rename

View File

@@ -1,39 +0,0 @@
//===--- 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 <string>
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);
// Converts a Decl into a USR.
std::string getUSRForDecl(const Decl *Decl);
}
}
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H

View File

@@ -1,118 +0,0 @@
//===--- 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 rename every symbol at a point.
///
//===----------------------------------------------------------------------===//
#include "USRFindingAction.h"
#include "USRFinder.h"
#include "clang/AST/AST.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/Preprocessor.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string>
#include <vector>
using namespace llvm;
namespace clang {
namespace rename {
// Get the USRs for the constructors of the class.
static std::vector<std::string> getAllConstructorUSRs(
const CXXRecordDecl *Decl) {
std::vector<std::string> USRs;
// We need to get the definition of the record (as opposed to any forward
// declarations) in order to find the constructor and destructor.
const auto *RecordDecl = Decl->getDefinition();
// Iterate over all the constructors and add their USRs.
for (const auto &CtorDecl : RecordDecl->ctors())
USRs.push_back(getUSRForDecl(CtorDecl));
// Ignore destructors. GetLocationsOfUSR will find the declaration of and
// explicit calls to a destructor through TagTypeLoc (and it is better for the
// purpose of renaming).
//
// For example, in the following code segment,
// 1 class C {
// 2 ~C();
// 3 };
// At line 3, there is a NamedDecl starting from '~' and a TagTypeLoc starting
// from 'C'.
return USRs;
}
struct NamedDeclFindingConsumer : public ASTConsumer {
void HandleTranslationUnit(ASTContext &Context) override {
const auto &SourceMgr = Context.getSourceManager();
// The file we look for the USR in will always be the main source file.
const auto Point = SourceMgr.getLocForStartOfFile(
SourceMgr.getMainFileID()).getLocWithOffset(SymbolOffset);
if (!Point.isValid())
return;
const NamedDecl *FoundDecl = getNamedDeclAt(Context, Point);
if (FoundDecl == nullptr) {
FullSourceLoc FullLoc(Point, SourceMgr);
errs() << "clang-rename: could not find symbol at "
<< SourceMgr.getFilename(Point) << ":"
<< FullLoc.getSpellingLineNumber() << ":"
<< FullLoc.getSpellingColumnNumber() << " (offset " << SymbolOffset
<< ").\n";
return;
}
// If the decl is a constructor or destructor, we want to instead take the
// decl of the parent record.
if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
FoundDecl = CtorDecl->getParent();
else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
FoundDecl = DtorDecl->getParent();
// If the decl is in any way relatedpp to a class, we want to make sure we
// search for the constructor and destructor as well as everything else.
if (const auto *Record = dyn_cast<CXXRecordDecl>(FoundDecl))
*USRs = getAllConstructorUSRs(Record);
USRs->push_back(getUSRForDecl(FoundDecl));
*SpellingName = FoundDecl->getNameAsString();
}
unsigned SymbolOffset;
std::string *SpellingName;
std::vector<std::string> *USRs;
};
std::unique_ptr<ASTConsumer>
USRFindingAction::newASTConsumer() {
std::unique_ptr<NamedDeclFindingConsumer> Consumer(
new NamedDeclFindingConsumer);
SpellingName = "";
Consumer->SymbolOffset = SymbolOffset;
Consumer->USRs = &USRs;
Consumer->SpellingName = &SpellingName;
return std::move(Consumer);
}
} // namespace rename
} // namespace clang

View File

@@ -1,50 +0,0 @@
//===--- 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 relevent 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/Frontend/FrontendAction.h"
namespace clang {
class ASTConsumer;
class CompilerInstance;
class NamedDecl;
namespace rename {
struct USRFindingAction {
USRFindingAction(unsigned Offset) : SymbolOffset(Offset) {
}
std::unique_ptr<ASTConsumer> newASTConsumer();
// \brief get the spelling of the USR(s) as it would appear in source files.
const std::string &getUSRSpelling() {
return SpellingName;
}
const std::vector<std::string> &getUSRs() {
return USRs;
}
private:
unsigned SymbolOffset;
std::string SpellingName;
std::vector<std::string> USRs;
};
}
}
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H_

View File

@@ -1,103 +0,0 @@
//===--- 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/SourceLocation.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/SmallVector.h"
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::string USR) : USR(USR) {
}
// Declaration visitors:
bool VisitNamedDecl(const NamedDecl *Decl) {
if (getUSRForDecl(Decl) == USR) {
LocationsFound.push_back(Decl->getLocation());
}
return true;
}
// Expression visitors:
bool VisitDeclRefExpr(const DeclRefExpr *Expr) {
const auto *Decl = Expr->getFoundDecl();
checkNestedNameSpecifierLoc(Expr->getQualifierLoc());
if (getUSRForDecl(Decl) == USR) {
LocationsFound.push_back(Expr->getLocation());
}
return true;
}
bool VisitMemberExpr(const MemberExpr *Expr) {
const auto *Decl = Expr->getFoundDecl().getDecl();
if (getUSRForDecl(Decl) == USR) {
LocationsFound.push_back(Expr->getMemberLoc());
}
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;
}
private:
// Namespace traversal:
void checkNestedNameSpecifierLoc(NestedNameSpecifierLoc NameLoc) {
while (NameLoc) {
const auto *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace();
if (Decl && getUSRForDecl(Decl) == USR)
LocationsFound.push_back(NameLoc.getLocalBeginLoc());
NameLoc = NameLoc.getPrefix();
}
}
// All the locations of the USR were found.
const std::string USR;
std::vector<clang::SourceLocation> LocationsFound;
};
} // namespace
std::vector<SourceLocation> getLocationsOfUSR(const std::string USR,
Decl *Decl) {
USRLocFindingASTVisitor visitor(USR);
visitor.TraverseDecl(Decl);
return visitor.getLocationsFound();
}
} // namespace rename
} // namespace clang

View File

@@ -1,35 +0,0 @@
//===--- 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 <string>
#include <vector>
namespace clang {
class Decl;
class SourceLocation;
namespace rename {
// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
std::vector<SourceLocation> getLocationsOfUSR(const std::string usr,
Decl *decl);
}
}
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H

View File

@@ -1,11 +0,0 @@
add_clang_executable(clang-rename ClangRename.cpp)
target_link_libraries(clang-rename
clangBasic
clangFrontend
clangRename
clangRewrite
clangTooling
)
install(TARGETS clang-rename RUNTIME DESTINATION bin)

View File

@@ -1,151 +0,0 @@
//===--- tools/extra/clang-rename/ClangRename.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 This file implements a clang-rename tool that automatically finds and
/// renames symbols in C++ code.
///
//===----------------------------------------------------------------------===//
#include "../USRFindingAction.h"
#include "../RenamingAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CommandLineSourceLoc.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Lexer.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/Host.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string>
#include <vector>
using namespace llvm;
cl::OptionCategory ClangRenameCategory("Clang-rename options");
static cl::opt<std::string>
NewName(
"new-name",
cl::desc("The new name to change the symbol to."),
cl::cat(ClangRenameCategory));
static cl::opt<unsigned>
SymbolOffset(
"offset",
cl::desc("Locates the symbol by offset as opposed to <line>:<column>."),
cl::cat(ClangRenameCategory));
static cl::opt<bool>
Inplace(
"i",
cl::desc("Overwrite edited <file>s."),
cl::cat(ClangRenameCategory));
static cl::opt<bool>
PrintName(
"pn",
cl::desc("Print the found symbol's name prior to renaming to stderr."),
cl::cat(ClangRenameCategory));
static cl::opt<bool>
PrintLocations(
"pl",
cl::desc("Print the locations affected by renaming to stderr."),
cl::cat(ClangRenameCategory));
#define CLANG_RENAME_VERSION "0.0.1"
static void PrintVersion() {
outs() << "clang-rename version " << CLANG_RENAME_VERSION << "\n";
}
using namespace clang;
const char RenameUsage[] = "A tool to rename symbols in C/C++ code.\n\
clang-rename renames every occurrence of a symbol found at <offset> in\n\
<source0>. If -i is specified, the edited files are overwritten to disk.\n\
Otherwise, the results are written to stdout.\n";
int main(int argc, const char **argv) {
cl::SetVersionPrinter(PrintVersion);
tooling::CommonOptionsParser OP(argc, argv, ClangRenameCategory, RenameUsage);
// Check the arguments for correctness.
if (NewName.empty()) {
errs() << "clang-rename: no new name provided.\n\n";
cl::PrintHelpMessage();
exit(1);
}
// Get the USRs.
auto Files = OP.getSourcePathList();
tooling::RefactoringTool Tool(OP.getCompilations(), Files);
rename::USRFindingAction USRAction(SymbolOffset);
// Find the USRs.
Tool.run(tooling::newFrontendActionFactory(&USRAction).get());
const auto &USRs = USRAction.getUSRs();
const auto &PrevName = USRAction.getUSRSpelling();
if (PrevName.empty())
// An error should have already been printed.
exit(1);
if (PrintName)
errs() << "clang-rename: found name: " << PrevName;
// Perform the renaming.
rename::RenamingAction RenameAction(NewName, PrevName, USRs,
Tool.getReplacements(), PrintLocations);
auto Factory = tooling::newFrontendActionFactory(&RenameAction);
int res;
if (Inplace) {
res = Tool.runAndSave(Factory.get());
} else {
res = Tool.run(Factory.get());
// Write every file to stdout. Right now we just barf the files without any
// indication of which files start where, other than that we print the files
// in the same order we see them.
LangOptions DefaultLangOptions;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
new DiagnosticOptions();
TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
&*DiagOpts, &DiagnosticPrinter, false);
auto &FileMgr = Tool.getFiles();
SourceManager Sources(Diagnostics, FileMgr);
Rewriter Rewrite(Sources, DefaultLangOptions);
Tool.applyAllReplacements(Rewrite);
for (const auto &File : Files) {
const auto *Entry = FileMgr.getFile(File);
auto ID = Sources.translateFile(Entry);
Rewrite.getEditBuffer(ID).write(outs());
}
}
exit(res);
}

View File

@@ -1,13 +0,0 @@
CLANG_LEVEL := ../../../..
TOOLNAME = clang-rename
include $(CLANG_LEVEL)/../../Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
USEDLIBS = clangRename.a clangFrontend.a clangSerialization.a clangDriver.a \
clangTooling.a clangToolingCore.a \
clangParse.a clangSema.a clangIndex.a \
clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
clangStaticAnalyzerCore.a clangAnalysis.a clangRewriteFrontend.a \
clangRewrite.a clangEdit.a clangAST.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile

View File

@@ -21,12 +21,9 @@ add_clang_library(clangTidy
clangStaticAnalyzerCore
clangStaticAnalyzerFrontend
clangTooling
clangToolingCore
)
add_subdirectory(tool)
add_subdirectory(llvm)
add_subdirectory(google)
add_subdirectory(misc)
add_subdirectory(readability)
add_subdirectory(utils)

View File

@@ -34,7 +34,6 @@
#include "clang/Rewrite/Frontend/FrontendActions.h"
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/ReplacementsYaml.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
@@ -180,10 +179,10 @@ private:
class ClangTidyASTConsumer : public MultiplexConsumer {
public:
ClangTidyASTConsumer(std::vector<std::unique_ptr<ASTConsumer>> Consumers,
ClangTidyASTConsumer(const SmallVectorImpl<ASTConsumer *> &Consumers,
std::unique_ptr<ast_matchers::MatchFinder> Finder,
std::vector<std::unique_ptr<ClangTidyCheck>> Checks)
: MultiplexConsumer(std::move(Consumers)), Finder(std::move(Finder)),
: MultiplexConsumer(Consumers), Finder(std::move(Finder)),
Checks(std::move(Checks)) {}
private:
@@ -204,8 +203,8 @@ ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
}
}
std::unique_ptr<clang::ASTConsumer>
ClangTidyASTConsumerFactory::CreateASTConsumer(
clang::ASTConsumer *ClangTidyASTConsumerFactory::CreateASTConsumer(
clang::CompilerInstance &Compiler, StringRef File) {
// FIXME: Move this to a separate method, so that CreateASTConsumer doesn't
// modify Compiler.
@@ -214,21 +213,18 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
Context.setASTContext(&Compiler.getASTContext());
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
CheckFactories->createChecks(&Context, Checks);
ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
if (auto *P = Context.getCheckProfileData())
FinderOptions.CheckProfiling.emplace(P->Records);
ChecksFilter &Filter = Context.getChecksFilter();
CheckFactories->createChecks(Filter, Checks);
std::unique_ptr<ast_matchers::MatchFinder> Finder(
new ast_matchers::MatchFinder(std::move(FinderOptions)));
new ast_matchers::MatchFinder);
for (auto &Check : Checks) {
Check->setContext(&Context);
Check->registerMatchers(&*Finder);
Check->registerPPCallbacks(Compiler);
}
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
SmallVector<ASTConsumer *, 2> Consumers;
if (!Checks.empty())
Consumers.push_back(Finder->newASTConsumer());
@@ -238,28 +234,28 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
AnalyzerOptions->Config["cfg-temporary-dtors"] =
Context.getOptions().AnalyzeTemporaryDtors ? "true" : "false";
GlobList &Filter = Context.getChecksFilter();
AnalyzerOptions->CheckersControlList = getCheckersControlList(Filter);
if (!AnalyzerOptions->CheckersControlList.empty()) {
AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
AnalyzerOptions->AnalysisDiagOpt = PD_NONE;
AnalyzerOptions->AnalyzeNestedBlocks = true;
AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true;
std::unique_ptr<ento::AnalysisASTConsumer> AnalysisConsumer =
ento::CreateAnalysisConsumer(Compiler);
ento::AnalysisASTConsumer *AnalysisConsumer = ento::CreateAnalysisConsumer(
Compiler.getPreprocessor(), Compiler.getFrontendOpts().OutputFile,
AnalyzerOptions, Compiler.getFrontendOpts().Plugins);
AnalysisConsumer->AddDiagnosticConsumer(
new AnalyzerDiagnosticConsumer(Context));
Consumers.push_back(std::move(AnalysisConsumer));
Consumers.push_back(AnalysisConsumer);
}
return llvm::make_unique<ClangTidyASTConsumer>(
std::move(Consumers), std::move(Finder), std::move(Checks));
return new ClangTidyASTConsumer(Consumers, std::move(Finder),
std::move(Checks));
}
std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
std::vector<std::string>
ClangTidyASTConsumerFactory::getCheckNames(ChecksFilter &Filter) {
std::vector<std::string> CheckNames;
GlobList &Filter = Context.getChecksFilter();
for (const auto &CheckFactory : *CheckFactories) {
if (Filter.contains(CheckFactory.first))
if (Filter.isCheckEnabled(CheckFactory.first))
CheckNames.push_back(CheckFactory.first);
}
@@ -270,17 +266,8 @@ std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
return CheckNames;
}
ClangTidyOptions::OptionMap ClangTidyASTConsumerFactory::getCheckOptions() {
ClangTidyOptions::OptionMap Options;
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
CheckFactories->createChecks(&Context, Checks);
for (const auto &Check : Checks)
Check->storeOptions(Options);
return Options;
}
ClangTidyASTConsumerFactory::CheckersList
ClangTidyASTConsumerFactory::getCheckersControlList(GlobList &Filter) {
ClangTidyASTConsumerFactory::getCheckersControlList(ChecksFilter &Filter) {
CheckersList List;
bool AnalyzerChecksEnabled = false;
@@ -288,7 +275,7 @@ ClangTidyASTConsumerFactory::getCheckersControlList(GlobList &Filter) {
std::string Checker((AnalyzerCheckNamePrefix + CheckName).str());
AnalyzerChecksEnabled =
AnalyzerChecksEnabled ||
(!CheckName.startswith("debug") && Filter.contains(Checker));
(!CheckName.startswith("debug") && Filter.isCheckEnabled(Checker));
}
if (AnalyzerChecksEnabled) {
@@ -303,7 +290,7 @@ ClangTidyASTConsumerFactory::getCheckersControlList(GlobList &Filter) {
std::string Checker((AnalyzerCheckNamePrefix + CheckName).str());
if (CheckName.startswith("core") ||
(!CheckName.startswith("debug") && Filter.contains(Checker)))
(!CheckName.startswith("debug") && Filter.isCheckEnabled(Checker)))
List.push_back(std::make_pair(CheckName, true));
}
}
@@ -320,68 +307,40 @@ void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
check(Result);
}
OptionsView::OptionsView(StringRef CheckName,
const ClangTidyOptions::OptionMap &CheckOptions)
: NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {}
std::string OptionsView::get(StringRef LocalName, std::string Default) const {
const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str());
if (Iter != CheckOptions.end())
return Iter->second;
return Default;
}
void OptionsView::store(ClangTidyOptions::OptionMap &Options,
StringRef LocalName, StringRef Value) const {
Options[NamePrefix + LocalName.str()] = Value;
}
void OptionsView::store(ClangTidyOptions::OptionMap &Options,
StringRef LocalName, int64_t Value) const {
store(Options, LocalName, llvm::itostr(Value));
void ClangTidyCheck::setName(StringRef Name) {
assert(CheckName.empty());
CheckName = Name.str();
}
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) {
clang::tidy::ClangTidyContext Context(
llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
Options));
new DefaultOptionsProvider(ClangTidyGlobalOptions(), Options));
ClangTidyASTConsumerFactory Factory(Context);
return Factory.getCheckNames();
return Factory.getCheckNames(Context.getChecksFilter());
}
ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options) {
clang::tidy::ClangTidyContext Context(
llvm::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(),
Options));
ClangTidyASTConsumerFactory Factory(Context);
return Factory.getCheckOptions();
}
ClangTidyStats
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
std::vector<ClangTidyError> *Errors, ProfileData *Profile) {
ClangTidyStats runClangTidy(ClangTidyOptionsProvider *OptionsProvider,
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
std::vector<ClangTidyError> *Errors) {
ClangTool Tool(Compilations, InputFiles);
clang::tidy::ClangTidyContext Context(std::move(OptionsProvider));
if (Profile)
Context.setCheckProfileData(Profile);
clang::tidy::ClangTidyContext Context(OptionsProvider);
ClangTidyDiagnosticConsumer DiagConsumer(Context);
Tool.setDiagnosticConsumer(&DiagConsumer);
class ActionFactory : public FrontendActionFactory {
public:
ActionFactory(ClangTidyContext &Context) : ConsumerFactory(Context) {}
FrontendAction *create() override { return new Action(&ConsumerFactory); }
ActionFactory(ClangTidyASTConsumerFactory *ConsumerFactory)
: ConsumerFactory(ConsumerFactory) {}
FrontendAction *create() override { return new Action(ConsumerFactory); }
private:
class Action : public ASTFrontendAction {
public:
Action(ClangTidyASTConsumerFactory *Factory) : Factory(Factory) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
StringRef File) override {
ASTConsumer *CreateASTConsumer(CompilerInstance &Compiler,
StringRef File) override {
return Factory->CreateASTConsumer(Compiler, File);
}
@@ -389,11 +348,10 @@ runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
ClangTidyASTConsumerFactory *Factory;
};
ClangTidyASTConsumerFactory ConsumerFactory;
ClangTidyASTConsumerFactory *ConsumerFactory;
};
ActionFactory Factory(Context);
Tool.run(&Factory);
Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context)));
*Errors = Context.getErrors();
return Context.getStats();
}
@@ -405,16 +363,5 @@ void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix) {
Reporter.Finish();
}
void exportReplacements(const std::vector<ClangTidyError> &Errors,
raw_ostream &OS) {
tooling::TranslationUnitReplacements TUR;
for (const ClangTidyError &Error : Errors)
TUR.Replacements.insert(TUR.Replacements.end(), Error.Fix.begin(),
Error.Fix.end());
yaml::Output YAML(OS);
YAML << TUR;
}
} // namespace tidy
} // namespace clang

View File

@@ -16,10 +16,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Tooling/Refactoring.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <type_traits>
#include <vector>
namespace clang {
@@ -31,55 +28,6 @@ class CompilationDatabase;
namespace tidy {
/// \brief Provides access to the \c ClangTidyCheck options via check-local
/// names.
///
/// Methods of this class prepend <tt>CheckName + "."</tt> to translate
/// check-local option names to global option names.
class OptionsView {
public:
/// \brief Initializes the instance using \p CheckName + "." as a prefix.
OptionsView(StringRef CheckName,
const ClangTidyOptions::OptionMap &CheckOptions);
/// \brief Read a named option from the \c Context.
///
/// Reads the option with the check-local name \p LocalName from the
/// \c CheckOptions. If the corresponding key is not present, returns
/// \p Default.
std::string get(StringRef LocalName, std::string Default) const;
/// \brief Read a named option from the \c Context and parse it as an integral
/// type \c T.
///
/// Reads the option with the check-local name \p LocalName from the
/// \c CheckOptions. If the corresponding key is not present, returns
/// \p Default.
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
get(StringRef LocalName, T Default) const {
std::string Value = get(LocalName, "");
T Result = Default;
if (!Value.empty())
StringRef(Value).getAsInteger(10, Result);
return Result;
}
/// \brief Stores an option with the check-local name \p LocalName with string
/// value \p Value to \p Options.
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
StringRef Value) const;
/// \brief Stores an option with the check-local name \p LocalName with
/// \c int64_t value \p Value to \p Options.
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
int64_t Value) const;
private:
std::string NamePrefix;
const ClangTidyOptions::OptionMap &CheckOptions;
};
/// \brief Base class for all clang-tidy checks.
///
/// To implement a \c ClangTidyCheck, write a subclass and overwrite some of the
@@ -101,18 +49,6 @@ private:
/// useful/necessary.
class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
public:
/// \brief Initializes the check with \p CheckName and \p Context.
///
/// Derived classes must implement the constructor with this signature or
/// delegate it. If a check needs to read options, it can do this in the
/// constructor using the Options.get() methods below.
ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
: CheckName(CheckName), Context(Context),
Options(CheckName, Context->getOptions().CheckOptions) {
assert(Context != nullptr);
assert(!CheckName.empty());
}
virtual ~ClangTidyCheck() {}
/// \brief Overwrite this to register \c PPCallbacks with \c Compiler.
@@ -139,25 +75,21 @@ public:
/// work in here.
virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {}
/// \brief The infrastructure sets the context to \p Ctx with this function.
void setContext(ClangTidyContext *Ctx) { Context = Ctx; }
/// \brief Add a diagnostic with the check's name.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
/// \brief Should store all options supported by this check with their
/// current values or default values for options that haven't been overridden.
///
/// The check should use \c Options.store() to store each option it supports
/// whether it has the default value or it has been overridden.
virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {}
/// \brief Sets the check name. Intended to be used by the clang-tidy
/// framework. Can be called only once.
void setName(StringRef Name);
private:
void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
StringRef getID() const override { return CheckName; }
std::string CheckName;
ClangTidyContext *Context;
protected:
OptionsView Options;
std::string CheckName;
};
class ClangTidyCheckFactories;
@@ -167,18 +99,15 @@ public:
ClangTidyASTConsumerFactory(ClangTidyContext &Context);
/// \brief Returns an ASTConsumer that runs the specified clang-tidy checks.
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File);
clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &Compiler,
StringRef File);
/// \brief Get the list of enabled checks.
std::vector<std::string> getCheckNames();
/// \brief Get the union of options from all checks.
ClangTidyOptions::OptionMap getCheckOptions();
std::vector<std::string> getCheckNames(ChecksFilter &Filter);
private:
typedef std::vector<std::pair<std::string, bool>> CheckersList;
CheckersList getCheckersControlList(GlobList &Filter);
typedef std::vector<std::pair<std::string, bool> > CheckersList;
CheckersList getCheckersControlList(ChecksFilter &Filter);
ClangTidyContext &Context;
std::unique_ptr<ClangTidyCheckFactories> CheckFactories;
@@ -188,24 +117,14 @@ private:
/// filters are applied.
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options);
/// \brief Returns the effective check-specific options.
///
/// The method configures ClangTidy with the specified \p Options and collects
/// effective options from all created checks. The returned set of options
/// includes default check-specific options for all keys not overridden by \p
/// Options.
ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options);
/// \brief Run a set of clang-tidy checks on a set of files.
///
/// \param Profile if provided, it enables check profile collection in
/// MatchFinder, and will contain the result of the profile.
/// Takes ownership of the \c OptionsProvider.
ClangTidyStats
runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
runClangTidy(ClangTidyOptionsProvider *OptionsProvider,
const tooling::CompilationDatabase &Compilations,
ArrayRef<std::string> InputFiles,
std::vector<ClangTidyError> *Errors,
ProfileData *Profile = nullptr);
std::vector<ClangTidyError> *Errors);
// FIXME: This interface will need to be significantly extended to be useful.
// FIXME: Implement confidence levels for displaying/fixing errors.
@@ -214,11 +133,6 @@ runClangTidy(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
/// Errors containing fixes are automatically applied.
void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix);
/// \brief Serializes replacements into YAML and writes them to the specified
/// output stream.
void exportReplacements(const std::vector<ClangTidyError> &Errors,
raw_ostream &OS);
} // end namespace tidy
} // end namespace clang

View File

@@ -146,24 +146,22 @@ static llvm::Regex ConsumeGlob(StringRef &GlobList) {
return llvm::Regex(RegexText);
}
GlobList::GlobList(StringRef Globs)
: Positive(!ConsumeNegativeIndicator(Globs)),
Regex(ConsumeGlob(Globs)),
NextGlob(Globs.empty() ? nullptr : new GlobList(Globs)) {}
ChecksFilter::ChecksFilter(StringRef GlobList)
: Positive(!ConsumeNegativeIndicator(GlobList)),
Regex(ConsumeGlob(GlobList)),
NextFilter(GlobList.empty() ? nullptr : new ChecksFilter(GlobList)) {}
bool GlobList::contains(StringRef S, bool Contains) {
if (Regex.match(S))
Contains = Positive;
bool ChecksFilter::isCheckEnabled(StringRef Name, bool Enabled) {
if (Regex.match(Name))
Enabled = Positive;
if (NextGlob)
Contains = NextGlob->contains(S, Contains);
return Contains;
if (NextFilter)
Enabled = NextFilter->isCheckEnabled(Name, Enabled);
return Enabled;
}
ClangTidyContext::ClangTidyContext(
std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider)
: DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)),
Profile(nullptr) {
ClangTidyContext::ClangTidyContext(ClangTidyOptionsProvider *OptionsProvider)
: DiagEngine(nullptr), OptionsProvider(OptionsProvider) {
// Before the first translation unit we can get errors related to command-line
// parsing, use empty string for the file name in this case.
setCurrentFile("");
@@ -204,10 +202,7 @@ void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
void ClangTidyContext::setCurrentFile(StringRef File) {
CurrentFile = File;
// Safeguard against options with unset values.
CurrentOptions = ClangTidyOptions::getDefaults().mergeWith(
OptionsProvider->getOptions(CurrentFile));
CheckFilter.reset(new GlobList(*getOptions().Checks));
CheckFilter.reset(new ChecksFilter(getOptions().Checks));
}
void ClangTidyContext::setASTContext(ASTContext *Context) {
@@ -219,14 +214,10 @@ const ClangTidyGlobalOptions &ClangTidyContext::getGlobalOptions() const {
}
const ClangTidyOptions &ClangTidyContext::getOptions() const {
return CurrentOptions;
return OptionsProvider->getOptions(CurrentFile);
}
void ClangTidyContext::setCheckProfileData(ProfileData *P) {
Profile = P;
}
GlobList &ClangTidyContext::getChecksFilter() {
ChecksFilter &ClangTidyContext::getChecksFilter() {
assert(CheckFilter != nullptr);
return *CheckFilter;
}
@@ -257,7 +248,7 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)
void ClangTidyDiagnosticConsumer::finalizeLastError() {
if (!Errors.empty()) {
ClangTidyError &Error = Errors.back();
if (!Context.getChecksFilter().contains(Error.CheckName) &&
if (!Context.getChecksFilter().isCheckEnabled(Error.CheckName) &&
Error.DiagLevel != ClangTidyError::Error) {
++Context.Stats.ErrorsIgnoredCheckFilter;
Errors.pop_back();
@@ -277,9 +268,6 @@ void ClangTidyDiagnosticConsumer::finalizeLastError() {
void ClangTidyDiagnosticConsumer::HandleDiagnostic(
DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
// Count warnings/errors.
DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
if (DiagLevel == DiagnosticsEngine::Note) {
assert(!Errors.empty() &&
"A diagnostic note can only be appended to a message.");
@@ -340,7 +328,7 @@ void ClangTidyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
const Preprocessor *PP) {
// Before the first translation unit we don't need HeaderFilter, as we
// shouldn't get valid source locations in diagnostics.
HeaderFilter.reset(new llvm::Regex(*Context.getOptions().HeaderFilterRegex));
HeaderFilter.reset(new llvm::Regex(Context.getOptions().HeaderFilterRegex));
}
bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef FileName,
@@ -370,8 +358,7 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location) {
}
const SourceManager &Sources = Diags->getSourceManager();
if (!*Context.getOptions().SystemHeaders &&
Sources.isInSystemHeader(Location))
if (Sources.isInSystemHeader(Location))
return;
// FIXME: We start with a conservative approach here, but the actual type of

View File

@@ -15,9 +15,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Tooling/Refactoring.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Timer.h"
namespace clang {
@@ -67,25 +65,24 @@ struct ClangTidyError {
Level DiagLevel;
};
/// \brief Read-only set of strings represented as a list of positive and
/// negative globs. Positive globs add all matched strings to the set, negative
/// globs remove them in the order of appearance in the list.
class GlobList {
/// \brief Filters checks by name.
class ChecksFilter {
public:
/// \brief \p GlobList is a comma-separated list of globs (only '*'
/// metacharacter is supported) with optional '-' prefix to denote exclusion.
GlobList(StringRef Globs);
ChecksFilter(StringRef GlobList);
/// \brief Returns \c true if the pattern matches \p S. The result is the last
/// matching glob's Positive flag.
bool contains(StringRef S) { return contains(S, false); }
/// \brief Returns \c true if the check with the specified \p Name should be
/// enabled. The result is the last matching glob's Positive flag. If \p Name
/// is not matched by any globs, the check is not enabled.
bool isCheckEnabled(StringRef Name) { return isCheckEnabled(Name, false); }
private:
bool contains(StringRef S, bool Contains);
bool isCheckEnabled(StringRef Name, bool Enabled);
bool Positive;
llvm::Regex Regex;
std::unique_ptr<GlobList> NextGlob;
std::unique_ptr<ChecksFilter> NextFilter;
};
/// \brief Contains displayed and ignored diagnostic counters for a ClangTidy
@@ -107,12 +104,7 @@ struct ClangTidyStats {
}
};
/// \brief Container for clang-tidy profiling data.
struct ProfileData {
llvm::StringMap<llvm::TimeRecord> Records;
};
/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
/// provided by this context.
///
/// A \c ClangTidyCheck always has access to the active context to report
@@ -124,7 +116,9 @@ struct ProfileData {
class ClangTidyContext {
public:
/// \brief Initializes \c ClangTidyContext instance.
ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider);
///
/// Takes ownership of the \c OptionsProvider.
ClangTidyContext(ClangTidyOptionsProvider *OptionsProvider);
/// \brief Report any errors detected using this method.
///
@@ -151,7 +145,7 @@ public:
StringRef getCheckName(unsigned DiagnosticID) const;
/// \brief Returns check filter for the \c CurrentFile.
GlobList &getChecksFilter();
ChecksFilter &getChecksFilter();
/// \brief Returns global options.
const ClangTidyGlobalOptions &getGlobalOptions() const;
@@ -169,13 +163,6 @@ public:
/// \brief Clears collected errors.
void clearErrors() { Errors.clear(); }
/// \brief Set the output struct for profile data.
///
/// Setting a non-null pointer here will enable profile collection in
/// clang-tidy.
void setCheckProfileData(ProfileData* Profile);
ProfileData* getCheckProfileData() const { return Profile; }
private:
// Calls setDiagnosticsEngine() and storeError().
friend class ClangTidyDiagnosticConsumer;
@@ -192,14 +179,11 @@ private:
std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
std::string CurrentFile;
ClangTidyOptions CurrentOptions;
std::unique_ptr<GlobList> CheckFilter;
std::unique_ptr<ChecksFilter> CheckFilter;
ClangTidyStats Stats;
llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
ProfileData *Profile;
};
/// \brief A diagnostic consumer that turns each \c Diagnostic into a

View File

@@ -16,24 +16,27 @@
namespace clang {
namespace tidy {
void ClangTidyCheckFactories::registerCheckFactory(StringRef Name,
CheckFactory Factory) {
ClangTidyCheckFactories::~ClangTidyCheckFactories() {
for (const auto &Factory : Factories)
delete Factory.second;
}
void ClangTidyCheckFactories::addCheckFactory(StringRef Name,
CheckFactoryBase *Factory) {
Factories[Name] = Factory;
}
void ClangTidyCheckFactories::createChecks(
ClangTidyContext *Context,
ChecksFilter &Filter,
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks) {
GlobList &Filter = Context->getChecksFilter();
for (const auto &Factory : Factories) {
if (Filter.contains(Factory.first))
Checks.emplace_back(Factory.second(Factory.first, Context));
if (Filter.isCheckEnabled(Factory.first)) {
ClangTidyCheck *Check = Factory.second->createCheck();
Check->setName(Factory.first);
Checks.emplace_back(Check);
}
}
}
ClangTidyOptions ClangTidyModule::getModuleOptions() {
return ClangTidyOptions();
}
} // namespace tidy
} // namespace clang

View File

@@ -11,73 +11,52 @@
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_MODULE_H
#include "ClangTidy.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <functional>
#include <map>
#include <string>
#include <utility>
namespace clang {
namespace tidy {
/// \brief A collection of \c ClangTidyCheckFactory instances.
/// \brief A factory, that can instantiate a specific clang-tidy check for
/// processing a translation unit.
///
/// All clang-tidy modules register their check factories with an instance of
/// this object.
class ClangTidyCheckFactories {
/// In order to register your check with the \c ClangTidyModule, create a
/// subclass of \c CheckFactoryBase and implement \c createCheck(). Then, use
/// this subclass in \c ClangTidyModule::addCheckFactories().
class CheckFactoryBase {
public:
typedef std::function<ClangTidyCheck *(
StringRef Name, ClangTidyContext *Context)> CheckFactory;
/// \brief Registers check \p Factory with name \p Name.
///
/// For all checks that have default constructors, use \c registerCheck.
void registerCheckFactory(StringRef Name, CheckFactory Factory);
/// \brief Registers the \c CheckType with the name \p Name.
///
/// This method should be used for all \c ClangTidyChecks that don't require
/// constructor parameters.
///
/// For example, if have a clang-tidy check like:
/// \code
/// class MyTidyCheck : public ClangTidyCheck {
/// void registerMatchers(ast_matchers::MatchFinder *Finder) override {
/// ..
/// }
/// };
/// \endcode
/// you can register it with:
/// \code
/// class MyModule : public ClangTidyModule {
/// void addCheckFactories(ClangTidyCheckFactories &Factories) override {
/// Factories.registerCheck<MyTidyCheck>("myproject-my-check");
/// }
/// };
/// \endcode
template <typename CheckType> void registerCheck(StringRef CheckName) {
registerCheckFactory(CheckName,
[](StringRef Name, ClangTidyContext *Context) {
return new CheckType(Name, Context);
});
}
/// \brief Create instances of all checks matching \p CheckRegexString and
/// store them in \p Checks.
///
/// The caller takes ownership of the return \c ClangTidyChecks.
void createChecks(ClangTidyContext *Context,
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks);
typedef std::map<std::string, CheckFactory> FactoryMap;
FactoryMap::const_iterator begin() const { return Factories.begin(); }
FactoryMap::const_iterator end() const { return Factories.end(); }
bool empty() const { return Factories.empty(); }
private:
FactoryMap Factories;
virtual ~CheckFactoryBase() {}
virtual ClangTidyCheck *createCheck() = 0;
};
/// \brief A subclass of \c CheckFactoryBase that should be used for all
/// \c ClangTidyChecks that don't require constructor parameters.
///
/// For example, if have a clang-tidy check like:
/// \code
/// class MyTidyCheck : public ClangTidyCheck {
/// void registerMatchers(ast_matchers::MatchFinder *Finder) override {
/// ..
/// }
/// };
/// \endcode
/// you can register it with:
/// \code
/// class MyModule : public ClangTidyModule {
/// void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
/// CheckFactories.addCheckFactory(
/// "myproject-my-check", new ClangTidyCheckFactory<MyTidyCheck>());
/// }
/// };
/// \endcode
template <typename T> class ClangTidyCheckFactory : public CheckFactoryBase {
public:
ClangTidyCheck *createCheck() override { return new T; }
};
class ClangTidyCheckFactories;
/// \brief A clang-tidy module groups a number of \c ClangTidyChecks and gives
/// them a prefixed name.
class ClangTidyModule {
@@ -87,9 +66,36 @@ public:
/// \brief Implement this function in order to register all \c CheckFactories
/// belonging to this module.
virtual void addCheckFactories(ClangTidyCheckFactories &CheckFactories) = 0;
};
/// \brief Gets default options for checks defined in this module.
virtual ClangTidyOptions getModuleOptions();
/// \brief A collection of \c ClangTidyCheckFactory instances.
///
/// All clang-tidy modules register their check factories with an instance of
/// this object.
class ClangTidyCheckFactories {
public:
ClangTidyCheckFactories() {}
~ClangTidyCheckFactories();
/// \brief Register \p Factory with the name \p Name.
///
/// The \c ClangTidyCheckFactories object takes ownership of the \p Factory.
void addCheckFactory(StringRef Name, CheckFactoryBase *Factory);
/// \brief Create instances of all checks matching \p CheckRegexString and
/// store them in \p Checks.
///
/// The caller takes ownership of the return \c ClangTidyChecks.
void createChecks(ChecksFilter &Filter,
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks);
typedef std::map<std::string, CheckFactoryBase *> FactoryMap;
FactoryMap::const_iterator begin() const { return Factories.begin(); }
FactoryMap::const_iterator end() const { return Factories.end(); }
bool empty() const { return Factories.empty(); }
private:
FactoryMap Factories;
};
} // end namespace tidy

View File

@@ -8,25 +8,13 @@
//===----------------------------------------------------------------------===//
#include "ClangTidyOptions.h"
#include "ClangTidyModuleRegistry.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/YAMLTraits.h"
#include <utility>
#define DEBUG_TYPE "clang-tidy-options"
using clang::tidy::ClangTidyOptions;
using clang::tidy::FileFilter;
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
LLVM_YAML_IS_SEQUENCE_VECTOR(ClangTidyOptions::StringPair)
namespace llvm {
namespace yaml {
@@ -59,35 +47,11 @@ template <> struct MappingTraits<FileFilter> {
}
};
template <> struct MappingTraits<ClangTidyOptions::StringPair> {
static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue) {
IO.mapRequired("key", KeyValue.first);
IO.mapRequired("value", KeyValue.second);
}
};
struct NOptionMap {
NOptionMap(IO &) {}
NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap)
: Options(OptionMap.begin(), OptionMap.end()) {}
ClangTidyOptions::OptionMap denormalize(IO &) {
ClangTidyOptions::OptionMap Map;
for (const auto &KeyValue : Options)
Map[KeyValue.first] = KeyValue.second;
return Map;
}
std::vector<ClangTidyOptions::StringPair> Options;
};
template <> struct MappingTraits<ClangTidyOptions> {
static void mapping(IO &IO, ClangTidyOptions &Options) {
MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
IO, Options.CheckOptions);
IO.mapOptional("Checks", Options.Checks);
IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors);
IO.mapOptional("User", Options.User);
IO.mapOptional("CheckOptions", NOpts->Options);
}
};
@@ -97,184 +61,19 @@ template <> struct MappingTraits<ClangTidyOptions> {
namespace clang {
namespace tidy {
ClangTidyOptions ClangTidyOptions::getDefaults() {
ClangTidyOptions Options;
Options.Checks = "";
Options.HeaderFilterRegex = "";
Options.SystemHeaders = false;
Options.AnalyzeTemporaryDtors = false;
Options.User = llvm::None;
for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
E = ClangTidyModuleRegistry::end();
I != E; ++I)
Options = Options.mergeWith(I->instantiate()->getModuleOptions());
return Options;
}
ClangTidyOptions
ClangTidyOptions::mergeWith(const ClangTidyOptions &Other) const {
ClangTidyOptions Result = *this;
// Merge comma-separated glob lists by appending the new value after a comma.
if (Other.Checks)
Result.Checks =
(Result.Checks && !Result.Checks->empty() ? *Result.Checks + "," : "") +
*Other.Checks;
if (Other.HeaderFilterRegex)
Result.HeaderFilterRegex = Other.HeaderFilterRegex;
if (Other.SystemHeaders)
Result.SystemHeaders = Other.SystemHeaders;
if (Other.AnalyzeTemporaryDtors)
Result.AnalyzeTemporaryDtors = Other.AnalyzeTemporaryDtors;
if (Other.User)
Result.User = Other.User;
for (const auto &KeyValue : Other.CheckOptions)
Result.CheckOptions[KeyValue.first] = KeyValue.second;
return Result;
}
FileOptionsProvider::FileOptionsProvider(
const ClangTidyGlobalOptions &GlobalOptions,
const ClangTidyOptions &DefaultOptions,
const ClangTidyOptions &OverrideOptions)
: DefaultOptionsProvider(GlobalOptions, DefaultOptions),
OverrideOptions(OverrideOptions) {
ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
CachedOptions[""] = DefaultOptions.mergeWith(OverrideOptions);
}
FileOptionsProvider::FileOptionsProvider(
const ClangTidyGlobalOptions &GlobalOptions,
const ClangTidyOptions &DefaultOptions,
const ClangTidyOptions &OverrideOptions,
const FileOptionsProvider::ConfigFileHandlers &ConfigHandlers)
: DefaultOptionsProvider(GlobalOptions, DefaultOptions),
OverrideOptions(OverrideOptions), ConfigHandlers(ConfigHandlers) {
CachedOptions[""] = DefaultOptions.mergeWith(OverrideOptions);
}
// FIXME: This method has some common logic with clang::format::getStyle().
// Consider pulling out common bits to a findParentFileWithName function or
// similar.
const ClangTidyOptions &FileOptionsProvider::getOptions(StringRef FileName) {
DEBUG(llvm::dbgs() << "Getting options for file " << FileName << "...\n");
SmallString<256> FilePath(FileName);
if (std::error_code EC = llvm::sys::fs::make_absolute(FilePath)) {
llvm::errs() << "Can't make absolute path from " << FileName << ": "
<< EC.message() << "\n";
// FIXME: Figure out what to do.
} else {
FileName = FilePath;
}
// Look for a suitable configuration file in all parent directories of the
// file. Start with the immediate parent directory and move up.
StringRef Path = llvm::sys::path::parent_path(FileName);
for (StringRef CurrentPath = Path;;
CurrentPath = llvm::sys::path::parent_path(CurrentPath)) {
llvm::Optional<ClangTidyOptions> Result;
auto Iter = CachedOptions.find(CurrentPath);
if (Iter != CachedOptions.end())
Result = Iter->second;
if (!Result)
Result = TryReadConfigFile(CurrentPath);
if (Result) {
// Store cached value for all intermediate directories.
while (Path != CurrentPath) {
DEBUG(llvm::dbgs() << "Caching configuration for path " << Path
<< ".\n");
CachedOptions[Path] = *Result;
Path = llvm::sys::path::parent_path(Path);
}
return CachedOptions[Path] = *Result;
}
}
}
llvm::Optional<ClangTidyOptions>
FileOptionsProvider::TryReadConfigFile(StringRef Directory) {
assert(!Directory.empty());
if (!llvm::sys::fs::is_directory(Directory)) {
llvm::errs() << "Error reading configuration from " << Directory
<< ": directory doesn't exist.\n";
return llvm::None;
}
for (const ConfigFileHandler &ConfigHandler : ConfigHandlers) {
SmallString<128> ConfigFile(Directory);
llvm::sys::path::append(ConfigFile, ConfigHandler.first);
DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
bool IsFile = false;
// Ignore errors from is_regular_file: we only need to know if we can read
// the file or not.
llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
if (!IsFile)
continue;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
llvm::MemoryBuffer::getFile(ConfigFile.c_str());
if (std::error_code EC = Text.getError()) {
llvm::errs() << "Can't read " << ConfigFile << ": " << EC.message()
<< "\n";
continue;
}
// Skip empty files, e.g. files opened for writing via shell output
// redirection.
if ((*Text)->getBuffer().empty())
continue;
llvm::ErrorOr<ClangTidyOptions> ParsedOptions =
ConfigHandler.second((*Text)->getBuffer());
if (!ParsedOptions) {
if (ParsedOptions.getError())
llvm::errs() << "Error parsing " << ConfigFile << ": "
<< ParsedOptions.getError().message() << "\n";
continue;
}
ClangTidyOptions Defaults = DefaultOptionsProvider::getOptions(Directory);
// Only use checks from the config file.
Defaults.Checks = None;
return Defaults.mergeWith(*ParsedOptions).mergeWith(OverrideOptions);
}
return llvm::None;
}
/// \brief Parses -line-filter option and stores it to the \c Options.
std::error_code parseLineFilter(StringRef LineFilter,
std::error_code parseLineFilter(const std::string &LineFilter,
clang::tidy::ClangTidyGlobalOptions &Options) {
llvm::yaml::Input Input(LineFilter);
Input >> Options.LineFilter;
return Input.error();
}
llvm::ErrorOr<ClangTidyOptions> parseConfiguration(StringRef Config) {
std::error_code parseConfiguration(const std::string &Config,
clang::tidy::ClangTidyOptions &Options) {
llvm::yaml::Input Input(Config);
ClangTidyOptions Options;
Input >> Options;
if (Input.error())
return Input.error();
return Options;
}
std::string configurationAsText(const ClangTidyOptions &Options) {
std::string Text;
llvm::raw_string_ostream Stream(Text);
llvm::yaml::Output Output(Stream);
// We use the same mapping method for input and output, so we need a non-const
// reference here.
ClangTidyOptions NonConstValue = Options;
Output << NonConstValue;
return Stream.str();
return Input.error();
}
} // namespace tidy

View File

@@ -10,12 +10,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_OPTIONS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_OPTIONS_H
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorOr.h"
#include <functional>
#include <map>
#include <string>
#include <system_error>
#include <utility>
@@ -47,42 +42,18 @@ struct ClangTidyGlobalOptions {
/// \brief Contains options for clang-tidy. These options may be read from
/// configuration files, and may be different for different translation units.
struct ClangTidyOptions {
/// \brief These options are used for all settings that haven't been
/// overridden by the \c OptionsProvider.
///
/// Allow no checks and no headers by default. This method initializes
/// check-specific options by calling \c ClangTidyModule::getModuleOptions()
/// of each registered \c ClangTidyModule.
static ClangTidyOptions getDefaults();
/// \brief Creates a new \c ClangTidyOptions instance combined from all fields
/// of this instance overridden by the fields of \p Other that have a value.
ClangTidyOptions mergeWith(const ClangTidyOptions &Other) const;
/// \brief Allow all checks and no headers by default.
ClangTidyOptions() : Checks("*"), AnalyzeTemporaryDtors(false) {}
/// \brief Checks filter.
llvm::Optional<std::string> Checks;
std::string Checks;
/// \brief Output warnings from headers matching this filter. Warnings from
/// main files will always be displayed.
llvm::Optional<std::string> HeaderFilterRegex;
/// \brief Output warnings from system headers matching \c HeaderFilterRegex.
llvm::Optional<bool> SystemHeaders;
std::string HeaderFilterRegex;
/// \brief Turns on temporary destructor-based analysis.
llvm::Optional<bool> AnalyzeTemporaryDtors;
/// \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()
/// comments in the relevant check.
llvm::Optional<std::string> User;
typedef std::pair<std::string, std::string> StringPair;
typedef std::map<std::string, std::string> OptionMap;
/// \brief Key-value mapping used to store check-specific options.
OptionMap CheckOptions;
bool AnalyzeTemporaryDtors;
};
/// \brief Abstract interface for retrieving various ClangTidy options.
@@ -108,7 +79,7 @@ public:
const ClangTidyGlobalOptions &getGlobalOptions() override {
return GlobalOptions;
}
const ClangTidyOptions &getOptions(llvm::StringRef /*FileName*/) override {
const ClangTidyOptions &getOptions(llvm::StringRef) override {
return DefaultOptions;
}
@@ -117,98 +88,13 @@ private:
ClangTidyOptions DefaultOptions;
};
/// \brief Implementation of the \c ClangTidyOptionsProvider interface, which
/// tries to find a configuration file in the closest parent directory of each
/// source file.
///
/// By default, files named ".clang-tidy" will be considered, and the
/// \c clang::tidy::parseConfiguration function will be used for parsing, but a
/// custom set of configuration file names and parsing functions can be
/// specified using the appropriate constructor.
class FileOptionsProvider : public DefaultOptionsProvider {
public:
// \brief A pair of configuration file base name and a function parsing
// configuration from text in the corresponding format.
typedef std::pair<std::string, std::function<llvm::ErrorOr<ClangTidyOptions>(
llvm::StringRef)>> ConfigFileHandler;
/// \brief Configuration file handlers listed in the order of priority.
///
/// Custom configuration file formats can be supported by constructing the
/// list of handlers and passing it to the appropriate \c FileOptionsProvider
/// constructor. E.g. initialization of a \c FileOptionsProvider with support
/// of a custom configuration file format for files named ".my-tidy-config"
/// could look similar to this:
/// \code
/// FileOptionsProvider::ConfigFileHandlers ConfigHandlers;
/// ConfigHandlers.emplace_back(".my-tidy-config", parseMyConfigFormat);
/// ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
/// return llvm::make_unique<FileOptionsProvider>(
/// GlobalOptions, DefaultOptions, OverrideOptions, ConfigHandlers);
/// \endcode
///
/// With the order of handlers shown above, the ".my-tidy-config" file would
/// take precedence over ".clang-tidy" if both reside in the same directory.
typedef std::vector<ConfigFileHandler> ConfigFileHandlers;
/// \brief Initializes the \c FileOptionsProvider instance.
///
/// \param GlobalOptions are just stored and returned to the caller of
/// \c getGlobalOptions.
///
/// \param DefaultOptions are used for all settings not specified in a
/// configuration file.
///
/// If any of the \param OverrideOptions fields are set, they will override
/// whatever options are read from the configuration file.
FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions,
const ClangTidyOptions &DefaultOptions,
const ClangTidyOptions &OverrideOptions);
/// \brief Initializes the \c FileOptionsProvider instance with a custom set
/// of configuration file handlers.
///
/// \param GlobalOptions are just stored and returned to the caller of
/// \c getGlobalOptions.
///
/// \param DefaultOptions are used for all settings not specified in a
/// configuration file.
///
/// If any of the \param OverrideOptions fields are set, they will override
/// whatever options are read from the configuration file.
///
/// \param ConfigHandlers specifies a custom set of configuration file
/// handlers. Each handler is a pair of configuration file name and a function
/// that can parse configuration from this file type. The configuration files
/// in each directory are searched for in the order of appearance in
/// \p ConfigHandlers.
FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions,
const ClangTidyOptions &DefaultOptions,
const ClangTidyOptions &OverrideOptions,
const ConfigFileHandlers &ConfigHandlers);
const ClangTidyOptions &getOptions(llvm::StringRef FileName) override;
private:
/// \brief Try to read configuration files from \p Directory using registered
/// \c ConfigHandlers.
llvm::Optional<ClangTidyOptions> TryReadConfigFile(llvm::StringRef Directory);
llvm::StringMap<ClangTidyOptions> CachedOptions;
ClangTidyOptions OverrideOptions;
ConfigFileHandlers ConfigHandlers;
};
/// \brief Parses LineFilter from JSON and stores it to the \p Options.
std::error_code parseLineFilter(llvm::StringRef LineFilter,
ClangTidyGlobalOptions &Options);
std::error_code parseLineFilter(const std::string &LineFilter,
clang::tidy::ClangTidyGlobalOptions &Options);
/// \brief Parses configuration from JSON and returns \c ClangTidyOptions or an
/// error.
llvm::ErrorOr<ClangTidyOptions> parseConfiguration(llvm::StringRef Config);
/// \brief Serializes configuration to a YAML-encoded string.
std::string configurationAsText(const ClangTidyOptions &Options);
/// \brief Parses configuration from JSON and stores it to the \p Options.
std::error_code parseConfiguration(const std::string &Config,
clang::tidy::ClangTidyOptions &Options);
} // end namespace tidy
} // end namespace clang

View File

@@ -11,6 +11,6 @@ CLANG_LEVEL := ../../..
LIBRARYNAME := clangTidy
include $(CLANG_LEVEL)/../../Makefile.config
DIRS = utils readability llvm google misc tool
DIRS = llvm google misc tool
include $(CLANG_LEVEL)/Makefile

View File

@@ -1,225 +0,0 @@
#!/usr/bin/env python
#
#===- add_new_check.py - clang-tidy check generator ----------*- python -*--===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
import os
import re
import sys
# Adapts the module's CMakelist file. Returns 'True' if it could add a new entry
# and 'False' if the entry already existed.
def adapt_cmake(module_path, check_name_camel):
filename = os.path.join(module_path, 'CMakeLists.txt')
with open(filename, 'r') as f:
lines = f.read().split('\n')
# .split with separator returns one more element. Ignore it.
lines = lines[:-1]
cpp_file = check_name_camel + '.cpp'
# Figure out whether this check already exists.
for line in lines:
if line.strip() == cpp_file:
return False
with open(filename, 'w') as f:
cpp_found = False
file_added = False
for line in lines:
if not file_added and (line.endswith('.cpp') or cpp_found):
cpp_found = True
if line.strip() > cpp_file:
f.write(' ' + cpp_file + '\n')
file_added = True
f.write(line + '\n')
return True
# Adds a header for the new check.
def write_header(module_path, module, check_name, check_name_camel):
filename = os.path.join(module_path, check_name_camel) + '.h'
with open(filename, 'w') as f:
header_guard = ('LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_' + module.upper() +
'_' + check_name.upper().replace('-', '_') + '_H')
f.write('//===--- ')
f.write(os.path.basename(filename))
f.write(' - clang-tidy')
f.write('-' * max(0, 43 - len(os.path.basename(filename))))
f.write('*- C++ -*-===//')
f.write("""
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef %(header_guard)s
#define %(header_guard)s
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
class %(check_name)s : public ClangTidyCheck {
public:
%(check_name)s(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace tidy
} // namespace clang
#endif // %(header_guard)s
""" % {'header_guard': header_guard,
'check_name': check_name_camel})
# Adds the implementation of the new check.
def write_implementation(module_path, check_name_camel):
filename = os.path.join(module_path, check_name_camel) + '.cpp'
with open(filename, 'w') as f:
f.write('//===--- ')
f.write(os.path.basename(filename))
f.write(' - clang-tidy')
f.write('-' * max(0, 52 - len(os.path.basename(filename))))
f.write('-===//')
f.write("""
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "%(check_name)s.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
void %(check_name)s::registerMatchers(MatchFinder *Finder) {
// FIXME: Add matchers.
Finder->addMatcher(functionDecl().bind("x"), this);
}
void %(check_name)s::check(const MatchFinder::MatchResult &Result) {
// FIXME: Add callback implementation.
const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x");
if (MatchedDecl->getName().startswith("awesome_"))
return;
diag(MatchedDecl->getLocation(), "function '%%0' is insufficiently awesome")
<< MatchedDecl->getName()
<< FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_");
}
} // namespace tidy
} // namespace clang
""" % {'check_name': check_name_camel})
# Modifies the module to include the new check.
def adapt_module(module_path, module, check_name, check_name_camel):
filename = os.path.join(module_path, module.capitalize() + 'TidyModule.cpp')
with open(filename, 'r') as f:
lines = f.read().split('\n')
# .split with separator returns one more element. Ignore it.
lines = lines[:-1]
with open(filename, 'w') as f:
header_added = False
header_found = False
check_added = False
check_decl = (' CheckFactories.registerCheck<' + check_name_camel +
'>(\n "' + module + '-' + check_name + '");\n')
for line in lines:
if not header_added:
match = re.search('#include "(.*)"', line)
if match:
header_found = True
if match.group(1) > check_name_camel:
header_added = True
f.write('#include "' + check_name_camel + '.h"\n')
elif header_found:
header_added = True
f.write('#include "' + check_name_camel + '.h"\n')
if not check_added:
if line.strip() == '}':
check_added = True
f.write(check_decl)
else:
match = re.search('registerCheck<(.*)>', line)
if match and match.group(1) > check_name_camel:
check_added = True
f.write(check_decl)
f.write(line + '\n')
# Adds a test for the check.
def write_test(module_path, module, check_name):
check_name_dashes = module + '-' + check_name
filename = os.path.join(module_path, '../../test/clang-tidy',
check_name_dashes + '.cpp')
with open(filename, 'w') as f:
f.write(
"""// RUN: $(dirname %%s)/check_clang_tidy.sh %%s %(check_name_dashes)s %%t
// REQUIRES: shell
// FIXME: Add something that triggers the check here.
void f();
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [%(check_name_dashes)s]
// FIXME: Verify the applied fix.
// * Make the CHECK patterns specific enough and try to make verified lines
// unique to avoid incorrect matches.
// * Use {{}} for regular expressions.
// CHECK-FIXES: {{^}}void awesome_f();{{$}}
// FIXME: Add something that doesn't trigger the check here.
void awesome_f2();
""" % {"check_name_dashes" : check_name_dashes})
def main():
if len(sys.argv) != 3:
print 'Usage: add_new_check.py <module> <check>, e.g.\n'
print 'add_new_check.py misc awesome-functions\n'
return
module = sys.argv[1]
check_name = sys.argv[2]
check_name_camel = ''.join(map(lambda elem: elem.capitalize(),
check_name.split('-'))) + 'Check'
clang_tidy_path = os.path.dirname(sys.argv[0])
module_path = os.path.join(clang_tidy_path, module)
if not adapt_cmake(module_path, check_name_camel):
return
write_header(module_path, module, check_name, check_name_camel)
write_implementation(module_path, check_name_camel)
adapt_module(module_path, module, check_name, check_name_camel)
write_test(module_path, module, check_name)
if __name__ == '__main__':
main()

View File

@@ -28,7 +28,10 @@ AvoidCStyleCastsCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
// FIXME: Remove this once this is fixed in the AST.
unless(hasParent(substNonTypeTemplateParmExpr())),
// Avoid matches in template instantiations.
unless(isInTemplateInstantiation())).bind("cast"),
unless(hasAncestor(decl(
anyOf(recordDecl(ast_matchers::isTemplateInstantiation()),
functionDecl(ast_matchers::isTemplateInstantiation()))))))
.bind("cast"),
this);
}
@@ -57,12 +60,6 @@ bool pointedTypesAreEqual(QualType SourceType, QualType DestType) {
void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
auto ParenRange = CharSourceRange::getTokenRange(CastExpr->getLParenLoc(),
CastExpr->getRParenLoc());
// Ignore casts in macros.
if (ParenRange.getBegin().isMacroID() || ParenRange.getEnd().isMacroID())
return;
// Casting to void is an idiomatic way to mute "unused variable" and similar
// warnings.
if (CastExpr->getTypeAsWritten()->isVoidType())
@@ -72,29 +69,23 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
CastExpr->getSubExprAsWritten()->getType().getCanonicalType();
QualType DestType = CastExpr->getTypeAsWritten().getCanonicalType();
auto ParenRange = CharSourceRange::getTokenRange(CastExpr->getLParenLoc(),
CastExpr->getRParenLoc());
if (SourceType == DestType) {
diag(CastExpr->getLocStart(), "Redundant cast to the same type.")
<< FixItHint::CreateRemoval(ParenRange);
return;
}
// The rest of this check is only relevant to C++.
if (!Result.Context->getLangOpts().CPlusPlus)
return;
// Leave type spelling exactly as it was (unlike
// getTypeAsWritten().getAsString() which would spell enum types 'enum X').
StringRef DestTypeString = Lexer::getSourceText(
CharSourceRange::getTokenRange(
CastExpr->getLParenLoc().getLocWithOffset(1),
CastExpr->getRParenLoc().getLocWithOffset(-1)),
*Result.SourceManager, Result.Context->getLangOpts());
std::string DestTypeString = CastExpr->getTypeAsWritten().getAsString();
auto diag_builder =
diag(CastExpr->getLocStart(), "C-style casts are discouraged. %0");
auto ReplaceWithCast = [&](StringRef CastType) {
diag_builder << ("Use " + CastType + ".").str();
if (ParenRange.getBegin().isMacroID() || ParenRange.getEnd().isMacroID())
return;
const Expr *SubExpr = CastExpr->getSubExprAsWritten()->IgnoreImpCasts();
std::string CastText = (CastType + "<" + DestTypeString + ">").str();
@@ -123,13 +114,7 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
ReplaceWithCast("const_cast");
return;
}
// FALLTHROUGH
case clang::CK_IntegralCast:
// Convert integral and no-op casts between builtin types and enums to
// static_cast. A cast from enum to integer may be unnecessary, but it's
// still retained.
if ((SourceType->isBuiltinType() || SourceType->isEnumeralType()) &&
(DestType->isBuiltinType() || DestType->isEnumeralType())) {
if (SourceType->isBuiltinType() && DestType->isBuiltinType()) {
ReplaceWithCast("static_cast");
return;
}

View File

@@ -26,8 +26,6 @@ namespace readability {
/// ones generated by -Wold-style-cast.
class AvoidCStyleCastsCheck : public ClangTidyCheck {
public:
AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -5,12 +5,10 @@ add_clang_library(clangTidyGoogleModule
ExplicitConstructorCheck.cpp
ExplicitMakePairCheck.cpp
GoogleTidyModule.cpp
IntegerTypesCheck.cpp
MemsetZeroLengthCheck.cpp
NamedParameterCheck.cpp
OverloadedUnaryAndCheck.cpp
StringReferenceMemberCheck.cpp
TodoCommentCheck.cpp
UnnamedNamespaceInHeaderCheck.cpp
UsingNamespaceDirectiveCheck.cpp
@@ -20,5 +18,4 @@ add_clang_library(clangTidyGoogleModule
clangBasic
clangLex
clangTidy
clangTidyReadabilityModule
)

View File

@@ -19,8 +19,7 @@ namespace clang {
namespace tidy {
void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(constructorDecl(unless(isInstantiated())).bind("ctor"),
this);
Finder->addMatcher(constructorDecl().bind("ctor"), this);
}
// Looks for the token matching the predicate and returns the range of the found
@@ -48,33 +47,15 @@ SourceRange FindToken(const SourceManager &Sources, LangOptions LangOpts,
return SourceRange();
}
bool isStdInitializerList(QualType Type) {
if (const RecordType *RT = Type.getCanonicalType()->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *Specialization =
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl())) {
ClassTemplateDecl *Template = Specialization->getSpecializedTemplate();
// First use the fast getName() method to avoid unnecessary calls to the
// slow getQualifiedNameAsString().
return Template->getName() == "initializer_list" &&
Template->getQualifiedNameAsString() == "std::initializer_list";
}
}
return false;
}
void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
const CXXConstructorDecl *Ctor =
Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
// Do not be confused: isExplicit means 'explicit' keyword is present,
// isImplicit means that it's a compiler-generated constructor.
if (Ctor->isOutOfLine() || Ctor->isImplicit() || Ctor->isDeleted() ||
Ctor->getNumParams() == 0 || Ctor->getMinRequiredArguments() > 1)
if (Ctor->isOutOfLine() || Ctor->isImplicit() || Ctor->isDeleted())
return;
bool takesInitializerList = isStdInitializerList(
Ctor->getParamDecl(0)->getType().getNonReferenceType());
if (Ctor->isExplicit() &&
(Ctor->isCopyOrMoveConstructor() || takesInitializerList)) {
if (Ctor->isExplicit() && Ctor->isCopyOrMoveConstructor()) {
auto isKWExplicit = [](const Token &Tok) {
return Tok.is(tok::raw_identifier) &&
Tok.getRawIdentifier() == "explicit";
@@ -82,31 +63,21 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
SourceRange ExplicitTokenRange =
FindToken(*Result.SourceManager, Result.Context->getLangOpts(),
Ctor->getOuterLocStart(), Ctor->getLocEnd(), isKWExplicit);
StringRef ConstructorDescription;
if (Ctor->isMoveConstructor())
ConstructorDescription = "move";
else if (Ctor->isCopyConstructor())
ConstructorDescription = "copy";
else
ConstructorDescription = "initializer-list";
DiagnosticBuilder Diag =
diag(Ctor->getLocation(),
"%0 constructor should not be declared explicit")
<< ConstructorDescription;
diag(Ctor->getLocation(), "%0 constructor declared explicit.")
<< (Ctor->isMoveConstructor() ? "Move" : "Copy");
if (ExplicitTokenRange.isValid()) {
Diag << FixItHint::CreateRemoval(
CharSourceRange::getCharRange(ExplicitTokenRange));
}
return;
}
if (Ctor->isExplicit() || Ctor->isCopyOrMoveConstructor() ||
takesInitializerList)
Ctor->getNumParams() == 0 || Ctor->getMinRequiredArguments() > 1)
return;
SourceLocation Loc = Ctor->getLocation();
diag(Loc, "single-argument constructors must be explicit")
diag(Loc, "Single-argument constructors must be explicit")
<< FixItHint::CreateInsertion(Loc, "explicit ");
}

View File

@@ -21,8 +21,6 @@ namespace tidy {
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Explicit_Constructors
class ExplicitConstructorCheck : public ClangTidyCheck {
public:
ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -20,6 +20,15 @@ namespace ast_matchers {
AST_MATCHER(DeclRefExpr, hasExplicitTemplateArgs) {
return Node.hasExplicitTemplateArgs();
}
// FIXME: This should just be callee(ignoringImpCasts()) but it's not overloaded
// for Expr.
AST_MATCHER_P(CallExpr, calleeIgnoringParenImpCasts, internal::Matcher<Stmt>,
InnerMatcher) {
const Expr *ExprNode = Node.getCallee();
return (ExprNode != nullptr &&
InnerMatcher.matches(*ExprNode->IgnoreParenImpCasts(), Finder, Builder));
}
} // namespace ast_matchers
namespace tidy {
@@ -30,11 +39,13 @@ ExplicitMakePairCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
// Look for std::make_pair with explicit template args. Ignore calls in
// templates.
Finder->addMatcher(
callExpr(unless(isInTemplateInstantiation()),
callee(expr(ignoringParenImpCasts(
callExpr(unless(hasAncestor(decl(anyOf(
recordDecl(ast_matchers::isTemplateInstantiation()),
functionDecl(ast_matchers::isTemplateInstantiation()))))),
calleeIgnoringParenImpCasts(
declRefExpr(hasExplicitTemplateArgs(),
to(functionDecl(hasName("::std::make_pair"))))
.bind("declref"))))).bind("call"),
.bind("declref"))).bind("call"),
this);
}

View File

@@ -24,8 +24,6 @@ namespace build {
/// Corresponding cpplint.py check name: 'build/explicit_make_pair'.
class ExplicitMakePairCheck : public ClangTidyCheck {
public:
ExplicitMakePairCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -13,18 +13,12 @@
#include "AvoidCStyleCastsCheck.h"
#include "ExplicitConstructorCheck.h"
#include "ExplicitMakePairCheck.h"
#include "IntegerTypesCheck.h"
#include "MemsetZeroLengthCheck.h"
#include "NamedParameterCheck.h"
#include "OverloadedUnaryAndCheck.h"
#include "StringReferenceMemberCheck.h"
#include "TodoCommentCheck.h"
#include "UnnamedNamespaceInHeaderCheck.h"
#include "UsingNamespaceDirectiveCheck.h"
#include "../readability/BracesAroundStatementsCheck.h"
#include "../readability/FunctionSize.h"
#include "../readability/NamespaceCommentCheck.h"
#include "../readability/RedundantSmartptrGet.h"
using namespace clang::ast_matchers;
@@ -34,47 +28,33 @@ namespace tidy {
class GoogleModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<build::ExplicitMakePairCheck>(
"google-build-explicit-make-pair");
CheckFactories.registerCheck<build::UnnamedNamespaceInHeaderCheck>(
"google-build-namespaces");
CheckFactories.registerCheck<build::UsingNamespaceDirectiveCheck>(
"google-build-using-namespace");
CheckFactories.registerCheck<ExplicitConstructorCheck>(
"google-explicit-constructor");
CheckFactories.registerCheck<runtime::IntegerTypesCheck>(
"google-runtime-int");
CheckFactories.registerCheck<runtime::OverloadedUnaryAndCheck>(
"google-runtime-operator");
CheckFactories.registerCheck<runtime::StringReferenceMemberCheck>(
"google-runtime-member-string-references");
CheckFactories.registerCheck<runtime::MemsetZeroLengthCheck>(
"google-runtime-memset");
CheckFactories.registerCheck<readability::AvoidCStyleCastsCheck>(
"google-readability-casting");
CheckFactories.registerCheck<readability::NamedParameterCheck>(
"google-readability-function");
CheckFactories.registerCheck<readability::TodoCommentCheck>(
"google-readability-todo");
CheckFactories.registerCheck<readability::BracesAroundStatementsCheck>(
"google-readability-braces-around-statements");
CheckFactories.registerCheck<readability::FunctionSizeCheck>(
"google-readability-function-size");
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"google-readability-namespace-comments");
CheckFactories.registerCheck<readability::RedundantSmartptrGet>(
"google-readability-redundant-smartptr-get");
}
ClangTidyOptions getModuleOptions() override {
ClangTidyOptions Options;
auto &Opts = Options.CheckOptions;
Opts["google-readability-braces-around-statements.ShortStatementLines"] =
"1";
Opts["google-readability-function-size.StatementThreshold"] = "800";
Opts["google-readability-namespace-comments.ShortNamespaceLines"] = "10";
Opts["google-readability-namespace-comments.SpacesBeforeComments"] = "2";
return Options;
CheckFactories.addCheckFactory(
"google-build-explicit-make-pair",
new ClangTidyCheckFactory<build::ExplicitMakePairCheck>());
CheckFactories.addCheckFactory(
"google-build-namespaces",
new ClangTidyCheckFactory<build::UnnamedNamespaceInHeaderCheck>());
CheckFactories.addCheckFactory(
"google-build-using-namespace",
new ClangTidyCheckFactory<build::UsingNamespaceDirectiveCheck>());
CheckFactories.addCheckFactory(
"google-explicit-constructor",
new ClangTidyCheckFactory<ExplicitConstructorCheck>());
CheckFactories.addCheckFactory(
"google-runtime-operator",
new ClangTidyCheckFactory<runtime::OverloadedUnaryAndCheck>());
CheckFactories.addCheckFactory(
"google-runtime-member-string-references",
new ClangTidyCheckFactory<runtime::StringReferenceMemberCheck>());
CheckFactories.addCheckFactory(
"google-runtime-memset",
new ClangTidyCheckFactory<runtime::MemsetZeroLengthCheck>());
CheckFactories.addCheckFactory(
"google-readability-casting",
new ClangTidyCheckFactory<readability::AvoidCStyleCastsCheck>());
CheckFactories.addCheckFactory(
"google-readability-function",
new ClangTidyCheckFactory<readability::NamedParameterCheck>());
}
};

View File

@@ -1,102 +0,0 @@
//===--- IntegerTypesCheck.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 "IntegerTypesCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/TargetInfo.h"
namespace clang {
namespace tidy {
namespace runtime {
using namespace ast_matchers;
void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
// Find all TypeLocs.
Finder->addMatcher(typeLoc().bind("tl"), this);
}
void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) {
// The relevant Style Guide rule only applies to C++.
if (!Result.Context->getLangOpts().CPlusPlus)
return;
auto TL = *Result.Nodes.getNodeAs<TypeLoc>("tl");
SourceLocation Loc = TL.getLocStart();
if (Loc.isInvalid() || Loc.isMacroID())
return;
// Look through qualification.
if (auto QualLoc = TL.getAs<QualifiedTypeLoc>())
TL = QualLoc.getUnqualifiedLoc();
auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();
if (!BuiltinLoc)
return;
bool IsSigned;
unsigned Width;
const TargetInfo &TargetInfo = Result.Context->getTargetInfo();
// Look for uses of short, long, long long and their unsigned versions.
switch (BuiltinLoc.getTypePtr()->getKind()) {
case BuiltinType::Short:
Width = TargetInfo.getShortWidth();
IsSigned = true;
break;
case BuiltinType::Long:
Width = TargetInfo.getLongWidth();
IsSigned = true;
break;
case BuiltinType::LongLong:
Width = TargetInfo.getLongLongWidth();
IsSigned = true;
break;
case BuiltinType::UShort:
Width = TargetInfo.getShortWidth();
IsSigned = false;
break;
case BuiltinType::ULong:
Width = TargetInfo.getLongWidth();
IsSigned = false;
break;
case BuiltinType::ULongLong:
Width = TargetInfo.getLongLongWidth();
IsSigned = false;
break;
default:
return;
}
// We allow "unsigned short port" as that's reasonably common and required by
// the sockets API.
const StringRef Port = "unsigned short port";
const char *Data = Result.SourceManager->getCharacterData(Loc);
if (!std::strncmp(Data, Port.data(), Port.size()) &&
!isIdentifierBody(Data[Port.size()]))
return;
std::string Replacement =
((IsSigned ? SignedTypePrefix : UnsignedTypePrefix) + Twine(Width) +
(AddUnderscoreT ? "_t" : "")).str();
// We don't add a fix-it as changing the type can easily break code,
// e.g. when a function requires a 'long' argument on all platforms.
// QualTypes are printed with implicit quotes.
diag(Loc, "consider replacing %0 with '%1'") << BuiltinLoc.getType()
<< Replacement;
}
} // namespace runtime
} // namespace tidy
} // namespace clang

View File

@@ -1,40 +0,0 @@
//===--- IntegerTypesCheck.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_GOOGLE_INTEGERTYPESCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_INTEGERTYPESCHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace runtime {
/// \brief Finds uses of short, long and long long and suggest replacing them
/// with u?intXX(_t)?.
/// Correspondig cpplint.py check: runtime/int.
class IntegerTypesCheck : public ClangTidyCheck {
public:
IntegerTypesCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), UnsignedTypePrefix("uint"),
SignedTypePrefix("int"), AddUnderscoreT(false) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
const StringRef UnsignedTypePrefix;
const StringRef SignedTypePrefix;
const bool AddUnderscoreT;
};
} // namespace runtime
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_INTEGERTYPESCHECK_H

View File

@@ -21,12 +21,15 @@ namespace runtime {
void
MemsetZeroLengthCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
auto InTemplateInstantiation = hasAncestor(
decl(anyOf(recordDecl(ast_matchers::isTemplateInstantiation()),
functionDecl(ast_matchers::isTemplateInstantiation()))));
// Look for memset(x, y, 0) as those is most likely an argument swap.
// TODO: Also handle other standard functions that suffer from the same
// problem, e.g. memchr.
Finder->addMatcher(
callExpr(callee(functionDecl(hasName("::memset"))), argumentCountIs(3),
unless(isInTemplateInstantiation())).bind("decl"),
unless(InTemplateInstantiation)).bind("decl"),
this);
}

View File

@@ -24,8 +24,6 @@ namespace runtime {
/// Corresponding cpplint.py check name: 'runtime/memset'.
class MemsetZeroLengthCheck : public ClangTidyCheck {
public:
MemsetZeroLengthCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -19,7 +19,13 @@ namespace tidy {
namespace readability {
void NamedParameterCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
Finder->addMatcher(functionDecl(unless(isInstantiated())).bind("decl"), this);
Finder->addMatcher(
functionDecl(
unless(hasAncestor(decl(
anyOf(recordDecl(ast_matchers::isTemplateInstantiation()),
functionDecl(ast_matchers::isTemplateInstantiation()))))))
.bind("decl"),
this);
}
void NamedParameterCheck::check(const MatchFinder::MatchResult &Result) {
@@ -31,15 +37,6 @@ void NamedParameterCheck::check(const MatchFinder::MatchResult &Result) {
if (Function->isImplicit())
return;
// Ignore declarations without a definition if we're not dealing with an
// overriden method.
const FunctionDecl *Definition = nullptr;
if ((!Function->isDefined(Definition) || Function->isDefaulted() ||
Function->isDeleted()) &&
(!isa<CXXMethodDecl>(Function) ||
cast<CXXMethodDecl>(Function)->size_overridden_methods() == 0))
return;
// TODO: Handle overloads.
// TODO: We could check that all redeclarations use the same name for
// arguments in the same position.
@@ -49,26 +46,11 @@ void NamedParameterCheck::check(const MatchFinder::MatchResult &Result) {
if (!Parm->getName().empty())
continue;
// Don't warn on the dummy argument on post-inc and post-dec operators.
if ((Function->getOverloadedOperator() == OO_PlusPlus ||
Function->getOverloadedOperator() == OO_MinusMinus) &&
Parm->getType()->isSpecificBuiltinType(BuiltinType::Int))
continue;
// Sanity check the source locations.
if (!Parm->getLocation().isValid() || Parm->getLocation().isMacroID() ||
!SM.isWrittenInSameFile(Parm->getLocStart(), Parm->getLocation()))
continue;
// Skip gmock testing::Unused parameters.
if (auto Typedef = Parm->getType()->getAs<clang::TypedefType>())
if (Typedef->getDecl()->getQualifiedNameAsString() == "testing::Unused")
continue;
// Skip std::nullptr_t.
if (Parm->getType().getCanonicalType()->isNullPtrType())
continue;
// Look for comments. We explicitly want to allow idioms like
// void foo(int /*unused*/)
const char *Begin = SM.getCharacterData(Parm->getLocStart());
@@ -88,34 +70,25 @@ void NamedParameterCheck::check(const MatchFinder::MatchResult &Result) {
"all parameters should be named in a function");
for (auto P : UnnamedParams) {
// Fallback to an unused marker.
StringRef NewName = "unused";
// If the method is overridden, try to copy the name from the base method
// into the overrider.
const ParmVarDecl *Parm = P.first->getParamDecl(P.second);
const auto *M = dyn_cast<CXXMethodDecl>(P.first);
if (M && M->size_overridden_methods() > 0) {
const ParmVarDecl *OtherParm =
(*M->begin_overridden_methods())->getParamDecl(P.second);
StringRef Name = OtherParm->getName();
if (!Name.empty())
NewName = Name;
std::string Name = OtherParm->getNameAsString();
if (!Name.empty()) {
D << FixItHint::CreateInsertion(Parm->getLocation(),
" /*" + Name + "*/");
continue;
}
}
// If the definition has a named parameter use that name.
if (Definition) {
const ParmVarDecl *DefParm = Definition->getParamDecl(P.second);
StringRef Name = DefParm->getName();
if (!Name.empty())
NewName = Name;
}
// Now insert the comment. Note that getLocation() points to the place
// where the name would be, this allows us to also get complex cases like
// function pointers right.
const ParmVarDecl *Parm = P.first->getParamDecl(P.second);
D << FixItHint::CreateInsertion(Parm->getLocation(),
" /*" + NewName.str() + "*/");
// Otherwise just insert an unused marker. Note that getLocation() points
// to the place where the name would be, this allows us to also get
// complex cases like function pointers right.
D << FixItHint::CreateInsertion(Parm->getLocation(), " /*unused*/");
}
}
}

View File

@@ -22,8 +22,6 @@ namespace readability {
/// Corresponding cpplint.py check name: 'readability/function'.
class NamedParameterCheck : public ClangTidyCheck {
public:
NamedParameterCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -22,8 +22,6 @@ namespace runtime {
/// Corresponding cpplint.py check name: 'runtime/operator'.
class OverloadedUnaryAndCheck : public ClangTidyCheck {
public:
OverloadedUnaryAndCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -26,8 +26,12 @@ void StringReferenceMemberCheck::registerMatchers(
auto ConstString = qualType(isConstQualified(), hasDeclaration(String));
// Ignore members in template instantiations.
auto InTemplateInstantiation = hasAncestor(
decl(anyOf(recordDecl(ast_matchers::isTemplateInstantiation()),
functionDecl(ast_matchers::isTemplateInstantiation()))));
Finder->addMatcher(fieldDecl(hasType(references(ConstString)),
unless(isInstantiated())).bind("member"),
unless(InTemplateInstantiation)).bind("member"),
this);
}

View File

@@ -39,8 +39,6 @@ namespace runtime {
/// Corresponding cpplint.py check name: 'runtime/member_string_reference'.
class StringReferenceMemberCheck : public ClangTidyCheck {
public:
StringReferenceMemberCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -1,64 +0,0 @@
//===--- TodoCommentCheck.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 "TodoCommentCheck.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
namespace clang {
namespace tidy {
namespace readability {
class TodoCommentCheck::TodoCommentHandler : public CommentHandler {
public:
TodoCommentHandler(TodoCommentCheck &Check, llvm::Optional<std::string> User)
: Check(Check), User(User ? *User : "unknown"),
TodoMatch("^// *TODO *(\\(.*\\))?:?( )?(.*)$") {}
bool HandleComment(Preprocessor &PP, SourceRange Range) override {
StringRef Text =
Lexer::getSourceText(CharSourceRange::getCharRange(Range),
PP.getSourceManager(), PP.getLangOpts());
SmallVector<StringRef, 4> Matches;
if (!TodoMatch.match(Text, &Matches))
return false;
StringRef Username = Matches[1];
StringRef Comment = Matches[3];
if (!Username.empty())
return false;
std::string NewText = ("// TODO(" + Twine(User) + "): " + Comment).str();
Check.diag(Range.getBegin(), "missing username/bug in TODO")
<< FixItHint::CreateReplacement(CharSourceRange::getCharRange(Range),
NewText);
return false;
}
private:
TodoCommentCheck &Check;
std::string User;
llvm::Regex TodoMatch;
};
TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
Handler(llvm::make_unique<TodoCommentHandler>(
*this, Context->getOptions().User)) {}
void TodoCommentCheck::registerPPCallbacks(CompilerInstance &Compiler) {
Compiler.getPreprocessor().addCommentHandler(Handler.get());
}
} // namespace readability
} // namespace tidy
} // namespace clang

View File

@@ -1,36 +0,0 @@
//===--- TodoCommentCheck.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_GOOGLE_TODOCOMMENTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_TODOCOMMENTCHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace readability {
/// \brief Finds TODO comments without a username or bug number.
///
/// Corresponding cpplint.py check: readability/todo
class TodoCommentCheck : public ClangTidyCheck {
public:
TodoCommentCheck(StringRef Name, ClangTidyContext *Context);
void registerPPCallbacks(CompilerInstance &Compiler) override;
private:
class TodoCommentHandler;
std::unique_ptr<TodoCommentHandler> Handler;
};
} // namespace readability
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_TODOCOMMENTCHECK_H

View File

@@ -22,8 +22,6 @@ namespace build {
/// Corresponding cpplint.py check name: 'build/namespaces'.
class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck {
public:
UnnamedNamespaceInHeaderCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -22,8 +22,6 @@ namespace build {
/// Corresponding cpplint.py check name: 'build/namespaces'.
class UsingNamespaceDirectiveCheck : public ClangTidyCheck {
public:
UsingNamespaceDirectiveCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -1,9 +1,9 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyLLVMModule
HeaderGuardCheck.cpp
IncludeOrderCheck.cpp
LLVMTidyModule.cpp
NamespaceCommentCheck.cpp
TwineLocalCheck.cpp
LINK_LIBS
@@ -12,7 +12,4 @@ add_clang_library(clangTidyLLVMModule
clangBasic
clangLex
clangTidy
clangTidyReadabilityModule
clangTidyUtils
clangTooling
)

View File

@@ -1,53 +0,0 @@
//===--- HeaderGuardCheck.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 "HeaderGuardCheck.h"
namespace clang {
namespace tidy {
bool LLVMHeaderGuardCheck::shouldFixHeaderGuard(StringRef Filename) {
return Filename.endswith(".h");
}
std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef Filename,
StringRef OldGuard) {
std::string Guard = tooling::getAbsolutePath(Filename);
// Sanitize the path. There are some rules for compatibility with the historic
// style in include/llvm and include/clang which we want to preserve.
// We don't want _INCLUDE_ in our guards.
size_t PosInclude = Guard.rfind("include/");
if (PosInclude != StringRef::npos)
Guard = Guard.substr(PosInclude + std::strlen("include/"));
// For clang we drop the _TOOLS_.
size_t PosToolsClang = Guard.rfind("tools/clang/");
if (PosToolsClang != StringRef::npos)
Guard = Guard.substr(PosToolsClang + std::strlen("tools/"));
// The remainder is LLVM_FULL_PATH_TO_HEADER_H
size_t PosLLVM = Guard.rfind("llvm/");
if (PosLLVM != StringRef::npos)
Guard = Guard.substr(PosLLVM);
std::replace(Guard.begin(), Guard.end(), '/', '_');
std::replace(Guard.begin(), Guard.end(), '.', '_');
std::replace(Guard.begin(), Guard.end(), '-', '_');
// The prevalent style in clang is LLVM_CLANG_FOO_BAR_H
if (StringRef(Guard).startswith("clang"))
Guard = "LLVM_" + Guard;
return StringRef(Guard).upper();
}
} // namespace tidy
} // namespace clang

View File

@@ -1,31 +0,0 @@
//===--- HeaderGuardCheck.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_LLVM_HEADER_GUARD_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_HEADER_GUARD_CHECK_H
#include "../utils/HeaderGuard.h"
namespace clang {
namespace tidy {
/// Finds and fixes header guards that do not adhere to LLVM style.
class LLVMHeaderGuardCheck : public HeaderGuardCheck {
public:
LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context)
: HeaderGuardCheck(Name, Context) {}
bool shouldSuggestEndifComment(StringRef Filename) override { return false; }
bool shouldFixHeaderGuard(StringRef Filename) override;
std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override;
};
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_HEADER_GUARD_CHECK_H

View File

@@ -18,149 +18,26 @@ namespace tidy {
namespace {
class IncludeOrderPPCallbacks : public PPCallbacks {
public:
explicit IncludeOrderPPCallbacks(ClangTidyCheck &Check, SourceManager &SM)
: LookForMainModule(true), Check(Check), SM(SM) {}
explicit IncludeOrderPPCallbacks(IncludeOrderCheck &Check) : Check(Check) {}
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
const Module *Imported) override;
void EndOfMainFile() override;
const Module *Imported) override {
// FIXME: This is a dummy implementation to show how to get at preprocessor
// information. Implement a real include order check.
Check.diag(HashLoc, "This is an include");
}
private:
struct IncludeDirective {
SourceLocation Loc; ///< '#' location in the include directive
CharSourceRange Range; ///< SourceRange for the file name
StringRef Filename; ///< Filename as a string
bool IsAngled; ///< true if this was an include with angle brackets
bool IsMainModule; ///< true if this was the first include in a file
};
std::vector<IncludeDirective> IncludeDirectives;
bool LookForMainModule;
ClangTidyCheck &Check;
SourceManager &SM;
IncludeOrderCheck &Check;
};
} // namespace
void IncludeOrderCheck::registerPPCallbacks(CompilerInstance &Compiler) {
Compiler.getPreprocessor().addPPCallbacks(
llvm::make_unique<IncludeOrderPPCallbacks>(*this,
Compiler.getSourceManager()));
}
static int getPriority(StringRef Filename, bool IsAngled, bool IsMainModule) {
// We leave the main module header at the top.
if (IsMainModule)
return 0;
// LLVM and clang headers are in the penultimate position.
if (Filename.startswith("llvm/") || Filename.startswith("llvm-c/") ||
Filename.startswith("clang/") || Filename.startswith("clang-c/"))
return 2;
// System headers are sorted to the end.
if (IsAngled || Filename.startswith("gtest/"))
return 3;
// Other headers are inserted between the main module header and LLVM headers.
return 1;
}
void IncludeOrderPPCallbacks::InclusionDirective(
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
// We recognize the first include as a special main module header and want
// to leave it in the top position.
IncludeDirective ID = {HashLoc, FilenameRange, FileName, IsAngled, false};
if (LookForMainModule && !IsAngled) {
ID.IsMainModule = true;
LookForMainModule = false;
}
IncludeDirectives.push_back(std::move(ID));
}
void IncludeOrderPPCallbacks::EndOfMainFile() {
LookForMainModule = true;
if (IncludeDirectives.empty())
return;
// TODO: find duplicated includes.
// Form blocks of includes. We don't want to sort across blocks. This also
// implicitly makes us never reorder over #defines or #if directives.
// FIXME: We should be more careful about sorting below comments as we don't
// know if the comment refers to the next include or the whole block that
// follows.
std::vector<unsigned> Blocks(1, 0);
for (unsigned I = 1, E = IncludeDirectives.size(); I != E; ++I)
if (SM.getExpansionLineNumber(IncludeDirectives[I].Loc) !=
SM.getExpansionLineNumber(IncludeDirectives[I - 1].Loc) + 1)
Blocks.push_back(I);
Blocks.push_back(IncludeDirectives.size()); // Sentinel value.
// Get a vector of indices.
std::vector<unsigned> IncludeIndices;
for (unsigned I = 0, E = IncludeDirectives.size(); I != E; ++I)
IncludeIndices.push_back(I);
// Sort the includes. We first sort by priority, then lexicographically.
for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI)
std::sort(IncludeIndices.begin() + Blocks[BI],
IncludeIndices.begin() + Blocks[BI + 1],
[this](unsigned LHSI, unsigned RHSI) {
IncludeDirective &LHS = IncludeDirectives[LHSI];
IncludeDirective &RHS = IncludeDirectives[RHSI];
int PriorityLHS =
getPriority(LHS.Filename, LHS.IsAngled, LHS.IsMainModule);
int PriorityRHS =
getPriority(RHS.Filename, RHS.IsAngled, RHS.IsMainModule);
return std::tie(PriorityLHS, LHS.Filename) <
std::tie(PriorityRHS, RHS.Filename);
});
// Emit a warning for each block and fixits for all changes within that block.
for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI) {
// Find the first include that's not in the right position.
unsigned I, E;
for (I = Blocks[BI], E = Blocks[BI + 1]; I != E; ++I)
if (IncludeIndices[I] != I)
break;
if (I == E)
continue;
// Emit a warning.
auto D = Check.diag(IncludeDirectives[I].Loc,
"#includes are not sorted properly");
// Emit fix-its for all following includes in this block.
for (; I != E; ++I) {
if (IncludeIndices[I] == I)
continue;
const IncludeDirective &CopyFrom = IncludeDirectives[IncludeIndices[I]];
SourceLocation FromLoc = CopyFrom.Range.getBegin();
const char *FromData = SM.getCharacterData(FromLoc);
unsigned FromLen = std::strcspn(FromData, "\n");
StringRef FixedName(FromData, FromLen);
SourceLocation ToLoc = IncludeDirectives[I].Range.getBegin();
const char *ToData = SM.getCharacterData(ToLoc);
unsigned ToLen = std::strcspn(ToData, "\n");
auto ToRange =
CharSourceRange::getCharRange(ToLoc, ToLoc.getLocWithOffset(ToLen));
D << FixItHint::CreateReplacement(ToRange, FixedName);
}
}
IncludeDirectives.clear();
Compiler.getPreprocessor()
.addPPCallbacks(new IncludeOrderPPCallbacks(*this));
}
} // namespace tidy

View File

@@ -20,8 +20,6 @@ namespace tidy {
/// see: http://llvm.org/docs/CodingStandards.html#include-style
class IncludeOrderCheck : public ClangTidyCheck {
public:
IncludeOrderCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerPPCallbacks(CompilerInstance &Compiler) override;
};

View File

@@ -10,9 +10,8 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "HeaderGuardCheck.h"
#include "IncludeOrderCheck.h"
#include "../readability/NamespaceCommentCheck.h"
#include "NamespaceCommentCheck.h"
#include "TwineLocalCheck.h"
namespace clang {
@@ -21,11 +20,14 @@ namespace tidy {
class LLVMModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<LLVMHeaderGuardCheck>("llvm-header-guard");
CheckFactories.registerCheck<IncludeOrderCheck>("llvm-include-order");
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"llvm-namespace-comment");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
CheckFactories.addCheckFactory(
"llvm-include-order", new ClangTidyCheckFactory<IncludeOrderCheck>());
CheckFactories.addCheckFactory(
"llvm-namespace-comment",
new ClangTidyCheckFactory<NamespaceCommentCheck>());
CheckFactories.addCheckFactory(
"llvm-twine-local",
new ClangTidyCheckFactory<TwineLocalCheck>());
}
};

View File

@@ -0,0 +1,117 @@
//===--- NamespaceCommentCheck.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 "NamespaceCommentCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
NamespaceCommentCheck::NamespaceCommentCheck()
: NamespaceCommentPattern("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
"namespace( +([a-zA-Z0-9_]+))? *(\\*/)?$",
llvm::Regex::IgnoreCase),
ShortNamespaceLines(1) {}
void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(namespaceDecl().bind("namespace"), this);
}
bool locationsInSameFile(const SourceManager &Sources, SourceLocation Loc1,
SourceLocation Loc2) {
return Loc1.isFileID() && Loc2.isFileID() &&
Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
}
std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak) {
std::string Fix = "// namespace";
if (!ND->isAnonymousNamespace())
Fix.append(" ").append(ND->getNameAsString());
if (InsertLineBreak)
Fix.append("\n");
return Fix;
}
void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
const NamespaceDecl *ND = Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
const SourceManager &Sources = *Result.SourceManager;
if (!locationsInSameFile(Sources, ND->getLocStart(), ND->getRBraceLoc()))
return;
// Don't require closing comments for namespaces spanning less than certain
// number of lines.
unsigned StartLine = Sources.getSpellingLineNumber(ND->getLocStart());
unsigned EndLine = Sources.getSpellingLineNumber(ND->getRBraceLoc());
if (EndLine - StartLine + 1 <= ShortNamespaceLines)
return;
// Find next token after the namespace closing brace.
SourceLocation AfterRBrace = ND->getRBraceLoc().getLocWithOffset(1);
SourceLocation Loc = AfterRBrace;
Token Tok;
// Skip whitespace until we find the next token.
while (Lexer::getRawToken(Loc, Tok, Sources, Result.Context->getLangOpts())) {
Loc = Loc.getLocWithOffset(1);
}
if (!locationsInSameFile(Sources, ND->getRBraceLoc(), Loc))
return;
bool NextTokenIsOnSameLine = Sources.getSpellingLineNumber(Loc) == EndLine;
// If we insert a line comment before the token in the same line, we need
// to insert a line break.
bool NeedLineBreak = NextTokenIsOnSameLine && Tok.isNot(tok::eof);
// Try to find existing namespace closing comment on the same line.
if (Tok.is(tok::comment) && NextTokenIsOnSameLine) {
StringRef Comment(Sources.getCharacterData(Loc), Tok.getLength());
SmallVector<StringRef, 6> Groups;
if (NamespaceCommentPattern.match(Comment, &Groups)) {
StringRef NamespaceNameInComment = Groups.size() >= 6 ? Groups[5] : "";
// Check if the namespace in the comment is the same.
if ((ND->isAnonymousNamespace() && NamespaceNameInComment.empty()) ||
ND->getNameAsString() == NamespaceNameInComment) {
// FIXME: Maybe we need a strict mode, where we always fix namespace
// comments with different format.
return;
}
// Otherwise we need to fix the comment.
NeedLineBreak = Comment.startswith("/*");
CharSourceRange OldCommentRange = CharSourceRange::getCharRange(
SourceRange(Loc, Loc.getLocWithOffset(Tok.getLength())));
diag(Loc, "namespace closing comment refers to a wrong namespace '%0'")
<< NamespaceNameInComment
<< FixItHint::CreateReplacement(
OldCommentRange, getNamespaceComment(ND, NeedLineBreak));
return;
}
// This is not a recognized form of a namespace closing comment.
// Leave line comment on the same line. Move block comment to the next line,
// as it can be multi-line or there may be other tokens behind it.
if (Comment.startswith("//"))
NeedLineBreak = false;
}
diag(ND->getLocation(), "namespace not terminated with a closing comment")
<< FixItHint::CreateInsertion(
AfterRBrace, " " + getNamespaceComment(ND, NeedLineBreak));
}
} // namespace tidy
} // namespace clang

View File

@@ -0,0 +1,36 @@
//===--- NamespaceCommentCheck.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_LLVM_NAMESPACE_COMMENT_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_NAMESPACE_COMMENT_CHECK_H
#include "../ClangTidy.h"
#include "llvm/Support/Regex.h"
namespace clang {
namespace tidy {
/// \brief Checks that long namespaces have a closing comment.
///
/// see: http://llvm.org/docs/CodingStandards.html#namespace-indentation
class NamespaceCommentCheck : public ClangTidyCheck {
public:
NamespaceCommentCheck();
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
llvm::Regex NamespaceCommentPattern;
const unsigned ShortNamespaceLines;
};
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_NAMESPACE_COMMENT_CHECK_H

View File

@@ -17,6 +17,8 @@ using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
TwineLocalCheck::TwineLocalCheck() {}
void TwineLocalCheck::registerMatchers(MatchFinder *Finder) {
auto TwineType =
qualType(hasDeclaration(recordDecl(hasName("::llvm::Twine"))));

View File

@@ -19,8 +19,7 @@ namespace tidy {
/// and should be generally avoided.
class TwineLocalCheck : public ClangTidyCheck {
public:
TwineLocalCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
TwineLocalCheck();
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -8,6 +8,9 @@
//===----------------------------------------------------------------------===//
#include "ArgumentCommentCheck.h"
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
@@ -18,21 +21,11 @@ using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
ArgumentCommentCheck::ArgumentCommentCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
ArgumentCommentCheck::ArgumentCommentCheck()
: IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
void ArgumentCommentCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
callExpr(unless(operatorCallExpr()),
// NewCallback's arguments relate to the pointed function, don't
// check them against NewCallback's parameter names.
// FIXME: Make this configurable.
unless(hasDeclaration(functionDecl(anyOf(
hasName("NewCallback"), hasName("NewPermanentCallback"))))))
.bind("expr"),
this);
Finder->addMatcher(callExpr(unless(operatorCallExpr())).bind("expr"), this);
Finder->addMatcher(constructExpr().bind("expr"), this);
}
@@ -88,10 +81,10 @@ ArgumentCommentCheck::isLikelyTypo(llvm::ArrayRef<ParmVarDecl *> Params,
if (ThisED >= UpperBound)
return false;
for (unsigned I = 0, E = Params.size(); I != E; ++I) {
if (I == ArgIndex)
for (const auto &Param : Params) {
if (&Param - Params.begin() == ArgIndex)
continue;
IdentifierInfo *II = Params[I]->getIdentifier();
IdentifierInfo *II = Param->getIdentifier();
if (!II)
continue;
@@ -121,15 +114,6 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
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;
}
}
SourceLocation BeginSLoc, EndSLoc = Args[i]->getLocStart();
if (i == 0)

View File

@@ -19,7 +19,7 @@ namespace tidy {
/// \brief Checks that argument comments match parameter names.
class ArgumentCommentCheck : public ClangTidyCheck {
public:
ArgumentCommentCheck(StringRef Name, ClangTidyContext *Context);
ArgumentCommentCheck();
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

View File

@@ -32,8 +32,7 @@ void BoolPointerImplicitConversion::registerMatchers(MatchFinder *Finder) {
hasSourceExpression(expr(
hasType(pointerType(pointee(isBoolean()))),
ignoringParenImpCasts(declRefExpr().bind("expr")))),
isPointerToBoolean())))),
unless(isInTemplateInstantiation())).bind("if"),
isPointerToBoolean()))))).bind("if"),
this);
}
@@ -42,10 +41,6 @@ BoolPointerImplicitConversion::check(const MatchFinder::MatchResult &Result) {
auto *If = Result.Nodes.getStmtAs<IfStmt>("if");
auto *Var = Result.Nodes.getStmtAs<DeclRefExpr>("expr");
// Ignore macros.
if (Var->getLocStart().isMacroID())
return;
// Only allow variable accesses for now, no function calls or member exprs.
// Check that we don't dereference the variable anywhere within the if. This
// avoids false positives for checks of the pointer for nullptr before it is

View File

@@ -23,8 +23,6 @@ namespace tidy {
/// }
class BoolPointerImplicitConversion : public ClangTidyCheck {
public:
BoolPointerImplicitConversion(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -4,10 +4,8 @@ add_clang_library(clangTidyMiscModule
ArgumentCommentCheck.cpp
BoolPointerImplicitConversion.cpp
MiscTidyModule.cpp
RedundantSmartptrGet.cpp
SwappedArgumentsCheck.cpp
UndelegatedConstructor.cpp
UnusedRAII.cpp
UniqueptrResetRelease.cpp
UseOverride.cpp
LINK_LIBS

View File

@@ -12,10 +12,8 @@
#include "../ClangTidyModuleRegistry.h"
#include "ArgumentCommentCheck.h"
#include "BoolPointerImplicitConversion.h"
#include "RedundantSmartptrGet.h"
#include "SwappedArgumentsCheck.h"
#include "UndelegatedConstructor.h"
#include "UnusedRAII.h"
#include "UniqueptrResetRelease.h"
#include "UseOverride.h"
namespace clang {
@@ -24,17 +22,21 @@ namespace tidy {
class MiscModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<ArgumentCommentCheck>("misc-argument-comment");
CheckFactories.registerCheck<BoolPointerImplicitConversion>(
"misc-bool-pointer-implicit-conversion");
CheckFactories.registerCheck<SwappedArgumentsCheck>(
"misc-swapped-arguments");
CheckFactories.registerCheck<UndelegatedConstructorCheck>(
"misc-undelegated-constructor");
CheckFactories.registerCheck<UniqueptrResetRelease>(
"misc-uniqueptr-reset-release");
CheckFactories.registerCheck<UnusedRAIICheck>("misc-unused-raii");
CheckFactories.registerCheck<UseOverride>("misc-use-override");
CheckFactories.addCheckFactory(
"misc-argument-comment",
new ClangTidyCheckFactory<ArgumentCommentCheck>());
CheckFactories.addCheckFactory(
"misc-bool-pointer-implicit-conversion",
new ClangTidyCheckFactory<BoolPointerImplicitConversion>());
CheckFactories.addCheckFactory(
"misc-redundant-smartptr-get",
new ClangTidyCheckFactory<RedundantSmartptrGet>());
CheckFactories.addCheckFactory(
"misc-swapped-arguments",
new ClangTidyCheckFactory<SwappedArgumentsCheck>());
CheckFactories.addCheckFactory(
"misc-use-override",
new ClangTidyCheckFactory<UseOverride>());
}
};

View File

@@ -15,7 +15,6 @@ using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace readability {
namespace {
internal::Matcher<Expr> callToGet(internal::Matcher<Decl> OnClass) {
@@ -118,6 +117,5 @@ void RedundantSmartptrGet::check(const MatchFinder::MatchResult &Result) {
<< FixItHint::CreateReplacement(GetCall->getSourceRange(), Replacement);
}
} // namespace readability
} // namespace tidy
} // namespace clang

View File

@@ -0,0 +1,34 @@
//===--- RedundantSmartptrGet.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_MISC_REDUNDANT_SMARTPTR_GET_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
/// \brief Find and remove redundant calls to smart pointer's .get() method.
///
/// Examples:
/// ptr.get()->Foo() ==> ptr->Foo()
/// *ptr.get() ==> *ptr
/// *ptr->get() ==> **ptr
class RedundantSmartptrGet : public ClangTidyCheck {
public:
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H

View File

@@ -19,8 +19,6 @@ namespace tidy {
/// conversions.
class SwappedArgumentsCheck : public ClangTidyCheck {
public:
SwappedArgumentsCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -1,74 +0,0 @@
//===--- UndelegatedConstructor.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 "UndelegatedConstructor.h"
#include "clang/AST/ASTContext.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace ast_matchers {
AST_MATCHER_P(Stmt, ignoringTemporaryExpr, internal::Matcher<Stmt>,
InnerMatcher) {
const Stmt *E = &Node;
for (;;) {
// Temporaries with non-trivial dtors.
if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
E = EWC->getSubExpr();
// Temporaries with zero or more than two ctor arguments.
else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BTE->getSubExpr();
// Temporaries with exactly one ctor argument.
else if (const auto *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
E = FCE->getSubExpr();
else
break;
}
return InnerMatcher.matches(*E, Finder, Builder);
}
// Finds a node if it's a base of an already bound node.
AST_MATCHER_P(CXXRecordDecl, baseOfBoundNode, std::string, ID) {
return Builder->removeBindings([&](const internal::BoundNodesMap &Nodes) {
const auto *Derived = Nodes.getNodeAs<CXXRecordDecl>(ID);
return Derived != &Node && !Derived->isDerivedFrom(&Node);
});
}
} // namespace ast_matchers
namespace tidy {
void UndelegatedConstructorCheck::registerMatchers(MatchFinder *Finder) {
// We look for calls to constructors of the same type in constructors. To do
// this we have to look through a variety of nodes that occur in the path,
// depending on the type's destructor and the number of arguments on the
// constructor call, this is handled by ignoringTemporaryExpr. Ignore template
// instantiations to reduce the number of duplicated warnings.
Finder->addMatcher(
compoundStmt(
hasParent(constructorDecl(ofClass(recordDecl().bind("parent")))),
forEach(ignoringTemporaryExpr(
constructExpr(hasDeclaration(constructorDecl(ofClass(
recordDecl(baseOfBoundNode("parent"))))))
.bind("construct"))),
unless(isInTemplateInstantiation())),
this);
}
void UndelegatedConstructorCheck::check(const MatchFinder::MatchResult &Result) {
const auto *E = Result.Nodes.getStmtAs<CXXConstructExpr>("construct");
diag(E->getLocStart(), "did you intend to call a delegated constructor? "
"A temporary object is created here instead");
}
} // namespace tidy
} // namespace clang

View File

@@ -1,32 +0,0 @@
//===--- UndelegatedConstructor.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_MISC_UNDELEGATED_CONSTRUCTOR_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNDELEGATED_CONSTRUCTOR_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
/// \brief Finds creation of temporary objects in constructors that look like a
/// function call to another constructor of the same class. The user most likely
/// meant to use a delegating constructor or base class initializer.
class UndelegatedConstructorCheck : public ClangTidyCheck {
public:
UndelegatedConstructorCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNDELEGATED_CONSTRUCTOR_H

View File

@@ -1,66 +0,0 @@
//===--- UniqueptrResetRelease.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 "UniqueptrResetRelease.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
void UniqueptrResetRelease::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
memberCallExpr(
on(expr().bind("left")), callee(memberExpr().bind("reset_member")),
callee(methodDecl(hasName("reset"),
ofClass(hasName("::std::unique_ptr")))),
has(memberCallExpr(
on(expr().bind("right")),
callee(memberExpr().bind("release_member")),
callee(methodDecl(hasName("release"),
ofClass(hasName("::std::unique_ptr")))))))
.bind("reset_call"),
this);
}
void UniqueptrResetRelease::check(const MatchFinder::MatchResult &Result) {
const auto *ResetMember = Result.Nodes.getNodeAs<MemberExpr>("reset_member");
const auto *ReleaseMember =
Result.Nodes.getNodeAs<MemberExpr>("release_member");
const auto *Right = Result.Nodes.getNodeAs<Expr>("right");
const auto *Left = Result.Nodes.getNodeAs<Expr>("left");
const auto *ResetCall =
Result.Nodes.getNodeAs<CXXMemberCallExpr>("reset_call");
std::string LeftText = clang::Lexer::getSourceText(
CharSourceRange::getTokenRange(Left->getSourceRange()),
*Result.SourceManager, Result.Context->getLangOpts());
std::string RightText = clang::Lexer::getSourceText(
CharSourceRange::getTokenRange(Right->getSourceRange()),
*Result.SourceManager, Result.Context->getLangOpts());
if (ResetMember->isArrow())
LeftText = "*" + LeftText;
if (ReleaseMember->isArrow())
RightText = "*" + RightText;
// Even if x was rvalue, *x is not rvalue anymore.
if (!Right->isRValue() || ReleaseMember->isArrow())
RightText = "std::move(" + RightText + ")";
std::string NewText = LeftText + " = " + RightText;
diag(ResetMember->getExprLoc(),
"prefer ptr1 = std::move(ptr2) over ptr1.reset(ptr2.release())")
<< FixItHint::CreateReplacement(
CharSourceRange::getTokenRange(ResetCall->getSourceRange()), NewText);
}
} // namespace tidy
} // namespace clang

View File

@@ -1,38 +0,0 @@
//===--- UniqueptrResetRelease.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_MISC_UNIQUEPTR_RESET_RELEASE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNIQUEPTR_RESET_RELEASE_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
/// \brief Find and replace unique_ptr::reset(release()) with std::move
///
/// Example:
/// std::unique_ptr<Foo> x, y;
/// x.reset(y.release()); -> x = std::move(y);
///
/// If "y" is already rvalue, std::move is not added.
/// "x" and "y" can also be std::unique_ptr<Foo>*.
class UniqueptrResetRelease : public ClangTidyCheck {
public:
UniqueptrResetRelease(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNIQUEPTR_RESET_RELEASE_H

View File

@@ -1,83 +0,0 @@
//===--- UnusedRAII.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 "UnusedRAII.h"
#include "clang/AST/ASTContext.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace ast_matchers {
AST_MATCHER(CXXRecordDecl, hasUserDeclaredDestructor) {
// TODO: If the dtor is there but empty we don't want to warn either.
return Node.hasDefinition() && Node.hasUserDeclaredDestructor();
}
} // namespace ast_matchers
namespace tidy {
void UnusedRAIICheck::registerMatchers(MatchFinder *Finder) {
// Look for temporaries that are constructed in-place and immediately
// destroyed. Look for temporaries created by a functional cast but not for
// those returned from a call.
auto BindTemp = bindTemporaryExpr(unless(has(callExpr()))).bind("temp");
Finder->addMatcher(
exprWithCleanups(unless(isInTemplateInstantiation()),
hasParent(compoundStmt().bind("compound")),
hasType(recordDecl(hasUserDeclaredDestructor())),
anyOf(has(BindTemp), has(functionalCastExpr(
has(BindTemp))))).bind("expr"),
this);
}
void UnusedRAIICheck::check(const MatchFinder::MatchResult &Result) {
const auto *E = Result.Nodes.getStmtAs<Expr>("expr");
// We ignore code expanded from macros to reduce the number of false
// positives.
if (E->getLocStart().isMacroID())
return;
// Don't emit a warning for the last statement in the surrounding compund
// statement.
const auto *CS = Result.Nodes.getStmtAs<CompoundStmt>("compound");
if (E == CS->body_back())
return;
// Emit a warning.
auto D = diag(E->getLocStart(), "object destroyed immediately after "
"creation; did you mean to name the object?");
const char *Replacement = " give_me_a_name";
// If this is a default ctor we have to remove the parens or we'll introduce a
// most vexing parse.
const auto *BTE = Result.Nodes.getStmtAs<CXXBindTemporaryExpr>("temp");
if (const auto *TOE = dyn_cast<CXXTemporaryObjectExpr>(BTE->getSubExpr()))
if (TOE->getNumArgs() == 0) {
D << FixItHint::CreateReplacement(
CharSourceRange::getTokenRange(TOE->getParenOrBraceRange()),
Replacement);
return;
}
// Otherwise just suggest adding a name. To find the place to insert the name
// find the first TypeLoc in the children of E, which always points to the
// written type.
auto Matches =
match(expr(hasDescendant(typeLoc().bind("t"))), *E, *Result.Context);
const auto *TL = selectFirst<TypeLoc>("t", Matches);
D << FixItHint::CreateInsertion(
Lexer::getLocForEndOfToken(TL->getLocEnd(), 0, *Result.SourceManager,
Result.Context->getLangOpts()),
Replacement);
}
} // namespace tidy
} // namespace clang

View File

@@ -1,49 +0,0 @@
//===--- UnusedRAII.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_MISC_UNUSED_RAII_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_RAII_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
/// \brief Finds temporaries that look like RAII objects.
///
/// The canonical example for this is a scoped lock.
/// \code
/// {
/// scoped_lock(&global_mutex);
/// critical_section();
/// }
/// \endcode
/// The destructor of the scoped_lock is called before the critical_section is
/// entered, leaving it unprotected.
///
/// We apply a number of heuristics to reduce the false positive count of this
/// check:
/// - Ignore code expanded from macros. Testing frameworks make heavy use of
/// this.
/// - Ignore types with no user-declared constructor. Those are very unlikely
/// to be RAII objects.
/// - Ignore objects at the end of a compound statement (doesn't change behavior).
/// - Ignore objects returned from a call.
class UnusedRAIICheck : public ClangTidyCheck {
public:
UnusedRAIICheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNUSED_RAII_H

View File

@@ -74,8 +74,8 @@ void UseOverride::check(const MatchFinder::MatchResult &Result) {
DiagnosticBuilder Diag = diag(
Method->getLocation(),
OnlyVirtualSpecified
? "Prefer using 'override' or (rarely) 'final' instead of 'virtual'"
: "Annotate this function with 'override' or (rarely) 'final'");
? "Prefer using 'override' or 'final' instead of 'virtual'"
: "Use exactly one of 'virtual', 'override' or (rarely) 'final'");
CharSourceRange FileRange = Lexer::makeFileCharRange(
CharSourceRange::getTokenRange(Method->getSourceRange()), Sources,
@@ -98,10 +98,8 @@ void UseOverride::check(const MatchFinder::MatchResult &Result) {
if (Method->hasAttrs()) {
for (const clang::Attr *A : Method->getAttrs()) {
if (!A->isImplicit()) {
SourceLocation Loc = Sources.getExpansionLoc(A->getLocation());
if (!InsertLoc.isValid() ||
Sources.isBeforeInTranslationUnit(Loc, InsertLoc))
InsertLoc = Loc;
InsertLoc = Sources.getExpansionLoc(A->getLocation());
break;
}
}
}

View File

@@ -18,8 +18,6 @@ namespace tidy {
/// \brief Use C++11's 'override' and remove 'virtual' where applicable.
class UseOverride : public ClangTidyCheck {
public:
UseOverride(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

View File

@@ -1,257 +0,0 @@
//===--- BracesAroundStatementsCheck.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 "BracesAroundStatementsCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace readability {
namespace {
tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
const ASTContext *Context) {
Token Tok;
SourceLocation Beginning =
Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts());
const bool Invalid =
Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts());
assert(!Invalid && "Expected a valid token.");
if (Invalid)
return tok::NUM_TOKENS;
return Tok.getKind();
}
SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc,
const SourceManager &SM,
const ASTContext *Context) {
assert(Loc.isValid());
for (;;) {
while (isWhitespace(*FullSourceLoc(Loc, SM).getCharacterData()))
Loc = Loc.getLocWithOffset(1);
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
if (TokKind == tok::NUM_TOKENS || TokKind != tok::comment)
return Loc;
// Fast-forward current token.
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
}
}
SourceLocation findEndLocation(SourceLocation LastTokenLoc,
const SourceManager &SM,
const ASTContext *Context) {
SourceLocation Loc = LastTokenLoc;
// Loc points to the beginning of the last (non-comment non-ws) token
// before end or ';'.
assert(Loc.isValid());
bool SkipEndWhitespaceAndComments = true;
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi ||
TokKind == tok::r_brace) {
// If we are at ";" or "}", we found the last token. We could use as well
// `if (isa<NullStmt>(S))`, but it wouldn't work for nested statements.
SkipEndWhitespaceAndComments = false;
}
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
// Loc points past the last token before end or after ';'.
if (SkipEndWhitespaceAndComments) {
Loc = forwardSkipWhitespaceAndComments(Loc, SM, Context);
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
if (TokKind == tok::semi)
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
}
for (;;) {
assert(Loc.isValid());
while (isHorizontalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData()))
Loc = Loc.getLocWithOffset(1);
if (isVerticalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) {
// EOL, insert brace before.
break;
}
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
if (TokKind != tok::comment) {
// Non-comment token, insert brace before.
break;
}
SourceLocation TokEndLoc =
Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
SourceRange TokRange(Loc, TokEndLoc);
StringRef Comment = Lexer::getSourceText(
CharSourceRange::getTokenRange(TokRange), SM, Context->getLangOpts());
if (Comment.startswith("/*") && Comment.find('\n') != StringRef::npos) {
// Multi-line block comment, insert brace before.
break;
}
// else: Trailing comment, insert brace after the newline.
// Fast-forward current token.
Loc = TokEndLoc;
}
return Loc;
}
} // namespace
BracesAroundStatementsCheck::BracesAroundStatementsCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
// Always add braces by default.
ShortStatementLines(Options.get("ShortStatementLines", 0U)) {}
void
BracesAroundStatementsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "ShortStatementLines", ShortStatementLines);
}
void BracesAroundStatementsCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(ifStmt().bind("if"), this);
Finder->addMatcher(whileStmt().bind("while"), this);
Finder->addMatcher(doStmt().bind("do"), this);
Finder->addMatcher(forStmt().bind("for"), this);
Finder->addMatcher(forRangeStmt().bind("for-range"), this);
}
void
BracesAroundStatementsCheck::check(const MatchFinder::MatchResult &Result) {
const SourceManager &SM = *Result.SourceManager;
const ASTContext *Context = Result.Context;
// Get location of closing parenthesis or 'do' to insert opening brace.
if (auto S = Result.Nodes.getNodeAs<ForStmt>("for")) {
checkStmt(Result, S->getBody(), S->getRParenLoc());
} else if (auto S = Result.Nodes.getNodeAs<CXXForRangeStmt>("for-range")) {
checkStmt(Result, S->getBody(), S->getRParenLoc());
} else if (auto S = Result.Nodes.getNodeAs<DoStmt>("do")) {
checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc());
} else if (auto S = Result.Nodes.getNodeAs<WhileStmt>("while")) {
SourceLocation StartLoc = findRParenLoc(S, SM, Context);
if (StartLoc.isInvalid())
return;
checkStmt(Result, S->getBody(), StartLoc);
} else if (auto S = Result.Nodes.getNodeAs<IfStmt>("if")) {
SourceLocation StartLoc = findRParenLoc(S, SM, Context);
if (StartLoc.isInvalid())
return;
checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc());
const Stmt *Else = S->getElse();
if (Else && !isa<IfStmt>(Else)) {
// Omit 'else if' statements here, they will be handled directly.
checkStmt(Result, Else, S->getElseLoc());
}
} else {
llvm_unreachable("Invalid match");
}
}
/// Find location of right parenthesis closing condition
template <typename IfOrWhileStmt>
SourceLocation
BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
const SourceManager &SM,
const ASTContext *Context) {
// Skip macros
if (S->getLocStart().isMacroID())
return SourceLocation();
static const char *const ErrorMessage =
"cannot find location of closing parenthesis ')'";
SourceLocation CondEndLoc = S->getCond()->getLocEnd();
if (const DeclStmt *CondVar = S->getConditionVariableDeclStmt())
CondEndLoc = CondVar->getLocEnd();
assert(CondEndLoc.isValid());
SourceLocation PastCondEndLoc =
Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, Context->getLangOpts());
if (PastCondEndLoc.isInvalid()) {
diag(CondEndLoc, ErrorMessage);
return SourceLocation();
}
SourceLocation RParenLoc =
forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, Context);
if (RParenLoc.isInvalid()) {
diag(PastCondEndLoc, ErrorMessage);
return SourceLocation();
}
tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, Context);
if (TokKind != tok::r_paren) {
diag(RParenLoc, ErrorMessage);
return SourceLocation();
}
return RParenLoc;
}
void
BracesAroundStatementsCheck::checkStmt(const MatchFinder::MatchResult &Result,
const Stmt *S, SourceLocation InitialLoc,
SourceLocation EndLocHint) {
// 1) If there's a corresponding "else" or "while", the check inserts "} "
// right before that token.
// 2) If there's a multi-line block comment starting on the same line after
// the location we're inserting the closing brace at, or there's a non-comment
// token, the check inserts "\n}" right before that token.
// 3) Otherwise the check finds the end of line (possibly after some block or
// line comments) and inserts "\n}" right before that EOL.
if (!S || isa<CompoundStmt>(S)) {
// Already inside braces.
return;
}
// Skip macros.
if (S->getLocStart().isMacroID())
return;
const SourceManager &SM = *Result.SourceManager;
const ASTContext *Context = Result.Context;
// InitialLoc points at the last token before opening brace to be inserted.
assert(InitialLoc.isValid());
SourceLocation StartLoc =
Lexer::getLocForEndOfToken(InitialLoc, 0, SM, Context->getLangOpts());
// StartLoc points at the location of the opening brace to be inserted.
SourceLocation EndLoc;
std::string ClosingInsertion;
if (EndLocHint.isValid()) {
EndLoc = EndLocHint;
ClosingInsertion = "} ";
} else {
EndLoc = findEndLocation(S->getLocEnd(), SM, Context);
ClosingInsertion = "\n}";
}
assert(StartLoc.isValid());
assert(EndLoc.isValid());
// Don't require braces for statements spanning less than certain number of
// lines.
if (ShortStatementLines) {
unsigned StartLine = SM.getSpellingLineNumber(StartLoc);
unsigned EndLine = SM.getSpellingLineNumber(EndLoc);
if (EndLine - StartLine < ShortStatementLines)
return;
}
auto Diag = diag(StartLoc, "statement should be inside braces");
Diag << FixItHint::CreateInsertion(StartLoc, " {")
<< FixItHint::CreateInsertion(EndLoc, ClosingInsertion);
}
} // namespace readability
} // namespace tidy
} // namespace clang

Some files were not shown because too many files have changed in this diff Show More