From klimek at google.com Mon May 14 03:15:59 2012 From: klimek at google.com (Manuel Klimek) Date: Mon, 14 May 2012 10:15:59 +0200 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: <4FB07FFA.5000702@gmail.com> References: <4FB07FFA.5000702@gmail.com> Message-ID: On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc wrote: > On 5/13/12 1:00 AM, Manuel Klimek wrote: > >> + @property >> + def translation_unit(self): >> + """Returns the TranslationUnit to which this Cursor belongs.""" >> + return getattr(self, '_tu', None) >> >> What's the reason for the default value? Do we expect that people create >> cursers via the lowlevel calls? Why would just return tu_ not work? >> > Just defensive programming. If you return self._tu, that may raise an > AttributeError if _tu is not set. Theoretically, the API should ensure that > a TU is defined on all Cursor instances, so maybe an AttributeError would > be acceptable. I'd prefer that - to me defensive programming means to: 1. never crash for invalid user input 2. crash hard if there's an actual bug in the library If the cursor should never be generated by a user (-> the contract of the library is to not break that), I think we should use _tu and have the AttributeError thrown if it's not there. Or I'm also fine with putting in an assert that checks that the attribute is there and delivers a nicer error in case it's missing. > + # Store a reference to the TU in the Python object so it won't >> get GC'd >> + # before the Cursor. >> + tu = None >> + for arg in args: >> + if isinstance(arg, TranslationUnit): >> + tu = arg >> + break >> + >> + if hasattr(arg, 'translation_unit'): >> + tu = arg.translation_unit >> + break >> + >> + assert tu is not None >> + >> + res._tu = tu >> >> That seems - odd. I can't find docs what from_result is supposed to do, >> or what "args" are provided. But having to search through them for a TU >> seems wrong - shouldn't they all have a TU? >> > from_result is the errcheck function for the ctypes functions that return > a Cursor. The 3rd argument to an errcheck function are the original > arguments passed into the called function. For many of the functions, the > original argument is a Cursor. However, clang_getTypeDeclaration takes a > Type and clang_getTranslationUnitCursor receives a TranslationUnit. > > It is true that all of the functions today receive a single argument, so > the iteration isn't required. However, that may change with the addition of > new APIs in the future (this is how I coded it in my nearly > feature-complete branch, so I'm guessing it is actually required from a > future patch). The question is: don't we just want to assert that all of those have a TU (or are a TU)? > > >> Also, regarding the test - would it be possible to create a test that >> drops the reference, triggers the gc and then makes sure the cursor is >> still valid (as that is what we really care about)? >> >> Sure! > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/8dfcdc21/attachment.html From hans at chromium.org Mon May 14 03:31:48 2012 From: hans at chromium.org (Hans Wennborg) Date: Mon, 14 May 2012 09:31:48 +0100 Subject: [cfe-commits] [PATCH 4/4] [clang.py] Implement Cursor.is_static_method In-Reply-To: <4FB08018.8040004@gmail.com> References: <4FB08018.8040004@gmail.com> Message-ID: On Mon, May 14, 2012 at 4:46 AM, Gregory Szorc wrote: > On 5/13/12 1:19 AM, Manuel Klimek wrote: >> + ? ? ? ?Returns True if it is or False if not or if the Cursor does >> not refer >> + ? ? ? ?to a function template declaration or method declaration. >> >> This took me a while to parse... So two things: first, shouldn't that >> be "member function template"? > I don't know! >> Second, how about: "Returns whether the Cursor refers to a static >> member function template or method declaration." > Yeah, it is hard to read. I'll update the description. >> I'm also not quite sure whether all this is necessary, and "method" is >> not good enough to describe the intent here, but my C++-foo is >> probably not good enough for that argument. > Perhaps someone who knows the C++ terminology could weigh in here. Looking at clang_CXXMethod_isStatic in include/clang-c/Index.h, that says "Determine if a C++ member function or member function template is declared 'static'." So maybe something like: "Returns true if the cursor refers to a C++ member function or member function template that is declared 'static'."? - Hans From klimek at google.com Mon May 14 10:16:36 2012 From: klimek at google.com (Manuel Klimek) Date: Mon, 14 May 2012 17:16:36 +0200 Subject: [cfe-commits] [PATCH] ClangPlugin tutorial Message-ID: Find a proposal for a short ClangPlugin tutorial attached. Cheers, /Manuel -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/311cb674/attachment-0002.html -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/311cb674/attachment-0003.html From dblaikie at gmail.com Mon May 14 10:55:17 2012 From: dblaikie at gmail.com (David Blaikie) Date: Mon, 14 May 2012 08:55:17 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: Message-ID: Ping On Sun, May 6, 2012 at 7:02 PM, David Blaikie wrote: > This patch adds an iterator much like boost's transform_iterator > (without some extra bells & whistles) for use in some changes I'd like > to make to Clang to correct some misimplemented iterators there. > > A few gotchas that could be improved/changed depending on opinions: > * I may be playing a little loose with the return type of the functor > (see the example/motivating functor, to_pointer) - the return type > actually must be a reference, though the result_type provides the > underlying value type, not the reference type. If this is violated > Clang will emit a warning, but I could make it more robust with a > compile time assertion in the TransformIterator that the result_type > is actually a reference type, and strip that off to provide the > value_type of the TransformIterator. > * I realize adding pointer-yness back onto an iterator over references > when the underlying data structure (in the Clang patch you can see > this situation) is a sequence of pointers may be a bit overkill - > though the alternatives are writing different algorithms in the two > cases where I've used TransformIterator, or having the decl_iterator > iterate over pointers (in which case I should probably change the > other iterators I've modified to iterate over pointers for symmetry). > > At some point I'll also be looking to add a FilterIterator (& possibly > a specific Filtering+Transforming iterator, as I'm not sure the > composition of the two independently will be great for the use case I > have in mind) as well since that's one of the motivation for tidying > up these iterators - to pull out the common functionality in the > specific/filtered_iterators in DeclContext. > > Thanks, > - David -------------- next part -------------- A non-text attachment was scrubbed... Name: TransformIterator_clang_usage.diff Type: application/octet-stream Size: 40302 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/8e627667/attachment-0002.obj -------------- next part -------------- A non-text attachment was scrubbed... Name: TransformIterator.diff Type: application/octet-stream Size: 4007 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/8e627667/attachment-0003.obj From hans at chromium.org Mon May 14 11:25:08 2012 From: hans at chromium.org (Hans Wennborg) Date: Mon, 14 May 2012 17:25:08 +0100 Subject: [cfe-commits] [PATCH] ClangPlugin tutorial In-Reply-To: References: Message-ID: On Mon, May 14, 2012 at 4:16 PM, Manuel Klimek wrote: > Find a proposal for a short ClangPlugin tutorial attached. Nice! Some nits inline: > >

Writing a PluginASTAction

> > >

The main difference when writing PluginASTActions is that you can handle Main difference compared to what? Maybe make PluginASTAction a link to the doxygen? In fact, the more links to the doxygen, the better :) > >

Registering a plugin

> > >

A plugin is loaded as dynamic library at runtime by the compiler. To register As *a* dynamic library? > a plugin in a library, use FrontendPluginRegistry::Add:

>
>   static FrontendPluginRegistry::Add X("my-plugin-name", "my plugin description");

The < and > around MyPlugin need to be escaped.

> 
> 

Putting it all together

> > >

Let's look at an example plugin that prints top-level function names. > This example is also checked into the clang repository; please also take a look > at the latest checked in version of PrintFunctionNames.cpp.

Remove the "revision=..." part from the URL? > >

Running the plugin

> > >

To run a plugin the dynamic library containing the plugin registry must be I'd put a comma after "To run a plugin". > loaded via the -load command line option. This will load all plugins that are > registered, and you can select the plugins to run by specifying the -plugin > option. Additional parameters for the plugins can be passed with -plugin-arg-<plugin-name>.

> >

Note that those options must be reach clang's cc1 process. There are two "must be reach" >

Also see the print-function-name plugin example's > README

Again, the URL should probably point to the HEAD revision? Thanks, Hans From klimek at google.com Mon May 14 11:43:39 2012 From: klimek at google.com (Manuel Klimek) Date: Mon, 14 May 2012 18:43:39 +0200 Subject: [cfe-commits] [PATCH] ClangPlugin tutorial In-Reply-To: References: Message-ID: On Mon, May 14, 2012 at 6:25 PM, Hans Wennborg wrote: > On Mon, May 14, 2012 at 4:16 PM, Manuel Klimek wrote: > > Find a proposal for a short ClangPlugin tutorial attached. > > Nice! Some nits inline: > > > > >

Writing a PluginASTAction

> > > > > >

The main difference when writing PluginASTActions is that you can > handle > > Main difference compared to what? > Maybe make PluginASTAction a link to the doxygen? In fact, the more > links to the doxygen, the better :) > Changed the sentence. I'm planning to add the doxygen links for all documentation later. I want to get content in first, and iterate on it. > > >

Registering a plugin

> > > > > >

A plugin is loaded as dynamic library at runtime by the compiler. To > register > > As *a* dynamic library? > Changed to "from a dynamic library". > > a plugin in a library, use FrontendPluginRegistry::Add:

> >
> >   static FrontendPluginRegistry::Add X("my-plugin-name", "my
> plugin description");
>
> The < and > around MyPlugin need to be escaped.
>

Escaped the <. (> doesn't need to be escaped, right?)


> > 
> > 

Putting it all together

> > > > > >

Let's look at an example plugin that prints top-level function names. > > This example is also checked into the clang repository; please also take > a look > > at the latest checked > in version of PrintFunctionNames.cpp.

> > Remove the "revision=..." part from the URL? > Done. > > > >

Running the plugin

> > > > > >

To run a plugin the dynamic library containing the plugin registry > must be > > I'd put a comma after "To run a plugin". > Done. > > loaded via the -load command line option. This will load all plugins > that are > > registered, and you can select the plugins to run by specifying the > -plugin > > option. Additional parameters for the plugins can be passed with > -plugin-arg-<plugin-name>.

> > > >

Note that those options must be reach clang's cc1 process. There are > two > > "must be reach" > Done. > >

Also see the print-function-name plugin example's > > README

> > Again, the URL should probably point to the HEAD revision? > Done. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/453fa1c9/attachment.html -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/453fa1c9/attachment-0001.html From gribozavr at gmail.com Mon May 14 12:10:33 2012 From: gribozavr at gmail.com (Dmitri Gribenko) Date: Mon, 14 May 2012 20:10:33 +0300 Subject: [cfe-commits] [PATCH] ClangPlugin tutorial In-Reply-To: References: Message-ID: Hi Manuel, > [...] In this tutorial, we'll > demonstrate how to run clang's SyntaxOnlyAction But PrintFunctionNamesAction is used in the example. Dmitri -- main(i,j){for(i=2;;i++){for(j=2;j*/ From jediknil at belkadan.com Mon May 14 12:58:36 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Mon, 14 May 2012 17:58:36 -0000 Subject: [cfe-commits] r156769 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/CStringChecker.cpp test/Analysis/string.c Message-ID: <20120514175836.2F3292A6C065@llvm.org> Author: jrose Date: Mon May 14 12:58:35 2012 New Revision: 156769 URL: http://llvm.org/viewvc/llvm-project?rev=156769&view=rev Log: [analyzer] strncpy: Special-case a length of 0 to avoid an incorrect warning. We check the address of the last element accessed, but with 0 calculating that address results in element -1. This patch bails out early (and avoids a bunch of other work at that). Fixes PR12807. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp cfe/trunk/test/Analysis/string.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=156769&r1=156768&r2=156769&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Mon May 14 12:58:35 2012 @@ -1404,6 +1404,24 @@ // For strncpy, this is just checking that lenVal <= sizeof(dst) // (Yes, strncpy and strncat differ in how they treat termination. // strncat ALWAYS terminates, but strncpy doesn't.) + + // We need a special case for when the copy size is zero, in which + // case strncpy will do no work at all. Our bounds check uses n-1 + // as the last element accessed, so n == 0 is problematic. + ProgramStateRef StateZeroSize, StateNonZeroSize; + llvm::tie(StateZeroSize, StateNonZeroSize) = + assumeZero(C, state, *lenValNL, sizeTy); + + // If the size is known to be zero, we're done. + if (StateZeroSize && !StateNonZeroSize) { + StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal); + C.addTransition(StateZeroSize); + return; + } + + // Otherwise, go ahead and figure out the last element we'll touch. + // We don't record the non-zero assumption here because we can't + // be sure. We won't warn on a possible zero. NonLoc one = cast(svalBuilder.makeIntVal(1, sizeTy)); maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL, one, sizeTy); Modified: cfe/trunk/test/Analysis/string.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156769&r1=156768&r2=156769&view=diff ============================================================================== --- cfe/trunk/test/Analysis/string.c (original) +++ cfe/trunk/test/Analysis/string.c Mon May 14 12:58:35 2012 @@ -578,6 +578,17 @@ (void)*(int*)0; // no-warning } +void strncpy_zero(char *src) { + char dst[] = "123"; + strncpy(dst, src, 0); // no-warning +} + +void strncpy_empty() { + char dst[] = "123"; + char src[] = ""; + strncpy(dst, src, 4); // no-warning +} + //===----------------------------------------------------------------------=== // strncat() //===----------------------------------------------------------------------=== @@ -716,6 +727,17 @@ strncat(dst, src, 2); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}} } +void strncat_zero(char *src) { + char dst[] = "123"; + strncat(dst, src, 0); // no-warning +} + +void strncat_empty() { + char dst[8] = "123"; + char src[] = ""; + strncat(dst, src, 4); // no-warning +} + //===----------------------------------------------------------------------=== // strcmp() //===----------------------------------------------------------------------=== From chandlerc at gmail.com Mon May 14 13:31:18 2012 From: chandlerc at gmail.com (Chandler Carruth) Date: Mon, 14 May 2012 18:31:18 -0000 Subject: [cfe-commits] r156771 - in /cfe/trunk: lib/Driver/Tools.cpp test/Driver/nodefaultlib.c Message-ID: <20120514183118.B8CFF2A6C065@llvm.org> Author: chandlerc Date: Mon May 14 13:31:18 2012 New Revision: 156771 URL: http://llvm.org/viewvc/llvm-project?rev=156771&view=rev Log: Teach the driver on Linux to respect -nodefaultlibs. Patch from Andrew C. Morrow. Added: cfe/trunk/test/Driver/nodefaultlib.c Modified: cfe/trunk/lib/Driver/Tools.cpp Modified: cfe/trunk/lib/Driver/Tools.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=156771&r1=156770&r2=156771&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Tools.cpp (original) +++ cfe/trunk/lib/Driver/Tools.cpp Mon May 14 13:31:18 2012 @@ -5313,7 +5313,9 @@ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); - if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib)) { + if (D.CCCIsCXX && + !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && !Args.hasArg(options::OPT_static); if (OnlyLibstdcxxStatic) @@ -5328,22 +5330,23 @@ addAsanRTLinux(getToolChain(), Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib)) { - if (Args.hasArg(options::OPT_static)) - CmdArgs.push_back("--start-group"); - - AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); + if (!Args.hasArg(options::OPT_nodefaultlibs)) { + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("--start-group"); - if (Args.hasArg(options::OPT_pthread) || - Args.hasArg(options::OPT_pthreads)) - CmdArgs.push_back("-lpthread"); + AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); - CmdArgs.push_back("-lc"); + if (Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads)) + CmdArgs.push_back("-lpthread"); - if (Args.hasArg(options::OPT_static)) - CmdArgs.push_back("--end-group"); - else - AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); + CmdArgs.push_back("-lc"); + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("--end-group"); + else + AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); + } if (!Args.hasArg(options::OPT_nostartfiles)) { const char *crtend; Added: cfe/trunk/test/Driver/nodefaultlib.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/nodefaultlib.c?rev=156771&view=auto ============================================================================== --- cfe/trunk/test/Driver/nodefaultlib.c (added) +++ cfe/trunk/test/Driver/nodefaultlib.c Mon May 14 13:31:18 2012 @@ -0,0 +1,8 @@ +// RUN: %clang -target i686-pc-linux-gnu -### -nodefaultlibs %s 2> %t +// RUN: FileCheck < %t %s +// +// CHECK-NOT: start-group +// CHECK-NOT: -lgcc +// CHECK-NOT: -lc +// CHECK: crtbegin +// CHECK: crtend From rjmccall at apple.com Mon May 14 13:34:58 2012 From: rjmccall at apple.com (John McCall) Date: Mon, 14 May 2012 11:34:58 -0700 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: References: Message-ID: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> On May 12, 2012, at 3:50 AM, Jonathan Schleifer wrote: > Attached is a patch that adds the option -fobjc-direct-class-refs to Clang. It allows using direct references to classes with the GNU ABI, which Clang already emits, but does not use yet. > > I have tested it with my own runtime, but it should also work with the GNUstep runtime. > > I'd appreciate any feedback and would love to get it committed if the patch is done correctly. If the GNU runtime supports emitting direct references to the class, why is a command-line option necessary? I am opposed to providing an ever-expanding spectrum of command line flags ? particularly driver flags! ? to slightly tweak the ABI. Even if we supported this, it would be an IR-gen option, not a language option. John. From js at webkeks.org Mon May 14 13:44:12 2012 From: js at webkeks.org (Jonathan Schleifer) Date: Mon, 14 May 2012 20:44:12 +0200 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> Message-ID: <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> Am 14.05.2012 um 20:34 schrieb John McCall: > If the GNU runtime supports emitting direct references to the class, why is a command-line option necessary? The GNU runtime does not. The GNUstep runtime does and mine does. It needs to be an option as this is not even part of the new, non-fragile ABI. So when compiling against the GNUstep or my runtime, this flag can be used to directly reference classes - this makes for more than a 2x speedup in real world application. This also means this is independent on whether you use the fragile or non-fragile ABI. You might want to use the fragile ABI with -fobjc-direct-class-refs for maximum performance. > I am opposed to providing an ever-expanding spectrum of command line flags ? particularly driver flags! ? to slightly tweak the ABI. Then we need a module for each runtime so we have multiple -f*-runtime. CGObjCGNU.cpp would need to be splitted into CGObjCGNU.cpp, CGObjCGNUstep.cpp and CGObjCObjFW.cpp for -fgnu-runtime, -fgnustep-runtime and -fobjfw-runtime - for just a few lines of differences. Is this really better? > Even if we supported this, it would be an IR-gen option, not a language option. Can you elaborate, please? I'm new to Clang's code. I'd really like to get this patch or a similar patch providing the same functionality upstream. The performance without it is really slow and I don't want to tell all users to apply the patch manually and rebuild clang to get acceptable performance. It would be much more desirable if it would just be incorporated upstream. PS: I'm still not subscribed to the list - please CC me. -- Jonathan From eli.friedman at gmail.com Mon May 14 14:08:21 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Mon, 14 May 2012 12:08:21 -0700 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> Message-ID: On Mon, May 14, 2012 at 11:44 AM, Jonathan Schleifer wrote: > Am 14.05.2012 um 20:34 schrieb John McCall: > >> If the GNU runtime supports emitting direct references to the class, why is a command-line option necessary? > > The GNU runtime does not. The GNUstep runtime does and mine does. > > It needs to be an option as this is not even part of the new, non-fragile ABI. So when compiling against the GNUstep or my runtime, this flag can be used to directly reference classes - this makes for more than a 2x speedup in real world application. This also means this is independent on whether you use the fragile or non-fragile ABI. You might want to use the fragile ABI with -fobjc-direct-class-refs for maximum performance. > >> I am opposed to providing an ever-expanding spectrum of command line flags ? particularly driver flags! ? to slightly tweak the ABI. > > Then we need a module for each runtime so we have multiple -f*-runtime. CGObjCGNU.cpp would need to be splitted into CGObjCGNU.cpp, CGObjCGNUstep.cpp and CGObjCObjFW.cpp for -fgnu-runtime, -fgnustep-runtime and -fobjfw-runtime - for just a few lines of differences. Is this really better? I'm not following your objection here: the organization of the code and the user-visible command-line options are completely independent. -Eli From js at webkeks.org Mon May 14 14:11:51 2012 From: js at webkeks.org (Jonathan Schleifer) Date: Mon, 14 May 2012 21:11:51 +0200 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> Message-ID: <2384B322-8069-4881-A47F-3EF2EF0C13AD@webkeks.org> Am 14.05.2012 um 21:08 schrieb Eli Friedman : > I'm not following your objection here: the organization of the code > and the user-visible command-line options are completely independent. Then I'm not sure I get the idea: Put -fgnu-runtime, -fgnustep-runtime and -fobjfw-runtime all in CGObjCGNU.cpp and get rid of all the other flags? What to do in CGObjCMac.cpp then? Get rid of the ABI flags there too? -- Jonathan From rjmccall at apple.com Mon May 14 14:12:24 2012 From: rjmccall at apple.com (John McCall) Date: Mon, 14 May 2012 12:12:24 -0700 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> Message-ID: <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> On May 14, 2012, at 11:44 AM, Jonathan Schleifer wrote: > Am 14.05.2012 um 20:34 schrieb John McCall: >> If the GNU runtime supports emitting direct references to the class, why is a command-line option necessary? > > The GNU runtime does not. The GNUstep runtime does and mine does. > > It needs to be an option as this is not even part of the new, non-fragile ABI. So when compiling against the GNUstep or my runtime, this flag can be used to directly reference classes - this makes for more than a 2x speedup in real world application. This also means this is independent on whether you use the fragile or non-fragile ABI. You might want to use the fragile ABI with -fobjc-direct-class-refs for maximum performance. I agree that this is at least theoretically independent of the fragile ABI vs. the nonfragile ABI, although I suspect that you'd need to check both implementations to verify that they do, in fact, guarantee the correctness of this. In Darwin's runtime, at least, the nonfragile ABI reserves the right to make class references "forward", so that the address of the global symbol is not necessarily the address of the class. >> I am opposed to providing an ever-expanding spectrum of command line flags ? particularly driver flags! ? to slightly tweak the ABI. > > Then we need a module for each runtime so we have multiple -f*-runtime. CGObjCGNU.cpp would need to be splitted into CGObjCGNU.cpp, CGObjCGNUstep.cpp and CGObjCObjFW.cpp for -fgnu-runtime, -fgnustep-runtime and -fobjfw-runtime - for just a few lines of differences. Is this really better? Or, you know, it could be a subclass that just implements GetClass differently, or even just sets a flag in the common GNU implementation that is honored by GetClass. There is no need to leap to the most absurd possible implementation. The right thing to do is to propagate information down like "please optimize for this specific runtime". Whether that means "-fgnustep-runtime" or "-fgnu-runtime=gnustep" or "-foptimize-runtime=gnustep" is a separable choice. >> Even if we supported this, it would be an IR-gen option, not a language option. > > Can you elaborate, please? I'm new to Clang's code. There is a separate structure called the CodeGenOptions which carries options which don't alter the language dialect but which do impact how code is emitted to implement it. John. From csdavec at swan.ac.uk Mon May 14 14:15:49 2012 From: csdavec at swan.ac.uk (David Chisnall) Date: Mon, 14 May 2012 20:15:49 +0100 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> Message-ID: On 14 May 2012, at 20:12, John McCall wrote: > I agree that this is at least theoretically independent of the fragile ABI vs. the nonfragile ABI, although I suspect that you'd need to check both implementations to verify that they do, in fact, guarantee the correctness of this. In Darwin's runtime, at least, the nonfragile ABI reserves the right to make class references "forward", so that the address of the global symbol is not necessarily the address of the class. That's more or less what we do for the GNUstep runtime. We always emit the call to the class lookup function, and then have an optimisation pass that turns the lookup call into a direct reference if we can prove that it will be visible, or caches the result of the call if we can't. David From js at webkeks.org Mon May 14 14:20:19 2012 From: js at webkeks.org (Jonathan Schleifer) Date: Mon, 14 May 2012 21:20:19 +0200 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> Message-ID: <21316473-94E5-4053-A13C-A87C8FEA311E@webkeks.org> Am 14.05.2012 um 21:12 schrieb John McCall: > I agree that this is at least theoretically independent of the fragile ABI vs. the nonfragile ABI, although I suspect that you'd need to check both implementations to verify that they do, in fact, guarantee the correctness of this. Well, not only theoretically: The GNUstep runtime uses the non-fragile ABI, while my runtime currently uses the fragile ABI (I wanted to be compatible to GCC and didn't have the time yet). What I do is that in the configure of my runtime I check if -fobjc-direct-class-refs is accepted by Clang and if so use it and then later output it when the runtime is queried for the OBJCFLAGS to compile with. > In Darwin's runtime, at least, the nonfragile ABI reserves the right to make class references "forward", so that the address of the global symbol is not necessarily the address of the class. Yes, but should this really be tied to the non-fragile ABI? IMHO even a ABI version would make more sense than saying "non-fragile ABI also means direct class references". This would also mean that we break existing stuff: Currently, the non-fragile ABI does not emit direct-class refs. If it suddenly would, I'm sure stuff will break. > Or, you know, it could be a subclass that just implements GetClass differently, or even just sets a flag in the common GNU implementation that is honored by GetClass. There is no need to leap to the most absurd possible implementation. > > The right thing to do is to propagate information down like "please optimize for this specific runtime". Whether that means "-fgnustep-runtime" or "-fgnu-runtime=gnustep" or "-foptimize-runtime=gnustep" is a separable choice. We would also need to specify the version, as an old version of the runtime can be lacking a feature. > There is a separate structure called the CodeGenOptions which carries options which don't alter the language dialect but which do impact how code is emitted to implement it. Ok, I will look into moving it there. I still don't see a reason why this shouldn't be a separate flag, so I'm still hoping of being able to get that in. I'd like to have a solution for my users where they don't have to recompile Clang or as a hack build some LLVM optimization module that replaces it (especially since last time I tried -emit-llvm, stuff would just crash). So, what I'm looking for is a solution that could get upstream and won't require the user to do anything, so that my configure could just check if Clang supports it and if so use it. -- Jonathan From anders at 0x63.nu Mon May 14 14:23:30 2012 From: anders at 0x63.nu (Anders Waldenborg) Date: Mon, 14 May 2012 21:23:30 +0200 Subject: [cfe-commits] [PATCH 4/4] [clang.py] TranslationUnit API improvements In-Reply-To: References: <20120508061740.GG27902@gagarin.0x63.nu> Message-ID: <20120514192330.GA31577@gagarin.0x63.nu> On Sat, May 12, 2012 at 02:19:08PM -0700, Gregory Szorc wrote: > On Mon, May 7, 2012 at 11:17 PM, Anders Waldenborg wrote: > > Also possibly mention the -x argument in the paragraph > > about "C++ in test.c". > > What are you referring to? I'm was referring last paragraph in TranslationUnit.from_source documentation: Also note that Clang infers the source language from the extension of the input filename. If you pass in source code containing a C++ class declaration with the filename "test.c" parsing will fail. I was thinking that it would be useful to mention "-x" in that context. eg: TranslationUnit.from_source(args=["-x", "c", "filewithnonstandardextension.code"]) [...] > > Did you consider to make the different types of > > TranslationUnitSaveError subclasses? > > Yes, and it didn't feel very Pythonic. If I were writing Java, this is > probably how I would do it. But, Python is not Java. If there is more > data hung off save errors later, then we have a case for different > classes. Until then, I think simplicity should win. I'm not sure I agree about which is most pythonic of those variants. I'm not dutch but I would say the most pythonic way would be to use built-in exceptions to greatest possible extent (so in this case if res == 1: raise RuntimeError("Known unknown error saving tu") elif res == 2: raise ValueError("Error saving tu with errors") elif res == 3: raise TypeError("Not a valid tu")). My point was not to make a javaish huge class hierachy just because. But as the only attribute on the exception was a sub-type it felt natural to instead expose this in the type. TranslationUnitSaveError(Exception): pass TranslationUnitUnknownError(TranslationUnitSaveError): pass TranslationUnitSaveWithErrorsError(TranslationUnitSaveError): pass TranslationUnitInvalidError(TranslationUnitSaveError): pass This gives effortless string representation (as the class name is included): >>> tu.save() Traceback (most recent call last): File "", line 1, in File "", line 2, in save TranslationUnitSaveWithErrorsError: Couldn't save translationunit Also I find it annoying to have to inspect attributes of the exception to know how to handle it. Like this: try: op() except IOError as e: if e.errno in nonfatalerrnos: continue raise This became way too long for such tiny detail. I guess I just had to defend myself after being accused for writing java in python :) anders From dblaikie at gmail.com Mon May 14 16:43:16 2012 From: dblaikie at gmail.com (David Blaikie) Date: Mon, 14 May 2012 14:43:16 -0700 Subject: [cfe-commits] r154929 - in /cfe/trunk: include/clang/Tooling/CompilationDatabase.h lib/Tooling/CompilationDatabase.cpp In-Reply-To: <20120417165426.8B1872A6C065@llvm.org> References: <20120417165426.8B1872A6C065@llvm.org> Message-ID: Excuse my slightly delayed feedback, On Tue, Apr 17, 2012 at 9:54 AM, Manuel Klimek wrote: > Author: klimek > Date: Tue Apr 17 11:54:26 2012 > New Revision: 154929 > > URL: http://llvm.org/viewvc/llvm-project?rev=154929&view=rev > Log: > Switches the JSONCompilationDatabase to use the YAML parser. > This will allow us to delete the JSON parser from llvm. > > The biggest change is a general change of strategy - instead > of storing StringRef's to the values for the command line and > directory in the input buffer, we store ScalarNode*'s. The > reason is that the YAML parser's getRawValue on ScalarNodes > returns a string that includes the quotes in case of double > quoted strings. > > For the same reason we're removing the JSON parsing part of > the command line parsing - this means an extra copy for a > command line when it is requested (and only when it is requested). > > > Modified: > ? ?cfe/trunk/include/clang/Tooling/CompilationDatabase.h > ? ?cfe/trunk/lib/Tooling/CompilationDatabase.cpp > > Modified: cfe/trunk/include/clang/Tooling/CompilationDatabase.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/CompilationDatabase.h?rev=154929&r1=154928&r2=154929&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Tooling/CompilationDatabase.h (original) > +++ cfe/trunk/include/clang/Tooling/CompilationDatabase.h Tue Apr 17 11:54:26 2012 > @@ -34,13 +34,11 @@ > ?#include "llvm/ADT/StringMap.h" > ?#include "llvm/ADT/StringRef.h" > ?#include "llvm/Support/MemoryBuffer.h" > +#include "llvm/Support/SourceMgr.h" > +#include "llvm/Support/YAMLParser.h" > ?#include > ?#include > > -namespace llvm { > -class MemoryBuffer; > -} // end namespace llvm > - > ?namespace clang { > ?namespace tooling { > > @@ -139,7 +137,7 @@ > ?private: > ? /// \brief Constructs a JSON compilation database on a memory buffer. > ? JSONCompilationDatabase(llvm::MemoryBuffer *Database) > - ? ?: Database(Database) {} > + ? ?: Database(Database), YAMLStream(Database->getBuffer(), SM) {} > > ? /// \brief Parses the database file and creates the index. > ? /// > @@ -147,14 +145,17 @@ > ? /// failed. > ? bool parse(std::string &ErrorMessage); > > - ?// Tuple (directory, commandline) where 'commandline' is a JSON escaped bash > - ?// escaped command line. > - ?typedef std::pair CompileCommandRef; > + ?// Tuple (directory, commandline) where 'commandline' pointing to the > + ?// corresponding nodes in the YAML stream. > + ?typedef std::pair + ? ? ? ? ? ? ? ? ? ?llvm::yaml::ScalarNode*> CompileCommandRef; > > ? // Maps file paths to the compile command lines for that file. > ? llvm::StringMap< std::vector > IndexByFile; > > ? llvm::OwningPtr Database; > + ?llvm::SourceMgr SM; > + ?llvm::yaml::Stream YAMLStream; > ?}; > > ?} // end namespace tooling > > Modified: cfe/trunk/lib/Tooling/CompilationDatabase.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CompilationDatabase.cpp?rev=154929&r1=154928&r2=154929&view=diff > ============================================================================== > --- cfe/trunk/lib/Tooling/CompilationDatabase.cpp (original) > +++ cfe/trunk/lib/Tooling/CompilationDatabase.cpp Tue Apr 17 11:54:26 2012 > @@ -13,7 +13,7 @@ > > ?#include "clang/Tooling/CompilationDatabase.h" > ?#include "llvm/ADT/SmallString.h" > -#include "llvm/Support/JSONParser.h" > +#include "llvm/Support/YAMLParser.h" > ?#include "llvm/Support/Path.h" > ?#include "llvm/Support/system_error.h" > > @@ -22,10 +22,10 @@ > > ?namespace { > > -/// \brief A parser for JSON escaped strings of command line arguments. > +/// \brief A parser for escaped strings of command line arguments. > ?/// > ?/// Assumes \-escaping for quoted arguments (see the documentation of > -/// unescapeJSONCommandLine(...)). > +/// unescapeCommandLine(...)). > ?class CommandLineArgumentParser { > ?public: > ? CommandLineArgumentParser(StringRef CommandLine) > @@ -90,9 +90,6 @@ > > ? bool next() { > ? ? ++Position; > - ? ?if (Position == Input.end()) return false; > - ? ?// Remove the JSON escaping first. This is done unconditionally. > - ? ?if (*Position == '\\') ++Position; > ? ? return Position != Input.end(); > ? } > > @@ -101,9 +98,9 @@ > ? std::vector CommandLine; > ?}; > > -std::vector unescapeJSONCommandLine( > - ? ?StringRef JSONEscapedCommandLine) { > - ?CommandLineArgumentParser parser(JSONEscapedCommandLine); > +std::vector unescapeCommandLine( > + ? ?StringRef EscapedCommandLine) { > + ?CommandLineArgumentParser parser(EscapedCommandLine); > ? return parser.parse(); > ?} > > @@ -162,65 +159,77 @@ > ? const std::vector &CommandsRef = CommandsRefI->getValue(); > ? std::vector Commands; > ? for (int I = 0, E = CommandsRef.size(); I != E; ++I) { > + ? ?llvm::SmallString<8> DirectoryStorage; > + ? ?llvm::SmallString<1024> CommandStorage; > ? ? Commands.push_back(CompileCommand( > ? ? ? // FIXME: Escape correctly: > - ? ? ?CommandsRef[I].first, > - ? ? ?unescapeJSONCommandLine(CommandsRef[I].second))); > + ? ? ?CommandsRef[I].first->getValue(DirectoryStorage), > + ? ? ?unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage)))); > ? } > ? return Commands; > ?} > > ?bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { > - ?llvm::SourceMgr SM; > - ?llvm::JSONParser Parser(Database->getBuffer(), &SM); > - ?llvm::JSONValue *Root = Parser.parseRoot(); > + ?llvm::yaml::document_iterator I = YAMLStream.begin(); > + ?if (I == YAMLStream.end()) { > + ? ?ErrorMessage = "Error while parsing YAML."; > + ? ?return false; > + ?} > + ?llvm::yaml::Node *Root = I->getRoot(); > ? if (Root == NULL) { > - ? ?ErrorMessage = "Error while parsing JSON."; > + ? ?ErrorMessage = "Error while parsing YAML."; > ? ? return false; > ? } > - ?llvm::JSONArray *Array = dyn_cast(Root); > + ?llvm::yaml::SequenceNode *Array = > + ? ?llvm::dyn_cast(Root); > ? if (Array == NULL) { > ? ? ErrorMessage = "Expected array."; > ? ? return false; > ? } > - ?for (llvm::JSONArray::const_iterator AI = Array->begin(), AE = Array->end(); > + ?for (llvm::yaml::SequenceNode::iterator AI = Array->begin(), > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AE = Array->end(); > ? ? ? ?AI != AE; ++AI) { > - ? ?const llvm::JSONObject *Object = dyn_cast(*AI); > + ? ?llvm::yaml::MappingNode *Object = > + ? ? ?llvm::dyn_cast(&*AI); > ? ? if (Object == NULL) { > ? ? ? ErrorMessage = "Expected object."; > ? ? ? return false; > ? ? } > - ? ?StringRef EntryDirectory; > - ? ?StringRef EntryFile; > - ? ?StringRef EntryCommand; > - ? ?for (llvm::JSONObject::const_iterator KVI = Object->begin(), > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?KVE = Object->end(); > + ? ?llvm::yaml::ScalarNode *Directory; > + ? ?llvm::yaml::ScalarNode *Command; > + ? ?llvm::SmallString<8> FileStorage; > + ? ?llvm::StringRef File; > + ? ?for (llvm::yaml::MappingNode::iterator KVI = Object->begin(), > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? KVE = Object->end(); > ? ? ? ? ?KVI != KVE; ++KVI) { > - ? ? ?const llvm::JSONValue *Value = (*KVI)->Value; > + ? ? ?llvm::yaml::Node *Value = (*KVI).getValue(); > ? ? ? if (Value == NULL) { > ? ? ? ? ErrorMessage = "Expected value."; > ? ? ? ? return false; > ? ? ? } > - ? ? ?const llvm::JSONString *ValueString = > - ? ? ? ?dyn_cast(Value); > + ? ? ?llvm::yaml::ScalarNode *ValueString = > + ? ? ? ?llvm::dyn_cast(Value); Should this be a (non-dyn) llvm::cast? Or should it be null checked before it's dereferenced 5 lines down? > ? ? ? if (ValueString == NULL) { > ? ? ? ? ErrorMessage = "Expected string as value."; > ? ? ? ? return false; > ? ? ? } > - ? ? ?if ((*KVI)->Key->getRawText() == "directory") { > - ? ? ? ?EntryDirectory = ValueString->getRawText(); > - ? ? ?} else if ((*KVI)->Key->getRawText() == "file") { > - ? ? ? ?EntryFile = ValueString->getRawText(); > - ? ? ?} else if ((*KVI)->Key->getRawText() == "command") { > - ? ? ? ?EntryCommand = ValueString->getRawText(); > + ? ? ?llvm::yaml::ScalarNode *KeyString = > + ? ? ? ?llvm::dyn_cast((*KVI).getKey()); > + ? ? ?llvm::SmallString<8> KeyStorage; > + ? ? ?if (KeyString->getValue(KeyStorage) == "directory") { > + ? ? ? ?Directory = ValueString; > + ? ? ?} else if (KeyString->getValue(KeyStorage) == "command") { > + ? ? ? ?Command = ValueString; > + ? ? ?} else if (KeyString->getValue(KeyStorage) == "file") { > + ? ? ? ?File = ValueString->getValue(FileStorage); > ? ? ? } else { > - ? ? ? ?ErrorMessage = (Twine("Unknown key: \"") + > - ? ? ? ? ? ? ? ? ? ? ? ?(*KVI)->Key->getRawText() + "\"").str(); > + ? ? ? ?ErrorMessage = ("Unknown key: \"" + > + ? ? ? ? ? ? ? ? ? ? ? ?KeyString->getRawValue() + "\"").str(); > ? ? ? ? return false; > ? ? ? } > ? ? } > - ? ?IndexByFile[EntryFile].push_back( > - ? ? ?CompileCommandRef(EntryDirectory, EntryCommand)); > + ? ?IndexByFile[File].push_back( > + ? ? ?CompileCommandRef(Directory, Command)); Are 'Directory' and 'Command' guaranteed to have been initialized by the above loop? (perhaps the file has been verified to contain a 'directory' and 'command' key by some previous code? I haven't looked closely) GCC's maybe-uninitialized mentioned this so I just thought I'd have a look around at it. - David > ? } > ? return true; > ?} > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From richard-llvm at metafoo.co.uk Mon May 14 16:57:22 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Mon, 14 May 2012 21:57:22 -0000 Subject: [cfe-commits] r156781 - in /cfe/trunk: lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/cxx0x-initializer-references.cpp test/CodeGenCXX/cxx11-initializer-aggregate.cpp Message-ID: <20120514215722.36C1A2A6C065@llvm.org> Author: rsmith Date: Mon May 14 16:57:21 2012 New Revision: 156781 URL: http://llvm.org/viewvc/llvm-project?rev=156781&view=rev Log: Implement IRGen for C++11's "T{1, 2, 3}", where T is an aggregate and the expression is treated as an lvalue. Added: cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.h cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=156781&r1=156780&r2=156781&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon May 14 16:57:21 2012 @@ -671,10 +671,7 @@ case Expr::PseudoObjectExprClass: return EmitPseudoObjectLValue(cast(E)); case Expr::InitListExprClass: - assert(cast(E)->getNumInits() == 1 && - "Only single-element init list can be lvalue."); - return EmitLValue(cast(E)->getInit(0)); - + return EmitInitListLValue(cast(E)); case Expr::CXXTemporaryObjectExprClass: case Expr::CXXConstructExprClass: return EmitCXXConstructLValue(cast(E)); @@ -2129,6 +2126,16 @@ return Result; } +LValue CodeGenFunction::EmitInitListLValue(const InitListExpr *E) { + if (!E->isGLValue()) + // Initializing an aggregate temporary in C++11: T{...}. + return EmitAggExprToLValue(E); + + // An lvalue initializer list must be initializing a reference. + assert(E->getNumInits() == 1 && "reference init with multiple values"); + return EmitLValue(E->getInit(0)); +} + LValue CodeGenFunction:: EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) { if (!expr->isGLValue()) { @@ -2188,11 +2195,11 @@ return MakeAddrLValue(phi, expr->getType()); } -/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast. -/// If the cast is a dynamic_cast, we can have the usual lvalue result, +/// EmitCastLValue - Casts are never lvalues unless that cast is to a reference +/// type. If the cast is to a reference, we can have the usual lvalue result, /// otherwise if a cast is needed by the code generator in an lvalue context, /// then it must mean that we need the address of an aggregate in order to -/// access one of its fields. This can happen for all the reasons that casts +/// access one of its members. This can happen for all the reasons that casts /// are permitted with aggregate result, including noop aggregate casts, and /// cast from scalar to union. LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=156781&r1=156780&r2=156781&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon May 14 16:57:21 2012 @@ -2104,6 +2104,7 @@ LValue EmitMemberExpr(const MemberExpr *E); LValue EmitObjCIsaExpr(const ObjCIsaExpr *E); LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E); + LValue EmitInitListLValue(const InitListExpr *E); LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E); LValue EmitCastLValue(const CastExpr *E); LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E); Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp?rev=156781&r1=156780&r2=156781&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp (original) +++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp Mon May 14 16:57:21 2012 @@ -28,6 +28,10 @@ // CHECK-NEXT: store %{{.*}}* %{{.*}}, %{{.*}}** % A &ra1a = {a}; + using T = A&; + // CHECK-NEXT: store %{{.*}}* %{{.*}}, %{{.*}}** % + A &ra1b = T{a}; + // CHECK-NEXT: ret } Added: cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp?rev=156781&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp (added) +++ cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Mon May 14 16:57:21 2012 @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s + +struct A { int a, b; int f(); }; + +// CHECK: define {{.*}}@_Z3fn1i( +int fn1(int x) { + // CHECK: %[[INITLIST:.*]] = alloca %struct.A + // CHECK: %[[A:.*]] = getelementptr inbounds %struct.A* %[[INITLIST]], i32 0, i32 0 + // CHECK: store i32 %{{.*}}, i32* %[[A]], align 4 + // CHECK: %[[B:.*]] = getelementptr inbounds %struct.A* %[[INITLIST]], i32 0, i32 1 + // CHECK: store i32 5, i32* %[[B]], align 4 + // CHECK: call i32 @_ZN1A1fEv(%struct.A* %[[INITLIST]]) + return A{x, 5}.f(); +} + +struct B { int &r; int &f() { return r; } }; + +// CHECK: define {{.*}}@_Z3fn2Ri( +int &fn2(int &v) { + // CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8 + // CHECK: %[[R:.*]] = getelementptr inbounds %struct.B* %[[INITLIST2:.*]], i32 0, i32 0 + // CHECK: store i32* %{{.*}}, i32** %[[R]], align 8 + // CHECK: %call = call i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]]) + return B{v}.f(); +} From akyrtzi at gmail.com Mon May 14 17:01:53 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Mon, 14 May 2012 22:01:53 -0000 Subject: [cfe-commits] r156782 - in /cfe/trunk: lib/Edit/EditedSource.cpp lib/Edit/RewriteObjCFoundationAPI.cpp test/ARCMT/objcmt-numeric-literals.m test/ARCMT/objcmt-numeric-literals.m.result test/ARCMT/objcmt-subscripting-literals.m test/ARCMT/objcmt-subscripting-literals.m.result Message-ID: <20120514220153.6DD772A6C065@llvm.org> Author: akirtzidis Date: Mon May 14 17:01:53 2012 New Revision: 156782 URL: http://llvm.org/viewvc/llvm-project?rev=156782&view=rev Log: [objcmt] When rewriting to array/dictionary literals, add an explicit cast to 'id' for any argument that requires it. Part of rdar://11438360. Modified: cfe/trunk/lib/Edit/EditedSource.cpp cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp cfe/trunk/test/ARCMT/objcmt-numeric-literals.m cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result Modified: cfe/trunk/lib/Edit/EditedSource.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/EditedSource.cpp?rev=156782&r1=156781&r2=156782&view=diff ============================================================================== --- cfe/trunk/lib/Edit/EditedSource.cpp (original) +++ cfe/trunk/lib/Edit/EditedSource.cpp Mon May 14 17:01:53 2012 @@ -100,8 +100,11 @@ FileOffset B = I->first; FileOffset E = B.getWithOffset(FA.RemoveLen); + if (BeginOffs == B) + break; + if (BeginOffs < E) { - if (BeginOffs >= B) { + if (BeginOffs > B) { BeginOffs = E; ++I; } Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp?rev=156782&r1=156781&r2=156782&view=diff ============================================================================== --- cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp (original) +++ cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Mon May 14 17:01:53 2012 @@ -229,6 +229,9 @@ // rewriteToArrayLiteral. //===----------------------------------------------------------------------===// +/// \brief Adds an explicit cast to 'id' if the type is not objc object. +static void objectifyExpr(const Expr *E, Commit &commit); + static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { Selector Sel = Msg->getSelector(); @@ -244,6 +247,7 @@ if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObject)) { if (Msg->getNumArgs() != 1) return false; + objectifyExpr(Msg->getArg(0), commit); SourceRange ArgRange = Msg->getArg(0)->getSourceRange(); commit.replaceWithInner(MsgRange, ArgRange); commit.insertWrap("@[", ArgRange, "]"); @@ -257,6 +261,9 @@ if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr)) return false; + for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i) + objectifyExpr(Msg->getArg(i), commit); + if (Msg->getNumArgs() == 1) { commit.replace(MsgRange, "@[]"); return true; @@ -291,6 +298,10 @@ NSAPI::NSDict_dictionaryWithObjectForKey)) { if (Msg->getNumArgs() != 2) return false; + + objectifyExpr(Msg->getArg(0), commit); + objectifyExpr(Msg->getArg(1), commit); + SourceRange ValRange = Msg->getArg(0)->getSourceRange(); SourceRange KeyRange = Msg->getArg(1)->getSourceRange(); // Insert key before the value. @@ -319,6 +330,9 @@ } for (unsigned i = 0; i < SentinelIdx; i += 2) { + objectifyExpr(Msg->getArg(i), commit); + objectifyExpr(Msg->getArg(i+1), commit); + SourceRange ValRange = Msg->getArg(i)->getSourceRange(); SourceRange KeyRange = Msg->getArg(i+1)->getSourceRange(); // Insert value after key. @@ -585,3 +599,52 @@ } return true; } + +static bool castOperatorNeedsParens(const Expr *FullExpr) { + const Expr* Expr = FullExpr->IgnoreImpCasts(); + if (isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(FullExpr) || + isa(Expr) || + isa(Expr) || + isa(Expr)) + return false; + + return true; +} + +static void objectifyExpr(const Expr *E, Commit &commit) { + if (!E) return; + + QualType T = E->getType(); + if (T->isObjCObjectPointerType()) { + if (const ImplicitCastExpr *ICE = dyn_cast(E)) { + if (ICE->getCastKind() != CK_CPointerToObjCPointerCast) + return; + } else { + return; + } + } else if (!T->isPointerType()) { + return; + } + + SourceRange Range = E->getSourceRange(); + if (castOperatorNeedsParens(E)) + commit.insertWrap("(", Range, ")"); + commit.insertBefore(Range.getBegin(), "(id)"); +} Modified: cfe/trunk/test/ARCMT/objcmt-numeric-literals.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-numeric-literals.m?rev=156782&r1=156781&r2=156782&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-numeric-literals.m (original) +++ cfe/trunk/test/ARCMT/objcmt-numeric-literals.m Mon May 14 17:01:53 2012 @@ -1,6 +1,7 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c++ // RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c++ %s.result #define YES __objc_yes #define NO __objc_no Modified: cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result?rev=156782&r1=156781&r2=156782&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result (original) +++ cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result Mon May 14 17:01:53 2012 @@ -1,6 +1,7 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c++ // RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c++ %s.result #define YES __objc_yes #define NO __objc_no Modified: cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m?rev=156782&r1=156781&r2=156782&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m (original) +++ cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m Mon May 14 17:01:53 2012 @@ -1,10 +1,13 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c -triple x86_64-apple-darwin11 // RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c %s.result typedef signed char BOOL; #define nil ((void*) 0) +typedef const struct __CFString * CFStringRef; + @interface NSObject + (id)alloc; @end @@ -135,3 +138,17 @@ o = [*parr objectAtIndex:2]; } @end + +extern const CFStringRef globStr; + +void test1(NSString *str) { + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: str, globStr, nil]; + dict = [NSDictionary dictionaryWithObjectsAndKeys: globStr, str, nil]; + dict = [NSDictionary dictionaryWithObject:str forKey:globStr]; + dict = [NSDictionary dictionaryWithObject:globStr forKey:str]; + + NSArray *arr = [NSArray arrayWithObjects: globStr, globStr, nil]; + arr = [NSArray arrayWithObjects: str, globStr, nil]; + arr = [NSArray arrayWithObjects: globStr, str, nil]; + arr = [NSArray arrayWithObject:globStr]; +} Modified: cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result?rev=156782&r1=156781&r2=156782&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result (original) +++ cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result Mon May 14 17:01:53 2012 @@ -1,10 +1,13 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c -triple x86_64-apple-darwin11 // RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c %s.result typedef signed char BOOL; #define nil ((void*) 0) +typedef const struct __CFString * CFStringRef; + @interface NSObject + (id)alloc; @end @@ -135,3 +138,17 @@ o = (*parr)[2]; } @end + +extern const CFStringRef globStr; + +void test1(NSString *str) { + NSDictionary *dict = @{(id)globStr: str}; + dict = @{str: (id)globStr}; + dict = @{(id)globStr: str}; + dict = @{str: (id)globStr}; + + NSArray *arr = @[(id)globStr, (id)globStr]; + arr = @[str, (id)globStr]; + arr = @[(id)globStr, str]; + arr = @[(id)globStr]; +} From richard-llvm at metafoo.co.uk Mon May 14 17:06:02 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Mon, 14 May 2012 22:06:02 -0000 Subject: [cfe-commits] r156783 - /cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Message-ID: <20120514220602.5ED612A6C065@llvm.org> Author: rsmith Date: Mon May 14 17:06:02 2012 New Revision: 156783 URL: http://llvm.org/viewvc/llvm-project?rev=156783&view=rev Log: Slightly generalize FileCheck patterns to unbreak -Asserts builds. Modified: cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Modified: cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp?rev=156783&r1=156782&r2=156783&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp (original) +++ cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Mon May 14 17:06:02 2012 @@ -20,6 +20,6 @@ // CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8 // CHECK: %[[R:.*]] = getelementptr inbounds %struct.B* %[[INITLIST2:.*]], i32 0, i32 0 // CHECK: store i32* %{{.*}}, i32** %[[R]], align 8 - // CHECK: %call = call i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]]) + // CHECK: call i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]]) return B{v}.f(); } From rjmccall at apple.com Mon May 14 17:15:31 2012 From: rjmccall at apple.com (John McCall) Date: Mon, 14 May 2012 15:15:31 -0700 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> Message-ID: On May 14, 2012, at 12:15 PM, David Chisnall wrote: > On 14 May 2012, at 20:12, John McCall wrote: >> I agree that this is at least theoretically independent of the fragile ABI vs. the nonfragile ABI, although I suspect that you'd need to check both implementations to verify that they do, in fact, guarantee the correctness of this. In Darwin's runtime, at least, the nonfragile ABI reserves the right to make class references "forward", so that the address of the global symbol is not necessarily the address of the class. > > That's more or less what we do for the GNUstep runtime. We always emit the call to the class lookup function, and then have an optimisation pass that turns the lookup call into a direct reference if we can prove that it will be visible, or caches the result of the call if we can't. That's not what I meant. The Darwin nonfragile runtime does not guarantee that the object pointer for a class will actually be the global object that the compiler laid out. If we see a compelling reason to, we can copy all those class objects into heap allocations. It would be expensive, and we don't see a really compelling reason right now, but if we wanted to (say) change the layout of the class objects used by the runtime, we have that capability. It sounds like the GNUstep runtime, at least, does not reserve this right ? if it did, that optimization pass would be invalid. John. From rjmccall at apple.com Mon May 14 17:37:54 2012 From: rjmccall at apple.com (John McCall) Date: Mon, 14 May 2012 15:37:54 -0700 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <21316473-94E5-4053-A13C-A87C8FEA311E@webkeks.org> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> <21316473-94E5-4053-A13C-A87C8FEA311E@webkeks.org> Message-ID: <3AB519D3-FA30-4BA7-B29E-27EA91BC90E1@apple.com> On May 14, 2012, at 12:20 PM, Jonathan Schleifer wrote: > Am 14.05.2012 um 21:12 schrieb John McCall: >> I agree that this is at least theoretically independent of the fragile ABI vs. the nonfragile ABI, although I suspect that you'd need to check both implementations to verify that they do, in fact, guarantee the correctness of this. > > Well, not only theoretically: The GNUstep runtime uses the non-fragile ABI, while my runtime currently uses the fragile ABI (I wanted to be compatible to GCC and didn't have the time yet). > > What I do is that in the configure of my runtime I check if -fobjc-direct-class-refs is accepted by Clang and if so use it and then later output it when the runtime is queried for the OBJCFLAGS to compile with. > >> In Darwin's runtime, at least, the nonfragile ABI reserves the right to make class references "forward", so that the address of the global symbol is not necessarily the address of the class. > > Yes, but should this really be tied to the non-fragile ABI? IMHO even a ABI version would make more sense than saying "non-fragile ABI also means direct class references". This would also mean that we break existing stuff: Currently, the non-fragile ABI does not emit direct-class refs. If it suddenly would, I'm sure stuff will break. On Darwin, the "fragile ABI" is really a completely different runtime with its own metadata layouts, entrypoints, etc. The GNU fragile and nonfragile runtimes are much more closely related, but the difference still implies more than just object layouts. I would be much happier if the "runtime"-selecting and "ABI"-selecting switches were combined, but that ship has sailed and we have to maintain compatibility. That is part of why I am very reluctant to compound the problem by adding new flags for every new thing which really ought to be implied by something else. Regardless, I did not bring up fragile vs. non-fragile ABIs, and I certainly never implied that this should be tied to that flag. >> Or, you know, it could be a subclass that just implements GetClass differently, or even just sets a flag in the common GNU implementation that is honored by GetClass. There is no need to leap to the most absurd possible implementation. >> >> The right thing to do is to propagate information down like "please optimize for this specific runtime". Whether that means "-fgnustep-runtime" or "-fgnu-runtime=gnustep" or "-foptimize-runtime=gnustep" is a separable choice. > > We would also need to specify the version, as an old version of the runtime can be lacking a feature. Features like "it is legal to emit class references as direct symbol references"? That seems like a pretty broad guarantee which a runtime either does or does not provide. But yes, in principle it makes sense to write something like -fgnu-runtime=gnustep-1.0. > So, what I'm looking for is a solution that could get upstream and won't require the user to do anything, so that my configure could just check if Clang supports it and if so use it. I have no problem with providing some way to get the compiler to emit direct references. I just don't want it to be a command-line option. There are already too many different command-line options controlling the ObjC dialect. John. From ganna at apple.com Mon May 14 17:38:24 2012 From: ganna at apple.com (Anna Zaks) Date: Mon, 14 May 2012 22:38:24 -0000 Subject: [cfe-commits] r156784 - in /cfe/trunk: include/clang/AST/RecursiveASTVisitor.h test/Analysis/templates.cpp Message-ID: <20120514223824.E95D52A6C065@llvm.org> Author: zaks Date: Mon May 14 17:38:24 2012 New Revision: 156784 URL: http://llvm.org/viewvc/llvm-project?rev=156784&view=rev Log: [analyzer] Fix a crash in templated code which uses blocks. We should investigate why signature info is not set in this case. Added: cfe/trunk/test/Analysis/templates.cpp Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=156784&r1=156783&r2=156784&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon May 14 17:38:24 2012 @@ -1241,7 +1241,9 @@ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc())); + TypeSourceInfo *TInfo = D->getSignatureAsWritten(); + if (TInfo) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); // This return statement makes sure the traversal of nodes in // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) Added: cfe/trunk/test/Analysis/templates.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/templates.cpp?rev=156784&view=auto ============================================================================== --- cfe/trunk/test/Analysis/templates.cpp (added) +++ cfe/trunk/test/Analysis/templates.cpp Mon May 14 17:38:24 2012 @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -fblocks -verify %s + +// Do not crash on this templated code which uses a block. +typedef void (^my_block)(void); +static void useBlock(my_block block){} +template class MyClass; +typedef MyClass Mf; + +template +class MyClass +{ +public: + MyClass() {} + MyClass(T a); + void I(); +private: + static const T one; +}; + +template const T MyClass::one = static_cast(1); +template inline MyClass::MyClass(T a){} +template void MyClass::I() { + static MyClass* mPtr = 0; + useBlock(^{ mPtr = new MyClass (MyClass::one); }); +}; +int main(){ + Mf m; + m.I(); +} From richard-llvm at metafoo.co.uk Mon May 14 17:43:34 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Mon, 14 May 2012 22:43:34 -0000 Subject: [cfe-commits] r156786 - in /cfe/trunk: lib/Parse/Parser.cpp test/Parser/MicrosoftExtensions.cpp Message-ID: <20120514224334.5146D2A6C065@llvm.org> Author: rsmith Date: Mon May 14 17:43:34 2012 New Revision: 156786 URL: http://llvm.org/viewvc/llvm-project?rev=156786&view=rev Log: Recover properly from a redundant 'typename' before a non-nested name. This is permitted as a Microsoft extension. Patch by William Wilson! (Plus some minor tweaking by me.) Modified: cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/test/Parser/MicrosoftExtensions.cpp Modified: cfe/trunk/lib/Parse/Parser.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=156786&r1=156785&r2=156786&view=diff ============================================================================== --- cfe/trunk/lib/Parse/Parser.cpp (original) +++ cfe/trunk/lib/Parse/Parser.cpp Mon May 14 17:43:34 2012 @@ -1248,7 +1248,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) - || Tok.is(tok::kw_decltype)) && "Cannot be a type or scope token!"); + || Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) + && "Cannot be a type or scope token!"); if (Tok.is(tok::kw_typename)) { // Parse a C++ typename-specifier, e.g., "typename T::type". @@ -1264,10 +1265,21 @@ 0, /*IsTypename*/true)) return true; if (!SS.isSet()) { - if (getLangOpts().MicrosoftExt) - Diag(Tok.getLocation(), diag::warn_expected_qualified_after_typename); - else - Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); + if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { + // Attempt to recover by skipping the invalid 'typename' + if (!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) && + Tok.isAnnotation()) { + unsigned DiagID = diag::err_expected_qualified_after_typename; + // MS compatibility: MSVC permits using known types with typename. + // e.g. "typedef typename T* pointer_type" + if (getLangOpts().MicrosoftExt) + DiagID = diag::warn_expected_qualified_after_typename; + Diag(Tok.getLocation(), DiagID); + return false; + } + } + + Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); return true; } Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=156786&r1=156785&r2=156786&view=diff ============================================================================== --- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original) +++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Mon May 14 17:43:34 2012 @@ -151,11 +151,24 @@ class AAAA { }; +template +class SimpleTemplate {}; + template void redundant_typename() { typename T t;// expected-warning {{expected a qualified name after 'typename'}} typename AAAA a;// expected-warning {{expected a qualified name after 'typename'}} + t = 3; + + typedef typename T* pointerT;// expected-warning {{expected a qualified name after 'typename'}} + typedef typename SimpleTemplate templateT;// expected-warning {{expected a qualified name after 'typename'}} + + pointerT pT = &t; + *pT = 4; + + int var; + int k = typename var;// expected-error {{expected a qualified name after 'typename'}} } From richard at metafoo.co.uk Mon May 14 17:48:34 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Mon, 14 May 2012 15:48:34 -0700 Subject: [cfe-commits] [PATCH] Allow typedef with unnecessary "typename" when ms-extensions are enabled. In-Reply-To: References: Message-ID: On Sat, May 12, 2012 at 7:18 AM, Will Wilson wrote: > > This is still only producing a warning if 'typename' is followed by > > something which isn't a type name in MS mode. We should reject this: > > > > int n; int k = typename n; > > Thanks for the review. I've updated the patch to only issue the > warning if an annotated typename was parsed, otherwise it defaults to > the error case. I've also updated the MS test cases. See what you > think... > Thanks, I've committed this as r156786. I tweaked it slightly to only return 'false' if we managed to produce a (type) annotation. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/45052a29/attachment.html From fjahanian at apple.com Mon May 14 17:48:56 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Mon, 14 May 2012 22:48:56 -0000 Subject: [cfe-commits] r156788 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/SemaObjC/id.m Message-ID: <20120514224856.8A8B12A6C065@llvm.org> Author: fjahanian Date: Mon May 14 17:48:56 2012 New Revision: 156788 URL: http://llvm.org/viewvc/llvm-project?rev=156788&view=rev Log: objc: allow typedef'ing an id to a pointer to a c-struct only. // rdar://11356439 Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/SemaObjC/id.m Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=156788&r1=156787&r2=156788&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon May 14 17:48:56 2012 @@ -1518,12 +1518,22 @@ switch (TypeID->getLength()) { default: break; case 2: - if (!TypeID->isStr("id")) - break; - Context.setObjCIdRedefinitionType(New->getUnderlyingType()); - // Install the built-in type for 'id', ignoring the current definition. - New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); - return; + { + if (!TypeID->isStr("id")) + break; + QualType T = New->getUnderlyingType(); + if (!T->isPointerType()) + break; + if (!T->isVoidPointerType()) { + QualType PT = T->getAs()->getPointeeType(); + if (!PT->isStructureType()) + break; + } + Context.setObjCIdRedefinitionType(T); + // Install the built-in type for 'id', ignoring the current definition. + New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); + return; + } case 5: if (!TypeID->isStr("Class")) break; Modified: cfe/trunk/test/SemaObjC/id.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/id.m?rev=156788&r1=156787&r2=156788&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/id.m (original) +++ cfe/trunk/test/SemaObjC/id.m Mon May 14 17:48:56 2012 @@ -16,6 +16,16 @@ } // Test attempt to redefine 'id' in an incompatible fashion. -typedef int id; // FIXME: Decide how we want to deal with this (now that 'id' is more of a built-in type). +// rdar://11356439 +typedef int id; // expected-error {{typedef redefinition with different types ('int' vs 'id')}} id b; +typedef double id; // expected-error {{typedef redefinition with different types ('double' vs 'id')}} + +typedef char *id; // expected-error {{typedef redefinition with different types ('char *' vs 'id')}} + +typedef union U{ int iu; } *id; // expected-error {{typedef redefinition with different types ('union U *' vs 'id')}} + +void test11356439(id o) { + o->x; // expected-error {{member reference base type 'id' is not a structure or union}} +} From akyrtzi at gmail.com Mon May 14 18:33:50 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Mon, 14 May 2012 23:33:50 -0000 Subject: [cfe-commits] r156789 - in /cfe/trunk: lib/Edit/RewriteObjCFoundationAPI.cpp test/ARCMT/objcmt-subscripting-literals.m test/ARCMT/objcmt-subscripting-literals.m.result Message-ID: <20120514233350.30F372A6C065@llvm.org> Author: akirtzidis Date: Mon May 14 18:33:49 2012 New Revision: 156789 URL: http://llvm.org/viewvc/llvm-project?rev=156789&view=rev Log: [objcmt] When rewriting to subscripting syntax, make sure we put the receiver in parentheses when necessary. Part of rdar://11438360 Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp?rev=156789&r1=156788&r2=156789&view=diff ============================================================================== --- cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp (original) +++ cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Mon May 14 18:33:49 2012 @@ -77,9 +77,10 @@ // rewriteToObjCSubscriptSyntax. //===----------------------------------------------------------------------===// +static bool subscriptOperatorNeedsParens(const Expr *FullExpr); + static void maybePutParensOnReceiver(const Expr *Receiver, Commit &commit) { - Receiver = Receiver->IgnoreImpCasts(); - if (isa(Receiver) || isa(Receiver)) { + if (subscriptOperatorNeedsParens(Receiver)) { SourceRange RecRange = Receiver->getSourceRange(); commit.insertWrap("(", RecRange, ")"); } @@ -600,6 +601,29 @@ return true; } +// FIXME: Make determination of operator precedence more general and +// make it broadly available. +static bool subscriptOperatorNeedsParens(const Expr *FullExpr) { + const Expr* Expr = FullExpr->IgnoreImpCasts(); + if (isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(FullExpr) || + isa(Expr) || + isa(Expr)) + return false; + + return true; +} static bool castOperatorNeedsParens(const Expr *FullExpr) { const Expr* Expr = FullExpr->IgnoreImpCasts(); if (isa(Expr) || Modified: cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m?rev=156789&r1=156788&r2=156789&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m (original) +++ cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m Mon May 14 18:33:49 2012 @@ -136,6 +136,8 @@ [mdict setObject:[dict objectForKey:@"key1"] forKey:[dict objectForKey:[NSArray arrayWithObject:@"arrkey"]]]; __strong NSArray **parr = 0; o = [*parr objectAtIndex:2]; + void *hd; + o = [(NSArray*)hd objectAtIndex:2]; } @end Modified: cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result?rev=156789&r1=156788&r2=156789&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result (original) +++ cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result Mon May 14 18:33:49 2012 @@ -136,6 +136,8 @@ mdict[dict[@[@"arrkey"]]] = dict[@"key1"]; __strong NSArray **parr = 0; o = (*parr)[2]; + void *hd; + o = ((NSArray*)hd)[2]; } @end From ganna at apple.com Mon May 14 18:40:56 2012 From: ganna at apple.com (Anna Zaks) Date: Mon, 14 May 2012 16:40:56 -0700 Subject: [cfe-commits] [PATCH] Add analyzer_assert for regression tests In-Reply-To: <881546B4-753E-499A-A279-04FD0F182FEF@belkadan.com> References: <881546B4-753E-499A-A279-04FD0F182FEF@belkadan.com> Message-ID: <6A305ACC-5BF0-4281-8B01-C3F3E4228F57@apple.com> Jordy, I think having something like this is a great idea. > A downside I am realizing is that silent success means the output looks the same whether debug.Asserts is on or off...not sure yet what to do about that. How about having something like "clang_analyzer_check_expr()" that always produces a warning which tells us about the expression's state, like "true", "false", "unknown"? I've added a taint debug checker, which serves similar purpose. We could also use this to check taint or other info by appending another string to the warning message "true (tainted:true)", but possibly with better markup. A few minor comments: - I'd prefix these asserts with "clang_analyzer". - We should check for undefined here. This checker is not guaranteed to be run along with other checkers. Cheers, Anna. On May 13, 2012, at 10:01 AM, Jordy Rose wrote: > > > > On May 13, 2012, at 12:13, Jordy Rose wrote: > >> Hi, Anna, Ted, and everyone else. Currently a number of static analyzer regression tests have constructs like the following to test how the analyzer's handling its constraints: >> >> void testUnsigned (unsigned a) { >> if (a > 0) >> return; >> >> void *sentinel = malloc(1); >> if (a) >> return; // expected-warning{{never executed}} >> free(sentinel); >> } >> >> void testSigned (int a) { >> if (a > 0) >> return; >> >> void *sentinel = malloc(1); >> if (a) >> return; // expected-warning{{leak}} >> free(sentinel); >> } >> >> That is, we're using MallocChecker, UnreachableCodeChecker, and others to trigger warnings based on the truth or falsehood of conditions. I propose a checker that looks for "calls" to functions named analyzer_assert and analyzer_assert_unknown. Unlike regular assertions, which are /added/ to the analyzer's constraint store, these assertions will warn if they do not match what is /already/ known. This would allow us to much more cleanly write the above tests: >> >> // Any signature with an integral type will do. >> // 'bool' would be canonical in C++. >> void analyzer_assert(int); >> void analyzer_assert_unknown(int); >> >> void testUnsigned (unsigned a) { >> if (a > 0) >> return; >> >> analyzer_assert(a == 0); >> } >> >> void testSigned (int a) { >> if (a > 0) >> return; >> >> analyzer_assert_unknown(a == 0); >> } >> >> Proper use of these functions will never include an expected warning. >> >> Comments? I think makes a lot of our regression tests a lot simpler. >> >> Jordy >> >> > From rjmccall at apple.com Mon May 14 21:01:59 2012 From: rjmccall at apple.com (John McCall) Date: Tue, 15 May 2012 02:01:59 -0000 Subject: [cfe-commits] r156794 - in /cfe/trunk: lib/AST/ItaniumMangle.cpp test/CodeGenCXX/mangle-ref-qualifiers.cpp Message-ID: <20120515020159.CF4AF2A6C065@llvm.org> Author: rjmccall Date: Mon May 14 21:01:59 2012 New Revision: 156794 URL: http://llvm.org/viewvc/llvm-project?rev=156794&view=rev Log: Change the mangling of a ref-qualifier on a function type so that it is placed in a position which is never ambiguous with a reference-to-function type. This follows some recent discussion and ensuing proposal on cxx-abi-dev. It is not necessary to change the mangling of CV-qualifiers because you cannot apply CV-qualification in the normal sense to a function type. It is not necessary to change the mangling of ref-qualifiers on method declarations because they appear in an unambiguous location. In addition, mangle CV-qualifiers and ref-qualifiers on function types when they occur in positions other than member pointers (that is, when they appear as template arguments). This is a minor ABI break with previous releases of clang. It is not considered critical because (1) ref-qualifiers are relatively rare, since AFAIK we're the only implementing compiler, and (2) they're particularly likely to come up in contexts that do not rely on the ODR for correctness. We apologize for any inconvenience; this is the right thing to do. Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/test/CodeGenCXX/mangle-ref-qualifiers.cpp Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=156794&r1=156793&r2=156794&view=diff ============================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon May 14 21:01:59 2012 @@ -1892,12 +1892,23 @@ } // ::= -// ::= F [Y] E +// ::= [] F [Y] +// [] E +// (Proposal to cxx-abi-dev, 2012-05-11) void CXXNameMangler::mangleType(const FunctionProtoType *T) { + // Mangle CV-qualifiers, if present. These are 'this' qualifiers, + // e.g. "const" in "int (A::*)() const". + mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals())); + Out << 'F'; + // FIXME: We don't have enough information in the AST to produce the 'Y' // encoding for extern "C" function types. mangleBareFunctionType(T, /*MangleReturnType=*/true); + + // Mangle the ref-qualifier, if present. + mangleRefQualifier(T->getRefQualifier()); + Out << 'E'; } void CXXNameMangler::mangleType(const FunctionNoProtoType *T) { @@ -1990,8 +2001,6 @@ mangleType(QualType(T->getClass(), 0)); QualType PointeeType = T->getPointeeType(); if (const FunctionProtoType *FPT = dyn_cast(PointeeType)) { - mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals())); - mangleRefQualifier(FPT->getRefQualifier()); mangleType(FPT); // Itanium C++ ABI 5.1.8: @@ -2005,9 +2014,11 @@ // which the function is a member is considered part of the type of // function. + // Given that we already substitute member function pointers as a + // whole, the net effect of this rule is just to unconditionally + // suppress substitution on the function type in a member pointer. // We increment the SeqID here to emulate adding an entry to the - // substitution table. We can't actually add it because we don't want this - // particular function type to be substituted. + // substitution table. ++SeqID; } else mangleType(PointeeType); Modified: cfe/trunk/test/CodeGenCXX/mangle-ref-qualifiers.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ref-qualifiers.cpp?rev=156794&r1=156793&r2=156794&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-ref-qualifiers.cpp (original) +++ cfe/trunk/test/CodeGenCXX/mangle-ref-qualifiers.cpp Mon May 14 21:01:59 2012 @@ -12,5 +12,11 @@ // CHECK: define i32 @_ZNKO1X1hEv int X::h() const && { return 0; } -// CHECK: define void @_Z1fM1XRFivEMS_OFivEMS_KOFivE +// CHECK: define void @_Z1fM1XFivREMS_FivOEMS_KFivOE void f(int (X::*)() &, int (X::*)() &&, int (X::*)() const&&) { } + +// CHECK: define void @_Z1g1AIFivEES_IFivREES_IFivOEES_IKFivEES_IKFivREES_IKFivOEES_IVKFivEES_IVKFivREES_IVKFivOEE() +template struct A {}; +void g(A, A, A, + A, A, A, + A, A, A) {} From rjmccall at apple.com Mon May 14 21:46:16 2012 From: rjmccall at apple.com (John McCall) Date: Mon, 14 May 2012 19:46:16 -0700 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <6488E49F-D4E1-4012-BF9E-16AE0F9E28D2@theravensnest.org> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> <21316473-94E5-4053-A13C-A87C8FEA311E@webkeks.org> <3AB519D3-FA30-4BA7-B29E-27EA91BC90E1@apple.com> <6488E49F-D4E1-4012-BF9E-16AE0F9E28D2@theravensnest.org> Message-ID: <1EEE3EDD-7A77-4AD7-954B-699CA34FEA2D@apple.com> On May 14, 2012, at 3:42 PM, David Chisnall wrote: > On 14 May 2012, at 23:37, John McCall wrote: >> But yes, in principle it makes sense to write something like -fgnu-runtime=gnustep-1.0. > > I would like to see something like -fobjc-runtime={gcc,gnustep,mac,objfw} and -fobjc-runtime-version={whatever}, with -fgnu-runtime, -fnext-runtime and -fobjc-nonfragile-abi as legacy options that mapped to some combination of these. We already have a few extraneous things like -fobjc-legacy-dispatch that should really not be there as stand-alone options. Splitting the argument into name and version works for me. We'd want to separate "mac" into two different "darwin" and "darwin_fragile" runtimes. For GNU, that distinction is implied by "gcc" (fragile) vs. "gnustep" (non-fragile) vs. "objfw" (currently fragile, but we'll see)? John. From dgregor at apple.com Mon May 14 22:26:09 2012 From: dgregor at apple.com (Douglas Gregor) Date: Mon, 14 May 2012 20:26:09 -0700 Subject: [cfe-commits] [patch] Template instantiation and visibility (take 2) In-Reply-To: References: <2EF19F2C-1738-4936-8962-4847C452DC1C@apple.com> Message-ID: On May 9, 2012, at 9:14 PM, Rafael Esp?ndola wrote: >> ping > > Ping. (17 days since the last feedback on this patch). > > A rebased patch is attached. Sorry for the loooong delay. I definitely like this direction; it's a lot simpler than what we had before. Go for it! - Doug From theraven at theravensnest.org Mon May 14 17:42:08 2012 From: theraven at theravensnest.org (David Chisnall) Date: Mon, 14 May 2012 23:42:08 +0100 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <3AB519D3-FA30-4BA7-B29E-27EA91BC90E1@apple.com> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> <21316473-94E5-4053-A13C-A87C8FEA311E@webkeks.org> <3AB519D3-FA30-4BA7-B29E-27EA91BC90E1@apple.com> Message-ID: <6488E49F-D4E1-4012-BF9E-16AE0F9E28D2@theravensnest.org> On 14 May 2012, at 23:37, John McCall wrote: > But yes, in principle it makes sense to write something like -fgnu-runtime=gnustep-1.0. I would like to see something like -fobjc-runtime={gcc,gnustep,mac,objfw} and -fobjc-runtime-version={whatever}, with -fgnu-runtime, -fnext-runtime and -fobjc-nonfragile-abi as legacy options that mapped to some combination of these. We already have a few extraneous things like -fobjc-legacy-dispatch that should really not be there as stand-alone options. David From richard-llvm at metafoo.co.uk Mon May 14 23:39:51 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 04:39:51 -0000 Subject: [cfe-commits] r156802 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp test/CXX/class/p6-0x.cpp test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp test/SemaCXX/PR10243.cpp test/SemaCXX/cxx0x-cursory-default-delete.cpp test/SemaCXX/cxx0x-defaulted-functions.cpp Message-ID: <20120515043951.EED0A2A6C065@llvm.org> Author: rsmith Date: Mon May 14 23:39:51 2012 New Revision: 156802 URL: http://llvm.org/viewvc/llvm-project?rev=156802&view=rev Log: Fold the six functions checking explicitly-defaulted special member functions into one. These were all performing almost identical checks, with different bugs in each of them. This fixes PR12806 (we weren't setting the exception specification for an explicitly-defaulted, non-user-provided default constructor) and enforces 8.4.2/2's rule that an in-class defaulted member must exactly match the implicit parameter type. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/test/CXX/class/p6-0x.cpp cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp cfe/trunk/test/SemaCXX/PR10243.cpp cfe/trunk/test/SemaCXX/cxx0x-cursory-default-delete.cpp cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon May 14 23:39:51 2012 @@ -4984,60 +4984,33 @@ InGroup, DefaultIgnore; // C++11 defaulted functions -def err_defaulted_default_ctor_params : Error< - "an explicitly-defaulted default constructor must have no parameters">; -def err_defaulted_copy_ctor_params : Error< - "an explicitly-defaulted copy constructor must have exactly one parameter">; -def err_defaulted_copy_ctor_volatile_param : Error< - "the parameter for an explicitly-defaulted copy constructor may not be " - "volatile">; -def err_defaulted_copy_ctor_const_param : Error< - "the parameter for this explicitly-defaulted copy constructor is const, but " - "a member or base requires it to be non-const">; -def err_defaulted_copy_assign_params : Error< - "an explicitly-defaulted copy assignment operator must have exactly one " - "parameter">; -def err_defaulted_copy_assign_return_type : Error< - "an explicitly-defaulted copy assignment operator must return an unqualified " - "lvalue reference to its class type">; +def err_defaulted_special_member_params : Error< + "an explicitly-defaulted %select{|copy |move }0constructor cannot " + "have default arguments">; +def err_defaulted_special_member_return_type : Error< + "explicitly-defaulted %select{copy|move}0 assignment operator must " + "return %1">; +def err_defaulted_special_member_quals : Error< + "an explicitly-defaulted %select{copy|move}0 assignment operator may not " + "have 'const', 'constexpr' or 'volatile' qualifiers">; +def err_defaulted_special_member_volatile_param : Error< + "the parameter for an explicitly-defaulted %select{<>|" + "copy constructor|move constructor|copy assignment operator|" + "move assignment operator|<>}0 may not be volatile">; +def err_defaulted_special_member_move_const_param : Error< + "the parameter for an explicitly-defaulted move " + "%select{constructor|assignment operator}0 may not be const">; +def err_defaulted_special_member_copy_const_param : Error< + "the parameter for this explicitly-defaulted copy " + "%select{constructor|assignment operator}0 is const, but a member or base " + "requires it to be non-const">; +def err_defaulted_special_member_copy_non_const_param : Error< + "explicitly-defaulted copy %select{constructor|assignment operator}0 with " + "a non-const parameter must be defaulted outside the class, unless a base or " + "member requires the parameter to be non-const">; def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; -def err_defaulted_copy_assign_volatile_param : Error< - "the parameter for an explicitly-defaulted copy assignment operator may not " - "be volatile">; -def err_defaulted_copy_assign_const_param : Error< - "the parameter for this explicitly-defaulted copy assignment operator is " - "const, but a member or base requires it to be non-const">; -def err_defaulted_copy_assign_quals : Error< - "an explicitly-defaulted copy assignment operator may not have 'const', " - "'constexpr' or 'volatile' qualifiers">; -def err_defaulted_move_ctor_params : Error< - "an explicitly-defaulted move constructor must have exactly one parameter">; -def err_defaulted_move_ctor_volatile_param : Error< - "the parameter for an explicitly-defaulted move constructor may not be " - "volatile">; -def err_defaulted_move_ctor_const_param : Error< - "the parameter for an explicitly-defaulted move constructor may not be " - "const">; -def err_defaulted_move_assign_params : Error< - "an explicitly-defaulted move assignment operator must have exactly one " - "parameter">; -def err_defaulted_move_assign_return_type : Error< - "an explicitly-defaulted move assignment operator must return an unqualified " - "lvalue reference to its class type">; -def err_defaulted_move_assign_not_ref : Error< - "the parameter for an explicitly-defaulted move assignment operator must be an " - "rvalue reference type">; -def err_defaulted_move_assign_volatile_param : Error< - "the parameter for an explicitly-defaulted move assignment operator may not " - "be volatile">; -def err_defaulted_move_assign_const_param : Error< - "the parameter for an explicitly-defaulted move assignment operator may not " - "be const">; -def err_defaulted_move_assign_quals : Error< - "an explicitly-defaulted move assignment operator may not have 'const', " - "'constexpr' or 'volatile' qualifiers">; def err_incorrect_defaulted_exception_spec : Error< "exception specification of explicitly defaulted %select{default constructor|" "copy constructor|move constructor|copy assignment operator|move assignment " Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon May 14 23:39:51 2012 @@ -3306,11 +3306,21 @@ ComputedEST = EST_Delayed; } - FunctionProtoType::ExtProtoInfo getEPI() const { - FunctionProtoType::ExtProtoInfo EPI; + /// \brief Have we been unable to compute this exception specification? + bool isDelayed() { + return ComputedEST == EST_Delayed; + } + + /// \brief Overwrite an EPI's exception specification with this + /// computed exception specification. + void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const { EPI.ExceptionSpecType = getExceptionSpecType(); EPI.NumExceptions = size(); EPI.Exceptions = data(); + } + FunctionProtoType::ExtProtoInfo getEPI() const { + FunctionProtoType::ExtProtoInfo EPI; + getEPI(EPI); return EPI; } }; @@ -4276,12 +4286,7 @@ Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); void CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record); - void CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *Method); - void CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *Method); - void CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *Dtor); + void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD); //===--------------------------------------------------------------------===// // C++ Derived Classes Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon May 14 23:39:51 2012 @@ -3801,550 +3801,204 @@ void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) { for (CXXRecordDecl::method_iterator MI = Record->method_begin(), ME = Record->method_end(); - MI != ME; ++MI) { - if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) { - switch (getSpecialMember(&*MI)) { - case CXXDefaultConstructor: - CheckExplicitlyDefaultedDefaultConstructor( - cast(&*MI)); - break; - - case CXXDestructor: - CheckExplicitlyDefaultedDestructor(cast(&*MI)); - break; - - case CXXCopyConstructor: - CheckExplicitlyDefaultedCopyConstructor(cast(&*MI)); - break; - - case CXXCopyAssignment: - CheckExplicitlyDefaultedCopyAssignment(&*MI); - break; - - case CXXMoveConstructor: - CheckExplicitlyDefaultedMoveConstructor(cast(&*MI)); - break; - - case CXXMoveAssignment: - CheckExplicitlyDefaultedMoveAssignment(&*MI); - break; - - case CXXInvalid: - llvm_unreachable("non-special member explicitly defaulted!"); - } - } - } - + MI != ME; ++MI) + if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) + CheckExplicitlyDefaultedSpecialMember(&*MI); } -void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { - assert(CD->isExplicitlyDefaulted() && CD->isDefaultConstructor()); - - // Whether this was the first-declared instance of the constructor. - // This affects whether we implicitly add an exception spec (and, eventually, - // constexpr). It is also ill-formed to explicitly default a constructor such - // that it would be deleted. (C++0x [decl.fct.def.default]) - bool First = CD == CD->getCanonicalDecl(); - - bool HadError = false; - if (CD->getNumParams() != 0) { - Diag(CD->getLocation(), diag::err_defaulted_default_ctor_params) - << CD->getSourceRange(); - HadError = true; - } - - ImplicitExceptionSpecification Spec - = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent()); - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - if (EPI.ExceptionSpecType == EST_Delayed) { - // Exception specification depends on some deferred part of the class. We'll - // try again when the class's definition has been fully processed. - return; - } - const FunctionProtoType *CtorType = CD->getType()->getAs(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs(); - - // C++11 [dcl.fct.def.default]p2: - // An explicitly-defaulted function may be declared constexpr only if it - // would have been implicitly declared as constexpr, - // Do not apply this rule to templates, since core issue 1358 makes such - // functions always instantiate to constexpr functions. - if (CD->isConstexpr() && - CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - if (!CD->getParent()->defaultedDefaultConstructorIsConstexpr()) { - Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) - << CXXDefaultConstructor; - HadError = true; - } - } - // and may have an explicit exception-specification only if it is compatible - // with the exception-specification on the implicit declaration. - if (CtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXDefaultConstructor, - PDiag(), - ExceptionType, SourceLocation(), - CtorType, CD->getLocation())) { - HadError = true; - } - } - - // If a function is explicitly defaulted on its first declaration, - if (First) { - // -- it is implicitly considered to be constexpr if the implicit - // definition would be, - CD->setConstexpr(CD->getParent()->defaultedDefaultConstructorIsConstexpr()); - - // -- it is implicitly considered to have the same - // exception-specification as if it had been implicitly declared - // - // FIXME: a compatible, but different, explicit exception specification - // will be silently overridden. We should issue a warning if this happens. - EPI.ExtInfo = CtorType->getExtInfo(); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - CD->setTrivial(CD->getParent()->hasTrivialDefaultConstructor()); - } - - if (HadError) { - CD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(CD, CXXDefaultConstructor)) { - if (First) { - CD->setDeletedAsWritten(); - } else { - Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXDefaultConstructor; - CD->setInvalidDecl(); - } - } -} +void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { + CXXRecordDecl *RD = MD->getParent(); + CXXSpecialMember CSM = getSpecialMember(MD); -void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { - assert(CD->isExplicitlyDefaulted() && CD->isCopyConstructor()); + assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid && + "not an explicitly-defaulted special member"); // Whether this was the first-declared instance of the constructor. - bool First = CD == CD->getCanonicalDecl(); - - bool HadError = false; - if (CD->getNumParams() != 1) { - Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_params) - << CD->getSourceRange(); - HadError = true; - } - - ImplicitExceptionSpecification Spec(*this); - bool Const; - llvm::tie(Spec, Const) = - ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent()); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *CtorType = CD->getType()->getAs(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs(); - - // Check for parameter type matching. - // This is a copy ctor so we know it's a cv-qualified reference to T. - QualType ArgType = CtorType->getArgType(0); - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_volatile_param); - HadError = true; - } - if (ArgType->getPointeeType().isConstQualified() && !Const) { - Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_const_param); - HadError = true; - } - - // C++11 [dcl.fct.def.default]p2: - // An explicitly-defaulted function may be declared constexpr only if it - // would have been implicitly declared as constexpr, - // Do not apply this rule to templates, since core issue 1358 makes such - // functions always instantiate to constexpr functions. - if (CD->isConstexpr() && - CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - if (!CD->getParent()->defaultedCopyConstructorIsConstexpr()) { - Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) - << CXXCopyConstructor; - HadError = true; - } - } - // and may have an explicit exception-specification only if it is compatible - // with the exception-specification on the implicit declaration. - if (CtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXCopyConstructor, - PDiag(), - ExceptionType, SourceLocation(), - CtorType, CD->getLocation())) { - HadError = true; - } - } - - // If a function is explicitly defaulted on its first declaration, - if (First) { - // -- it is implicitly considered to be constexpr if the implicit - // definition would be, - CD->setConstexpr(CD->getParent()->defaultedCopyConstructorIsConstexpr()); - - // -- it is implicitly considered to have the same - // exception-specification as if it had been implicitly declared, and - // - // FIXME: a compatible, but different, explicit exception specification - // will be silently overridden. We should issue a warning if this happens. - EPI.ExtInfo = CtorType->getExtInfo(); - - // -- [...] it shall have the same parameter type as if it had been - // implicitly declared. - CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - CD->setTrivial(CD->getParent()->hasTrivialCopyConstructor()); - } - - if (HadError) { - CD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(CD, CXXCopyConstructor)) { - if (First) { - CD->setDeletedAsWritten(); - } else { - Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXCopyConstructor; - CD->setInvalidDecl(); - } - } -} - -void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { - assert(MD->isExplicitlyDefaulted()); - - // Whether this was the first-declared instance of the operator + // This affects whether we implicitly add an exception spec and constexpr. bool First = MD == MD->getCanonicalDecl(); bool HadError = false; - if (MD->getNumParams() != 1) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_params) - << MD->getSourceRange(); - HadError = true; - } - QualType ReturnType = - MD->getType()->getAs()->getResultType(); - if (!ReturnType->isLValueReferenceType() || - !Context.hasSameType( - Context.getCanonicalType(ReturnType->getPointeeType()), - Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_return_type); + // C++11 [dcl.fct.def.default]p1: + // A function that is explicitly defaulted shall + // -- be a special member function (checked elsewhere), + // -- have the same type (except for ref-qualifiers, and except that a + // copy operation can take a non-const reference) as an implicit + // declaration, and + // -- not have default arguments. + unsigned ExpectedParams = 1; + if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) + ExpectedParams = 0; + if (MD->getNumParams() != ExpectedParams) { + // This also checks for default arguments: a copy or move constructor with a + // default argument is classified as a default constructor, and assignment + // operations and destructors can't have default arguments. + Diag(MD->getLocation(), diag::err_defaulted_special_member_params) + << CSM << MD->getSourceRange(); HadError = true; } + const FunctionProtoType *Type = MD->getType()->getAs(); + + // Compute implicit exception specification, argument constness, constexpr + // and triviality. ImplicitExceptionSpecification Spec(*this); - bool Const; - llvm::tie(Spec, Const) = - ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent()); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *OperType = MD->getType()->getAs(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs(); + bool Const = false; + bool Constexpr = false; + bool Trivial; + switch (CSM) { + case CXXDefaultConstructor: + Spec = ComputeDefaultedDefaultCtorExceptionSpec(RD); + if (Spec.isDelayed()) + // Exception specification depends on some deferred part of the class. + // We'll try again when the class's definition has been fully processed. + return; + Constexpr = RD->defaultedDefaultConstructorIsConstexpr(); + Trivial = RD->hasTrivialDefaultConstructor(); + break; + case CXXCopyConstructor: + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(RD); + Constexpr = RD->defaultedCopyConstructorIsConstexpr(); + Trivial = RD->hasTrivialCopyConstructor(); + break; + case CXXCopyAssignment: + llvm::tie(Spec, Const) = + ComputeDefaultedCopyAssignmentExceptionSpecAndConst(RD); + Trivial = RD->hasTrivialCopyAssignment(); + break; + case CXXMoveConstructor: + Spec = ComputeDefaultedMoveCtorExceptionSpec(RD); + Constexpr = RD->defaultedMoveConstructorIsConstexpr(); + Trivial = RD->hasTrivialMoveConstructor(); + break; + case CXXMoveAssignment: + Spec = ComputeDefaultedMoveAssignmentExceptionSpec(RD); + Trivial = RD->hasTrivialMoveAssignment(); + break; + case CXXDestructor: + Spec = ComputeDefaultedDtorExceptionSpec(RD); + Trivial = RD->hasTrivialDestructor(); + break; + case CXXInvalid: + llvm_unreachable("non-special member explicitly defaulted!"); + } - QualType ArgType = OperType->getArgType(0); - if (!ArgType->isLValueReferenceType()) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); - HadError = true; - } else { - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param); + QualType ReturnType = Context.VoidTy; + if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { + // Check for return type matching. + ReturnType = Type->getResultType(); + QualType ExpectedReturnType = + Context.getLValueReferenceType(Context.getTypeDeclType(RD)); + if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { + Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type) + << (CSM == CXXMoveAssignment) << ExpectedReturnType; HadError = true; } - if (ArgType->getPointeeType().isConstQualified() && !Const) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param); + + // A defaulted special member cannot have cv-qualifiers. + if (Type->getTypeQuals()) { + Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) + << (CSM == CXXMoveAssignment); HadError = true; } } - if (OperType->getTypeQuals()) { - Diag(MD->getLocation(), diag::err_defaulted_copy_assign_quals); - HadError = true; - } - - if (OperType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXCopyAssignment, - PDiag(), - ExceptionType, SourceLocation(), - OperType, MD->getLocation())) { + // Check for parameter type matching. + QualType ArgType = ExpectedParams ? Type->getArgType(0) : QualType(); + if (ExpectedParams && ArgType->isReferenceType()) { + // Argument must be reference to possibly-const T. + QualType ReferentType = ArgType->getPointeeType(); + + if (ReferentType.isVolatileQualified()) { + Diag(MD->getLocation(), + diag::err_defaulted_special_member_volatile_param) << CSM; HadError = true; } - } - if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. - EPI.RefQualifier = OperType->getRefQualifier(); - EPI.ExtInfo = OperType->getExtInfo(); - MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); - } - if (HadError) { - MD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(MD, CXXCopyAssignment)) { - if (First) { - MD->setDeletedAsWritten(); - } else { - Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXCopyAssignment; - MD->setInvalidDecl(); + if (ReferentType.isConstQualified() && !Const) { + if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { + Diag(MD->getLocation(), + diag::err_defaulted_special_member_copy_const_param) + << (CSM == CXXCopyAssignment); + // FIXME: Explain why this special member can't be const. + } else { + Diag(MD->getLocation(), + diag::err_defaulted_special_member_move_const_param) + << (CSM == CXXMoveAssignment); + } + HadError = true; } - } -} - -void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) { - assert(CD->isExplicitlyDefaulted() && CD->isMoveConstructor()); - - // Whether this was the first-declared instance of the constructor. - bool First = CD == CD->getCanonicalDecl(); - bool HadError = false; - if (CD->getNumParams() != 1) { - Diag(CD->getLocation(), diag::err_defaulted_move_ctor_params) - << CD->getSourceRange(); + // If a function is explicitly defaulted on its first declaration, it shall + // have the same parameter type as if it had been implicitly declared. + // (Presumably this is to prevent it from being trivial?) + if (!ReferentType.isConstQualified() && Const && First) + Diag(MD->getLocation(), + diag::err_defaulted_special_member_copy_non_const_param) + << (CSM == CXXCopyAssignment); + } else if (ExpectedParams) { + // A copy assignment operator can take its argument by value, but a + // defaulted one cannot. + assert(CSM == CXXCopyAssignment && "unexpected non-ref argument"); + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); HadError = true; } - ImplicitExceptionSpecification Spec( - ComputeDefaultedMoveCtorExceptionSpec(CD->getParent())); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *CtorType = CD->getType()->getAs(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs(); - - // Check for parameter type matching. - // This is a move ctor so we know it's a cv-qualified rvalue reference to T. - QualType ArgType = CtorType->getArgType(0); - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(CD->getLocation(), diag::err_defaulted_move_ctor_volatile_param); - HadError = true; - } - if (ArgType->getPointeeType().isConstQualified()) { - Diag(CD->getLocation(), diag::err_defaulted_move_ctor_const_param); - HadError = true; - } + // Rebuild the type with the implicit exception specification added. + FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); + Spec.getEPI(EPI); + const FunctionProtoType *ImplicitType = cast( + Context.getFunctionType(ReturnType, &ArgType, ExpectedParams, EPI)); // C++11 [dcl.fct.def.default]p2: // An explicitly-defaulted function may be declared constexpr only if it // would have been implicitly declared as constexpr, - // Do not apply this rule to templates, since core issue 1358 makes such - // functions always instantiate to constexpr functions. - if (CD->isConstexpr() && - CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - if (!CD->getParent()->defaultedMoveConstructorIsConstexpr()) { - Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) - << CXXMoveConstructor; - HadError = true; - } + // Do not apply this rule to members of class templates, since core issue 1358 + // makes such functions always instantiate to constexpr functions. For + // non-constructors, this is checked elsewhere. + if (isa(MD) && MD->isConstexpr() && !Constexpr && + MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM; + HadError = true; } // and may have an explicit exception-specification only if it is compatible // with the exception-specification on the implicit declaration. - if (CtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXMoveConstructor, - PDiag(), - ExceptionType, SourceLocation(), - CtorType, CD->getLocation())) { - HadError = true; - } - } + if (Type->hasExceptionSpec() && + CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) << CSM, + PDiag(), ImplicitType, SourceLocation(), Type, MD->getLocation())) + HadError = true; // If a function is explicitly defaulted on its first declaration, if (First) { // -- it is implicitly considered to be constexpr if the implicit // definition would be, - CD->setConstexpr(CD->getParent()->defaultedMoveConstructorIsConstexpr()); + MD->setConstexpr(Constexpr); - // -- it is implicitly considered to have the same - // exception-specification as if it had been implicitly declared, and - // - // FIXME: a compatible, but different, explicit exception specification - // will be silently overridden. We should issue a warning if this happens. - EPI.ExtInfo = CtorType->getExtInfo(); - - // -- [...] it shall have the same parameter type as if it had been - // implicitly declared. - CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + // -- it is implicitly considered to have the same exception-specification + // as if it had been implicitly declared, + MD->setType(QualType(ImplicitType, 0)); // Such a function is also trivial if the implicitly-declared function // would have been. - CD->setTrivial(CD->getParent()->hasTrivialMoveConstructor()); - } - - if (HadError) { - CD->setInvalidDecl(); - return; + MD->setTrivial(Trivial); } - if (ShouldDeleteSpecialMember(CD, CXXMoveConstructor)) { + if (ShouldDeleteSpecialMember(MD, CSM)) { if (First) { - CD->setDeletedAsWritten(); + MD->setDeletedAsWritten(); } else { - Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXMoveConstructor; - CD->setInvalidDecl(); - } - } -} - -void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) { - assert(MD->isExplicitlyDefaulted()); - - // Whether this was the first-declared instance of the operator - bool First = MD == MD->getCanonicalDecl(); - - bool HadError = false; - if (MD->getNumParams() != 1) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_params) - << MD->getSourceRange(); - HadError = true; - } - - QualType ReturnType = - MD->getType()->getAs()->getResultType(); - if (!ReturnType->isLValueReferenceType() || - !Context.hasSameType( - Context.getCanonicalType(ReturnType->getPointeeType()), - Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_return_type); - HadError = true; - } - - ImplicitExceptionSpecification Spec( - ComputeDefaultedMoveCtorExceptionSpec(MD->getParent())); - - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *OperType = MD->getType()->getAs(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs(); - - QualType ArgType = OperType->getArgType(0); - if (!ArgType->isRValueReferenceType()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_not_ref); - HadError = true; - } else { - if (ArgType->getPointeeType().isVolatileQualified()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_volatile_param); - HadError = true; - } - if (ArgType->getPointeeType().isConstQualified()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_const_param); + // C++11 [dcl.fct.def.default]p4: + // [For a] user-provided explicitly-defaulted function [...] if such a + // function is implicitly defined as deleted, the program is ill-formed. + Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; HadError = true; } } - if (OperType->getTypeQuals()) { - Diag(MD->getLocation(), diag::err_defaulted_move_assign_quals); - HadError = true; - } - - if (OperType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXMoveAssignment, - PDiag(), - ExceptionType, SourceLocation(), - OperType, MD->getLocation())) { - HadError = true; - } - } - if (First) { - // We set the declaration to have the computed exception spec here. - // We duplicate the one parameter type. - EPI.RefQualifier = OperType->getRefQualifier(); - EPI.ExtInfo = OperType->getExtInfo(); - MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); - } - - if (HadError) { + if (HadError) MD->setInvalidDecl(); - return; - } - - if (ShouldDeleteSpecialMember(MD, CXXMoveAssignment)) { - if (First) { - MD->setDeletedAsWritten(); - } else { - Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXMoveAssignment; - MD->setInvalidDecl(); - } - } -} - -void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { - assert(DD->isExplicitlyDefaulted()); - - // Whether this was the first-declared instance of the destructor. - bool First = DD == DD->getCanonicalDecl(); - - ImplicitExceptionSpecification Spec - = ComputeDefaultedDtorExceptionSpec(DD->getParent()); - FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); - const FunctionProtoType *DtorType = DD->getType()->getAs(), - *ExceptionType = Context.getFunctionType( - Context.VoidTy, 0, 0, EPI)->getAs(); - - if (DtorType->hasExceptionSpec()) { - if (CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << CXXDestructor, - PDiag(), - ExceptionType, SourceLocation(), - DtorType, DD->getLocation())) { - DD->setInvalidDecl(); - return; - } - } - if (First) { - // We set the declaration to have the computed exception spec here. - // There are no parameters. - EPI.ExtInfo = DtorType->getExtInfo(); - DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - DD->setTrivial(DD->getParent()->hasTrivialDestructor()); - } - - if (ShouldDeleteSpecialMember(DD, CXXDestructor)) { - if (First) { - DD->setDeletedAsWritten(); - } else { - Diag(DD->getLocation(), diag::err_out_of_line_default_deletes) - << CXXDestructor; - DD->setInvalidDecl(); - } - } } namespace { @@ -7021,7 +6675,7 @@ // specification is deferred until now. if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() && !ClassDecl->isDependentType()) - CheckExplicitlyDefaultedDefaultConstructor(CtorDecl); + CheckExplicitlyDefaultedSpecialMember(CtorDecl); } void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { @@ -7600,7 +7254,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst( CXXRecordDecl *ClassDecl) { if (ClassDecl->isInvalidDecl()) - return std::make_pair(ImplicitExceptionSpecification(*this), false); + return std::make_pair(ImplicitExceptionSpecification(*this), true); // C++ [class.copy]p10: // If the class definition does not explicitly declare a copy @@ -8635,7 +8289,7 @@ std::pair Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { if (ClassDecl->isInvalidDecl()) - return std::make_pair(ImplicitExceptionSpecification(*this), false); + return std::make_pair(ImplicitExceptionSpecification(*this), true); // C++ [class.copy]p5: // The implicitly-declared copy constructor for a class X will @@ -10546,7 +10200,7 @@ switch (Member) { case CXXDefaultConstructor: { CXXConstructorDecl *CD = cast(MD); - CheckExplicitlyDefaultedDefaultConstructor(CD); + CheckExplicitlyDefaultedSpecialMember(CD); if (!CD->isInvalidDecl()) DefineImplicitDefaultConstructor(DefaultLoc, CD); break; @@ -10554,14 +10208,14 @@ case CXXCopyConstructor: { CXXConstructorDecl *CD = cast(MD); - CheckExplicitlyDefaultedCopyConstructor(CD); + CheckExplicitlyDefaultedSpecialMember(CD); if (!CD->isInvalidDecl()) DefineImplicitCopyConstructor(DefaultLoc, CD); break; } case CXXCopyAssignment: { - CheckExplicitlyDefaultedCopyAssignment(MD); + CheckExplicitlyDefaultedSpecialMember(MD); if (!MD->isInvalidDecl()) DefineImplicitCopyAssignment(DefaultLoc, MD); break; @@ -10569,7 +10223,7 @@ case CXXDestructor: { CXXDestructorDecl *DD = cast(MD); - CheckExplicitlyDefaultedDestructor(DD); + CheckExplicitlyDefaultedSpecialMember(DD); if (!DD->isInvalidDecl()) DefineImplicitDestructor(DefaultLoc, DD); break; @@ -10577,14 +10231,14 @@ case CXXMoveConstructor: { CXXConstructorDecl *CD = cast(MD); - CheckExplicitlyDefaultedMoveConstructor(CD); + CheckExplicitlyDefaultedSpecialMember(CD); if (!CD->isInvalidDecl()) DefineImplicitMoveConstructor(DefaultLoc, CD); break; } case CXXMoveAssignment: { - CheckExplicitlyDefaultedMoveAssignment(MD); + CheckExplicitlyDefaultedSpecialMember(MD); if (!MD->isInvalidDecl()) DefineImplicitMoveAssignment(DefaultLoc, MD); break; Modified: cfe/trunk/test/CXX/class/p6-0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/p6-0x.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/test/CXX/class/p6-0x.cpp (original) +++ cfe/trunk/test/CXX/class/p6-0x.cpp Mon May 14 23:39:51 2012 @@ -19,7 +19,7 @@ Trivial2(const Trivial2 &) = default; Trivial2(Trivial2 &&) = default; Trivial2 &operator=(const Trivial2 &) = default; - Trivial2 &operator=(Trivial2 &) = default; + Trivial2 &operator=(Trivial2 &&) = default; ~Trivial2() = default; }; Modified: cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp (original) +++ cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp Mon May 14 23:39:51 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions %s // An explicitly-defaulted function may be declared constexpr only if it would // have been implicitly declared as constexpr. @@ -54,3 +54,61 @@ }; constexpr S5::S5() = default; static_assert(S5().m == 4, ""); + + +// An explicitly-defaulted function may have an exception specification only if +// it is compatible with the exception specification on an implicit declaration. +struct E1 { + E1() noexcept = default; + E1(const E1&) noexcept = default; + E1(E1&&) noexcept = default; + E1 &operator=(const E1&) noexcept = default; + E1 &operator=(E1&&) noexcept = default; + ~E1() noexcept = default; +}; +struct E2 { + E2() noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}} + E2(const E2&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted copy constructor does not match the calculated one}} + E2(E2&&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted move constructor does not match the calculated one}} + E2 &operator=(const E2&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted copy assignment operator does not match the calculated one}} + E2 &operator=(E2&&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted move assignment operator does not match the calculated one}} + ~E2() noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted destructor does not match the calculated one}} +}; + +// If a function is explicitly defaulted on its first declaration +// -- it is implicitly considered to have the same exception-specification as +// if it had been implicitly declared +struct E3 { + E3() = default; + E3(const E3&) = default; + E3(E3&&) = default; + E3 &operator=(const E3&) = default; + E3 &operator=(E3&&) = default; + ~E3() = default; +}; +E3 e3; +static_assert(noexcept(E3(), E3(E3()), E3(e3), e3 = E3(), e3 = e3), ""); +struct E4 { + E4() noexcept(false); + E4(const E4&) noexcept(false); + E4(E4&&) noexcept(false); + E4 &operator=(const E4&) noexcept(false); + E4 &operator=(E4&&) noexcept(false); + ~E4() noexcept(false); +}; +struct E5 { + E5() = default; + E5(const E5&) = default; + E5(E5&&) = default; + E5 &operator=(const E5&) = default; + E5 &operator=(E5&&) = default; + ~E5() = default; + + E4 e4; +}; +E5 e5; +static_assert(!noexcept(E5()), ""); +static_assert(!noexcept(E5(static_cast(e5))), ""); +static_assert(!noexcept(E5(e5)), ""); +static_assert(!noexcept(e5 = E5()), ""); +static_assert(!noexcept(e5 = e5), ""); Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp (original) +++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp Mon May 14 23:39:51 2012 @@ -72,7 +72,7 @@ DefaultedAggr(const DefaultedAggr &) = default; DefaultedAggr(DefaultedAggr &&) = default; DefaultedAggr &operator=(const DefaultedAggr &) = default; - DefaultedAggr &operator=(DefaultedAggr &) = default; + DefaultedAggr &operator=(DefaultedAggr &&) = default; ~DefaultedAggr() = default; }; DefaultedAggr da = { 42 } ; Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp (original) +++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp Mon May 14 23:39:51 2012 @@ -14,11 +14,11 @@ }; struct AssignmentRet1 { - AssignmentRet1&& operator=(AssignmentRet1&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}} + AssignmentRet1&& operator=(AssignmentRet1&&) = default; // expected-error {{explicitly-defaulted move assignment operator must return 'move::AssignmentRet1 &'}} }; struct AssignmentRet2 { - const AssignmentRet2& operator=(AssignmentRet2&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}} + const AssignmentRet2& operator=(AssignmentRet2&&) = default; // expected-error {{explicitly-defaulted move assignment operator must return 'move::AssignmentRet2 &'}} }; struct ConstAssignment { @@ -38,22 +38,35 @@ }; struct NonConst { - NonConst(NonConst&) = default; - NonConst& operator=(NonConst&) = default; + NonConst(NonConst&) = default; // expected-error {{must be defaulted outside the class}} + NonConst& operator=(NonConst&) = default; // expected-error {{must be defaulted outside the class}} + }; + + struct NonConst2 { + NonConst2(NonConst2&); + NonConst2& operator=(NonConst2&); + }; + NonConst2::NonConst2(NonConst2&) = default; + NonConst2 &NonConst2::operator=(NonConst2&) = default; + + struct NonConst3 { + NonConst3(NonConst3&) = default; + NonConst3& operator=(NonConst3&) = default; + NonConst nc; }; struct BadConst { - NonConst nc; // makes implicit copy non-const BadConst(const BadConst&) = default; // expected-error {{is const, but}} BadConst& operator=(const BadConst&) = default; // expected-error {{is const, but}} + NonConst nc; // makes implicit copy non-const }; struct AssignmentRet1 { - AssignmentRet1&& operator=(const AssignmentRet1&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}} + AssignmentRet1&& operator=(const AssignmentRet1&) = default; // expected-error {{explicitly-defaulted copy assignment operator must return 'copy::AssignmentRet1 &'}} }; struct AssignmentRet2 { - const AssignmentRet2& operator=(const AssignmentRet2&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}} + const AssignmentRet2& operator=(const AssignmentRet2&) = default; // expected-error {{explicitly-defaulted copy assignment operator must return 'copy::AssignmentRet2 &'}} }; struct ConstAssignment { Modified: cfe/trunk/test/SemaCXX/PR10243.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10243.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/PR10243.cpp (original) +++ cfe/trunk/test/SemaCXX/PR10243.cpp Mon May 14 23:39:51 2012 @@ -9,12 +9,12 @@ struct T1 { S s; // expected-error{{field has incomplete type 'S'}} - T1(T1&) = default; + T1(const T1&) = default; }; struct T2 { S s; // expected-error{{field has incomplete type 'S'}} - T2& operator=(T2&) = default; + T2& operator=(const T2&) = default; }; struct T3 { Modified: cfe/trunk/test/SemaCXX/cxx0x-cursory-default-delete.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-cursory-default-delete.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-cursory-default-delete.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-cursory-default-delete.cpp Mon May 14 23:39:51 2012 @@ -7,11 +7,14 @@ }; struct non_const_copy { - non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} - non_const_copy& operator = (non_const_copy&) & = default; // expected-note {{not viable}} - non_const_copy& operator = (non_const_copy&) && = default; // expected-note {{not viable}} + non_const_copy(non_const_copy&); + non_const_copy& operator = (non_const_copy&) &; + non_const_copy& operator = (non_const_copy&) &&; non_const_copy() = default; // expected-note {{not viable}} }; +non_const_copy::non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} +non_const_copy& non_const_copy::operator = (non_const_copy&) & = default; // expected-note {{not viable}} +non_const_copy& non_const_copy::operator = (non_const_copy&) && = default; // expected-note {{not viable}} void fn1 () { non_copiable nc; @@ -32,9 +35,9 @@ }; struct bad_decls { - bad_decls(volatile bad_decls&) = default; // expected-error {{may not be volatile}} - bad_decls&& operator = (bad_decls) = default; // expected-error 2{{lvalue reference}} - bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} + bad_decls(volatile bad_decls&) = default; // expected-error {{may not be volatile}} expected-error {{must be defaulted outside the class}} + bad_decls&& operator = (bad_decls) = default; // expected-error {{lvalue reference}} expected-error {{must return 'bad_decls &'}} + bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} expected-error {{must be defaulted outside the class}} bad_decls& operator = (const bad_decls&) const = default; // expected-error {{may not have 'const', 'constexpr' or 'volatile' qualifiers}} }; @@ -72,4 +75,3 @@ // (but not normal definitions) struct S { S(); }; S::S() __attribute((pure)) = default; - Modified: cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp?rev=156802&r1=156801&r2=156802&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp Mon May 14 23:39:51 2012 @@ -6,26 +6,26 @@ foo() = default; foo(const foo&) = default; - foo(foo&) = default; + foo(foo&&) = default; foo& operator = (const foo&) = default; - foo& operator = (foo&) = default; + foo& operator = (foo&&) = default; ~foo() = default; }; struct bar { bar(); bar(const bar&); - bar(bar&); + bar(bar&&); bar& operator = (const bar&); - bar& operator = (bar&); + bar& operator = (bar&&); ~bar(); }; bar::bar() = default; bar::bar(const bar&) = default; -bar::bar(bar&) = default; +bar::bar(bar&&) = default; bar& bar::operator = (const bar&) = default; -bar& bar::operator = (bar&) = default; +bar& bar::operator = (bar&&) = default; bar::~bar() = default; static_assert(__is_trivial(foo), "foo should be trivial"); From richard-llvm at metafoo.co.uk Tue May 15 00:04:02 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 05:04:02 -0000 Subject: [cfe-commits] r156803 - in /cfe/trunk: lib/Sema/SemaStmt.cpp test/SemaCXX/constant-expression-cxx11.cpp Message-ID: <20120515050402.DDE2E2A6C065@llvm.org> Author: rsmith Date: Tue May 15 00:04:02 2012 New Revision: 156803 URL: http://llvm.org/viewvc/llvm-project?rev=156803&view=rev Log: PR12826: Converting an lvalue to an xvalue is a no-op conversion, not an lvalue-to-rvalue conversion. Modified: cfe/trunk/lib/Sema/SemaStmt.cpp cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=156803&r1=156802&r2=156803&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue May 15 00:04:02 2012 @@ -2033,8 +2033,7 @@ if (AllowNRVO && (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true))) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, - Value->getType(), CK_LValueToRValue, - Value, VK_XValue); + Value->getType(), CK_NoOp, Value, VK_XValue); Expr *InitExpr = &AsRvalue; InitializationKind Kind @@ -2069,8 +2068,7 @@ // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. Value = ImplicitCastExpr::Create(Context, Value->getType(), - CK_LValueToRValue, Value, 0, - VK_XValue); + CK_NoOp, Value, 0, VK_XValue); // Complete type-checking the initialization of the return type // using the constructor we found. Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=156803&r1=156802&r2=156803&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original) +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Tue May 15 00:04:02 2012 @@ -1258,3 +1258,11 @@ auto& b = y.b; } } + +// Indirectly test that an implicit lvalue to xvalue conversion performed for +// an NRVO move operation isn't implemented as CK_LValueToRValue. +namespace PR12826 { + struct Foo {}; + constexpr Foo id(Foo x) { return x; } + constexpr Foo res(id(Foo())); +} From macmantrl at me.com Tue May 15 00:36:49 2012 From: macmantrl at me.com (Terry Long) Date: Tue, 15 May 2012 01:36:49 -0400 Subject: [cfe-commits] [PATCH] "missing argument" diagnostic should include argument name In-Reply-To: <74F4F0B2-E02D-46AE-8A42-DD3F7BB9F777@me.com> References: <064B25DD-8349-47B0-96FC-043540395F68@me.com> <44835A71-AFD9-49A1-A4A8-52F0DBCF07E3@me.com> <74F4F0B2-E02D-46AE-8A42-DD3F7BB9F777@me.com> Message-ID: <0FDB950E-7D30-4C03-850D-FBE46431795B@me.com> Any updates on if my latest patch incorporating Jordy's suggestions is acceptable and ready for commit by someone? Attached again is the patch for reference. Thanks, Terry -------------- next part -------------- A non-text attachment was scrubbed... Name: PR11857v3.patch Type: application/octet-stream Size: 9596 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/94cb8aa5/attachment.obj -------------- next part -------------- Am 11.05.2012 um 15:49 schrieb Terry Long: > Here's another patch which implements all of the suggested changes. > > -Terry > > > Am 11.05.2012 um 13:16 schrieb Terry Long: > >>> Sorry for weighing in so late, but some of the messages don't seem quite right to me. A "single" could help a lot for some of these cases (suggested fixes in brackets): >>> >>>> too few arguments to function call, [single] argument 'a' was not specified >>> >> >> I agree, using 'single' helps clarify that the function takes only one argument. >> >>> >>> Without the "single" I feel like this is a warning for /any/ "too few args" situation that's only missing one arg (e.g. 2 for 3). >>> >>>> candidate function not viable: requires [single] argument 'n', but 2 [arguments] were provided >>> >>> This doesn't feel like valid English as written. Two whats? ("I was going to go to the state of Hawaii, but I went to two instead.") And here the "single" really underscores that the problem is too many arguments. >> >> I originally had 'arguments' in the message, but took it out assuming "argument 'n'" was enough to know we were talking about arguments. Given your Hawaii example, I can see that the more correct way is probably to explicitly say 'arguments'. >> >>> >>>> candidate function not viable: requires[*] at most argument 'n', but 2 [arguments] were provided >>> >>> >>> * s/requires/allows? In this specific case of "0 or 1" it seems more fitting; not sure about the other "at most" warnings. Also "arguments", same as above. >> >> Yes, allows is more fitting. A function with 1 optional argument is not requiring anything. >> >>> >>>> candidate function not viable: requires at least argument 'n', but none[*] were provided >>> >>> s/none/no arguments/, same as above. >>> >>> Also, why no version for err_typecheck_call_too_many_args, since the overload resolution gets one for too many args? >> >> I overlooked this on my first attempt at the patch, and only added it to the 'candidate not viable' diagnostic because the same diagnostic was being used for /at most/at least/exactly/. I will definitely add this in. >> >>> >>>> too many arguments to function call, expected single argument 'n', have 2 [arguments] >>> >>> Here I could go either way on including the last "arguments", since it was already stated at the beginning. >> >> I would personally leave out 'arguments' to be consistent with all the other cases which use 'expected 2, have 0' form, and it is implied by the beginning phrase. >> >>> >>> What do you think? >> >> I will create a new patch with these changes unless anyone else objects. >> >> >> -Terry >> >> >>> Jordy >>> >>> >>> On May 11, 2012, at 1:18, Richard Smith wrote: >>> >>>> Great, thanks for working on this! Committed as r156607. >>>> >>>> On Thu, May 10, 2012 at 7:31 PM, Terry Long wrote: >>>> I've added more test coverage, removed deprecated methods, and extended the enhancement to the 'candidate function not viable' diagnostic for C++. >>>> >>>> Patch version 2 attached. >>>> >>>> -Terry Long >>>> >>>> >>>> >>>> >>>> Am 10.05.2012 um 19:17 schrieb Richard Smith: >>>> >>>>> On Thu, May 10, 2012 at 4:00 PM, Terry Long wrote: >>>>>> The patch generally looks good, thanks! >>>>> >>>>> Great, thanks for the feedback. >>>>> >>>>>> Presumably this only applies to the case where there are no arguments, because otherwise we couldn't know /which/ argument was missing? >>>>> >>>>> Yes, only for the case where there are no arguments to a function that takes 1 argument. Almost impossible to determine the missing argument(s) otherwise. >>>>> >>>>>> Please add test coverage for the err_typecheck_call_too_few_args_at_least_one diagnostic. Also, NamedDecl::getNameAsString is deprecated; please just use "<< FDecl->getParamDecl(0)", and use getParamDecl(0)->getDeclName()'s operator bool() in the test, rather than empty(). >>>>> >>>>> OK, I'll update this. I was using the online doxygen docs and didn't see any deprecation warnings. Anywhere where I can find that information? >>>>> >>>>> It's in include/clang/AST/Decl.h:138-141, though for some reason those comments aren't exposed to doxygen... >>>>> >>>>>> It would also be great to extend this to the 'candidate function not viable' diagnostics in C++. >>>>> >>>>> I can take a look at this too. >>>>> >>>>> Awesome, thanks. >>>> >>>> >>>> >>>> _______________________________________________ >>>> cfe-commits mailing list >>>> cfe-commits at cs.uiuc.edu >>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >>> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From richard-llvm at metafoo.co.uk Tue May 15 00:39:53 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 05:39:53 -0000 Subject: [cfe-commits] r156805 - /cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp Message-ID: <20120515053953.68C112A6C065@llvm.org> Author: rsmith Date: Tue May 15 00:39:53 2012 New Revision: 156805 URL: http://llvm.org/viewvc/llvm-project?rev=156805&view=rev Log: Test file I forgot to 'svn add' in r156802. Added: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp Added: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp?rev=156805&view=auto ============================================================================== --- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp (added) +++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp Tue May 15 00:39:53 2012 @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// A function that is explicitly defaulted shall +// [...] +// -- not have default arguments +struct DefArg { + DefArg(int n = 5) = default; // expected-error {{an explicitly-defaulted constructor cannot have default arguments}} + DefArg(const DefArg &DA = DefArg(2)) = default; // expected-error {{an explicitly-defaulted constructor cannot have default arguments}} + DefArg(const DefArg &DA, int k = 3) = default; // expected-error {{an explicitly-defaulted copy constructor cannot have default arguments}} + DefArg(DefArg &&DA, int k = 3) = default; // expected-error {{an explicitly-defaulted move constructor cannot have default arguments}} + DefArg &operator=(const DefArg&, int k = 4) = default; // expected-error {{parameter of overloaded 'operator=' cannot have a default argument}} + DefArg &operator=(DefArg&&, int k = 4) = default; // expected-error {{parameter of overloaded 'operator=' cannot have a default argument}} + ~DefArg(int k = 5) = default; // expected-error {{destructor cannot have any parameters}} +}; From richard at metafoo.co.uk Tue May 15 00:45:59 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Mon, 14 May 2012 22:45:59 -0700 Subject: [cfe-commits] [PATCH] "missing argument" diagnostic should include argument name In-Reply-To: <0FDB950E-7D30-4C03-850D-FBE46431795B@me.com> References: <064B25DD-8349-47B0-96FC-043540395F68@me.com> <44835A71-AFD9-49A1-A4A8-52F0DBCF07E3@me.com> <74F4F0B2-E02D-46AE-8A42-DD3F7BB9F777@me.com> <0FDB950E-7D30-4C03-850D-FBE46431795B@me.com> Message-ID: Can you add the word 'arguments' to the end of these diagnostics: + test18_a(b, b); // expected-error {{too many arguments to function call, expected single argument 'a', have 2}} + j(2, 3); // expected-error{{too many arguments to function call, expected at most single argument 'f', have 2}} Other than that, I think this is fine. On Mon, May 14, 2012 at 10:36 PM, Terry Long wrote: > Any updates on if my latest patch incorporating Jordy's suggestions is > acceptable and ready for commit by someone? > Attached again is the patch for reference. > > Thanks, > > Terry > > > > > Am 11.05.2012 um 15:49 schrieb Terry Long: > > > Here's another patch which implements all of the suggested changes. > > > > -Terry > > > > > > Am 11.05.2012 um 13:16 schrieb Terry Long: > > > >>> Sorry for weighing in so late, but some of the messages don't seem > quite right to me. A "single" could help a lot for some of these cases > (suggested fixes in brackets): > >>> > >>>> too few arguments to function call, [single] argument 'a' was not > specified > >>> > >> > >> I agree, using 'single' helps clarify that the function takes only one > argument. > >> > >>> > >>> Without the "single" I feel like this is a warning for /any/ "too few > args" situation that's only missing one arg (e.g. 2 for 3). > >>> > >>>> candidate function not viable: requires [single] argument 'n', but 2 > [arguments] were provided > >>> > >>> This doesn't feel like valid English as written. Two whats? ("I was > going to go to the state of Hawaii, but I went to two instead.") And here > the "single" really underscores that the problem is too many arguments. > >> > >> I originally had 'arguments' in the message, but took it out assuming > "argument 'n'" was enough to know we were talking about arguments. Given > your Hawaii example, I can see that the more correct way is probably to > explicitly say 'arguments'. > >> > >>> > >>>> candidate function not viable: requires[*] at most argument 'n', but > 2 [arguments] were provided > >>> > >>> > >>> * s/requires/allows? In this specific case of "0 or 1" it seems more > fitting; not sure about the other "at most" warnings. Also "arguments", > same as above. > >> > >> Yes, allows is more fitting. A function with 1 optional argument is not > requiring anything. > >> > >>> > >>>> candidate function not viable: requires at least argument 'n', but > none[*] were provided > >>> > >>> s/none/no arguments/, same as above. > >>> > >>> Also, why no version for err_typecheck_call_too_many_args, since the > overload resolution gets one for too many args? > >> > >> I overlooked this on my first attempt at the patch, and only added it > to the 'candidate not viable' diagnostic because the same diagnostic was > being used for /at most/at least/exactly/. I will definitely add this in. > >> > >>> > >>>> too many arguments to function call, expected single argument 'n', > have 2 [arguments] > >>> > >>> Here I could go either way on including the last "arguments", since it > was already stated at the beginning. > >> > >> I would personally leave out 'arguments' to be consistent with all the > other cases which use 'expected 2, have 0' form, and it is implied by the > beginning phrase. > >> > >>> > >>> What do you think? > >> > >> I will create a new patch with these changes unless anyone else objects. > >> > >> > >> -Terry > >> > >> > >>> Jordy > >>> > >>> > >>> On May 11, 2012, at 1:18, Richard Smith wrote: > >>> > >>>> Great, thanks for working on this! Committed as r156607. > >>>> > >>>> On Thu, May 10, 2012 at 7:31 PM, Terry Long wrote: > >>>> I've added more test coverage, removed deprecated methods, and > extended the enhancement to the 'candidate function not viable' diagnostic > for C++. > >>>> > >>>> Patch version 2 attached. > >>>> > >>>> -Terry Long > >>>> > >>>> > >>>> > >>>> > >>>> Am 10.05.2012 um 19:17 schrieb Richard Smith: > >>>> > >>>>> On Thu, May 10, 2012 at 4:00 PM, Terry Long > wrote: > >>>>>> The patch generally looks good, thanks! > >>>>> > >>>>> Great, thanks for the feedback. > >>>>> > >>>>>> Presumably this only applies to the case where there are no > arguments, because otherwise we couldn't know /which/ argument was missing? > >>>>> > >>>>> Yes, only for the case where there are no arguments to a function > that takes 1 argument. Almost impossible to determine the missing > argument(s) otherwise. > >>>>> > >>>>>> Please add test coverage for the > err_typecheck_call_too_few_args_at_least_one diagnostic. Also, > NamedDecl::getNameAsString is deprecated; please just use "<< > FDecl->getParamDecl(0)", and use getParamDecl(0)->getDeclName()'s operator > bool() in the test, rather than empty(). > >>>>> > >>>>> OK, I'll update this. I was using the online doxygen docs and didn't > see any deprecation warnings. Anywhere where I can find that information? > >>>>> > >>>>> It's in include/clang/AST/Decl.h:138-141, though for some reason > those comments aren't exposed to doxygen... > >>>>> > >>>>>> It would also be great to extend this to the 'candidate function > not viable' diagnostics in C++. > >>>>> > >>>>> I can take a look at this too. > >>>>> > >>>>> Awesome, thanks. > >>>> > >>>> > >>>> > >>>> _______________________________________________ > >>>> cfe-commits mailing list > >>>> cfe-commits at cs.uiuc.edu > >>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > >>> > >> > >> _______________________________________________ > >> cfe-commits mailing list > >> cfe-commits at cs.uiuc.edu > >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > > > _______________________________________________ > > cfe-commits mailing list > > cfe-commits at cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/32659004/attachment-0001.html From macmantrl at me.com Tue May 15 01:14:37 2012 From: macmantrl at me.com (Terry Long) Date: Tue, 15 May 2012 02:14:37 -0400 Subject: [cfe-commits] [PATCH] "missing argument" diagnostic should include argument name In-Reply-To: References: <064B25DD-8349-47B0-96FC-043540395F68@me.com> <44835A71-AFD9-49A1-A4A8-52F0DBCF07E3@me.com> <74F4F0B2-E02D-46AE-8A42-DD3F7BB9F777@me.com> <0FDB950E-7D30-4C03-850D-FBE46431795B@me.com> Message-ID: <926A2AE6-E3E9-4E33-8D59-B9BFA58996CB@me.com> OK, made that update. Here is the new patch. -Terry Am 15.05.2012 um 01:45 schrieb Richard Smith: > Can you add the word 'arguments' to the end of these diagnostics: > > + test18_a(b, b); // expected-error {{too many arguments to function call, expected single argument 'a', have 2}} > + j(2, 3); // expected-error{{too many arguments to function call, expected at most single argument 'f', have 2}} > > Other than that, I think this is fine. > > On Mon, May 14, 2012 at 10:36 PM, Terry Long wrote: > Any updates on if my latest patch incorporating Jordy's suggestions is acceptable and ready for commit by someone? > Attached again is the patch for reference. > > Thanks, > > Terry > > > > > Am 11.05.2012 um 15:49 schrieb Terry Long: > > > Here's another patch which implements all of the suggested changes. > > > > -Terry > > > > > > Am 11.05.2012 um 13:16 schrieb Terry Long: > > > >>> Sorry for weighing in so late, but some of the messages don't seem quite right to me. A "single" could help a lot for some of these cases (suggested fixes in brackets): > >>> > >>>> too few arguments to function call, [single] argument 'a' was not specified > >>> > >> > >> I agree, using 'single' helps clarify that the function takes only one argument. > >> > >>> > >>> Without the "single" I feel like this is a warning for /any/ "too few args" situation that's only missing one arg (e.g. 2 for 3). > >>> > >>>> candidate function not viable: requires [single] argument 'n', but 2 [arguments] were provided > >>> > >>> This doesn't feel like valid English as written. Two whats? ("I was going to go to the state of Hawaii, but I went to two instead.") And here the "single" really underscores that the problem is too many arguments. > >> > >> I originally had 'arguments' in the message, but took it out assuming "argument 'n'" was enough to know we were talking about arguments. Given your Hawaii example, I can see that the more correct way is probably to explicitly say 'arguments'. > >> > >>> > >>>> candidate function not viable: requires[*] at most argument 'n', but 2 [arguments] were provided > >>> > >>> > >>> * s/requires/allows? In this specific case of "0 or 1" it seems more fitting; not sure about the other "at most" warnings. Also "arguments", same as above. > >> > >> Yes, allows is more fitting. A function with 1 optional argument is not requiring anything. > >> > >>> > >>>> candidate function not viable: requires at least argument 'n', but none[*] were provided > >>> > >>> s/none/no arguments/, same as above. > >>> > >>> Also, why no version for err_typecheck_call_too_many_args, since the overload resolution gets one for too many args? > >> > >> I overlooked this on my first attempt at the patch, and only added it to the 'candidate not viable' diagnostic because the same diagnostic was being used for /at most/at least/exactly/. I will definitely add this in. > >> > >>> > >>>> too many arguments to function call, expected single argument 'n', have 2 [arguments] > >>> > >>> Here I could go either way on including the last "arguments", since it was already stated at the beginning. > >> > >> I would personally leave out 'arguments' to be consistent with all the other cases which use 'expected 2, have 0' form, and it is implied by the beginning phrase. > >> > >>> > >>> What do you think? > >> > >> I will create a new patch with these changes unless anyone else objects. > >> > >> > >> -Terry > >> > >> > >>> Jordy > >>> > >>> > >>> On May 11, 2012, at 1:18, Richard Smith wrote: > >>> > >>>> Great, thanks for working on this! Committed as r156607. > >>>> > >>>> On Thu, May 10, 2012 at 7:31 PM, Terry Long wrote: > >>>> I've added more test coverage, removed deprecated methods, and extended the enhancement to the 'candidate function not viable' diagnostic for C++. > >>>> > >>>> Patch version 2 attached. > >>>> > >>>> -Terry Long > >>>> > >>>> > >>>> > >>>> > >>>> Am 10.05.2012 um 19:17 schrieb Richard Smith: > >>>> > >>>>> On Thu, May 10, 2012 at 4:00 PM, Terry Long wrote: > >>>>>> The patch generally looks good, thanks! > >>>>> > >>>>> Great, thanks for the feedback. > >>>>> > >>>>>> Presumably this only applies to the case where there are no arguments, because otherwise we couldn't know /which/ argument was missing? > >>>>> > >>>>> Yes, only for the case where there are no arguments to a function that takes 1 argument. Almost impossible to determine the missing argument(s) otherwise. > >>>>> > >>>>>> Please add test coverage for the err_typecheck_call_too_few_args_at_least_one diagnostic. Also, NamedDecl::getNameAsString is deprecated; please just use "<< FDecl->getParamDecl(0)", and use getParamDecl(0)->getDeclName()'s operator bool() in the test, rather than empty(). > >>>>> > >>>>> OK, I'll update this. I was using the online doxygen docs and didn't see any deprecation warnings. Anywhere where I can find that information? > >>>>> > >>>>> It's in include/clang/AST/Decl.h:138-141, though for some reason those comments aren't exposed to doxygen... > >>>>> > >>>>>> It would also be great to extend this to the 'candidate function not viable' diagnostics in C++. > >>>>> > >>>>> I can take a look at this too. > >>>>> > >>>>> Awesome, thanks. > >>>> > >>>> > >>>> > >>>> _______________________________________________ > >>>> cfe-commits mailing list > >>>> cfe-commits at cs.uiuc.edu > >>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > >>> > >> > >> _______________________________________________ > >> cfe-commits mailing list > >> cfe-commits at cs.uiuc.edu > >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > > > _______________________________________________ > > cfe-commits mailing list > > cfe-commits at cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/a99891e9/attachment.html -------------- next part -------------- A non-text attachment was scrubbed... Name: PR11857v4.patch Type: application/octet-stream Size: 9616 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/a99891e9/attachment.obj -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/a99891e9/attachment-0001.html From richard-llvm at metafoo.co.uk Tue May 15 01:15:11 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 06:15:11 -0000 Subject: [cfe-commits] r156806 - in /cfe/trunk: lib/Sema/TreeTransform.h test/CodeGenCXX/virtual-destructor-calls.cpp Message-ID: <20120515061512.03BCB2A6C065@llvm.org> Author: rsmith Date: Tue May 15 01:15:11 2012 New Revision: 156806 URL: http://llvm.org/viewvc/llvm-project?rev=156806&view=rev Log: PR12798: Don't drop part of the nested name specifier when instantiating a pseudo-destructor expression. This can affect whether virtual dispatch for the destructor call is bypassed. Modified: cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=156806&r1=156805&r2=156806&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Tue May 15 01:15:11 2012 @@ -9268,7 +9268,11 @@ DeclarationNameInfo NameInfo(Name, Destroyed.getLocation()); NameInfo.setNamedTypeInfo(DestroyedType); - // FIXME: the ScopeType should be tacked onto SS. + // The scope type is now known to be a valid nested name specifier + // component. Tack it on to the end of the nested name specifier. + if (ScopeType) + SS.Extend(SemaRef.Context, SourceLocation(), + ScopeType->getTypeLoc(), CCLoc); SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. return getSema().BuildMemberReferenceExpr(Base, BaseType, Modified: cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp?rev=156806&r1=156805&r2=156806&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp (original) +++ cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp Tue May 15 01:15:11 2012 @@ -46,3 +46,14 @@ // CHECK: call void @_ZdlPv // Base dtor: just an alias to B's base dtor. + +namespace PR12798 { + // A qualified call to a base class destructor should not undergo virtual + // dispatch. Template instantiation used to lose the qualifier. + struct A { virtual ~A(); }; + template void f(T *p) { p->A::~A(); } + + // CHECK: define {{.*}} @_ZN7PR127981fINS_1AEEEvPT_( + // CHECK: call void @_ZN7PR127981AD1Ev( + template void f(A*); +} From richard-llvm at metafoo.co.uk Tue May 15 01:21:55 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 06:21:55 -0000 Subject: [cfe-commits] r156807 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp test/Sema/exprs.c test/SemaCXX/default1.cpp test/SemaCXX/overload-call.cpp test/SemaCXX/overload-member-call.cpp Message-ID: <20120515062155.83A0B2A6C065@llvm.org> Author: rsmith Date: Tue May 15 01:21:54 2012 New Revision: 156807 URL: http://llvm.org/viewvc/llvm-project?rev=156807&view=rev Log: Further improvement to wording of overload resolution diagnostics, and including the sole parameter name in the diagnostic in more cases. Patch by Terry Long! Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/Sema/exprs.c cfe/trunk/test/SemaCXX/default1.cpp cfe/trunk/test/SemaCXX/overload-call.cpp cfe/trunk/test/SemaCXX/overload-member-call.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156807&r1=156806&r2=156807&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 01:21:54 2012 @@ -2046,9 +2046,9 @@ "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" "function (the implicit move assignment operator)|" - "constructor (inherited)}0 %select{|template }1" - "not viable: requires%select{ at least| at most|}2 argument %3, but " - "%plural{0:none|:%4}4 were provided">; + "constructor (inherited)}0 %select{|template }1not viable: " + "%select{requires at least|allows at most single|requires single}2 " + "argument %3, but %plural{0:no|:%4}4 arguments were provided">; def note_ovl_candidate_deleted : Note< "candidate %select{function|function|constructor|" @@ -4572,7 +4572,7 @@ def err_typecheck_call_too_few_args_one : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " - "argument %1 was not specified">; + "single argument %1 was not specified">; def err_typecheck_call_too_few_args_at_least : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " @@ -4585,10 +4585,18 @@ "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2">; +def err_typecheck_call_too_many_args_one : Error< + "too many %select{|||execution configuration }0arguments to " + "%select{function|block|method|kernel function}0 call, " + "expected single argument %1, have %2 arguments">; def err_typecheck_call_too_many_args_at_most : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at most %1, have %2">; +def err_typecheck_call_too_many_args_at_most_one : Error< + "too many %select{|||execution configuration }0arguments to " + "%select{function|block|method|kernel function}0 call, " + "expected at most single argument %1, have %2 arguments">; def note_callee_decl : Note< "%0 declared here">; def note_defined_here : Note<"%0 defined here">; Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=156807&r1=156806&r2=156807&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue May 15 01:21:54 2012 @@ -3407,14 +3407,24 @@ // them. if (NumArgs > NumArgsInProto) { if (!Proto->isVariadic()) { - Diag(Args[NumArgsInProto]->getLocStart(), - MinArgs == NumArgsInProto - ? diag::err_typecheck_call_too_many_args - : diag::err_typecheck_call_too_many_args_at_most) - << FnKind - << NumArgsInProto << NumArgs << Fn->getSourceRange() - << SourceRange(Args[NumArgsInProto]->getLocStart(), - Args[NumArgs-1]->getLocEnd()); + if (NumArgsInProto == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName()) + Diag(Args[NumArgsInProto]->getLocStart(), + MinArgs == NumArgsInProto + ? diag::err_typecheck_call_too_many_args_one + : diag::err_typecheck_call_too_many_args_at_most_one) + << FnKind + << FDecl->getParamDecl(0) << NumArgs << Fn->getSourceRange() + << SourceRange(Args[NumArgsInProto]->getLocStart(), + Args[NumArgs-1]->getLocEnd()); + else + Diag(Args[NumArgsInProto]->getLocStart(), + MinArgs == NumArgsInProto + ? diag::err_typecheck_call_too_many_args + : diag::err_typecheck_call_too_many_args_at_most) + << FnKind + << NumArgsInProto << NumArgs << Fn->getSourceRange() + << SourceRange(Args[NumArgsInProto]->getLocStart(), + Args[NumArgs-1]->getLocEnd()); // Emit the location of the prototype. if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig) Modified: cfe/trunk/test/Sema/exprs.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/exprs.c?rev=156807&r1=156806&r2=156807&view=diff ============================================================================== --- cfe/trunk/test/Sema/exprs.c (original) +++ cfe/trunk/test/Sema/exprs.c Tue May 15 01:21:54 2012 @@ -165,14 +165,17 @@ // PR6501 & PR11857 void test18_a(int a); // expected-note 2 {{'test18_a' declared here}} void test18_b(int); // expected-note {{'test18_b' declared here}} -void test18_c(int a, int b); // expected-note {{'test18_c' declared here}} +void test18_c(int a, int b); // expected-note 2 {{'test18_c' declared here}} void test18_d(int a, ...); // expected-note {{'test18_d' declared here}} +void test18_e(int a, int b, ...); // expected-note {{'test18_e' declared here}} void test18(int b) { - test18_a(b, b); // expected-error {{too many arguments to function call, expected 1, have 2}} - test18_a(); // expected-error {{too few arguments to function call, argument 'a' was not specified}} + test18_a(b, b); // expected-error {{too many arguments to function call, expected single argument 'a', have 2}} + test18_a(); // expected-error {{too few arguments to function call, single argument 'a' was not specified}} test18_b(); // expected-error {{too few arguments to function call, expected 1, have 0}} test18_c(b); // expected-error {{too few arguments to function call, expected 2, have 1}} + test18_c(b, b, b); // expected-error {{too many arguments to function call, expected 2, have 3}} test18_d(); // expected-error {{too few arguments to function call, at least argument 'a' must be specified}} + test18_e(); // expected-error {{too few arguments to function call, expected at least 2, have 0}} } // PR7569 Modified: cfe/trunk/test/SemaCXX/default1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/default1.cpp?rev=156807&r1=156806&r2=156807&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/default1.cpp (original) +++ cfe/trunk/test/SemaCXX/default1.cpp Tue May 15 01:21:54 2012 @@ -47,6 +47,13 @@ void j (int f = 4); { void j (int f); // expected-note{{'j' declared here}} - j(); // expected-error{{too few arguments to function call, argument 'f' was not specified}} + j(); // expected-error{{too few arguments to function call, single argument 'f' was not specified}} + } +} + +int i2() { + void j(int f = 4); // expected-note{{'j' declared here}} + { + j(2, 3); // expected-error{{too many arguments to function call, expected at most single argument 'f', have 2}} } } Modified: cfe/trunk/test/SemaCXX/overload-call.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156807&r1=156806&r2=156807&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 01:21:54 2012 @@ -324,9 +324,9 @@ void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} // PR 11857 - void foo(int n); // expected-note {{candidate function not viable: requires argument 'n', but 2 were provided}} - void foo(unsigned n = 10); // expected-note {{candidate function not viable: requires at most argument 'n', but 2 were provided}} - void bar(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but none were provided}} + void foo(int n); // expected-note {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} + void foo(unsigned n = 10); // expected-note {{candidate function not viable: allows at most single argument 'n', but 2 arguments were provided}} + void bar(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}} void baz(int n = 0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}} void test() { Modified: cfe/trunk/test/SemaCXX/overload-member-call.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-member-call.cpp?rev=156807&r1=156806&r2=156807&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/overload-member-call.cpp (original) +++ cfe/trunk/test/SemaCXX/overload-member-call.cpp Tue May 15 01:21:54 2012 @@ -83,10 +83,10 @@ void baz(int i); // expected-note {{candidate function not viable: no known conversion from 'const test1::A' to 'int' for 1st argument}} // PR 11857 - void foo(int n); // expected-note {{candidate function not viable: requires argument 'n', but 2 were provided}} - void foo(unsigned n = 10); // expected-note {{candidate function not viable: requires at most argument 'n', but 2 were provided}} - void rab(double n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but none were provided}} - void rab(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but none were provided}} + void foo(int n); // expected-note {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} + void foo(unsigned n = 10); // expected-note {{candidate function not viable: allows at most single argument 'n', but 2 arguments were provided}} + void rab(double n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}} + void rab(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}} void zab(double n = 0.0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}} void zab(int n = 0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}} }; From richard at metafoo.co.uk Tue May 15 01:23:12 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Mon, 14 May 2012 23:23:12 -0700 Subject: [cfe-commits] [PATCH] "missing argument" diagnostic should include argument name In-Reply-To: <926A2AE6-E3E9-4E33-8D59-B9BFA58996CB@me.com> References: <064B25DD-8349-47B0-96FC-043540395F68@me.com> <44835A71-AFD9-49A1-A4A8-52F0DBCF07E3@me.com> <74F4F0B2-E02D-46AE-8A42-DD3F7BB9F777@me.com> <0FDB950E-7D30-4C03-850D-FBE46431795B@me.com> <926A2AE6-E3E9-4E33-8D59-B9BFA58996CB@me.com> Message-ID: Thanks, r156807! On Mon, May 14, 2012 at 11:14 PM, Terry Long wrote: > OK, made that update. Here is the new patch. > > > -Terry > > > Am 15.05.2012 um 01:45 schrieb Richard Smith: > > Can you add the word 'arguments' to the end of these diagnostics: > > + test18_a(b, b); // expected-error {{too many arguments to function > call, expected single argument 'a', have 2}} > + j(2, 3); // expected-error{{too many arguments to function call, > expected at most single argument 'f', have 2}} > > Other than that, I think this is fine. > > On Mon, May 14, 2012 at 10:36 PM, Terry Long wrote: > >> Any updates on if my latest patch incorporating Jordy's suggestions is >> acceptable and ready for commit by someone? >> Attached again is the patch for reference. >> >> Thanks, >> >> Terry >> >> >> >> >> Am 11.05.2012 um 15:49 schrieb Terry Long: >> >> > Here's another patch which implements all of the suggested changes. >> > >> > -Terry >> > >> > >> > Am 11.05.2012 um 13:16 schrieb Terry Long: >> > >> >>> Sorry for weighing in so late, but some of the messages don't seem >> quite right to me. A "single" could help a lot for some of these cases >> (suggested fixes in brackets): >> >>> >> >>>> too few arguments to function call, [single] argument 'a' was not >> specified >> >>> >> >> >> >> I agree, using 'single' helps clarify that the function takes only one >> argument. >> >> >> >>> >> >>> Without the "single" I feel like this is a warning for /any/ "too few >> args" situation that's only missing one arg (e.g. 2 for 3). >> >>> >> >>>> candidate function not viable: requires [single] argument 'n', but 2 >> [arguments] were provided >> >>> >> >>> This doesn't feel like valid English as written. Two whats? ("I was >> going to go to the state of Hawaii, but I went to two instead.") And here >> the "single" really underscores that the problem is too many arguments. >> >> >> >> I originally had 'arguments' in the message, but took it out assuming >> "argument 'n'" was enough to know we were talking about arguments. Given >> your Hawaii example, I can see that the more correct way is probably to >> explicitly say 'arguments'. >> >> >> >>> >> >>>> candidate function not viable: requires[*] at most argument 'n', but >> 2 [arguments] were provided >> >>> >> >>> >> >>> * s/requires/allows? In this specific case of "0 or 1" it seems more >> fitting; not sure about the other "at most" warnings. Also "arguments", >> same as above. >> >> >> >> Yes, allows is more fitting. A function with 1 optional argument is >> not requiring anything. >> >> >> >>> >> >>>> candidate function not viable: requires at least argument 'n', but >> none[*] were provided >> >>> >> >>> s/none/no arguments/, same as above. >> >>> >> >>> Also, why no version for err_typecheck_call_too_many_args, since the >> overload resolution gets one for too many args? >> >> >> >> I overlooked this on my first attempt at the patch, and only added it >> to the 'candidate not viable' diagnostic because the same diagnostic was >> being used for /at most/at least/exactly/. I will definitely add this in. >> >> >> >>> >> >>>> too many arguments to function call, expected single argument 'n', >> have 2 [arguments] >> >>> >> >>> Here I could go either way on including the last "arguments", since >> it was already stated at the beginning. >> >> >> >> I would personally leave out 'arguments' to be consistent with all the >> other cases which use 'expected 2, have 0' form, and it is implied by the >> beginning phrase. >> >> >> >>> >> >>> What do you think? >> >> >> >> I will create a new patch with these changes unless anyone else >> objects. >> >> >> >> >> >> -Terry >> >> >> >> >> >>> Jordy >> >>> >> >>> >> >>> On May 11, 2012, at 1:18, Richard Smith wrote: >> >>> >> >>>> Great, thanks for working on this! Committed as r156607. >> >>>> >> >>>> On Thu, May 10, 2012 at 7:31 PM, Terry Long >> wrote: >> >>>> I've added more test coverage, removed deprecated methods, and >> extended the enhancement to the 'candidate function not viable' diagnostic >> for C++. >> >>>> >> >>>> Patch version 2 attached. >> >>>> >> >>>> -Terry Long >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> Am 10.05.2012 um 19:17 schrieb Richard Smith: >> >>>> >> >>>>> On Thu, May 10, 2012 at 4:00 PM, Terry Long >> wrote: >> >>>>>> The patch generally looks good, thanks! >> >>>>> >> >>>>> Great, thanks for the feedback. >> >>>>> >> >>>>>> Presumably this only applies to the case where there are no >> arguments, because otherwise we couldn't know /which/ argument was missing? >> >>>>> >> >>>>> Yes, only for the case where there are no arguments to a function >> that takes 1 argument. Almost impossible to determine the missing >> argument(s) otherwise. >> >>>>> >> >>>>>> Please add test coverage for the >> err_typecheck_call_too_few_args_at_least_one diagnostic. Also, >> NamedDecl::getNameAsString is deprecated; please just use "<< >> FDecl->getParamDecl(0)", and use getParamDecl(0)->getDeclName()'s operator >> bool() in the test, rather than empty(). >> >>>>> >> >>>>> OK, I'll update this. I was using the online doxygen docs and >> didn't see any deprecation warnings. Anywhere where I can find that >> information? >> >>>>> >> >>>>> It's in include/clang/AST/Decl.h:138-141, though for some reason >> those comments aren't exposed to doxygen... >> >>>>> >> >>>>>> It would also be great to extend this to the 'candidate function >> not viable' diagnostics in C++. >> >>>>> >> >>>>> I can take a look at this too. >> >>>>> >> >>>>> Awesome, thanks. >> >>>> >> >>>> >> >>>> >> >>>> _______________________________________________ >> >>>> cfe-commits mailing list >> >>>> cfe-commits at cs.uiuc.edu >> >>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> >>> >> >> >> >> _______________________________________________ >> >> cfe-commits mailing list >> >> cfe-commits at cs.uiuc.edu >> >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> > >> > _______________________________________________ >> > cfe-commits mailing list >> > cfe-commits at cs.uiuc.edu >> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> >> >> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120514/c9495b73/attachment-0001.html From klimek at google.com Tue May 15 03:02:48 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 10:02:48 +0200 Subject: [cfe-commits] [PATCH] ClangPlugin tutorial In-Reply-To: References: Message-ID: On Mon, May 14, 2012 at 7:10 PM, Dmitri Gribenko wrote: > Hi Manuel, > > > [...] In this tutorial, we'll > > demonstrate how to run clang's SyntaxOnlyAction > > But PrintFunctionNamesAction is used in the example. > Hah, good catch :) Fixed. Thanks! /Manuel > > Dmitri > > -- > main(i,j){for(i=2;;i++){for(j=2;j (j){printf("%d\n",i);}}} /*Dmitri Gribenko */ > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/a218caa2/attachment.html -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/a218caa2/attachment-0001.html From klimek at google.com Tue May 15 03:58:48 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 08:58:48 -0000 Subject: [cfe-commits] r156809 - /cfe/trunk/tools/libclang/CMakeLists.txt Message-ID: <20120515085848.EC1CE2A6C065@llvm.org> Author: klimek Date: Tue May 15 03:58:48 2012 New Revision: 156809 URL: http://llvm.org/viewvc/llvm-project?rev=156809&view=rev Log: This patch fixes the cmake build to create libclang.so/libclang.a on linux instead of liblibclang.so/liblibclang.a. Patch by Arnaud de Grandmaison. Modified: cfe/trunk/tools/libclang/CMakeLists.txt Modified: cfe/trunk/tools/libclang/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CMakeLists.txt?rev=156809&r1=156808&r2=156809&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CMakeLists.txt (original) +++ cfe/trunk/tools/libclang/CMakeLists.txt Tue May 15 03:58:48 2012 @@ -53,11 +53,19 @@ set(SHARED_LIBRARY TRUE) add_clang_library(libclang ${SOURCES}) - set_target_properties(libclang - PROPERTIES - OUTPUT_NAME "libclang" - VERSION ${LIBCLANG_LIBRARY_VERSION} - DEFINE_SYMBOL _CINDEX_LIB_) + if(WIN32) + set_target_properties(libclang + PROPERTIES + OUTPUT_NAME "libclang" + VERSION ${LIBCLANG_LIBRARY_VERSION} + DEFINE_SYMBOL _CINDEX_LIB_) + else() + set_target_properties(libclang + PROPERTIES + OUTPUT_NAME "clang" + VERSION ${LIBCLANG_LIBRARY_VERSION} + DEFINE_SYMBOL _CINDEX_LIB_) + endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(LIBCLANG_LINK_FLAGS @@ -86,5 +94,5 @@ set_target_properties(${LIBCLANG_STATIC_TARGET_NAME} PROPERTIES - OUTPUT_NAME "libclang") + OUTPUT_NAME "clang") endif() From ggreif at gmail.com Tue May 15 06:21:03 2012 From: ggreif at gmail.com (Gabor Greif) Date: Tue, 15 May 2012 11:21:03 -0000 Subject: [cfe-commits] r156813 - /cfe/trunk/lib/Driver/ToolChains.cpp Message-ID: <20120515112103.2B7052A6C065@llvm.org> Author: ggreif Date: Tue May 15 06:21:03 2012 New Revision: 156813 URL: http://llvm.org/viewvc/llvm-project?rev=156813&view=rev Log: add embedded linux variants that occur in the field Modified: cfe/trunk/lib/Driver/ToolChains.cpp Modified: cfe/trunk/lib/Driver/ToolChains.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=156813&r1=156812&r2=156813&view=diff ============================================================================== --- cfe/trunk/lib/Driver/ToolChains.cpp (original) +++ cfe/trunk/lib/Driver/ToolChains.cpp Tue May 15 06:21:03 2012 @@ -1146,7 +1146,8 @@ "i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux", - "i486-slackware-linux" + "i486-slackware-linux", + "i686-montavista-linux" }; static const char *const MIPSLibDirs[] = { "/lib" }; @@ -1163,7 +1164,8 @@ static const char *const PPCTriples[] = { "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", - "powerpc-suse-linux" + "powerpc-suse-linux", + "powerpc-montavista-linuxspe" }; static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; static const char *const PPC64Triples[] = { From klimek at google.com Tue May 15 06:46:07 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 11:46:07 -0000 Subject: [cfe-commits] r156814 - in /cfe/trunk: lib/Tooling/CompilationDatabase.cpp unittests/Tooling/CompilationDatabaseTest.cpp Message-ID: <20120515114607.B25A52A6C065@llvm.org> Author: klimek Date: Tue May 15 06:46:07 2012 New Revision: 156814 URL: http://llvm.org/viewvc/llvm-project?rev=156814&view=rev Log: Fixes crasher bug in JSONCompilationDatabase for invalid input. Modified: cfe/trunk/lib/Tooling/CompilationDatabase.cpp cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp Modified: cfe/trunk/lib/Tooling/CompilationDatabase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CompilationDatabase.cpp?rev=156814&r1=156813&r2=156814&view=diff ============================================================================== --- cfe/trunk/lib/Tooling/CompilationDatabase.cpp (original) +++ cfe/trunk/lib/Tooling/CompilationDatabase.cpp Tue May 15 06:46:07 2012 @@ -222,10 +222,9 @@ ErrorMessage = "Expected object."; return false; } - llvm::yaml::ScalarNode *Directory; - llvm::yaml::ScalarNode *Command; - llvm::SmallString<8> FileStorage; - llvm::StringRef File; + llvm::yaml::ScalarNode *Directory = NULL; + llvm::yaml::ScalarNode *Command = NULL; + llvm::yaml::ScalarNode *File = NULL; for (llvm::yaml::MappingNode::iterator KVI = Object->begin(), KVE = Object->end(); KVI != KVE; ++KVI) { @@ -242,20 +241,37 @@ } llvm::yaml::ScalarNode *KeyString = llvm::dyn_cast((*KVI).getKey()); + if (KeyString == NULL) { + ErrorMessage = "Expected strings as key."; + return false; + } llvm::SmallString<8> KeyStorage; if (KeyString->getValue(KeyStorage) == "directory") { Directory = ValueString; } else if (KeyString->getValue(KeyStorage) == "command") { Command = ValueString; } else if (KeyString->getValue(KeyStorage) == "file") { - File = ValueString->getValue(FileStorage); + File = ValueString; } else { ErrorMessage = ("Unknown key: \"" + KeyString->getRawValue() + "\"").str(); return false; } } - IndexByFile[File].push_back( + if (!File) { + ErrorMessage = "Missing key: \"file\"."; + return false; + } + if (!Command) { + ErrorMessage = "Missing key: \"command\"."; + return false; + } + if (!Directory) { + ErrorMessage = "Missing key: \"directory\"."; + return false; + } + llvm::SmallString<8> FileStorage; + IndexByFile[File->getValue(FileStorage)].push_back( CompileCommandRef(Directory, Command)); } return true; Modified: cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp?rev=156814&r1=156813&r2=156814&view=diff ============================================================================== --- cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp (original) +++ cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp Tue May 15 06:46:07 2012 @@ -18,6 +18,26 @@ namespace clang { namespace tooling { +static void expectFailure(StringRef JSONDatabase, StringRef Explanation) { + std::string ErrorMessage; + EXPECT_EQ(NULL, JSONCompilationDatabase::loadFromBuffer(JSONDatabase, + ErrorMessage)) + << "Expected an error because of: " << Explanation; +} + +TEST(JSONCompilationDatabase, ErrsOnInvalidFormat) { + expectFailure("", "Empty database"); + expectFailure("{", "Invalid JSON"); + expectFailure("[[]]", "Array instead of object"); + expectFailure("[{\"a\":[]}]", "Array instead of value"); + expectFailure("[{\"a\":\"b\"}]", "Unknown key"); + expectFailure("[{[]:\"\"}]", "Incorrectly typed entry"); + expectFailure("[{}]", "Empty entry"); + expectFailure("[{\"directory\":\"\",\"command\":\"\"}]", "Missing file"); + expectFailure("[{\"directory\":\"\",\"file\":\"\"}]", "Missing command"); + expectFailure("[{\"command\":\"\",\"file\":\"\"}]", "Missing directory"); +} + static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName, StringRef JSONDatabase, std::string &ErrorMessage) { From klimek at google.com Tue May 15 06:48:14 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 13:48:14 +0200 Subject: [cfe-commits] r154929 - in /cfe/trunk: include/clang/Tooling/CompilationDatabase.h lib/Tooling/CompilationDatabase.cpp In-Reply-To: References: <20120417165426.8B1872A6C065@llvm.org> Message-ID: On Mon, May 14, 2012 at 11:43 PM, David Blaikie wrote: > Excuse my slightly delayed feedback, > > On Tue, Apr 17, 2012 at 9:54 AM, Manuel Klimek wrote: >> Author: klimek >> Date: Tue Apr 17 11:54:26 2012 >> New Revision: 154929 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=154929&view=rev >> Log: >> Switches the JSONCompilationDatabase to use the YAML parser. >> This will allow us to delete the JSON parser from llvm. >> >> The biggest change is a general change of strategy - instead >> of storing StringRef's to the values for the command line and >> directory in the input buffer, we store ScalarNode*'s. The >> reason is that the YAML parser's getRawValue on ScalarNodes >> returns a string that includes the quotes in case of double >> quoted strings. >> >> For the same reason we're removing the JSON parsing part of >> the command line parsing - this means an extra copy for a >> command line when it is requested (and only when it is requested). >> >> >> Modified: >> ? ?cfe/trunk/include/clang/Tooling/CompilationDatabase.h >> ? ?cfe/trunk/lib/Tooling/CompilationDatabase.cpp >> >> Modified: cfe/trunk/include/clang/Tooling/CompilationDatabase.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/CompilationDatabase.h?rev=154929&r1=154928&r2=154929&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/Tooling/CompilationDatabase.h (original) >> +++ cfe/trunk/include/clang/Tooling/CompilationDatabase.h Tue Apr 17 11:54:26 2012 >> @@ -34,13 +34,11 @@ >> ?#include "llvm/ADT/StringMap.h" >> ?#include "llvm/ADT/StringRef.h" >> ?#include "llvm/Support/MemoryBuffer.h" >> +#include "llvm/Support/SourceMgr.h" >> +#include "llvm/Support/YAMLParser.h" >> ?#include >> ?#include >> >> -namespace llvm { >> -class MemoryBuffer; >> -} // end namespace llvm >> - >> ?namespace clang { >> ?namespace tooling { >> >> @@ -139,7 +137,7 @@ >> ?private: >> ? /// \brief Constructs a JSON compilation database on a memory buffer. >> ? JSONCompilationDatabase(llvm::MemoryBuffer *Database) >> - ? ?: Database(Database) {} >> + ? ?: Database(Database), YAMLStream(Database->getBuffer(), SM) {} >> >> ? /// \brief Parses the database file and creates the index. >> ? /// >> @@ -147,14 +145,17 @@ >> ? /// failed. >> ? bool parse(std::string &ErrorMessage); >> >> - ?// Tuple (directory, commandline) where 'commandline' is a JSON escaped bash >> - ?// escaped command line. >> - ?typedef std::pair CompileCommandRef; >> + ?// Tuple (directory, commandline) where 'commandline' pointing to the >> + ?// corresponding nodes in the YAML stream. >> + ?typedef std::pair> + ? ? ? ? ? ? ? ? ? ?llvm::yaml::ScalarNode*> CompileCommandRef; >> >> ? // Maps file paths to the compile command lines for that file. >> ? llvm::StringMap< std::vector > IndexByFile; >> >> ? llvm::OwningPtr Database; >> + ?llvm::SourceMgr SM; >> + ?llvm::yaml::Stream YAMLStream; >> ?}; >> >> ?} // end namespace tooling >> >> Modified: cfe/trunk/lib/Tooling/CompilationDatabase.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CompilationDatabase.cpp?rev=154929&r1=154928&r2=154929&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Tooling/CompilationDatabase.cpp (original) >> +++ cfe/trunk/lib/Tooling/CompilationDatabase.cpp Tue Apr 17 11:54:26 2012 >> @@ -13,7 +13,7 @@ >> >> ?#include "clang/Tooling/CompilationDatabase.h" >> ?#include "llvm/ADT/SmallString.h" >> -#include "llvm/Support/JSONParser.h" >> +#include "llvm/Support/YAMLParser.h" >> ?#include "llvm/Support/Path.h" >> ?#include "llvm/Support/system_error.h" >> >> @@ -22,10 +22,10 @@ >> >> ?namespace { >> >> -/// \brief A parser for JSON escaped strings of command line arguments. >> +/// \brief A parser for escaped strings of command line arguments. >> ?/// >> ?/// Assumes \-escaping for quoted arguments (see the documentation of >> -/// unescapeJSONCommandLine(...)). >> +/// unescapeCommandLine(...)). >> ?class CommandLineArgumentParser { >> ?public: >> ? CommandLineArgumentParser(StringRef CommandLine) >> @@ -90,9 +90,6 @@ >> >> ? bool next() { >> ? ? ++Position; >> - ? ?if (Position == Input.end()) return false; >> - ? ?// Remove the JSON escaping first. This is done unconditionally. >> - ? ?if (*Position == '\\') ++Position; >> ? ? return Position != Input.end(); >> ? } >> >> @@ -101,9 +98,9 @@ >> ? std::vector CommandLine; >> ?}; >> >> -std::vector unescapeJSONCommandLine( >> - ? ?StringRef JSONEscapedCommandLine) { >> - ?CommandLineArgumentParser parser(JSONEscapedCommandLine); >> +std::vector unescapeCommandLine( >> + ? ?StringRef EscapedCommandLine) { >> + ?CommandLineArgumentParser parser(EscapedCommandLine); >> ? return parser.parse(); >> ?} >> >> @@ -162,65 +159,77 @@ >> ? const std::vector &CommandsRef = CommandsRefI->getValue(); >> ? std::vector Commands; >> ? for (int I = 0, E = CommandsRef.size(); I != E; ++I) { >> + ? ?llvm::SmallString<8> DirectoryStorage; >> + ? ?llvm::SmallString<1024> CommandStorage; >> ? ? Commands.push_back(CompileCommand( >> ? ? ? // FIXME: Escape correctly: >> - ? ? ?CommandsRef[I].first, >> - ? ? ?unescapeJSONCommandLine(CommandsRef[I].second))); >> + ? ? ?CommandsRef[I].first->getValue(DirectoryStorage), >> + ? ? ?unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage)))); >> ? } >> ? return Commands; >> ?} >> >> ?bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { >> - ?llvm::SourceMgr SM; >> - ?llvm::JSONParser Parser(Database->getBuffer(), &SM); >> - ?llvm::JSONValue *Root = Parser.parseRoot(); >> + ?llvm::yaml::document_iterator I = YAMLStream.begin(); >> + ?if (I == YAMLStream.end()) { >> + ? ?ErrorMessage = "Error while parsing YAML."; >> + ? ?return false; >> + ?} >> + ?llvm::yaml::Node *Root = I->getRoot(); >> ? if (Root == NULL) { >> - ? ?ErrorMessage = "Error while parsing JSON."; >> + ? ?ErrorMessage = "Error while parsing YAML."; >> ? ? return false; >> ? } >> - ?llvm::JSONArray *Array = dyn_cast(Root); >> + ?llvm::yaml::SequenceNode *Array = >> + ? ?llvm::dyn_cast(Root); >> ? if (Array == NULL) { >> ? ? ErrorMessage = "Expected array."; >> ? ? return false; >> ? } >> - ?for (llvm::JSONArray::const_iterator AI = Array->begin(), AE = Array->end(); >> + ?for (llvm::yaml::SequenceNode::iterator AI = Array->begin(), >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AE = Array->end(); >> ? ? ? ?AI != AE; ++AI) { >> - ? ?const llvm::JSONObject *Object = dyn_cast(*AI); >> + ? ?llvm::yaml::MappingNode *Object = >> + ? ? ?llvm::dyn_cast(&*AI); >> ? ? if (Object == NULL) { >> ? ? ? ErrorMessage = "Expected object."; >> ? ? ? return false; >> ? ? } >> - ? ?StringRef EntryDirectory; >> - ? ?StringRef EntryFile; >> - ? ?StringRef EntryCommand; >> - ? ?for (llvm::JSONObject::const_iterator KVI = Object->begin(), >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?KVE = Object->end(); >> + ? ?llvm::yaml::ScalarNode *Directory; >> + ? ?llvm::yaml::ScalarNode *Command; >> + ? ?llvm::SmallString<8> FileStorage; >> + ? ?llvm::StringRef File; >> + ? ?for (llvm::yaml::MappingNode::iterator KVI = Object->begin(), >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? KVE = Object->end(); >> ? ? ? ? ?KVI != KVE; ++KVI) { >> - ? ? ?const llvm::JSONValue *Value = (*KVI)->Value; >> + ? ? ?llvm::yaml::Node *Value = (*KVI).getValue(); >> ? ? ? if (Value == NULL) { >> ? ? ? ? ErrorMessage = "Expected value."; >> ? ? ? ? return false; >> ? ? ? } >> - ? ? ?const llvm::JSONString *ValueString = >> - ? ? ? ?dyn_cast(Value); >> + ? ? ?llvm::yaml::ScalarNode *ValueString = >> + ? ? ? ?llvm::dyn_cast(Value); > > Should this be a (non-dyn) llvm::cast? Or should it be null checked > before it's dereferenced 5 lines down? > >> ? ? ? if (ValueString == NULL) { >> ? ? ? ? ErrorMessage = "Expected string as value."; >> ? ? ? ? return false; >> ? ? ? } >> - ? ? ?if ((*KVI)->Key->getRawText() == "directory") { >> - ? ? ? ?EntryDirectory = ValueString->getRawText(); >> - ? ? ?} else if ((*KVI)->Key->getRawText() == "file") { >> - ? ? ? ?EntryFile = ValueString->getRawText(); >> - ? ? ?} else if ((*KVI)->Key->getRawText() == "command") { >> - ? ? ? ?EntryCommand = ValueString->getRawText(); >> + ? ? ?llvm::yaml::ScalarNode *KeyString = >> + ? ? ? ?llvm::dyn_cast((*KVI).getKey()); >> + ? ? ?llvm::SmallString<8> KeyStorage; >> + ? ? ?if (KeyString->getValue(KeyStorage) == "directory") { >> + ? ? ? ?Directory = ValueString; >> + ? ? ?} else if (KeyString->getValue(KeyStorage) == "command") { >> + ? ? ? ?Command = ValueString; >> + ? ? ?} else if (KeyString->getValue(KeyStorage) == "file") { >> + ? ? ? ?File = ValueString->getValue(FileStorage); >> ? ? ? } else { >> - ? ? ? ?ErrorMessage = (Twine("Unknown key: \"") + >> - ? ? ? ? ? ? ? ? ? ? ? ?(*KVI)->Key->getRawText() + "\"").str(); >> + ? ? ? ?ErrorMessage = ("Unknown key: \"" + >> + ? ? ? ? ? ? ? ? ? ? ? ?KeyString->getRawValue() + "\"").str(); >> ? ? ? ? return false; >> ? ? ? } >> ? ? } >> - ? ?IndexByFile[EntryFile].push_back( >> - ? ? ?CompileCommandRef(EntryDirectory, EntryCommand)); >> + ? ?IndexByFile[File].push_back( >> + ? ? ?CompileCommandRef(Directory, Command)); > > Are 'Directory' and 'Command' guaranteed to have been initialized by > the above loop? (perhaps the file has been verified to contain a > 'directory' and 'command' key by some previous code? I haven't looked > closely) > > GCC's maybe-uninitialized mentioned this so I just thought I'd have a > look around at it. Thanks! All fixed in r156814. Found some missing tests after a migration to a much broader interface ;) > > - David > >> ? } >> ? return true; >> ?} >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From csdavec at swan.ac.uk Tue May 15 08:18:03 2012 From: csdavec at swan.ac.uk (David Chisnall) Date: Tue, 15 May 2012 13:18:03 -0000 Subject: [cfe-commits] r156820 - /cfe/trunk/docs/ReleaseNotes.html Message-ID: <20120515131803.4C5D12A6C065@llvm.org> Author: theraven Date: Tue May 15 08:18:03 2012 New Revision: 156820 URL: http://llvm.org/viewvc/llvm-project?rev=156820&view=rev Log: Add a note about atomic builtins to c11 section of release notes. Modified: cfe/trunk/docs/ReleaseNotes.html Modified: cfe/trunk/docs/ReleaseNotes.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.html?rev=156820&r1=156819&r2=156820&view=diff ============================================================================== --- cfe/trunk/docs/ReleaseNotes.html (original) +++ cfe/trunk/docs/ReleaseNotes.html Tue May 15 08:18:03 2012 @@ -112,7 +112,12 @@

All warning and language selection flags which previously accepted c1x have been updated to accept c11. The old -c1x forms have been removed. +c1x forms have been removed.

+ +

Clang 3.1 adds a family of __c11_atomic builtins corresponding + directly to the _explict versions of the C11 atomic functions. + This means that C11's <stdatomic.h> can be implemented in + a small set of trivial macros.

C++ Language Changes in Clang

From rafael.espindola at gmail.com Tue May 15 09:09:56 2012 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 15 May 2012 14:09:56 -0000 Subject: [cfe-commits] r156821 - in /cfe/trunk: include/clang/Basic/Attr.td lib/AST/Decl.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGenCXX/visibility.cpp utils/TableGen/ClangAttrEmitter.cpp Message-ID: <20120515140956.7FABE2A6C065@llvm.org> Author: rafael Date: Tue May 15 09:09:55 2012 New Revision: 156821 URL: http://llvm.org/viewvc/llvm-project?rev=156821&view=rev Log: Fix our handling of visibility in explicit template instantiations. * Don't copy the visibility attribute during instantiations. We have to be able to distinguish struct HIDDEN foo {}; template DEFAULT void bar() {} template DEFAULT void bar(); from struct HIDDEN foo {}; template DEFAULT void bar() {} template void bar(); * If an instantiation has an attribute, it takes precedence over an attribute in the template. * With instantiation attributes handled with the above logic, we can now select the minimum visibility when looking at template arguments. Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/CodeGenCXX/visibility.cpp cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=156821&r1=156820&r2=156821&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Tue May 15 09:09:55 2012 @@ -93,6 +93,9 @@ list Namespaces = []; // Set to true for attributes with arguments which require delayed parsing. bit LateParsed = 0; + // Set to false to prevent an attribute from being propagated from a template + // to the instantiation. + bit Clone = 1; // Set to true for attributes which must be instantiated within templates bit TemplateDependent = 0; // Set to true for attributes that have a corresponding AST node. @@ -660,6 +663,7 @@ } def Visibility : InheritableAttr { + let Clone = 0; let Spellings = ["visibility"]; let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=156821&r1=156820&r2=156821&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Tue May 15 09:09:55 2012 @@ -158,14 +158,12 @@ return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), OnlyTemplate); } -static bool shouldConsiderTemplateLV(const FunctionDecl *fn, - const FunctionTemplateSpecializationInfo *spec) { - return !(spec->isExplicitSpecialization() && - fn->hasAttr()); +static bool shouldConsiderTemplateLV(const FunctionDecl *fn) { + return !fn->hasAttr(); } static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) { - return !(d->isExplicitSpecialization() && d->hasAttr()); + return !d->hasAttr(); } static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, @@ -376,7 +374,7 @@ // this is an explicit specialization with a visibility attribute. if (FunctionTemplateSpecializationInfo *specInfo = Function->getTemplateSpecializationInfo()) { - if (shouldConsiderTemplateLV(Function, specInfo)) { + if (shouldConsiderTemplateLV(Function)) { LV.merge(getLVForDecl(specInfo->getTemplate(), true)); const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; @@ -407,8 +405,8 @@ // The arguments at which the template was instantiated. const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LV.merge(getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate)); + LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs, + OnlyTemplate)); } } @@ -527,7 +525,7 @@ // the template parameters and arguments. if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { - if (shouldConsiderTemplateLV(MD, spec)) { + if (shouldConsiderTemplateLV(MD)) { LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments, OnlyTemplate)); if (!OnlyTemplate) Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=156821&r1=156820&r2=156821&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue May 15 09:09:55 2012 @@ -102,7 +102,8 @@ } else { Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); - New->addAttr(NewAttr); + if (NewAttr) + New->addAttr(NewAttr); } } } Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=156821&r1=156820&r2=156821&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/visibility.cpp (original) +++ cfe/trunk/test/CodeGenCXX/visibility.cpp Tue May 15 09:09:55 2012 @@ -712,3 +712,55 @@ // CHECK: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv } + +namespace test37 { + struct HIDDEN foo { + }; + template + DEFAULT void bar() {} + template DEFAULT void bar(); + // CHECK: define weak_odr void @_ZN6test373barINS_3fooEEEvv + // CHECK-HIDDEN: define weak_odr void @_ZN6test373barINS_3fooEEEvv +} + +namespace test38 { + template + class DEFAULT foo { + void bar() {} + }; + struct HIDDEN zed { + }; + template class foo; + // CHECK: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv + // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv +} + +namespace test39 { + class DEFAULT default_t; + class HIDDEN hidden_t; + template class A { + template class B { + HIDDEN void hidden() {} + void noattr() {} + template void temp() {} + }; + }; + template class DEFAULT A; + template class DEFAULT A::B; + template void A::B::temp(); + template void A::B::temp(); + + // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv + // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv + // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv + + // GCC produces a default for this one. Why? + // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv + + // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv + // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv + // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv + + // GCC produces a default for this one. Why? + // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv +} Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=156821&r1=156820&r2=156821&view=diff ============================================================================== --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original) +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Tue May 15 09:09:55 2012 @@ -1004,6 +1004,14 @@ continue; OS << " case attr::" << R.getName() << ": {\n"; + bool ShouldClone = R.getValueAsBit("Clone"); + + if (!ShouldClone) { + OS << " return NULL;\n"; + OS << " }\n"; + continue; + } + OS << " const " << R.getName() << "Attr *A = cast<" << R.getName() << "Attr>(At);\n"; bool TDependent = R.getValueAsBit("TemplateDependent"); From kcc at google.com Tue May 15 10:38:31 2012 From: kcc at google.com (Kostya Serebryany) Date: Tue, 15 May 2012 19:38:31 +0400 Subject: [cfe-commits] ThreadSanitizer library and linker flags: please review Message-ID: Hello, Please review the following patch which adds ThreadSanitizer (tsan) linker flags on Linux and also copies the tsan-rt into the appropriate place at build time. This mimics similar parts related to AddressSanitizer. http://codereview.appspot.com/6197087/ Thanks, --kcc -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/63cba58c/attachment.html -------------- next part -------------- A non-text attachment was scrubbed... Name: issue6197087_2001.diff Type: application/octet-stream Size: 2017 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/63cba58c/attachment.obj From macmantrl at me.com Tue May 15 11:05:55 2012 From: macmantrl at me.com (Terry Long) Date: Tue, 15 May 2012 12:05:55 -0400 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics Message-ID: Hi all, This patch mostly inspired by http://llvm.org/bugs/show_bug.cgi?id=9243 -- poor "duplicate case" diagnostic with enums Previously the diagnostic for duplicate case values in switch statements was always something like "duplicate case value '5'" What my patch changes: When the duplicate case is exactly the same in textual representation (in source code), the diagnostic will use that exact text in the diagnostic. e.g. using MyEnum twice gives the diagnostic "duplicate case value 'MyEnum'" If the textual representations differ, the new diagnostic explicitly states they are equal to the same value e.g. using MyEnum (equal to 5) and 5, the diagnostic displays "duplicate case value: 'MyEnum' and '5' both equal '5'" The patch does the same for any valid expression in a case statement (including macros, const ints, char literals, etc.). Concerns with my patch: 1. Multiline case statements, although unusual, will be printed out in the diagnostic exactly as they appear in the source. I'm not sure if this is a real issue. Possible solution would be checking if it spans multiple lines. If so, the diagnostic could be "duplicate case value: both expressions equal 'x'". e.g. case 1 + 2 + 3: 2. If a case statement includes a cast, the cast will also be included in the diagnostic. Sometimes this inclusion is helpful, for example in situations where the cast will cause an overflow (such as "(char)256" and "0"). Other times it is irrelevant, such as "(int)7" and "7", where a simple diagnostic of "duplicate case value '7'" makes more sense. I'm also not sure if this is an issue. Thanks! Terry Long -------------- next part -------------- A non-text attachment was scrubbed... Name: PR9243.patch Type: application/octet-stream Size: 5620 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/e0a348d2/attachment-0001.obj From jediknil at belkadan.com Tue May 15 11:15:06 2012 From: jediknil at belkadan.com (Jordan Rose) Date: Tue, 15 May 2012 12:15:06 -0400 Subject: [cfe-commits] [PATCH] Add analyzer_assert for regression tests In-Reply-To: <6A305ACC-5BF0-4281-8B01-C3F3E4228F57@apple.com> References: <881546B4-753E-499A-A279-04FD0F182FEF@belkadan.com> <6A305ACC-5BF0-4281-8B01-C3F3E4228F57@apple.com> Message-ID: <603F2830-8617-434C-BBA8-659F26524A5B@belkadan.com> All right, version 2, with your suggestions taken into account. What do you think? I went with clang_analyzer_eval because it's a little shorter, but it may be a bit less clear (does it eval integers as well?). The output is in all caps to try to avoid conflicts with legitimate warnings. Merging the constraint and taint testers would be possible, but it's something we can do later. In my working branch I've identified these files as systematically using null dereferencing and malloc leaks purely for error reporting: additive-folding-range-constraints.c additive-folding.c bstring.c constant-folding.c ptr-arith.c string-fail.c string.c (in this patch) (Many of those files were actually originally created or reformatted by me, so that's not surprising.) There are several more files where the policy is not as clear, but which should probably still be using this in at least one part of the test: array-struct-region.c (in this patch) base-init.cpp dynamic-cast.cpp (some null derefs remain, since it's about pointers anyway) global-region-invalidation.c initializer.cpp inline.c method-call-intra-p.cpp method-call.cpp objc-arc.m reference.cpp Finally, some of the "ps" miscellaneous files also use null dereferencing and deadcode warnings, but since a lot of those are taken verbatim from PRs and Radars it's possible the particular form is what triggered the past bug. I left those alone, but I'm planning to go ahead and change the other two sets above as well. I'm a little concerned about blame churn for the less-systematic tests, but it still seems like the right thing to do moving forward. Jordy -------------- next part -------------- A non-text attachment was scrubbed... Name: ConstraintTest.patch Type: application/octet-stream Size: 35027 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/22559967/attachment-0001.obj -------------- next part -------------- // Any signature with an integral type will do. // 'bool' would be canonical in C++. void clang_analyzer_eval(int); void testUnsigned (unsigned a) { if (a > 0) return; clang_analyzer_eval(a == 0); // expected-warning{{TRUE}} } void testSigned (int a) { if (a > 0) return; clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} } On May 14, 2012, at 19:40, Anna Zaks wrote: > Jordy, > > I think having something like this is a great idea. > >> A downside I am realizing is that silent success means the output looks the same whether debug.Asserts is on or off...not sure yet what to do about that. > > How about having something like "clang_analyzer_check_expr()" that always produces a warning which tells us about the expression's state, like "true", "false", "unknown"? > > I've added a taint debug checker, which serves similar purpose. We could also use this to check taint or other info by appending another string to the warning message "true (tainted:true)", but possibly with better markup. > > A few minor comments: > - I'd prefix these asserts with "clang_analyzer". > - We should check for undefined here. This checker is not guaranteed to be run along with other checkers. > > Cheers, > Anna. From dgregor at apple.com Tue May 15 11:19:10 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 09:19:10 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: Message-ID: On May 6, 2012, at 7:02 PM, David Blaikie wrote: > This patch adds an iterator much like boost's transform_iterator > (without some extra bells & whistles) for use in some changes I'd like > to make to Clang to correct some misimplemented iterators there. > > A few gotchas that could be improved/changed depending on opinions: > * I may be playing a little loose with the return type of the functor > (see the example/motivating functor, to_pointer) - the return type > actually must be a reference, though the result_type provides the > underlying value type, not the reference type. If this is violated > Clang will emit a warning, but I could make it more robust with a > compile time assertion in the TransformIterator that the result_type > is actually a reference type, and strip that off to provide the > value_type of the TransformIterator. It's much more correct for the value and reference types of the iterator type to be, e.g., typedef typename Functor::result_type reference; typedef typename remove_reference::type value_type; > * I realize adding pointer-yness back onto an iterator over references > when the underlying data structure (in the Clang patch you can see > this situation) is a sequence of pointers may be a bit overkill - > though the alternatives are writing different algorithms in the two > cases where I've used TransformIterator, or having the decl_iterator > iterate over pointers (in which case I should probably change the > other iterators I've modified to iterate over pointers for symmetry). diff --git include/clang/AST/DeclBase.h include/clang/AST/DeclBase.h index 6aef681..0a16ea5 100644 --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -1175,17 +1175,18 @@ public: Decl *Current; public: - typedef Decl* value_type; - typedef Decl* reference; - typedef Decl* pointer; + typedef Decl value_type; + typedef value_type& reference; + typedef value_type* pointer; Since we tend to traffic in declaration pointers, not references, it's really beneficial to have value_type be Decl*. Of course, it's fine for the reference type to be Decl* as well. > At some point I'll also be looking to add a FilterIterator (& possibly > a specific Filtering+Transforming iterator, as I'm not sure the > composition of the two independently will be great for the use case I > have in mind) as well since that's one of the motivation for tidying > up these iterators - to pull out the common functionality in the > specific/filtered_iterators in DeclContext. +//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ Header needs updating. + pointer operator->() const { + return m_func(*m_iter); + } This isn't going to work; m_func returns a value_type or reference. Dealing with -> is a real pain, because in the general case you need a proxy class. +// a convenient utility for a common adaptation +template +struct to_pointer { + typedef T * result_type; + typedef T argument_type; + result_type &operator()(T &t) const { + ptr = &t; + return ptr; + } +private: + mutable T *ptr; +}; 'to_pointer' is a very non-LLVM-y name. More generally, this particular function object seems like a bad idea. There's nothing wrong with having an iterator type whose reference type is not a true reference, which means that there is no reason to do this little dance with the mutable 'ptr'. - Doug From dblaikie at gmail.com Tue May 15 11:31:02 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 09:31:02 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 9:19 AM, Douglas Gregor wrote: > > On May 6, 2012, at 7:02 PM, David Blaikie wrote: > >> This patch adds an iterator much like boost's transform_iterator >> (without some extra bells & whistles) for use in some changes I'd like >> to make to Clang to correct some misimplemented iterators there. >> >> A few gotchas that could be improved/changed depending on opinions: >> * I may be playing a little loose with the return type of the functor >> (see the example/motivating functor, to_pointer) - the return type >> actually must be a reference, though the result_type provides the >> underlying value type, not the reference type. If this is violated >> Clang will emit a warning, but I could make it more robust with a >> compile time assertion in the TransformIterator that the result_type >> is actually a reference type, and strip that off to provide the >> value_type of the TransformIterator. > > It's much more correct for the value and reference types of the iterator type to be, e.g., > > ?typedef typename Functor::result_type reference; > ?typedef typename remove_reference::type value_type; > >> * I realize adding pointer-yness back onto an iterator over references >> when the underlying data structure (in the Clang patch you can see >> this situation) is a sequence of pointers may be a bit overkill - >> though the alternatives are writing different algorithms in the two >> cases where I've used TransformIterator, or having the decl_iterator >> iterate over pointers (in which case I should probably change the >> other iterators I've modified to iterate over pointers for symmetry). > > diff --git include/clang/AST/DeclBase.h include/clang/AST/DeclBase.h > index 6aef681..0a16ea5 100644 > --- include/clang/AST/DeclBase.h > +++ include/clang/AST/DeclBase.h > @@ -1175,17 +1175,18 @@ public: > ? ? Decl *Current; > > ? public: > - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? value_type; > - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? reference; > - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? pointer; > + ? ?typedef Decl ? ? ? ? ? ? ? ? ? ? value_type; > + ? ?typedef value_type& ? ? ? ? ? ? ?reference; > + ? ?typedef value_type* ? ? ? ? ? ? ?pointer; > > Since we tend to traffic in declaration pointers, not references, it's really beneficial to have value_type be Decl*. Fair enough - I was hoping to reduce the amount of pointers handed around, but I realize in this case especially (where the underlying sequence is a sequence of pointers) it's really an awkward fit. This means killing off the op-> for these iterators though, right? Or do you want to keep that as an excusable convenience? In which case my change boils down to just changing the pointer typedefs to be Decl** in these various iterator types. (& might make my planned work, generalizing the filtering iterators, a bit weird - possibly providing an op-> to the generic filtering iterators whenever the value type is a pointer to match/support this oddity) Would you prefer the other iterators I changed (specific_decl_iterator, filtered_decl_iterator) be switched to pointer value_type too? > Of course, it's fine for the reference type to be Decl* as well. Good point. >> At some point I'll also be looking to add a FilterIterator (& possibly >> a specific Filtering+Transforming iterator, as I'm not sure the >> composition of the two independently will be great for the use case I >> have in mind) as well since that's one of the motivation for tidying >> up these iterators - to pull out the common functionality in the >> specific/filtered_iterators in DeclContext. > > > +//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// > +// > +// ? ? ? ? ? ? ? ? ? ? The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===/ > > Header needs updating. > > + ?pointer operator->() const { > + ? ?return m_func(*m_iter); > + ?} > > This isn't going to work; m_func returns a value_type or reference. Dealing with -> is a real pain, because in the general case you need a proxy class. > > +// a convenient utility for a common adaptation > +template > +struct to_pointer { > + ?typedef T * result_type; > + ?typedef T argument_type; > + ?result_type &operator()(T &t) const { > + ? ?ptr = &t; > + ? ?return ptr; > + ?} > +private: > + ?mutable T *ptr; > +}; > > 'to_pointer' is a very non-LLVM-y name. > > More generally, this particular function object seems like a bad idea. There's nothing wrong with having an iterator type whose reference type is not a true reference, which means that there is no reason to do this little dance with the mutable 'ptr'. Yeah, a proxy would be nicer. In any case all this transformation stuff isn't needed for this change anymore if we're sticking with a pointer value_type. Thanks, - David From fjahanian at apple.com Tue May 15 11:33:04 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Tue, 15 May 2012 16:33:04 -0000 Subject: [cfe-commits] r156825 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaObjC/no-ivar-in-interface-block.m Message-ID: <20120515163304.D49EA2A6C065@llvm.org> Author: fjahanian Date: Tue May 15 11:33:04 2012 New Revision: 156825 URL: http://llvm.org/viewvc/llvm-project?rev=156825&view=rev Log: objective-c nonfragile abi: discourage ivar declarations in @interface by issuing warning (off by default) under opt'ed in flag -Winterface-block-ivar. // rdar://10763173 Added: cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156825&r1=156824&r2=156825&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 11:33:04 2012 @@ -3024,6 +3024,9 @@ def err_duplicate_member : Error<"duplicate member %0">; def err_misplaced_ivar : Error< "ivars may not be placed in %select{categories|class extension}0">; +def warn_ivar_in_interface_block : Warning< + "declaration of ivar in the interface block is deprecated">, + InGroup>, DefaultIgnore; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=156825&r1=156824&r2=156825&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue May 15 11:33:04 2012 @@ -9540,7 +9540,11 @@ S->AddDecl(NewID); IdResolver.AddDecl(NewID); } - + + if (LangOpts.ObjCNonFragileABI2 && + !NewID->isInvalidDecl() && isa(EnclosingDecl)) + Diag(Loc, diag::warn_ivar_in_interface_block); + return NewID; } Added: cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m?rev=156825&view=auto ============================================================================== --- cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m (added) +++ cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m Tue May 15 11:33:04 2012 @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Winterface-block-ivar %s +// rdar://10763173 + + at interface I +{ + @protected int P_IVAR; // expected-warning {{declaration of ivar in the interface block is deprecated}} + + @public int PU_IVAR; // expected-warning {{declaration of ivar in the interface block is deprecated}} + + @private int PRV_IVAR; // expected-warning {{declaration of ivar in the interface block is deprecated}} +} + at end + + at interface I() +{ + int I1; + int I2; +} + at end + + at interface I() +{ + int I3, I4; +} + at end + + at implementation I +{ + int I5; + int I6; +} + at end From js at webkeks.org Tue May 15 11:34:26 2012 From: js at webkeks.org (Jonathan Schleifer) Date: Tue, 15 May 2012 18:34:26 +0200 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <3AB519D3-FA30-4BA7-B29E-27EA91BC90E1@apple.com> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> <21316473-94E5-4053-A13C-A87C8FEA311E@webkeks.org> <3AB519D3-FA30-4BA7-B29E-27EA91BC90E1@apple.com> Message-ID: <1DF565A5-6B4E-4A7C-8680-03547FF0E14B@webkeks.org> Am 15.05.2012 um 00:37 schrieb John McCall: > I just don't want it to be a command-line option. I can think of advantages of having it as a command line option, though: If a new runtime emerges, it does not need to patch clang, but instead it can use the -f switches. And it also means if a runtime gains a new feature, it does not need to patch clang. I can understand that you don't want to have a long list of options that are required in order to work with the runtime, so I have another proposal: What about introducing a new -fobjc-runtime-features=foo,bar,baz with an alias for already known runtimes? For example, you could specify -fobjc-runtime-features=direct-class-refs,non-fragile-abi. But as an alias for these two, you could also specify -fobjc-runtime-features=gnustep-1.0. Any comments on this? -- Jonathan From dblaikie at gmail.com Tue May 15 11:56:36 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 16:56:36 -0000 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sema/array-init.c test/Sema/knr-def-call.c test/SemaCXX/bool.cpp test/SemaCXX/conversion.cpp test/SemaCXX/expressions.cpp test/SemaCXX/overload-call.cpp test/SemaCXX/warn-literal-conversion.cpp test/SemaTemplate/member-template-access-expr.cpp Message-ID: <20120515165637.367572A6C065@llvm.org> Author: dblaikie Date: Tue May 15 11:56:36 2012 New Revision: 156826 URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev Log: Improve some of the conversion warnings to fire on conversion to bool. Moves the bool bail-out down a little in SemaChecking - so now -Wnull-conversion and -Wliteral-conversion can fire when the target type is bool. Also improve the wording/details in the -Wliteral-conversion warning to match the -Wconstant-conversion. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/Analysis/array-struct-region.c cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp cfe/trunk/test/CXX/temp/temp.spec/p5.cpp cfe/trunk/test/PCH/exprs.h cfe/trunk/test/Sema/array-init.c cfe/trunk/test/Sema/knr-def-call.c cfe/trunk/test/SemaCXX/bool.cpp cfe/trunk/test/SemaCXX/conversion.cpp cfe/trunk/test/SemaCXX/expressions.cpp cfe/trunk/test/SemaCXX/overload-call.cpp cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 11:56:36 2012 @@ -1781,8 +1781,7 @@ "implicit truncation from %2 to bitfield changes value from %0 to %1">, InGroup; def warn_impcast_literal_float_to_integer : Warning< - "implicit conversion turns literal floating-point number into integer: " - "%0 to %1">, + "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup; def warn_impcast_string_literal_to_bool : Warning< "implicit conversion turns string literal into bool: %0 to %1">, Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 @@ -22,6 +22,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/EvaluatedExprVisitor.h" @@ -4081,8 +4082,17 @@ == llvm::APFloat::opOK && isExact) return; + SmallString<16> PrettySourceValue; + Value.toString(PrettySourceValue); + std::string PrettyTargetValue; + if (T->isSpecificBuiltinType(BuiltinType::Bool)) + PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; + else + PrettyTargetValue = IntegerValue.toString(10); + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) - << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); + << FL->getType() << T.getUnqualifiedType() << PrettySourceValue + << PrettyTargetValue << FL->getSourceRange() << SourceRange(CContext); } std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { @@ -4149,7 +4159,6 @@ } } } - return; // Other casts to bool are not checked. } // Strip vector types. @@ -4213,7 +4222,7 @@ } // If the target is integral, always warn. - if ((TargetBT && TargetBT->isInteger())) { + if (TargetBT && TargetBT->isInteger()) { if (S.SourceMgr.isInSystemMacro(CC)) return; @@ -4247,6 +4256,11 @@ return; } + // TODO: remove this early return once the false positives for constant->bool + // in templates, macros, etc, are reduced or removed. + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) + return; + IntRange SourceRange = GetExprRange(S.Context, E); IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); Modified: cfe/trunk/test/Analysis/array-struct-region.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/Analysis/array-struct-region.c (original) +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 11:56:36 2012 @@ -25,8 +25,8 @@ } void nested_compound_literals(int rad) { - int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // expected-warning 6 {{implicit conversion turns literal floating-point number into integer}} - {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // expected-warning 6 {{implicit conversion turns literal floating-point number into integer}} + int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}} + {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}} int a; for (a = 0; a < 6; ++a) { Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May 15 11:56:36 2012 @@ -4,7 +4,7 @@ bool b = !0; -bool b2 = !1.2; +bool b2 = !1.2; //expected-warning{{implicit conversion from 'double' to 'bool' changes value from 1.2 to true}} bool b3 = !4; Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 2012 @@ -14,7 +14,7 @@ }; template -T X0::value = 3.14; // expected-warning{{implicit conversion turns literal floating-point number into integer}} +T X0::value = 3.14; // expected-warning{{implicit conversion from 'double' to 'int' changes value from 3.14 to 3}} template struct X0; // expected-note{{previous explicit instantiation}} \ expected-note{{requested here}} Modified: cfe/trunk/test/PCH/exprs.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/PCH/exprs.h (original) +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 @@ -87,7 +87,7 @@ int x; float y; } designated_inits[3] = { [0].y = 17, - [2].x = 12.3, // expected-warning {{implicit conversion turns literal floating-point number into integer}} + [2].x = 12.3, // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} 3.5 }; // TypesCompatibleExpr Modified: cfe/trunk/test/Sema/array-init.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/Sema/array-init.c (original) +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 @@ -50,7 +50,7 @@ static long x2[3] = { 1.0, "abc", // expected-warning{{incompatible pointer to integer conversion initializing 'long' with an expression of type 'char [4]'}} - 5.8 }; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + 5.8 }; // expected-warning {{implicit conversion from 'double' to 'long' changes value from 5.8 to 5}} } void test() { Modified: cfe/trunk/test/Sema/knr-def-call.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/Sema/knr-def-call.c (original) +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 @@ -36,6 +36,6 @@ } void use_proto() { - proto(42.1); // expected-warning{{implicit conversion turns literal floating-point number into integer}} - (&proto)(42.1); // expected-warning{{implicit conversion turns literal floating-point number into integer}} + proto(42.1); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 42.1 to 42}} + (&proto)(42.1); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 42.1 to 42}} } Modified: cfe/trunk/test/SemaCXX/bool.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/bool.cpp (original) +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s // Bool literals can be enum values. enum { Modified: cfe/trunk/test/SemaCXX/conversion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/conversion.cpp (original) +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 @@ -65,7 +65,7 @@ int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} int d; d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} - bool bl = NULL; // FIXME: this should warn but we currently suppress a bunch of conversion-to-bool warnings including this one + bool bl = NULL; // expected-warning {{implicit conversion of NULL constant to 'bool'}} char ch = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}} unsigned char uch = NULL; // expected-warning {{implicit conversion of NULL constant to 'unsigned char'}} short sh = NULL; // expected-warning {{implicit conversion of NULL constant to 'short'}} @@ -104,3 +104,12 @@ tmpl2(); } } + +namespace test5 { + template + void func() { + bool b = I; + } + + template void func<3>(); +} Modified: cfe/trunk/test/SemaCXX/expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/expressions.cpp (original) +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s void choice(int); int choice(bool); Modified: cfe/trunk/test/SemaCXX/overload-call.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 2012 @@ -233,7 +233,7 @@ void intref_test() { float* ir1 = intref(5); - float* ir2 = intref(5.5); // expected-warning{{implicit conversion turns literal floating-point number into integer}} + float* ir2 = intref(5.5); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 5.5 to 5}} } void derived5(C&); // expected-note{{candidate function not viable: cannot bind base class object of type 'A' to derived class reference 'C &' for 1st argument}} Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 11:56:36 2012 @@ -5,29 +5,29 @@ // Warn when a literal float or double is assigned or bound to an integer. void test0() { // Float - int y0 = 1.2222F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y1 = (1.2222F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y2 = (((1.2222F))); // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y3 = 12E-1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y4 = 1.23E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y0 = 1.2222F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y1 = (1.2222F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y2 = (((1.2222F))); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y3 = 12E-1F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} + int y4 = 1.23E1F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 12.3 to 12}} // Double - int y5 = 1.2222; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y6 = 12E-1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y7 = 1.23E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y8 = (1.23E1); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y5 = 1.2222; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 1.2222 to 1}} + int y6 = 12E-1; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 1.2 to 1}} + int y7 = 1.23E1; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} + int y8 = (1.23E1); // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} // Test assignment to an existing variable. - y8 = 2.22F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + y8 = 2.22F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 2.22 to 2}} // Test direct initialization. - int y9(1.23F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y9(1.23F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.23 to 1}} // Test passing a literal floating-point value to a function that takes an integer. - foo(1.2F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + foo(1.2F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} - int y10 = -1.2F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y10 = -1.2F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} - // -Wconversion-literal does NOT catch const values. + // -Wliteral-conversion does NOT catch const values. // (-Wconversion DOES catch them.) static const float sales_tax_rate = .095F; int z = sales_tax_rate; Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original) +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue May 15 11:56:36 2012 @@ -60,7 +60,7 @@ void test_X1(X1 x1) { float *fp1 = x1.f1<>(17); - float *fp2 = x1.f1(3.14); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + float *fp2 = x1.f1(3.14); // expected-warning {{implicit conversion from 'double' to 'int' changes value from 3.14 to 3}} int *ip1 = x1.f1(17); float *ip2 = x1.f1(3.14); From dblaikie at gmail.com Tue May 15 11:59:16 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 09:59:16 -0700 Subject: [cfe-commits] Support -to-bool warnings for more contexts In-Reply-To: References: Message-ID: Committed some of the easier parts of this separately in r156826 - providing (floating) literal-to-bool and NULL-to-bool, but not exposing the problems with constant-to-bool until I can iron out the false positives. On Mon, Apr 23, 2012 at 4:35 PM, Nico Weber wrote: > On Sat, Apr 21, 2012 at 9:54 PM, David Blaikie wrote: >> On Sat, Apr 21, 2012 at 9:16 PM, Nico Weber wrote: >>> I gave this a try in chrome. Here's two cases where this warns on that >>> make me doubtful of this patch. >> >> I agree in its current state it'll need some tweaking to improve the >> accuracy of the cases it opens up. Or are you saying you think it's >> non-viable on principle/beyond correction? > > I was just commenting on the patch as-is. > >> >>> 1.) It warns on code like >>> >>> ? ? ? ?while(YY_CURRENT_BUFFER){ ... } >>> >>> where YY_CURRENT_BUFFER is something that's defined flex: >>> >>> ./compiler/glslang_lex.cpp:2878:8: warning: implicit conversion of >>> NULL constant to 'bool' [-Wnull-conversion] >>> ? ? ? ?while(YY_CURRENT_BUFFER){ >>> ? ? ? ? ? ? ?^~~~~~~~~~~~~~~~~ >>> ./compiler/glslang_lex.cpp:307:29: note: expanded from macro 'YY_CURRENT_BUFFER' >>> ? ? ? ? ? ? ? ? ? ? ? ? ?: NULL) >>> >>> If you use flex, you have to turn off Wnull-conversion because of this >>> issue. Before the patch, Wnull-conversion was a useful warning. >> >> Hmm - wonder what the right fix for this is... >> >> I wouldn't mind seeing the full definition of YY_CURRENT_BUFFER if you >> have a chance to send it to me. It /sounds/ like the conditional >> operator being used there isn't doing what the author thinks it's >> doing (it's probably got a bool argument on the LHS & so the NULL on >> the rhs is always being converted to 'false' & should just be written >> that way). >> >>> 2.) It warns on this: >>> >>> ../../third_party/skia/src/core/SkScalerContext.cpp:380:9: warning: >>> implicit conversion from 'int' to 'bool' changes value from 160 to >>> true [-Wconstant-conversion] >>> ? ?if (SK_FREETYPE_LCD_LERP) { >>> ? ? ? ?^~~~~~~~~~~~~~~~~~~~ >>> ../../third_party/skia/src/core/SkScalerContext.cpp:372:33: note: >>> expanded from macro 'SK_FREETYPE_LCD_LERP' >>> #define SK_FREETYPE_LCD_LERP ? ?160 >>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^~~ >>> >>> This is fairly common in code. >> >> Yep - my thinking was that we could reduce the -Wconstant-conversion >> cases that convert to bool could be limited to literals rather than >> arbitrary expressions (though we'd have to skip the macro/constant >> cases too - but that might miss a lot of really good cases... ) >> >>> (The warning did find a few cases where we're saying 'return NULL' but >>> should be saying 'return false', but nothing interesting. >> >> Curious - given all the fun things I found I'm surprised it didn't hit >> other fun things in chromium. Thanks for giving it a go, though. >> >>> I didn't do >>> a full build of chrome because the build died fairly quickly due to >>> visibility issues caused by one of espindola's recent patches, so I >>> tracked that down instead.) >> >> Fair enough, >> - David >> >>> >>> Nico >>> >>> On Wed, Apr 18, 2012 at 3:42 PM, David Blaikie wrote: >>>> On Wed, Apr 18, 2012 at 3:04 PM, Nico Weber wrote: >>>>> On Wed, Apr 18, 2012 at 11:36 AM, David Blaikie wrote: >>>>>> On Fri, Apr 6, 2012 at 4:42 PM, David Blaikie wrote: >>>>>>> On Mon, Apr 2, 2012 at 9:44 PM, Nico Weber wrote: >>>>>>>> Do you have any numbers on bug / false positive ratios before and >>>>>>>> after this change? >>>>>>> >>>>>>> I'm surprised this didn't catch more - but I found only 2 cases where >>>>>>> this diagnostic fired (on the same function call, no less) & they seem >>>>>>> like perfectly reasonable true positives. Something like: >>>>>>> >>>>>>> void func(bool, bool); >>>>>>> func(0.7, 0.3); >>>>>>> >>>>>>> I'm not really sure what the author intended, but I'm fairly certain >>>>>>> they didn't get it (unless their intent was to confuse future >>>>>>> readers). >>>>>> >>>>>> So this was a little more positive than it looks - these were the new >>>>>> warnings for -Wliteral-conversion that were found by this patch. The >>>>>> new warnings for -Wconstant-conversion (these were the vast majority >>>>>> of the new warnings for my change ?- though we don't use >>>>>> -Wnull-conversion at the moment, so I haven't measured the increase in >>>>>> that warning, for example) are a bit more difficult. >>>>>> >>>>>> While a lot of cases were legitimate, there are a few major false >>>>>> positive cases: >>>>> >>>>> This sounds to me like "more trouble than it's worth". Did you find >>>>> any interesting bugs with this? >>>> >>>> Quite a few, yes. Here's a smattering of examples: >>>> >>>> enum X { A, B, COUNT }; >>>> std::vector b(true, COUNT); >>>> >>>> x &= !flag; // in xerces, actually >>>> >>>> void log_if(int severity, bool condition); >>>> log_if(condition, 3); >>>> >>>> bool func() { ... return ERROR_CODE_FOO; } // various kinds of error >>>> codes, often enums >>>> >>>> bool b; >>>> int i; >>>> ... >>>> b = 10; // user seems to have jumbled up the variables, or their types >>>> i = true; >>>> // similar mistakes to this, except with function calls >>>> ("set_new_uid(5)" when the flag was really about whether a new uid is >>>> created, not specifying the uid value itself) >>>> // a lot of these, admittedly, come up in test code where more >>>> constants are used - though I'm not sure how much better that makes me >>>> feel about them >>>> >>>> void func(int); >>>> func(FLAG1 || FLAG2); // should be FLAG1 | FLAG2 >>>> >>>> if (FLAG1 || FLAG2) // should be "(x == FLAG1 || x == FLAG2)" >>>> >>>> bool maxThings = INT_MAX; // fairly clear mistake in the declaration >>>> of this type >>>> void func(int); >>>> func(maxThings); >>>> >>>> (x & !(sizeof(void*) - 1)) // probably meant '~' not '!', I believe >>>> >>>> if (0 == x && FLAG) // similar to previous examples >>>> >>>> bool status; >>>> ... >>>> status = -4; // yay, random constants! >>>> >>>> while (1729) // I've no idea what this person had in mind... but OK, >>>> probably working as they intended >>>> >>>> if (some_const % other_const) // false positive >>>> >>>> bool func() { >>>> ?... >>>> ? ?return 0; >>>> ?... >>>> ? ?return 1; >>>> ?... >>>> ? ?return 2; // aha! :/ >>>> } >>>> >>>> Well, that's a rough sample - the enum flag kind of cases seem pretty >>>> common, or just passing literals of the wrong type to functions or >>>> constructors (sometimes not as literals, but as constants defined >>>> elsewhere). >>>> >>>>> >>>>> Nico >>>>> >>>>>> >>>>>> * in the /existing/ warning, we have a 'false'-ish positive involving >>>>>> code like this: int i = std::string::npos; ... if (i == >>>>>> std::string::npos) - npos is actually, say, LONG_MAX, so when stored >>>>>> in an int it truncates to -1, but it compares == to -1 just fine. >>>>>> Perhaps we could subcategorize -Wconstant-conversion to allow these >>>>>> particular cases that happen to map back/forth non-destructively? >>>>>> >>>>>> * The major case of false positives with my improved warning amounts >>>>>> to a use case like this: #define MY_ALLOC(Type, Count) >>>>>> malloc(sizeof(Type) * ((Count) ? Count : 1)) // the actual code is a >>>>>> bit more involved, but it's in Python's PyMem_NEW macro >>>>>> ?The problem is that when you pass a compile-time constant count, now >>>>>> we appear to be truncating an integer (stuffing that big count into >>>>>> zero or one of a boolean). It would be nice if we could somehow detect >>>>>> the case where a macro parameter is used inside a constant expression >>>>>> & flag that constant expression as "not so constant". This logic will >>>>>> be necessary for improvements to Clang's unreachable code diagnostic >>>>>> anyway (we need to know when constant expressions might still vary >>>>>> depending on the build settings (or 'call' sites in the case of >>>>>> macros)) >>>>>> ?* equally, improvements to allow for sizeof expressions to trigger >>>>>> similar "not quite constant" flags would be good. While "if >>>>>> (sizeof(X))" is silly & we can happily warn on that, "if (sizeof(X) - >>>>>> 3)" might be less clear cut (or sizeof in some other part of a >>>>>> constant expression) - though I haven't seen (m)any false positives >>>>>> like this. >>>>>> >>>>>> * Template parameters - this leads to code a lot like macros: >>>>>> template void func() { ... if (N) { ... } }; I've currently >>>>>> worked around this by having "IgnoreParenImpCasts" not ignore >>>>>> SubstNonTypeTemplateParmExprs - this is a bit of a dirty hack (both >>>>>> because this code was presumably written this way for a reason - >>>>>> though removing it doesn't regress any test cases - and because I >>>>>> don't think it falls down as soon as N is a subexpression such as "if >>>>>> (N - 3)") >>>>>> >>>>>> Any thoughts on whether or not these are reasonable goals and how best >>>>>> to achieve them would be most welcome, >>>>>> >>>>>> - David >>>>>> >>>>>>> >>>>>>> - David >>>>>>> >>>>>>>> On Mon, Apr 2, 2012 at 6:03 PM, David Blaikie wrote: >>>>>>>>> SemaChecking.cpp:3989 currently returns early from checking implicit >>>>>>>>> conversions after it tests some specific X-to-boolean cases (including >>>>>>>>> string and funciton literals) but before checking various other cases >>>>>>>>> later on like NULL-to-X and wide integer literal to narrow integer. >>>>>>>>> >>>>>>>>> This change removes the early return, fixes the diagnostic (to >>>>>>>>> correctly emit the fact that non-zero literals produce a "true" >>>>>>>>> boolean value rather than simply truncating the larger integer >>>>>>>>> literal), and updates the tests. In some cases the test cases were >>>>>>>>> fixed or updated (//expected-warning), in others I simply suppressed >>>>>>>>> the diagnostic because there adding the expected-warnings would've >>>>>>>>> added a lot of noise to the test cases*. >>>>>>>>> >>>>>>>>> * This last case is a little bit questionable: in one specific case we >>>>>>>>> produce a really good diagnostic about constant integer literals used >>>>>>>>> in boolean contexts: >>>>>>>>> >>>>>>>>> int f1(); >>>>>>>>> bool f2() { >>>>>>>>> ?return f1() && 42; >>>>>>>>> } >>>>>>>>> >>>>>>>>> we produce: >>>>>>>>> >>>>>>>>> conv.cpp:3:15: warning: use of logical '&&' with constant operand >>>>>>>>> [-Wconstant-logical-operand] >>>>>>>>> ?return f1() && 42; >>>>>>>>> ? ? ? ? ? ? ?^ ?~~ >>>>>>>>> conv.cpp:3:15: note: use '&' for a bitwise operation >>>>>>>>> ?return f1() && 42; >>>>>>>>> ? ? ? ? ? ? ?^~ >>>>>>>>> ? ? ? ? ? ? ?& >>>>>>>>> conv.cpp:3:15: note: remove constant to silence this warning >>>>>>>>> ?return f1() && 42; >>>>>>>>> ? ? ? ? ? ? ~^~~~~ >>>>>>>>> >>>>>>>>> But then with my patch we get an extra diagnostic after the above warning/notes: >>>>>>>>> >>>>>>>>> conv.cpp:3:18: warning: implicit conversion from 'int' to 'bool' >>>>>>>>> changes value from 42 to true [-Wconstant-conversion] >>>>>>>>> ?return f1() && 42; >>>>>>>>> ? ? ? ? ? ? ?~~ ^~ >>>>>>>>> >>>>>>>>> which isn't great - since we already gave a much more specific >>>>>>>>> diagnosis of the problem in the first warning. If there's some nice >>>>>>>>> way that we could suppress the second one whenever the first one is >>>>>>>>> provided (unless the first one is only a warning and the second is >>>>>>>>> -Werror'd?) I'd be happy to implement that. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Another thing I noticed as I was exploring this. We have a warning for >>>>>>>>> float-literal-to-int such as: >>>>>>>>> >>>>>>>>> conv.cpp:2:9: warning: implicit conversion turns literal >>>>>>>>> floating-point number into integer: 'double' to 'int' >>>>>>>>> [-Wliteral-conversion] >>>>>>>>> int i = 3.1415; >>>>>>>>> ? ?~ ? ^~~~~~ >>>>>>>>> >>>>>>>>> But this warning is off-by-default. Why is that? It's already >>>>>>>>> relatively conservative (allowing things like : "int i = 3.0" because >>>>>>>>> 3.0 converts to an int without loss of precision) - though it's not a >>>>>>>>> DiagnoseRuntimeBehavior, which it could be changed to (to be >>>>>>>>> consistent with similar things for integers like "unsigned char c = >>>>>>>>> 256"). >>>>>>>>> >>>>>>>>> Or is it really that common to deliberately use floating point >>>>>>>>> literals to initialize integer values? >>>>>>>>> >>>>>>>>> _______________________________________________ >>>>>>>>> cfe-commits mailing list >>>>>>>>> cfe-commits at cs.uiuc.edu >>>>>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >>>>>>>>> From chandlerc at google.com Tue May 15 12:03:14 2012 From: chandlerc at google.com (Chandler Carruth) Date: Tue, 15 May 2012 11:03:14 -0600 Subject: [cfe-commits] ThreadSanitizer library and linker flags: please review In-Reply-To: References: Message-ID: Looks good. On Tue, May 15, 2012 at 9:38 AM, Kostya Serebryany wrote: > Hello, > > Please review the following patch which adds ThreadSanitizer (tsan) linker > flags on Linux > and also copies the tsan-rt into the appropriate place at build time. > This mimics similar parts related to AddressSanitizer. > > http://codereview.appspot.com/6197087/ > > Thanks, > > --kcc > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/0b725f6f/attachment.html From jediknil at belkadan.com Tue May 15 12:06:16 2012 From: jediknil at belkadan.com (Jordan Rose) Date: Tue, 15 May 2012 13:06:16 -0400 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sema/array-init.c test/Sema/knr-def-call.c test/SemaCXX/bool.cpp test/SemaCXX/conversion.cpp test/SemaCXX/expressions.cpp test/SemaCXX/overload-call.cpp test/SemaCXX/warn-literal-conversion.cpp test/SemaTemplate/member-template-access-expr.cpp In-Reply-To: <20120515165637.367572A6C065@llvm.org> References: <20120515165637.367572A6C065@llvm.org> Message-ID: On May 15, 2012, at 12:56, David Blaikie wrote: > + SmallString<16> PrettySourceValue; > + Value.toString(PrettySourceValue); > + std::string PrettyTargetValue; > + if (T->isSpecificBuiltinType(BuiltinType::Bool)) > + PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; > + else > + PrettyTargetValue = IntegerValue.toString(10); > + Why the std::string for the target? SmallString<16> PrettyTargetValue; if (T->isSpecificBuiltinType(BuiltinType::Bool)) PrettyTargetValue = (IntegerValue == 0) ? "false" : "true"; else IntegerValue.toString(PrettyTargetValue); (The base defaults to 10 for this version of toString.) Jordy From dblaikie at gmail.com Tue May 15 12:18:27 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 17:18:27 -0000 Subject: [cfe-commits] r156827 - /cfe/trunk/lib/Sema/SemaChecking.cpp Message-ID: <20120515171827.C9EF42A6C065@llvm.org> Author: dblaikie Date: Tue May 15 12:18:27 2012 New Revision: 156827 URL: http://llvm.org/viewvc/llvm-project?rev=156827&view=rev Log: Changing std::string to SmallString for r156826. Based on code review feedback by Jordan Rose. Modified: cfe/trunk/lib/Sema/SemaChecking.cpp Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156827&r1=156826&r2=156827&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 12:18:27 2012 @@ -4084,11 +4084,11 @@ SmallString<16> PrettySourceValue; Value.toString(PrettySourceValue); - std::string PrettyTargetValue; + SmallString<16> PrettyTargetValue; if (T->isSpecificBuiltinType(BuiltinType::Bool)) PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; else - PrettyTargetValue = IntegerValue.toString(10); + IntegerValue.toString(PrettyTargetValue); S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) << FL->getType() << T.getUnqualifiedType() << PrettySourceValue From dblaikie at gmail.com Tue May 15 12:19:49 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 10:19:49 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem Message-ID: On Tue, May 15, 2012 at 10:06 AM, Jordan Rose wrote: > > On May 15, 2012, at 12:56, David Blaikie wrote: > >> + ?SmallString<16> PrettySourceValue; >> + ?Value.toString(PrettySourceValue); >> + ?std::string PrettyTargetValue; >> + ?if (T->isSpecificBuiltinType(BuiltinType::Bool)) >> + ? ?PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; >> + ?else >> + ? ?PrettyTargetValue = IntegerValue.toString(10); >> + > > Why the std::string for the target? > > SmallString<16> PrettyTargetValue; > if (T->isSpecificBuiltinType(BuiltinType::Bool)) > ?PrettyTargetValue = (IntegerValue == 0) ? "false" : "true"; > else > ?IntegerValue.toString(PrettyTargetValue); > > (The base defaults to 10 for this version of toString.) Handy - just didn't see the toString(SmallString) version. Changed as suggested in r156827. Thanks, - David From rjmccall at apple.com Tue May 15 12:20:33 2012 From: rjmccall at apple.com (John McCall) Date: Tue, 15 May 2012 10:20:33 -0700 Subject: [cfe-commits] r156825 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaObjC/no-ivar-in-interface-block.m In-Reply-To: <20120515163304.D49EA2A6C065@llvm.org> References: <20120515163304.D49EA2A6C065@llvm.org> Message-ID: <4449D80B-7127-434E-9A91-8579FD2814FA@apple.com> On May 15, 2012, at 9:33 AM, Fariborz Jahanian wrote: > Author: fjahanian > Date: Tue May 15 11:33:04 2012 > New Revision: 156825 > > URL: http://llvm.org/viewvc/llvm-project?rev=156825&view=rev > Log: > objective-c nonfragile abi: discourage ivar declarations > in @interface by issuing warning (off by default) under > opt'ed in flag -Winterface-block-ivar. // rdar://10763173 The 'block' doesn't seem to be adding much. -Winterface-ivars? John. From grosbach at apple.com Tue May 15 12:36:07 2012 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 15 May 2012 17:36:07 -0000 Subject: [cfe-commits] r156830 - /cfe/trunk/tools/driver/cc1as_main.cpp Message-ID: <20120515173607.6D1232A6C065@llvm.org> Author: grosbach Date: Tue May 15 12:36:07 2012 New Revision: 156830 URL: http://llvm.org/viewvc/llvm-project?rev=156830&view=rev Log: Allow MCCodeEmitter access to the target MCRegisterInfo. Add MRI to the createMCCodeEmitter() call. Modified: cfe/trunk/tools/driver/cc1as_main.cpp Modified: cfe/trunk/tools/driver/cc1as_main.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/cc1as_main.cpp?rev=156830&r1=156829&r2=156830&view=diff ============================================================================== --- cfe/trunk/tools/driver/cc1as_main.cpp (original) +++ cfe/trunk/tools/driver/cc1as_main.cpp Tue May 15 12:36:07 2012 @@ -328,7 +328,7 @@ MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (Opts.ShowEncoding) { - CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx); + CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MAB = TheTarget->createMCAsmBackend(Opts.Triple); } Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true, @@ -342,7 +342,7 @@ } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); - MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx); + MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(Opts.Triple); Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out, CE, Opts.RelaxAll, From thakis at chromium.org Tue May 15 12:39:59 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 15 May 2012 10:39:59 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem Message-ID: Hi David, as mentioned on the thread for this warning, with this change clang warns on #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) // ... if ( ! YY_CURRENT_BUFFER ) { // ... } with this message: ./pp_lex.cpp:784:10: error: implicit conversion of NULL constant to 'bool' [-Werror,-Wnull-conversion] if ( ! YY_CURRENT_BUFFER ) { ^~~~~~~~~~~~~~~~~ ./pp_lex.cpp:295:29: note: expanded from macro 'YY_CURRENT_BUFFER' : NULL) ^ This looks like valid code to me. Nico On Tue, May 15, 2012 at 9:56 AM, David Blaikie wrote: > Author: dblaikie > Date: Tue May 15 11:56:36 2012 > New Revision: 156826 > > URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev > Log: > Improve some of the conversion warnings to fire on conversion to bool. > > Moves the bool bail-out down a little in SemaChecking - so now > -Wnull-conversion and -Wliteral-conversion can fire when the target type is > bool. > > Also improve the wording/details in the -Wliteral-conversion warning to > match > the -Wconstant-conversion. > > Modified: > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/lib/Sema/SemaChecking.cpp > cfe/trunk/test/Analysis/array-struct-region.c > cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp > cfe/trunk/test/CXX/temp/temp.spec/p5.cpp > cfe/trunk/test/PCH/exprs.h > cfe/trunk/test/Sema/array-init.c > cfe/trunk/test/Sema/knr-def-call.c > cfe/trunk/test/SemaCXX/bool.cpp > cfe/trunk/test/SemaCXX/conversion.cpp > cfe/trunk/test/SemaCXX/expressions.cpp > cfe/trunk/test/SemaCXX/overload-call.cpp > cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp > cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 > 11:56:36 2012 > @@ -1781,8 +1781,7 @@ > "implicit truncation from %2 to bitfield changes value from %0 to %1">, > InGroup; > def warn_impcast_literal_float_to_integer : Warning< > - "implicit conversion turns literal floating-point number into integer: " > - "%0 to %1">, > + "implicit conversion from %0 to %1 changes value from %2 to %3">, > InGroup; > def warn_impcast_string_literal_to_bool : Warning< > "implicit conversion turns string literal into bool: %0 to %1">, > > Modified: cfe/trunk/lib/Sema/SemaChecking.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) > +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 > @@ -22,6 +22,7 @@ > #include "clang/AST/CharUnits.h" > #include "clang/AST/DeclCXX.h" > #include "clang/AST/DeclObjC.h" > +#include "clang/AST/Expr.h" > #include "clang/AST/ExprCXX.h" > #include "clang/AST/ExprObjC.h" > #include "clang/AST/EvaluatedExprVisitor.h" > @@ -4081,8 +4082,17 @@ > == llvm::APFloat::opOK && isExact) > return; > > + SmallString<16> PrettySourceValue; > + Value.toString(PrettySourceValue); > + std::string PrettyTargetValue; > + if (T->isSpecificBuiltinType(BuiltinType::Bool)) > + PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; > + else > + PrettyTargetValue = IntegerValue.toString(10); > + > S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) > - << FL->getType() << T << FL->getSourceRange() << > SourceRange(CContext); > + << FL->getType() << T.getUnqualifiedType() << PrettySourceValue > + << PrettyTargetValue << FL->getSourceRange() << SourceRange(CContext); > } > > std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) > { > @@ -4149,7 +4159,6 @@ > } > } > } > - return; // Other casts to bool are not checked. > } > > // Strip vector types. > @@ -4213,7 +4222,7 @@ > } > > // If the target is integral, always warn. > - if ((TargetBT && TargetBT->isInteger())) { > + if (TargetBT && TargetBT->isInteger()) { > if (S.SourceMgr.isInSystemMacro(CC)) > return; > > @@ -4247,6 +4256,11 @@ > return; > } > > + // TODO: remove this early return once the false positives for > constant->bool > + // in templates, macros, etc, are reduced or removed. > + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) > + return; > + > IntRange SourceRange = GetExprRange(S.Context, E); > IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, > Target); > > > Modified: cfe/trunk/test/Analysis/array-struct-region.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/Analysis/array-struct-region.c (original) > +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 11:56:36 2012 > @@ -25,8 +25,8 @@ > } > > void nested_compound_literals(int rad) { > - int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // > expected-warning 6 {{implicit conversion turns literal floating-point > number into integer}} > - {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // > expected-warning 6 {{implicit conversion turns literal floating-point > number into integer}} > + int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // > expected-warning 6 {{implicit conversion from 'double' to 'int' changes > value from}} > + {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // > expected-warning 6 {{implicit conversion from 'double' to 'int' changes > value from}} > int a; > > for (a = 0; a < 6; ++a) { > > Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp (original) > +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May 15 > 11:56:36 2012 > @@ -4,7 +4,7 @@ > > bool b = !0; > > -bool b2 = !1.2; > +bool b2 = !1.2; //expected-warning{{implicit conversion from 'double' to > 'bool' changes value from 1.2 to true}} > > bool b3 = !4; > > > Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) > +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 2012 > @@ -14,7 +14,7 @@ > }; > > template > -T X0::value = 3.14; // expected-warning{{implicit conversion turns > literal floating-point number into integer}} > +T X0::value = 3.14; // expected-warning{{implicit conversion from > 'double' to 'int' changes value from 3.14 to 3}} > > template struct X0; // expected-note{{previous explicit > instantiation}} \ > expected-note{{requested here}} > > Modified: cfe/trunk/test/PCH/exprs.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/PCH/exprs.h (original) > +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 > @@ -87,7 +87,7 @@ > int x; > float y; > } designated_inits[3] = { [0].y = 17, > - [2].x = 12.3, // expected-warning {{implicit > conversion turns literal floating-point number into integer}} > + [2].x = 12.3, // expected-warning {{implicit > conversion from 'double' to 'int' changes value from 12.3 to 12}} > 3.5 }; > > // TypesCompatibleExpr > > Modified: cfe/trunk/test/Sema/array-init.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/Sema/array-init.c (original) > +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 > @@ -50,7 +50,7 @@ > > static long x2[3] = { 1.0, > "abc", // expected-warning{{incompatible pointer > to integer conversion initializing 'long' with an expression of type 'char > [4]'}} > - 5.8 }; // expected-warning {{implicit conversion > turns literal floating-point number into integer}} > + 5.8 }; // expected-warning {{implicit conversion > from 'double' to 'long' changes value from 5.8 to 5}} > } > > void test() { > > Modified: cfe/trunk/test/Sema/knr-def-call.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/Sema/knr-def-call.c (original) > +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 > @@ -36,6 +36,6 @@ > } > > void use_proto() { > - proto(42.1); // expected-warning{{implicit conversion turns literal > floating-point number into integer}} > - (&proto)(42.1); // expected-warning{{implicit conversion turns literal > floating-point number into integer}} > + proto(42.1); // expected-warning{{implicit conversion from 'double' to > 'int' changes value from 42.1 to 42}} > + (&proto)(42.1); // expected-warning{{implicit conversion from 'double' > to 'int' changes value from 42.1 to 42}} > } > > Modified: cfe/trunk/test/SemaCXX/bool.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/bool.cpp (original) > +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 -fsyntax-only -verify %s > +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s > > // Bool literals can be enum values. > enum { > > Modified: cfe/trunk/test/SemaCXX/conversion.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/conversion.cpp (original) > +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 > @@ -65,7 +65,7 @@ > int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL > constant to 'int'}} > int d; > d = ((((NULL)))); // expected-warning {{implicit conversion of NULL > constant to 'int'}} > - bool bl = NULL; // FIXME: this should warn but we currently suppress a > bunch of conversion-to-bool warnings including this one > + bool bl = NULL; // expected-warning {{implicit conversion of NULL > constant to 'bool'}} > char ch = NULL; // expected-warning {{implicit conversion of NULL > constant to 'char'}} > unsigned char uch = NULL; // expected-warning {{implicit conversion of > NULL constant to 'unsigned char'}} > short sh = NULL; // expected-warning {{implicit conversion of NULL > constant to 'short'}} > @@ -104,3 +104,12 @@ > tmpl2(); > } > } > + > +namespace test5 { > + template > + void func() { > + bool b = I; > + } > + > + template void func<3>(); > +} > > Modified: cfe/trunk/test/SemaCXX/expressions.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/expressions.cpp (original) > +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 -fsyntax-only -verify %s > +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s > > void choice(int); > int choice(bool); > > Modified: cfe/trunk/test/SemaCXX/overload-call.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) > +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 2012 > @@ -233,7 +233,7 @@ > > void intref_test() { > float* ir1 = intref(5); > - float* ir2 = intref(5.5); // expected-warning{{implicit conversion > turns literal floating-point number into integer}} > + float* ir2 = intref(5.5); // expected-warning{{implicit conversion from > 'double' to 'int' changes value from 5.5 to 5}} > } > > void derived5(C&); // expected-note{{candidate function not viable: > cannot bind base class object of type 'A' to derived class reference 'C &' > for 1st argument}} > > Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) > +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 11:56:36 > 2012 > @@ -5,29 +5,29 @@ > // Warn when a literal float or double is assigned or bound to an integer. > void test0() { > // Float > - int y0 = 1.2222F; // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > - int y1 = (1.2222F); // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > - int y2 = (((1.2222F))); // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > - int y3 = 12E-1F; // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > - int y4 = 1.23E1F; // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > + int y0 = 1.2222F; // expected-warning {{implicit conversion from > 'float' to 'int' changes value from 1.2222 to 1}} > + int y1 = (1.2222F); // expected-warning {{implicit conversion from > 'float' to 'int' changes value from 1.2222 to 1}} > + int y2 = (((1.2222F))); // expected-warning {{implicit conversion from > 'float' to 'int' changes value from 1.2222 to 1}} > + int y3 = 12E-1F; // expected-warning {{implicit conversion from 'float' > to 'int' changes value from 1.2 to 1}} > + int y4 = 1.23E1F; // expected-warning {{implicit conversion from > 'float' to 'int' changes value from 12.3 to 12}} > // Double > - int y5 = 1.2222; // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > - int y6 = 12E-1; // expected-warning {{implicit conversion turns literal > floating-point number into integer}} > - int y7 = 1.23E1; // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > - int y8 = (1.23E1); // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > + int y5 = 1.2222; // expected-warning {{implicit conversion from > 'double' to 'int' changes value from 1.2222 to 1}} > + int y6 = 12E-1; // expected-warning {{implicit conversion from 'double' > to 'int' changes value from 1.2 to 1}} > + int y7 = 1.23E1; // expected-warning {{implicit conversion from > 'double' to 'int' changes value from 12.3 to 12}} > + int y8 = (1.23E1); // expected-warning {{implicit conversion from > 'double' to 'int' changes value from 12.3 to 12}} > > // Test assignment to an existing variable. > - y8 = 2.22F; // expected-warning {{implicit conversion turns literal > floating-point number into integer}} > + y8 = 2.22F; // expected-warning {{implicit conversion from 'float' to > 'int' changes value from 2.22 to 2}} > > // Test direct initialization. > - int y9(1.23F); // expected-warning {{implicit conversion turns literal > floating-point number into integer}} > + int y9(1.23F); // expected-warning {{implicit conversion from 'float' > to 'int' changes value from 1.23 to 1}} > > // Test passing a literal floating-point value to a function that takes > an integer. > - foo(1.2F); // expected-warning {{implicit conversion turns literal > floating-point number into integer}} > + foo(1.2F); // expected-warning {{implicit conversion from 'float' to > 'int' changes value from 1.2 to 1}} > > - int y10 = -1.2F; // expected-warning {{implicit conversion turns > literal floating-point number into integer}} > + int y10 = -1.2F; // expected-warning {{implicit conversion from > 'float' to 'int' changes value from 1.2 to 1}} > > - // -Wconversion-literal does NOT catch const values. > + // -Wliteral-conversion does NOT catch const values. > // (-Wconversion DOES catch them.) > static const float sales_tax_rate = .095F; > int z = sales_tax_rate; > > Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original) > +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue May 15 > 11:56:36 2012 > @@ -60,7 +60,7 @@ > > void test_X1(X1 x1) { > float *fp1 = x1.f1<>(17); > - float *fp2 = x1.f1(3.14); // expected-warning {{implicit > conversion turns literal floating-point number into integer}} > + float *fp2 = x1.f1(3.14); // expected-warning {{implicit > conversion from 'double' to 'int' changes value from 3.14 to 3}} > int *ip1 = x1.f1(17); > float *ip2 = x1.f1(3.14); > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/c2998c1b/attachment-0001.html From jediknil at belkadan.com Tue May 15 12:42:35 2012 From: jediknil at belkadan.com (Jordan Rose) Date: Tue, 15 May 2012 13:42:35 -0400 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics In-Reply-To: References: Message-ID: I like this a lot! How does it fare against more complicated macros, though? #define CASE1 case 1 #define CASE(x) case x #define MULTI_CASE(x,y) case x: case y: switch (x) { CASE1: break; CASE(1U): break; MULTI_CASE(2,2): break; case 2: break; } As for multi-line case statements, I'd be inclined to simply fall back to the dumb version of the warning, rather than trying to format it nicely in the output. We already have a note showing where the relevant code is. And I wouldn't be worried about casts -- if they're there, the user probably thought they were making a difference. (I'd actually be more worried about things like parens, but I'd err on the side of including them anyway.) Jordy On May 15, 2012, at 12:05, Terry Long wrote: > Hi all, > > This patch mostly inspired by http://llvm.org/bugs/show_bug.cgi?id=9243 -- poor "duplicate case" diagnostic with enums > > Previously the diagnostic for duplicate case values in switch statements was always something like "duplicate case value '5'" > > What my patch changes: > When the duplicate case is exactly the same in textual representation (in source code), the diagnostic will use that exact text in the diagnostic. > e.g. using MyEnum twice gives the diagnostic "duplicate case value 'MyEnum'" > > If the textual representations differ, the new diagnostic explicitly states they are equal to the same value > e.g. using MyEnum (equal to 5) and 5, the diagnostic displays "duplicate case value: 'MyEnum' and '5' both equal '5'" > > The patch does the same for any valid expression in a case statement (including macros, const ints, char literals, etc.). > > Concerns with my patch: > 1. Multiline case statements, although unusual, will be printed out in the diagnostic exactly as they appear in the source. I'm not sure if this is a real issue. Possible solution would be checking if it spans multiple lines. If so, the diagnostic could be "duplicate case value: both expressions equal 'x'". > e.g. > case 1 + > 2 + > 3: > > 2. If a case statement includes a cast, the cast will also be included in the diagnostic. Sometimes this inclusion is helpful, for example in situations where the cast will cause an overflow (such as "(char)256" and "0"). Other times it is irrelevant, such as "(int)7" and "7", where a simple diagnostic of "duplicate case value '7'" makes more sense. I'm also not sure if this is an issue. > > > Thanks! > > Terry Long > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From dblaikie at gmail.com Tue May 15 12:43:32 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 10:43:32 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 10:39 AM, Nico Weber wrote: > Hi David, > > as mentioned on the thread for this warning, with this change clang warns on Ah, right - sorry, I'd forgotten that even the NULL case had some problems. I'll see what I can do to tidy this case up sooner rather than later. Thanks for the reminder. - David > > #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ > ? ? ? ? ? ? ? ? ? ? ? ? ? : NULL) > > // ... > > if ( ! YY_CURRENT_BUFFER ) { > // ... > } > > with this message: > > ./pp_lex.cpp:784:10: error: implicit conversion of NULL constant to 'bool' > [-Werror,-Wnull-conversion] > ? ? ? ? ? ? ? ? if ( ! YY_CURRENT_BUFFER ) { > ? ? ? ? ? ? ? ? ? ? ? ?^~~~~~~~~~~~~~~~~ > ./pp_lex.cpp:295:29: note: expanded from macro 'YY_CURRENT_BUFFER' > ? ? ? ? ? ? ? ? ? ? ? ? ? : NULL) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^ > > > This looks like valid code to me. > > Nico > > On Tue, May 15, 2012 at 9:56 AM, David Blaikie wrote: >> >> Author: dblaikie >> Date: Tue May 15 11:56:36 2012 >> New Revision: 156826 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev >> Log: >> Improve some of the conversion warnings to fire on conversion to bool. >> >> Moves the bool bail-out down a little in SemaChecking - so now >> -Wnull-conversion and -Wliteral-conversion can fire when the target type >> is >> bool. >> >> Also improve the wording/details in the -Wliteral-conversion warning to >> match >> the -Wconstant-conversion. >> >> Modified: >> ? ?cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> ? ?cfe/trunk/lib/Sema/SemaChecking.cpp >> ? ?cfe/trunk/test/Analysis/array-struct-region.c >> ? ?cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >> ? ?cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >> ? ?cfe/trunk/test/PCH/exprs.h >> ? ?cfe/trunk/test/Sema/array-init.c >> ? ?cfe/trunk/test/Sema/knr-def-call.c >> ? ?cfe/trunk/test/SemaCXX/bool.cpp >> ? ?cfe/trunk/test/SemaCXX/conversion.cpp >> ? ?cfe/trunk/test/SemaCXX/expressions.cpp >> ? ?cfe/trunk/test/SemaCXX/overload-call.cpp >> ? ?cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >> ? ?cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 >> 11:56:36 2012 >> @@ -1781,8 +1781,7 @@ >> ? "implicit truncation from %2 to bitfield changes value from %0 to %1">, >> ? InGroup; >> ?def warn_impcast_literal_float_to_integer : Warning< >> - ?"implicit conversion turns literal floating-point number into integer: >> " >> - ?"%0 to %1">, >> + ?"implicit conversion from %0 to %1 changes value from %2 to %3">, >> ? InGroup; >> ?def warn_impcast_string_literal_to_bool : Warning< >> ? "implicit conversion turns string literal into bool: %0 to %1">, >> >> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 >> @@ -22,6 +22,7 @@ >> ?#include "clang/AST/CharUnits.h" >> ?#include "clang/AST/DeclCXX.h" >> ?#include "clang/AST/DeclObjC.h" >> +#include "clang/AST/Expr.h" >> ?#include "clang/AST/ExprCXX.h" >> ?#include "clang/AST/ExprObjC.h" >> ?#include "clang/AST/EvaluatedExprVisitor.h" >> @@ -4081,8 +4082,17 @@ >> ? ? ? == llvm::APFloat::opOK && isExact) >> ? ? return; >> >> >> + ?SmallString<16> PrettySourceValue; >> + ?Value.toString(PrettySourceValue); >> + ?std::string PrettyTargetValue; >> + ?if (T->isSpecificBuiltinType(BuiltinType::Bool)) >> + ? ?PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; >> + ?else >> + ? ?PrettyTargetValue = IntegerValue.toString(10); >> + >> ? S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) >> - ? ?<< FL->getType() << T << FL->getSourceRange() << >> SourceRange(CContext); >> + ? ?<< FL->getType() << T.getUnqualifiedType() << PrettySourceValue >> + ? ?<< PrettyTargetValue << FL->getSourceRange() << >> SourceRange(CContext); >> ?} >> >> ?std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) >> { >> @@ -4149,7 +4159,6 @@ >> ? ? ? ? } >> ? ? ? } >> ? ? } >> - ? ?return; // Other casts to bool are not checked. >> ? } >> >> ? // Strip vector types. >> @@ -4213,7 +4222,7 @@ >> ? ? } >> >> ? ? // If the target is integral, always warn. >> - ? ?if ((TargetBT && TargetBT->isInteger())) { >> + ? ?if (TargetBT && TargetBT->isInteger()) { >> ? ? ? if (S.SourceMgr.isInSystemMacro(CC)) >> ? ? ? ? return; >> >> @@ -4247,6 +4256,11 @@ >> ? ? return; >> ? } >> >> + ?// TODO: remove this early return once the false positives for >> constant->bool >> + ?// in templates, macros, etc, are reduced or removed. >> + ?if (Target->isSpecificBuiltinType(BuiltinType::Bool)) >> + ? ?return; >> + >> ? IntRange SourceRange = GetExprRange(S.Context, E); >> ? IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, >> Target); >> >> >> Modified: cfe/trunk/test/Analysis/array-struct-region.c >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/Analysis/array-struct-region.c (original) >> +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 11:56:36 2012 >> @@ -25,8 +25,8 @@ >> ?} >> >> ?void nested_compound_literals(int rad) { >> - ?int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, ?// >> expected-warning 6 {{implicit conversion turns literal floating-point number >> into integer}} >> - ? ? ? ? ? ? ? ? ? {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >> expected-warning 6 {{implicit conversion turns literal floating-point number >> into integer}} >> + ?int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, ?// >> expected-warning 6 {{implicit conversion from 'double' to 'int' changes >> value from}} >> + ? ? ? ? ? ? ? ? ? {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >> expected-warning 6 {{implicit conversion from 'double' to 'int' changes >> value from}} >> ? int a; >> >> ? for (a = 0; a < 6; ++a) { >> >> Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp (original) >> +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May 15 >> 11:56:36 2012 >> @@ -4,7 +4,7 @@ >> >> ?bool b = !0; >> >> -bool b2 = !1.2; >> +bool b2 = !1.2; //expected-warning{{implicit conversion from 'double' to >> 'bool' changes value from 1.2 to true}} >> >> ?bool b3 = !4; >> >> >> Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) >> +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 2012 >> @@ -14,7 +14,7 @@ >> ?}; >> >> ?template >> -T X0::value = 3.14; // expected-warning{{implicit conversion turns >> literal floating-point number into integer}} >> +T X0::value = 3.14; // expected-warning{{implicit conversion from >> 'double' to 'int' changes value from 3.14 to 3}} >> >> ?template struct X0; // expected-note{{previous explicit >> instantiation}} \ >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? expected-note{{requested here}} >> >> Modified: cfe/trunk/test/PCH/exprs.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/PCH/exprs.h (original) >> +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 >> @@ -87,7 +87,7 @@ >> ? int x; >> ? float y; >> ?} designated_inits[3] = { [0].y = 17, >> - ? ? ? ? ? ? ? ? ? ? ? ? ?[2].x = 12.3, // expected-warning {{implicit >> conversion turns literal floating-point number into integer}} >> + ? ? ? ? ? ? ? ? ? ? ? ? ?[2].x = 12.3, // expected-warning {{implicit >> conversion from 'double' to 'int' changes value from 12.3 to 12}} >> ? ? ? ? ? ? ? ? ? ? ? ? ? 3.5 }; >> >> ?// TypesCompatibleExpr >> >> Modified: cfe/trunk/test/Sema/array-init.c >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/Sema/array-init.c (original) >> +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 >> @@ -50,7 +50,7 @@ >> >> ? static long x2[3] = { 1.0, >> ? ? ? ? ? ? ? ? ? ? ? ? "abc", // expected-warning{{incompatible pointer >> to integer conversion initializing 'long' with an expression of type 'char >> [4]'}} >> - ? ? ? ? ? ? ? ? ? ? ? ? 5.8 }; // expected-warning {{implicit conversion >> turns literal floating-point number into integer}} >> + ? ? ? ? ? ? ? ? ? ? ? ? 5.8 }; // expected-warning {{implicit conversion >> from 'double' to 'long' changes value from 5.8 to 5}} >> ?} >> >> ?void test() { >> >> Modified: cfe/trunk/test/Sema/knr-def-call.c >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/Sema/knr-def-call.c (original) >> +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 >> @@ -36,6 +36,6 @@ >> ?} >> >> ?void use_proto() { >> - ?proto(42.1); // expected-warning{{implicit conversion turns literal >> floating-point number into integer}} >> - ?(&proto)(42.1); // expected-warning{{implicit conversion turns literal >> floating-point number into integer}} >> + ?proto(42.1); // expected-warning{{implicit conversion from 'double' to >> 'int' changes value from 42.1 to 42}} >> + ?(&proto)(42.1); // expected-warning{{implicit conversion from 'double' >> to 'int' changes value from 42.1 to 42}} >> ?} >> >> Modified: cfe/trunk/test/SemaCXX/bool.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/SemaCXX/bool.cpp (original) >> +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 >> @@ -1,4 +1,4 @@ >> -// RUN: %clang_cc1 -fsyntax-only -verify %s >> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >> >> ?// Bool literals can be enum values. >> ?enum { >> >> Modified: cfe/trunk/test/SemaCXX/conversion.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/SemaCXX/conversion.cpp (original) >> +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 >> @@ -65,7 +65,7 @@ >> ? int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL >> constant to 'int'}} >> ? int d; >> ? d = ((((NULL)))); // expected-warning {{implicit conversion of NULL >> constant to 'int'}} >> - ?bool bl = NULL; // FIXME: this should warn but we currently suppress a >> bunch of conversion-to-bool warnings including this one >> + ?bool bl = NULL; // expected-warning {{implicit conversion of NULL >> constant to 'bool'}} >> ? char ch = NULL; // expected-warning {{implicit conversion of NULL >> constant to 'char'}} >> ? unsigned char uch = NULL; // expected-warning {{implicit conversion of >> NULL constant to 'unsigned char'}} >> ? short sh = NULL; // expected-warning {{implicit conversion of NULL >> constant to 'short'}} >> @@ -104,3 +104,12 @@ >> ? ? tmpl2(); >> ? } >> ?} >> + >> +namespace test5 { >> + ?template >> + ?void func() { >> + ? ?bool b = I; >> + ?} >> + >> + ?template void func<3>(); >> +} >> >> Modified: cfe/trunk/test/SemaCXX/expressions.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/SemaCXX/expressions.cpp (original) >> +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 >> @@ -1,4 +1,4 @@ >> -// RUN: %clang_cc1 -fsyntax-only -verify %s >> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >> >> ?void choice(int); >> ?int choice(bool); >> >> Modified: cfe/trunk/test/SemaCXX/overload-call.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) >> +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 2012 >> @@ -233,7 +233,7 @@ >> >> ?void intref_test() { >> ? float* ir1 = intref(5); >> - ?float* ir2 = intref(5.5); // expected-warning{{implicit conversion >> turns literal floating-point number into integer}} >> + ?float* ir2 = intref(5.5); // expected-warning{{implicit conversion from >> 'double' to 'int' changes value from 5.5 to 5}} >> ?} >> >> ?void derived5(C&); // expected-note{{candidate function not viable: >> cannot bind base class object of type 'A' to derived class reference 'C &' >> for 1st argument}} >> >> Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) >> +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 11:56:36 >> 2012 >> @@ -5,29 +5,29 @@ >> ?// Warn when a literal float or double is assigned or bound to an >> integer. >> ?void test0() { >> ? // Float >> - ?int y0 = 1.2222F; // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> - ?int y1 = (1.2222F); // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> - ?int y2 = (((1.2222F))); // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> - ?int y3 = 12E-1F; // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> - ?int y4 = 1.23E1F; // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> + ?int y0 = 1.2222F; // expected-warning {{implicit conversion from >> 'float' to 'int' changes value from 1.2222 to 1}} >> + ?int y1 = (1.2222F); // expected-warning {{implicit conversion from >> 'float' to 'int' changes value from 1.2222 to 1}} >> + ?int y2 = (((1.2222F))); // expected-warning {{implicit conversion from >> 'float' to 'int' changes value from 1.2222 to 1}} >> + ?int y3 = 12E-1F; // expected-warning {{implicit conversion from 'float' >> to 'int' changes value from 1.2 to 1}} >> + ?int y4 = 1.23E1F; // expected-warning {{implicit conversion from >> 'float' to 'int' changes value from 12.3 to 12}} >> ? // Double >> - ?int y5 = 1.2222; // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> - ?int y6 = 12E-1; // expected-warning {{implicit conversion turns literal >> floating-point number into integer}} >> - ?int y7 = 1.23E1; // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> - ?int y8 = (1.23E1); // expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> + ?int y5 = 1.2222; // expected-warning {{implicit conversion from >> 'double' to 'int' changes value from 1.2222 to 1}} >> + ?int y6 = 12E-1; // expected-warning {{implicit conversion from 'double' >> to 'int' changes value from 1.2 to 1}} >> + ?int y7 = 1.23E1; // expected-warning {{implicit conversion from >> 'double' to 'int' changes value from 12.3 to 12}} >> + ?int y8 = (1.23E1); // expected-warning {{implicit conversion from >> 'double' to 'int' changes value from 12.3 to 12}} >> >> ? // Test assignment to an existing variable. >> - ?y8 = 2.22F; // expected-warning {{implicit conversion turns literal >> floating-point number into integer}} >> + ?y8 = 2.22F; // expected-warning {{implicit conversion from 'float' to >> 'int' changes value from 2.22 to 2}} >> >> ? // Test direct initialization. >> - ?int y9(1.23F); // expected-warning {{implicit conversion turns literal >> floating-point number into integer}} >> + ?int y9(1.23F); // expected-warning {{implicit conversion from 'float' >> to 'int' changes value from 1.23 to 1}} >> >> ? // Test passing a literal floating-point value to a function that takes >> an integer. >> - ?foo(1.2F); // expected-warning {{implicit conversion turns literal >> floating-point number into integer}} >> + ?foo(1.2F); // expected-warning {{implicit conversion from 'float' to >> 'int' changes value from 1.2 to 1}} >> >> - ?int y10 = -1.2F; ?// expected-warning {{implicit conversion turns >> literal floating-point number into integer}} >> + ?int y10 = -1.2F; ?// expected-warning {{implicit conversion from >> 'float' to 'int' changes value from 1.2 to 1}} >> >> - ?// -Wconversion-literal does NOT catch const values. >> + ?// -Wliteral-conversion does NOT catch const values. >> ? // (-Wconversion DOES catch them.) >> ? static const float sales_tax_rate = .095F; >> ? int z = sales_tax_rate; >> >> Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original) >> +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue May 15 >> 11:56:36 2012 >> @@ -60,7 +60,7 @@ >> >> ?void test_X1(X1 x1) { >> ? float *fp1 = x1.f1<>(17); >> - ?float *fp2 = x1.f1(3.14); // expected-warning {{implicit >> conversion turns literal floating-point number into integer}} >> + ?float *fp2 = x1.f1(3.14); // expected-warning {{implicit >> conversion from 'double' to 'int' changes value from 3.14 to 3}} >> ? int *ip1 = x1.f1(17); >> ? float *ip2 = x1.f1(3.14); >> >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > From fjahanian at apple.com Tue May 15 12:43:16 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Tue, 15 May 2012 17:43:16 -0000 Subject: [cfe-commits] r156831 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaObjC/no-ivar-in-interface-block.m Message-ID: <20120515174316.C0B7E2A6C065@llvm.org> Author: fjahanian Date: Tue May 15 12:43:16 2012 New Revision: 156831 URL: http://llvm.org/viewvc/llvm-project?rev=156831&view=rev Log: Remove word 'block' from option and diagnostic I added in r156825. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156831&r1=156830&r2=156831&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 12:43:16 2012 @@ -3023,9 +3023,9 @@ def err_duplicate_member : Error<"duplicate member %0">; def err_misplaced_ivar : Error< "ivars may not be placed in %select{categories|class extension}0">; -def warn_ivar_in_interface_block : Warning< - "declaration of ivar in the interface block is deprecated">, - InGroup>, DefaultIgnore; +def warn_ivars_in_interface : Warning< + "declaration of ivars in the interface is deprecated">, + InGroup>, DefaultIgnore; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=156831&r1=156830&r2=156831&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue May 15 12:43:16 2012 @@ -9543,7 +9543,7 @@ if (LangOpts.ObjCNonFragileABI2 && !NewID->isInvalidDecl() && isa(EnclosingDecl)) - Diag(Loc, diag::warn_ivar_in_interface_block); + Diag(Loc, diag::warn_ivars_in_interface); return NewID; } Modified: cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m?rev=156831&r1=156830&r2=156831&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m (original) +++ cfe/trunk/test/SemaObjC/no-ivar-in-interface-block.m Tue May 15 12:43:16 2012 @@ -1,13 +1,13 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Winterface-block-ivar %s +// RUN: %clang_cc1 -fsyntax-only -verify -Winterface-ivars %s // rdar://10763173 @interface I { - @protected int P_IVAR; // expected-warning {{declaration of ivar in the interface block is deprecated}} + @protected int P_IVAR; // expected-warning {{declaration of ivars in the interface is deprecated}} - @public int PU_IVAR; // expected-warning {{declaration of ivar in the interface block is deprecated}} + @public int PU_IVAR; // expected-warning {{declaration of ivars in the interface is deprecated}} - @private int PRV_IVAR; // expected-warning {{declaration of ivar in the interface block is deprecated}} + @private int PRV_IVAR; // expected-warning {{declaration of ivars in the interface is deprecated}} } @end From rjmccall at apple.com Tue May 15 12:42:55 2012 From: rjmccall at apple.com (John McCall) Date: Tue, 15 May 2012 10:42:55 -0700 Subject: [cfe-commits] [PATCH] Add -fobjc-direct-class-refs In-Reply-To: <1DF565A5-6B4E-4A7C-8680-03547FF0E14B@webkeks.org> References: <591F27BF-EF11-423C-AC4D-20DEA8353BE2@apple.com> <61DFCBAC-96AB-4FA5-B863-DF020991EC22@webkeks.org> <68F84C80-0E49-41D0-AD41-9915117511A8@apple.com> <21316473-94E5-4053-A13C-A87C8FEA311E@webkeks.org> <3AB519D3-FA30-4BA7-B29E-27EA91BC90E1@apple.com> <1DF565A5-6B4E-4A7C-8680-03547FF0E14B@webkeks.org> Message-ID: <855513A4-629D-4602-93AB-79F6091FF256@apple.com> On May 15, 2012, at 9:34 AM, Jonathan Schleifer wrote: > Am 15.05.2012 um 00:37 schrieb John McCall: >> I just don't want it to be a command-line option. > > I can think of advantages of having it as a command line option, though: > If a new runtime emerges, it does not need to patch clang, but instead it can use the -f switches. If it decides that it's perfectly satisfied with the compiler-emitted structures of some existing runtime, yes. This feels like a really weird constraint to force on oneself. > And it also means if a runtime gains a new feature, it does not need to patch clang. If that new feature happens to be implemented in exactly the same way as some existing runtime, yes. Please remember that that is not even true for this patch. The compiler is easy to patch, and when you're distributing your own custom runtime and your own make system, it's easy enough to say "for best performance, please make sure you have X version of the compiler". I do not want to support an ad hoc runtime specification language in the command-line options. > What about introducing a new -fobjc-runtime-features=foo,bar,baz with an alias for already known runtimes? This has exactly the same problems. The *concept* is flawed, not the spelling. John. From fjahanian at apple.com Tue May 15 12:44:48 2012 From: fjahanian at apple.com (jahanian) Date: Tue, 15 May 2012 10:44:48 -0700 Subject: [cfe-commits] r156825 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaObjC/no-ivar-in-interface-block.m In-Reply-To: <4449D80B-7127-434E-9A91-8579FD2814FA@apple.com> References: <20120515163304.D49EA2A6C065@llvm.org> <4449D80B-7127-434E-9A91-8579FD2814FA@apple.com> Message-ID: On May 15, 2012, at 10:20 AM, John McCall wrote: > On May 15, 2012, at 9:33 AM, Fariborz Jahanian wrote: >> Author: fjahanian >> Date: Tue May 15 11:33:04 2012 >> New Revision: 156825 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=156825&view=rev >> Log: >> objective-c nonfragile abi: discourage ivar declarations >> in @interface by issuing warning (off by default) under >> opt'ed in flag -Winterface-block-ivar. // rdar://10763173 > > The 'block' doesn't seem to be adding much. -Winterface-ivars? Makes sense. In r156831. - Fariborz > > John. From gregory.szorc at gmail.com Tue May 15 12:50:00 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 15 May 2012 10:50:00 -0700 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: <4FB08149.6030101@gmail.com> References: <4FB07FFA.5000702@gmail.com> <4FB08149.6030101@gmail.com> Message-ID: Let's see if the mail systems don't reject this one... On Sun, May 13, 2012 at 8:51 PM, Gregory Szorc wrote: > Fresh patch attached. > > > On 5/13/12 8:46 PM, Gregory Szorc wrote: >> >> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>> >>> + ? ?@property >>> + ? ?def translation_unit(self): >>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>> + ? ? ? ?return getattr(self, '_tu', None) >>> >>> What's the reason for the default value? Do we expect that people >>> create cursers via the lowlevel calls? Why would just return tu_ not >>> work? >> >> Just defensive programming. If you return self._tu, that may raise an >> AttributeError if _tu is not set. Theoretically, the API should ensure >> that a TU is defined on all Cursor instances, so maybe an AttributeError >> would be acceptable. >> >>> + ? ? ? ?# Store a reference to the TU in the Python object so it >>> won't get GC'd >>> + ? ? ? ?# before the Cursor. >>> + ? ? ? ?tu = None >>> + ? ? ? ?for arg in args: >>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>> + ? ? ? ? ? ? ? ?tu = arg >>> + ? ? ? ? ? ? ? ?break >>> + >>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>> + ? ? ? ? ? ? ? ?break >>> + >>> + ? ? ? ?assert tu is not None >>> + >>> + ? ? ? ?res._tu = tu >>> >>> That seems - odd. I can't find docs what from_result is supposed to >>> do, or what "args" are provided. But having to search through them for >>> a TU seems wrong - shouldn't they all have a TU? >> >> from_result is the errcheck function for the ctypes functions that >> return a Cursor. The 3rd argument to an errcheck function are the >> original arguments passed into the called function. ?For many of the >> functions, the original argument is a Cursor. However, >> clang_getTypeDeclaration takes a Type and clang_getTranslationUnitCursor >> receives a TranslationUnit. >> >> It is true that all of the functions today receive a single argument, so >> the iteration isn't required. However, that may change with the addition >> of new APIs in the future (this is how I coded it in my nearly >> feature-complete branch, so I'm guessing it is actually required from a >> future patch). >>> >>> >>> Also, regarding the test - would it be possible to create a test that >>> drops the reference, triggers the gc and then makes sure the cursor is >>> still valid (as that is what we really care about)? >>> >> Sure! >> > > From gregory.szorc at gmail.com Tue May 15 12:51:08 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 15 May 2012 10:51:08 -0700 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> <4FB08149.6030101@gmail.com> Message-ID: Maybe if I attached the patch... On Tue, May 15, 2012 at 10:50 AM, Gregory Szorc wrote: > Let's see if the mail systems don't reject this one... > > On Sun, May 13, 2012 at 8:51 PM, Gregory Szorc wrote: >> Fresh patch attached. >> >> >> On 5/13/12 8:46 PM, Gregory Szorc wrote: >>> >>> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>>> >>>> + ? ?@property >>>> + ? ?def translation_unit(self): >>>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>>> + ? ? ? ?return getattr(self, '_tu', None) >>>> >>>> What's the reason for the default value? Do we expect that people >>>> create cursers via the lowlevel calls? Why would just return tu_ not >>>> work? >>> >>> Just defensive programming. If you return self._tu, that may raise an >>> AttributeError if _tu is not set. Theoretically, the API should ensure >>> that a TU is defined on all Cursor instances, so maybe an AttributeError >>> would be acceptable. >>> >>>> + ? ? ? ?# Store a reference to the TU in the Python object so it >>>> won't get GC'd >>>> + ? ? ? ?# before the Cursor. >>>> + ? ? ? ?tu = None >>>> + ? ? ? ?for arg in args: >>>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>>> + ? ? ? ? ? ? ? ?tu = arg >>>> + ? ? ? ? ? ? ? ?break >>>> + >>>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>>> + ? ? ? ? ? ? ? ?break >>>> + >>>> + ? ? ? ?assert tu is not None >>>> + >>>> + ? ? ? ?res._tu = tu >>>> >>>> That seems - odd. I can't find docs what from_result is supposed to >>>> do, or what "args" are provided. But having to search through them for >>>> a TU seems wrong - shouldn't they all have a TU? >>> >>> from_result is the errcheck function for the ctypes functions that >>> return a Cursor. The 3rd argument to an errcheck function are the >>> original arguments passed into the called function. ?For many of the >>> functions, the original argument is a Cursor. However, >>> clang_getTypeDeclaration takes a Type and clang_getTranslationUnitCursor >>> receives a TranslationUnit. >>> >>> It is true that all of the functions today receive a single argument, so >>> the iteration isn't required. However, that may change with the addition >>> of new APIs in the future (this is how I coded it in my nearly >>> feature-complete branch, so I'm guessing it is actually required from a >>> future patch). >>>> >>>> >>>> Also, regarding the test - would it be possible to create a test that >>>> drops the reference, triggers the gc and then makes sure the cursor is >>>> still valid (as that is what we really care about)? >>>> >>> Sure! >>> >> >> -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-clang.py-Store-reference-to-TranslationUnit-in-Curso.patch Type: application/octet-stream Size: 9849 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/2a7025c8/attachment-0001.obj From timurrrr at google.com Tue May 15 13:09:09 2012 From: timurrrr at google.com (Timur Iskhodzhanov) Date: Tue, 15 May 2012 22:09:09 +0400 Subject: [cfe-commits] [Windows] Use thiscall as the default calling convention for class methods In-Reply-To: <3CA2E7B4-4B4A-4A9C-8B55-1E08E765305B@apple.com> References: <3CA2E7B4-4B4A-4A9C-8B55-1E08E765305B@apple.com> Message-ID: On Fri, May 11, 2012 at 9:55 PM, John McCall wrote: > On May 11, 2012, at 6:58 AM, Timur Iskhodzhanov wrote: >> Can you please review the attached patch? >> >> In two words what it does is >> it overrides the CC_Default calling convention with >> context.getDefaultMethodCallConv() >> for all the used method definitions and calls. >> >> What I personally don't like is that the method declarations are >> stored with CC_Default and we have to replace that with >> context.getDefaultMethodCallConv() wherever we use it. >> Unfortunately, we can't change the CC in the global declarations storage. >> I'd prefer to put the declarations into the storage with the right CC >> but not sure: >> a) if we should do it >> b) how to do it >> c) it's possible at all > > I don't think modifying the AST is the right thing to do here anyway; > CC_Default is really the right way to model this. ok >> OTOH, it looks like there are only two places we need to alter the >> calling convention: method call and method definition :) >> So maybe I'm trying too hard to generalize... > I mostly like your patch, but I think it'd be slightly better to make the > terminal arrangeFunctionType take some sort of "function kind" > parameter (function vs. C++ instance method) and then have > ClangCallConvToLLVMCallConv consider that when mapping > CC_Default. > > Also, please put this in a more generically-named test, something like > microsoft-abi-methods.cpp. ?I'm sure there will be other changes that > we'll want to test for as time goes on. I got your point. I'll try doing that - I've started with tests and this has uncovered a few bugs in ctor/dtor handling. Will update as soon as it's fixed. > Also, please test: > ?- declarations of instance methods using CC_Default you mean, declarations without explicitly specified CC ? > ?- declarations of instance methods with an explicit CC Would you prefer __thiscall/__cdecl or __attribute__ ? > ?- declarations of static methods (to make sure they aren't thiscall) > ?- direct calls to instance methods using CC_Default > ?- direct calls to instance methods with an explicit CC > ?- direct calls to static methods using instance call syntax Thanks! > John. From fjahanian at apple.com Tue May 15 13:12:52 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Tue, 15 May 2012 18:12:52 -0000 Subject: [cfe-commits] r156832 - in /cfe/trunk: lib/Sema/SemaObjCProperty.cpp test/SemaObjC/property-ivar-mismatch.m Message-ID: <20120515181252.242062A6C065@llvm.org> Author: fjahanian Date: Tue May 15 13:12:51 2012 New Revision: 156832 URL: http://llvm.org/viewvc/llvm-project?rev=156832&view=rev Log: objc: avoid duplicate diagnostics on certain type mismatches between property and its backing ivar. Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp cfe/trunk/test/SemaObjC/property-ivar-mismatch.m Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=156832&r1=156831&r2=156832&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original) +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Tue May 15 13:12:51 2012 @@ -658,6 +658,7 @@ } ObjCIvarDecl *Ivar = 0; bool CompleteTypeErr = false; + bool compat = true; // Check that we have a valid, previously declared ivar for @synthesize if (Synthesize) { // @synthesize @@ -773,8 +774,8 @@ QualType IvarType = Context.getCanonicalType(Ivar->getType()); // Check that type of property and its ivar are type compatible. - if (Context.getCanonicalType(PropertyIvarType) != IvarType) { - bool compat = false; + if (!Context.hasSameType(PropertyIvarType, IvarType)) { + compat = false; if (isa(PropertyIvarType) && isa(IvarType)) compat = @@ -794,19 +795,20 @@ // Note! I deliberately want it to fall thru so, we have a // a property implementation and to avoid future warnings. } - - // FIXME! Rules for properties are somewhat different that those - // for assignments. Use a new routine to consolidate all cases; - // specifically for property redeclarations as well as for ivars. - QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); - QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); - if (lhsType != rhsType && - lhsType->isArithmeticType()) { - Diag(PropertyDiagLoc, diag::error_property_ivar_type) - << property->getDeclName() << PropType - << Ivar->getDeclName() << IvarType; - Diag(Ivar->getLocation(), diag::note_ivar_decl); - // Fall thru - see previous comment + else { + // FIXME! Rules for properties are somewhat different that those + // for assignments. Use a new routine to consolidate all cases; + // specifically for property redeclarations as well as for ivars. + QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); + QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); + if (lhsType != rhsType && + lhsType->isArithmeticType()) { + Diag(PropertyDiagLoc, diag::error_property_ivar_type) + << property->getDeclName() << PropType + << Ivar->getDeclName() << IvarType; + Diag(Ivar->getLocation(), diag::note_ivar_decl); + // Fall thru - see previous comment + } } // __weak is explicit. So it works on Canonical type. if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && @@ -840,7 +842,7 @@ : ObjCPropertyImplDecl::Dynamic), Ivar, PropertyIvarLoc); - if (CompleteTypeErr) + if (CompleteTypeErr || !compat) PIDecl->setInvalidDecl(); if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { Modified: cfe/trunk/test/SemaObjC/property-ivar-mismatch.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-ivar-mismatch.m?rev=156832&r1=156831&r2=156832&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/property-ivar-mismatch.m (original) +++ cfe/trunk/test/SemaObjC/property-ivar-mismatch.m Tue May 15 13:12:51 2012 @@ -12,3 +12,15 @@ @synthesize prop = ivar; // expected-error {{type of property 'prop' ('int') does not match type of ivar 'ivar' ('char')}} @end + + at interface Test5 +{ + void * _P; // expected-note {{ivar is declared here}} +} + at property int P; + at end + + at implementation Test5 + at synthesize P=_P; // expected-error {{ype of property 'P' ('int') does not match type of ivar '_P' ('void *')}} + at end + From dgregor at apple.com Tue May 15 13:24:01 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 11:24:01 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: Message-ID: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> On May 15, 2012, at 9:31 AM, David Blaikie wrote: > On Tue, May 15, 2012 at 9:19 AM, Douglas Gregor wrote: >> >> On May 6, 2012, at 7:02 PM, David Blaikie wrote: >> >>> This patch adds an iterator much like boost's transform_iterator >>> (without some extra bells & whistles) for use in some changes I'd like >>> to make to Clang to correct some misimplemented iterators there. >>> >>> A few gotchas that could be improved/changed depending on opinions: >>> * I may be playing a little loose with the return type of the functor >>> (see the example/motivating functor, to_pointer) - the return type >>> actually must be a reference, though the result_type provides the >>> underlying value type, not the reference type. If this is violated >>> Clang will emit a warning, but I could make it more robust with a >>> compile time assertion in the TransformIterator that the result_type >>> is actually a reference type, and strip that off to provide the >>> value_type of the TransformIterator. >> >> It's much more correct for the value and reference types of the iterator type to be, e.g., >> >> typedef typename Functor::result_type reference; >> typedef typename remove_reference::type value_type; >> >>> * I realize adding pointer-yness back onto an iterator over references >>> when the underlying data structure (in the Clang patch you can see >>> this situation) is a sequence of pointers may be a bit overkill - >>> though the alternatives are writing different algorithms in the two >>> cases where I've used TransformIterator, or having the decl_iterator >>> iterate over pointers (in which case I should probably change the >>> other iterators I've modified to iterate over pointers for symmetry). >> >> diff --git include/clang/AST/DeclBase.h include/clang/AST/DeclBase.h >> index 6aef681..0a16ea5 100644 >> --- include/clang/AST/DeclBase.h >> +++ include/clang/AST/DeclBase.h >> @@ -1175,17 +1175,18 @@ public: >> Decl *Current; >> >> public: >> - typedef Decl* value_type; >> - typedef Decl* reference; >> - typedef Decl* pointer; >> + typedef Decl value_type; >> + typedef value_type& reference; >> + typedef value_type* pointer; >> >> Since we tend to traffic in declaration pointers, not references, it's really beneficial to have value_type be Decl*. > > Fair enough - I was hoping to reduce the amount of pointers handed > around, but I realize in this case especially (where the underlying > sequence is a sequence of pointers) it's really an awkward fit. Why is reducing the number of pointers a specific goal? We tend use pointers (not references) for AST nodes throughout AST, Sema, and a number of other places in the compiler. > This means killing off the op-> for these iterators though, right? Or > do you want to keep that as an excusable convenience? Honestly, I preferred the world back in its conveniently-inconsistent state where operator* returned a pointer and operator-> returned that same pointer, because being able to refer to Iter->getDeclName() rather than (*Iter)->getDeclName() is *really* convenient. The inclusion of operator-> in the iterator concepts was a mistake. Nothing in the standard library actually depends on it, no sane algorithms need it, and it's a major PITA to implement for iterator adaptors (as you've noticed ). > In which case my > change boils down to just changing the pointer typedefs to be Decl** > in these various iterator types. (& might make my planned work, > generalizing the filtering iterators, a bit weird - possibly providing > an op-> to the generic filtering iterators whenever the value type is > a pointer to match/support this oddity) Decl** won't always work, though. You'll almost certainly need a proxy. > Would you prefer the other iterators I changed > (specific_decl_iterator, filtered_decl_iterator) be switched to > pointer value_type too? I did prefer the pointer value_type; perhaps others want to weigh in. >> This isn't going to work; m_func returns a value_type or reference. Dealing with -> is a real pain, because in the general case you need a proxy class. >> >> +// a convenient utility for a common adaptation >> +template >> +struct to_pointer { >> + typedef T * result_type; >> + typedef T argument_type; >> + result_type &operator()(T &t) const { >> + ptr = &t; >> + return ptr; >> + } >> +private: >> + mutable T *ptr; >> +}; >> >> 'to_pointer' is a very non-LLVM-y name. >> >> More generally, this particular function object seems like a bad idea. There's nothing wrong with having an iterator type whose reference type is not a true reference, which means that there is no reason to do this little dance with the mutable 'ptr'. > > Yeah, a proxy would be nicer. > > In any case all this transformation stuff isn't needed for this change > anymore if we're sticking with a pointer value_type. Right. - Doug From rjmccall at apple.com Tue May 15 13:34:52 2012 From: rjmccall at apple.com (John McCall) Date: Tue, 15 May 2012 11:34:52 -0700 Subject: [cfe-commits] [Windows] Use thiscall as the default calling convention for class methods In-Reply-To: References: <3CA2E7B4-4B4A-4A9C-8B55-1E08E765305B@apple.com> Message-ID: On May 15, 2012, at 11:09 AM, Timur Iskhodzhanov wrote: > On Fri, May 11, 2012 at 9:55 PM, John McCall wrote: >> On May 11, 2012, at 6:58 AM, Timur Iskhodzhanov wrote: >>> Can you please review the attached patch? >>> >>> In two words what it does is >>> it overrides the CC_Default calling convention with >>> context.getDefaultMethodCallConv() >>> for all the used method definitions and calls. >>> >>> What I personally don't like is that the method declarations are >>> stored with CC_Default and we have to replace that with >>> context.getDefaultMethodCallConv() wherever we use it. >>> Unfortunately, we can't change the CC in the global declarations storage. >>> I'd prefer to put the declarations into the storage with the right CC >>> but not sure: >>> a) if we should do it >>> b) how to do it >>> c) it's possible at all >> >> I don't think modifying the AST is the right thing to do here anyway; >> CC_Default is really the right way to model this. > ok > >>> OTOH, it looks like there are only two places we need to alter the >>> calling convention: method call and method definition :) >>> So maybe I'm trying too hard to generalize... >> I mostly like your patch, but I think it'd be slightly better to make the >> terminal arrangeFunctionType take some sort of "function kind" >> parameter (function vs. C++ instance method) and then have >> ClangCallConvToLLVMCallConv consider that when mapping >> CC_Default. >> >> Also, please put this in a more generically-named test, something like >> microsoft-abi-methods.cpp. I'm sure there will be other changes that >> we'll want to test for as time goes on. > I got your point. > I'll try doing that - I've started with tests and this has > uncovered a few bugs in ctor/dtor handling. > Will update as soon as it's fixed. Thanks! >> Also, please test: >> - declarations of instance methods using CC_Default > you mean, declarations without explicitly specified CC ? Yes. >> - declarations of instance methods with an explicit CC > Would you prefer __thiscall/__cdecl or __attribute__ ? If we predefine __thiscall in MS mode, then testing that way is fine. John. From klimek at google.com Tue May 15 13:35:28 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 20:35:28 +0200 Subject: [cfe-commits] [PATCH] Add OverwriteChangedFiles to the Rewriter In-Reply-To: References: Message-ID: Ping :) On Fri, May 11, 2012 at 1:33 PM, Manuel Klimek wrote: > On Tue, May 8, 2012 at 11:49 AM, Manuel Klimek wrote: >> On Thu, May 3, 2012 at 6:40 PM, Manuel Klimek wrote: >>> as requested by Doug in the clangRefactoring review... in addition, >>> this patch adds a unit test for the Rewriter (into Tooling/ so we >>> don't link yet another unit test), and pulls out a RewriterTestContext >>> which I need for clangRefactoring when it's checked in - but it's also >>> really nice to unit test Rewriter functionality... > > Inlining the patch in the hope that that speeds up review :) > > First, the changed code: > > Index: include/clang/Rewrite/Rewriter.h > =================================================================== > --- include/clang/Rewrite/Rewriter.h ? ?(revision 156059) > +++ include/clang/Rewrite/Rewriter.h ? ?(working copy) > @@ -279,6 +279,13 @@ > ? buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } > ? buffer_iterator buffer_end() { return RewriteBuffers.end(); } > > + ?/// SaveFiles - Save all changed files to disk. > + ?/// > + ?/// Returns whether all changes were saves successfully. > + ?/// Outputs diagnostics via the source manager's diagnostic engine > + ?/// in case of an error. > + ?bool OverwriteChangedFiles(); > + > ?private: > ? unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; > ?}; > Index: lib/Rewrite/Rewriter.cpp > =================================================================== > --- lib/Rewrite/Rewriter.cpp ? ?(revision 156059) > +++ lib/Rewrite/Rewriter.cpp ? ?(working copy) > @@ -15,8 +15,10 @@ > ?#include "clang/Rewrite/Rewriter.h" > ?#include "clang/AST/Stmt.h" > ?#include "clang/AST/Decl.h" > +#include "clang/Basic/FileManager.h" > +#include "clang/Basic/SourceManager.h" > ?#include "clang/Lex/Lexer.h" > -#include "clang/Basic/SourceManager.h" > +#include "clang/Frontend/FrontendDiagnostic.h" > ?#include "llvm/ADT/SmallString.h" > ?using namespace clang; > > @@ -412,3 +414,23 @@ > > ? return false; > ?} > + > +bool Rewriter::OverwriteChangedFiles() { > + ?bool AllWritten = true; > + ?for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { > + ? ?const FileEntry *Entry = > + ? ? ? ?getSourceMgr().getFileEntryForID(I->first); > + ? ?std::string ErrorInfo; > + ? ?llvm::raw_fd_ostream FileStream( > + ? ? ? ?Entry->getName(), ErrorInfo, llvm::raw_fd_ostream::F_Binary); > + ? ?if (!ErrorInfo.empty()) { > + ? ? ?getSourceMgr().getDiagnostics().Report(clang::diag::err_fe_unable_to_open_output) > + ? ? ? ?<< Entry->getName() << ErrorInfo; > + ? ? ?AllWritten = false; > + ? ? ?continue; > + ? ?} > + ? ?I->second.write(FileStream); > + ? ?FileStream.flush(); > + ?} > + ?return AllWritten; > +} > > Second, the testing overhead; note that the RewriterTestContext will > also be used in a subsequent CL which is currently under review, which > is why I pulled out a class. > > > Index: unittests/Tooling/RewriterTest.cpp > =================================================================== > --- unittests/Tooling/RewriterTest.cpp ?(revision 0) > +++ unittests/Tooling/RewriterTest.cpp ?(revision 0) > @@ -0,0 +1,37 @@ > +//===- unittest/Tooling/RewriterTest.cpp > ----------------------------------===// > +// > +// ? ? ? ? ? ? ? ? ? ? The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#include "RewriterTestContext.h" > +#include "gtest/gtest.h" > + > +namespace clang { > + > +TEST(Rewriter, OverwritesChangedFiles) { > + ?RewriterTestContext Context; > + ?FileID ID = Context.createOnDiskFile("t.cpp", "line1\nline2\nline3\nline4"); > + ?Context.Rewrite.ReplaceText(Context.getLocation(ID, 2, 1), 5, "replaced"); > + ?EXPECT_TRUE(Context.Rewrite.OverwriteChangedFiles()); > + ?EXPECT_EQ("line1\nreplaced\nline3\nline4", > + ? ? ? ? ? ?Context.getFileContentFromDisk("t.cpp")); > +} > + > +TEST(Rewriter, ContinuesOverwritingFilesOnError) { > + ?RewriterTestContext Context; > + ?FileID FailingID = Context.createInMemoryFile("invalid/failing.cpp", "test"); > + ?Context.Rewrite.ReplaceText(Context.getLocation(FailingID, 1, 2), > 1, "other"); > + ?FileID WorkingID = Context.createOnDiskFile( > + ? ?"working.cpp", "line1\nline2\nline3\nline4"); > + ?Context.Rewrite.ReplaceText(Context.getLocation(WorkingID, 2, 1), 5, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"replaced"); > + ?EXPECT_FALSE(Context.Rewrite.OverwriteChangedFiles()); > + ?EXPECT_EQ("line1\nreplaced\nline3\nline4", > + ? ? ? ? ? ?Context.getFileContentFromDisk("working.cpp")); > +} > + > +} // end namespace clang > > Index: unittests/Tooling/RewriterTestContext.h > =================================================================== > --- unittests/Tooling/RewriterTestContext.h ? ? (revision 0) > +++ unittests/Tooling/RewriterTestContext.h ? ? (revision 0) > @@ -0,0 +1,120 @@ > +//===--- RewriterTestContext.h ----------------------------------*- > C++ -*-===// > +// > +// ? ? ? ? ? ? ? ? ? ? The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +// > +// ?This file defines a utility class for Rewriter related tests. > +// > +//===----------------------------------------------------------------------===// > + > +#ifndef LLVM_CLANG_REWRITER_TEST_CONTEXT_H > +#define LLVM_CLANG_REWRITER_TEST_CONTEXT_H > + > +#include "clang/Basic/Diagnostic.h" > +#include "clang/Basic/FileManager.h" > +#include "clang/Basic/LangOptions.h" > +#include "clang/Basic/SourceManager.h" > +#include "clang/Frontend/DiagnosticOptions.h" > +#include "clang/Frontend/TextDiagnosticPrinter.h" > +#include "clang/Rewrite/Rewriter.h" > +#include "llvm/Support/Path.h" > +#include "llvm/Support/raw_ostream.h" > + > +namespace clang { > + > +/// \brief A class that sets up a ready to use Rewriter. > +/// > +/// Useful in unit tests that need a Rewriter. Creates all dependencies > +/// of a Rewriter with default values for testing and provides convenience > +/// methods, which help with writing tests that change files. > +class RewriterTestContext { > + public: > + ?RewriterTestContext() > + ? ? ?: Diagnostics(llvm::IntrusiveRefCntPtr()), > + ? ? ? ?DiagnosticPrinter(llvm::outs(), DiagnosticOptions()), > + ? ? ? ?Files((FileSystemOptions())), > + ? ? ? ?Sources(Diagnostics, Files), > + ? ? ? ?Rewrite(Sources, Options) { > + ? ?Diagnostics.setClient(&DiagnosticPrinter, false); > + ?} > + > + ?~RewriterTestContext() { > + ? ?if (TemporaryDirectory.isValid()) { > + ? ? ?std::string ErrorInfo; > + ? ? ?TemporaryDirectory.eraseFromDisk(true, &ErrorInfo); > + ? ? ?assert(ErrorInfo.empty()); > + ? ?} > + ?} > + > + ?FileID createInMemoryFile(StringRef Name, StringRef Content) { > + ? ?const llvm::MemoryBuffer *Source = > + ? ? ?llvm::MemoryBuffer::getMemBuffer(Content); > + ? ?const FileEntry *Entry = > + ? ? ?Files.getVirtualFile(Name, Source->getBufferSize(), 0); > + ? ?Sources.overrideFileContents(Entry, Source, true); > + ? ?assert(Entry != NULL); > + ? ?return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User); > + ?} > + > + ?FileID createOnDiskFile(StringRef Name, StringRef Content) { > + ? ?if (!TemporaryDirectory.isValid()) { > + ? ? ?std::string ErrorInfo; > + ? ? ?TemporaryDirectory = llvm::sys::Path::GetTemporaryDirectory(&ErrorInfo); > + ? ? ?assert(ErrorInfo.empty()); > + ? ?} > + ? ?llvm::SmallString<1024> Path(TemporaryDirectory.str()); > + ? ?llvm::sys::path::append(Path, Name); > + ? ?std::string ErrorInfo; > + ? ?llvm::raw_fd_ostream OutStream(Path.c_str(), > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ErrorInfo, llvm::raw_fd_ostream::F_Binary); > + ? ?assert(ErrorInfo.empty()); > + ? ?OutStream << Content; > + ? ?OutStream.close(); > + ? ?const FileEntry *File = Files.getFile(Path); > + ? ?assert(File != NULL); > + ? ?return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User); > + ?} > + > + ?SourceLocation getLocation(FileID ID, unsigned Line, unsigned Column) { > + ? ?SourceLocation Result = Sources.translateFileLineCol( > + ? ? ? ?Sources.getFileEntryForID(ID), Line, Column); > + ? ?assert(Result.isValid()); > + ? ?return Result; > + ?} > + > + ?std::string getRewrittenText(FileID ID) { > + ? ?std::string Result; > + ? ?llvm::raw_string_ostream OS(Result); > + ? ?Rewrite.getEditBuffer(ID).write(OS); > + ? ?return Result; > + ?} > + > + ?std::string getFileContentFromDisk(StringRef Name) { > + ? ?llvm::SmallString<1024> Path(TemporaryDirectory.str()); > + ? ?llvm::sys::path::append(Path, Name); > + ? ?// We need to read directly from the FileManager without relaying through > + ? ?// a FileEntry, as otherwise we'd read through an already opened file > + ? ?// descriptor, which might not see the changes made. > + ? ?// FIXME: Figure out whether there is a way to get the SourceManger to > + ? ?// reopen the file. > + ? ?return Files.getBufferForFile(Path, NULL)->getBuffer(); > + ?} > + > + ?DiagnosticsEngine Diagnostics; > + ?TextDiagnosticPrinter DiagnosticPrinter; > + ?FileManager Files; > + ?SourceManager Sources; > + ?LangOptions Options; > + ?Rewriter Rewrite; > + > + ?// Will be set once on disk files are generated. > + ?llvm::sys::Path TemporaryDirectory; > +}; > + > +} // end namespace clang > + > +#endif > Index: unittests/CMakeLists.txt > =================================================================== > --- unittests/CMakeLists.txt ? ?(revision 156059) > +++ unittests/CMakeLists.txt ? ?(working copy) > @@ -70,5 +70,6 @@ > ? Tooling/CompilationDatabaseTest.cpp > ? Tooling/ToolingTest.cpp > ? Tooling/RecursiveASTVisitorTest.cpp > - ?USED_LIBS gtest gtest_main clangAST clangTooling > + ?Tooling/RewriterTest.cpp > + ?USED_LIBS gtest gtest_main clangAST clangTooling clangRewrite > ?) From dgregor at apple.com Tue May 15 13:39:50 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 11:39:50 -0700 Subject: [cfe-commits] [PATCH] Add OverwriteChangedFiles to the Rewriter In-Reply-To: References: Message-ID: On May 11, 2012, at 4:33 AM, Manuel Klimek wrote: > On Tue, May 8, 2012 at 11:49 AM, Manuel Klimek wrote: >> On Thu, May 3, 2012 at 6:40 PM, Manuel Klimek wrote: >>> as requested by Doug in the clangRefactoring review... in addition, >>> this patch adds a unit test for the Rewriter (into Tooling/ so we >>> don't link yet another unit test), and pulls out a RewriterTestContext >>> which I need for clangRefactoring when it's checked in - but it's also >>> really nice to unit test Rewriter functionality... > > Inlining the patch in the hope that that speeds up review :) > > First, the changed code: > > Index: include/clang/Rewrite/Rewriter.h > =================================================================== > --- include/clang/Rewrite/Rewriter.h (revision 156059) > +++ include/clang/Rewrite/Rewriter.h (working copy) > @@ -279,6 +279,13 @@ > buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } > buffer_iterator buffer_end() { return RewriteBuffers.end(); } > > + /// SaveFiles - Save all changed files to disk. > + /// > + /// Returns whether all changes were saves successfully. > + /// Outputs diagnostics via the source manager's diagnostic engine > + /// in case of an error. > + bool OverwriteChangedFiles(); > + I think that's spelled: bool overwriteChangedFiles(); Also, we usually use a return of "true" to indicate that there was an error. > private: > unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; > }; > Index: lib/Rewrite/Rewriter.cpp > =================================================================== > --- lib/Rewrite/Rewriter.cpp (revision 156059) > +++ lib/Rewrite/Rewriter.cpp (working copy) > @@ -15,8 +15,10 @@ > #include "clang/Rewrite/Rewriter.h" > #include "clang/AST/Stmt.h" > #include "clang/AST/Decl.h" > +#include "clang/Basic/FileManager.h" > +#include "clang/Basic/SourceManager.h" > #include "clang/Lex/Lexer.h" > -#include "clang/Basic/SourceManager.h" > +#include "clang/Frontend/FrontendDiagnostic.h" > #include "llvm/ADT/SmallString.h" > using namespace clang; > > @@ -412,3 +414,23 @@ > > return false; > } > + > +bool Rewriter::OverwriteChangedFiles() { > + bool AllWritten = true; > + for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { > + const FileEntry *Entry = > + getSourceMgr().getFileEntryForID(I->first); > + std::string ErrorInfo; > + llvm::raw_fd_ostream FileStream( > + Entry->getName(), ErrorInfo, llvm::raw_fd_ostream::F_Binary); > + if (!ErrorInfo.empty()) { > + getSourceMgr().getDiagnostics().Report(clang::diag::err_fe_unable_to_open_output) > + << Entry->getName() << ErrorInfo; > + AllWritten = false; > + continue; > + } > + I->second.write(FileStream); > + FileStream.flush(); > + } > + return AllWritten; > +} It would be better to write the data to a temporary file and then rename it, like we do with other outputs. > Second, the testing overhead; note that the RewriterTestContext will > also be used in a subsequent CL which is currently under review, which > is why I pulled out a class. Okay. Everything else LGTM, thanks! - Doug From dgregor at apple.com Tue May 15 13:41:55 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 18:41:55 -0000 Subject: [cfe-commits] r156834 - /cfe/trunk/tools/scan-build/scan-build Message-ID: <20120515184155.BE8922A6C065@llvm.org> Author: dgregor Date: Tue May 15 13:41:55 2012 New Revision: 156834 URL: http://llvm.org/viewvc/llvm-project?rev=156834&view=rev Log: Add the output of "clang --version" to scan-build results, from Gerald Combs! Modified: cfe/trunk/tools/scan-build/scan-build Modified: cfe/trunk/tools/scan-build/scan-build URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/scan-build?rev=156834&r1=156833&r2=156834&view=diff ============================================================================== --- cfe/trunk/tools/scan-build/scan-build (original) +++ cfe/trunk/tools/scan-build/scan-build Tue May 15 13:41:55 2012 @@ -98,6 +98,7 @@ $Clang = $ClangSB; } my $ClangCXX = $Clang . "++"; +my $ClangVersion = HtmlEscape(`$Clang --version`); ##----------------------------------------------------------------------------## # GetHTMLRunDir - Construct an HTML directory name for the current sub-run. @@ -590,6 +591,7 @@ User:${UserName}\@${HostName} Working Directory:${CurrentDir} Command Line:${CmdArgs} +Clang Version:${ClangVersion} Date:${Date} ENDTEXT From dgregor at apple.com Tue May 15 13:43:00 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 11:43:00 -0700 Subject: [cfe-commits] [PATCH] Add clang version to scan-build output In-Reply-To: <4FAD4241.8050505@wireshark.org> References: <4FAD4241.8050505@wireshark.org> Message-ID: On May 11, 2012, at 9:45 AM, Gerald Combs wrote: > Hi, > > Attached is a trivial patch to add the output of "clang --version" to > the index.html file generated by scan-build. This can be helpful when > you're looking at a scan-build report but don't have access to the > machine that generated the report, e.g. your automated build system > uploads reports to a publicly accessible web site. Committed as r156834, thanks! - Doug From dblaikie at gmail.com Tue May 15 13:57:35 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 11:57:35 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: [-llvm-commits since it's not too relevant to that list at this point] On Tue, May 15, 2012 at 11:24 AM, Douglas Gregor wrote: > > On May 15, 2012, at 9:31 AM, David Blaikie wrote: > >> On Tue, May 15, 2012 at 9:19 AM, Douglas Gregor wrote: >>> >>> On May 6, 2012, at 7:02 PM, David Blaikie wrote: >>> >>>> This patch adds an iterator much like boost's transform_iterator >>>> (without some extra bells & whistles) for use in some changes I'd like >>>> to make to Clang to correct some misimplemented iterators there. >>>> >>>> A few gotchas that could be improved/changed depending on opinions: >>>> * I may be playing a little loose with the return type of the functor >>>> (see the example/motivating functor, to_pointer) - the return type >>>> actually must be a reference, though the result_type provides the >>>> underlying value type, not the reference type. If this is violated >>>> Clang will emit a warning, but I could make it more robust with a >>>> compile time assertion in the TransformIterator that the result_type >>>> is actually a reference type, and strip that off to provide the >>>> value_type of the TransformIterator. >>> >>> It's much more correct for the value and reference types of the iterator type to be, e.g., >>> >>> ?typedef typename Functor::result_type reference; >>> ?typedef typename remove_reference::type value_type; >>> >>>> * I realize adding pointer-yness back onto an iterator over references >>>> when the underlying data structure (in the Clang patch you can see >>>> this situation) is a sequence of pointers may be a bit overkill - >>>> though the alternatives are writing different algorithms in the two >>>> cases where I've used TransformIterator, or having the decl_iterator >>>> iterate over pointers (in which case I should probably change the >>>> other iterators I've modified to iterate over pointers for symmetry). >>> >>> diff --git include/clang/AST/DeclBase.h include/clang/AST/DeclBase.h >>> index 6aef681..0a16ea5 100644 >>> --- include/clang/AST/DeclBase.h >>> +++ include/clang/AST/DeclBase.h >>> @@ -1175,17 +1175,18 @@ public: >>> ? ? Decl *Current; >>> >>> ? public: >>> - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? value_type; >>> - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? reference; >>> - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? pointer; >>> + ? ?typedef Decl ? ? ? ? ? ? ? ? ? ? value_type; >>> + ? ?typedef value_type& ? ? ? ? ? ? ?reference; >>> + ? ?typedef value_type* ? ? ? ? ? ? ?pointer; >>> >>> Since we tend to traffic in declaration pointers, not references, it's really beneficial to have value_type be Decl*. >> >> Fair enough - I was hoping to reduce the amount of pointers handed >> around, but I realize in this case especially (where the underlying >> sequence is a sequence of pointers) it's really an awkward fit. > > Why is reducing the number of pointers a specific goal? Evidently not something everyone finds to be a useful goal - and on that basis perhaps I should just leave it alone. But for myself I find functions taking references (& locals that are references) easier to read/reason about because it's clear that they're not null. Trying to decide which functions are accepting optional values and which ones aren't makes me pause a little - though perhaps more out of habit than real curiosity about whether something is null. If switching things to references causes pointer-habitual people to have the same kind of pause then that's clearly not an outright improvement. > We tend use pointers ?(not references) for AST nodes throughout AST, Sema, and a number of other places in the compiler. Indeed - a simple search for "Decl &" turns up mostly VarDecl references in CodeGen more than anything/anywhere else. >> This means killing off the op-> for these iterators though, right? Or >> do you want to keep that as an excusable convenience? > > Honestly, I preferred the world back in its conveniently-inconsistent state where operator* returned a pointer and operator-> returned that same pointer, because being able to refer to Iter->getDeclName() rather than (*Iter)->getDeclName() is *really* convenient. It is convenient, certainly. Though I find op* returning T& to be convenient/useful as well. In many cases we assign *i to a local pointer (I'm not sure why - perhaps we should just have a better name for the iterator and use that directly) & don't get the convenience of op-> (I assume this code was written before the op-> was added, actually) let alone the convenience of just using '.'. But if that's what you want, I can do that. > The inclusion of operator-> in the iterator concepts was a mistake. Nothing in the standard library actually depends on it, no sane algorithms need it, and it's a major PITA to implement for iterator adaptors (as you've noticed ). That's fine - though, since I want to replace specific/filtered_decl_iterators with some generic adapters, those adapters will need to provide the op-> convenience you want, whether or not it was specified in the concept/standard. >> In which case my >> change boils down to just changing the pointer typedefs to be Decl** >> in these various iterator types. (& might make my planned work, >> generalizing the filtering iterators, a bit weird - possibly providing >> an op-> to the generic filtering iterators whenever the value type is >> a pointer to match/support this oddity) > > Decl** won't always work, though. You'll almost certainly need a proxy. For the basic decl_iterators they do (because the underlying sequence is Decl*) but for the specific/filtered, where it'd be SpecificDecl** but we don't have a real SpecificDecl* to point to, it wouldn't and I'd need a proxy. Are there other cases/reasons for needing a proxy that you're referring to? >> Would you prefer the other iterators I changed >> (specific_decl_iterator, filtered_decl_iterator) be switched to >> pointer value_type too? > > I did prefer the pointer value_type; perhaps others want to weigh in. I'm fairly sure all 3 of these should be consistent, and that the specific/filtered should be refactored into a common adapter (typedef'd in place so clients of Decl wouldn't need to change, of course). Generally I prefer references, but I realize they're not a perfect fit. Yeah - I'd like to be able to get more discussion on this & other stylistic (micro design?) aspects - I kind of feel like I'm just throwing stuff up & seeing what's stuck after a few weeks. >>> This isn't going to work; m_func returns a value_type or reference. Dealing with -> is a real pain, because in the general case you need a proxy class. >>> >>> +// a convenient utility for a common adaptation >>> +template >>> +struct to_pointer { >>> + ?typedef T * result_type; >>> + ?typedef T argument_type; >>> + ?result_type &operator()(T &t) const { >>> + ? ?ptr = &t; >>> + ? ?return ptr; >>> + ?} >>> +private: >>> + ?mutable T *ptr; >>> +}; >>> >>> 'to_pointer' is a very non-LLVM-y name. >>> >>> More generally, this particular function object seems like a bad idea. There's nothing wrong with having an iterator type whose reference type is not a true reference, which means that there is no reason to do this little dance with the mutable 'ptr'. >> >> Yeah, a proxy would be nicer. >> >> In any case all this transformation stuff isn't needed for this change >> anymore if we're sticking with a pointer value_type. > > Right. Thanks again for your time, - David From bob.wilson at apple.com Tue May 15 13:57:39 2012 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 15 May 2012 18:57:39 -0000 Subject: [cfe-commits] r156841 - in /cfe/trunk: lib/Driver/Tools.cpp test/Driver/arclite-link.c Message-ID: <20120515185739.F30732A6C065@llvm.org> Author: bwilson Date: Tue May 15 13:57:39 2012 New Revision: 156841 URL: http://llvm.org/viewvc/llvm-project?rev=156841&view=rev Log: Do not link with Objective-C libraries with -nostdlib or -nodefaultlibs. Modified: cfe/trunk/lib/Driver/Tools.cpp cfe/trunk/test/Driver/arclite-link.c Modified: cfe/trunk/lib/Driver/Tools.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=156841&r1=156840&r2=156841&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Tools.cpp (original) +++ cfe/trunk/lib/Driver/Tools.cpp Tue May 15 13:57:39 2012 @@ -4224,7 +4224,9 @@ // This is more complicated in gcc... CmdArgs.push_back("-lgomp"); - if (isObjCRuntimeLinked(Args)) { + if (isObjCRuntimeLinked(Args) && + !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { // Avoid linking compatibility stubs on i386 mac. if (!getDarwinToolChain().isTargetMacOS() || getDarwinToolChain().getArchName() != "i386") { Modified: cfe/trunk/test/Driver/arclite-link.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/arclite-link.c?rev=156841&r1=156840&r2=156841&view=diff ============================================================================== --- cfe/trunk/test/Driver/arclite-link.c (original) +++ cfe/trunk/test/Driver/arclite-link.c Tue May 15 13:57:39 2012 @@ -2,9 +2,11 @@ // RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-OSX %s // RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.8 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s // RUN: %clang -### -target i386-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s +// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -nostdlib %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOSTDLIB %s // CHECK-ARCLITE-OSX: libarclite_macosx.a // CHECK-ARCLITE-OSX: -framework // CHECK-ARCLITE-OSX: Foundation // CHECK-ARCLITE-OSX: -lobjc // CHECK-NOARCLITE-NOT: libarclite +// CHECK-NOSTDLIB-NOT: -lobjc From akyrtzi at gmail.com Tue May 15 14:17:44 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 15 May 2012 19:17:44 -0000 Subject: [cfe-commits] r156843 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExprObjC.cpp test/SemaObjC/boxing-illegal-types.m test/SemaObjCXX/boxing-illegal-types.mm Message-ID: <20120515191744.EDEBB2A6C065@llvm.org> Author: akirtzidis Date: Tue May 15 14:17:44 2012 New Revision: 156843 URL: http://llvm.org/viewvc/llvm-project?rev=156843&view=rev Log: Allow objc @() syntax for enum types. Previously we would reject it as illegal using a value of enum type and on ObjC++ it was illegal to use an enumerator as well. rdar://11454917 Added: cfe/trunk/test/SemaObjCXX/boxing-illegal-types.mm Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaExprObjC.cpp cfe/trunk/test/SemaObjC/boxing-illegal-types.m Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156843&r1=156842&r2=156843&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 14:17:44 2012 @@ -1540,6 +1540,8 @@ "cannot box a string value because NSString has not been declared">; def err_objc_illegal_boxed_expression_type : Error< "illegal type %0 used in a boxed expression">; +def err_objc_incomplete_boxed_expression_type : Error< + "incomplete type %0 used in a boxed expression">; def err_undeclared_nsarray : Error< "NSArray must be available to use Objective-C array literals">; def err_undeclared_nsdictionary : Error< Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=156843&r1=156842&r2=156843&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue May 15 14:17:44 2012 @@ -539,6 +539,17 @@ // Look for the appropriate method within NSNumber. BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType); BoxedType = NSNumberPointer; + + } else if (const EnumType *ET = ValueType->getAs()) { + if (!ET->getDecl()->isComplete()) { + Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type) + << ValueType << ValueExpr->getSourceRange(); + return ExprError(); + } + + BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), + ET->getDecl()->getIntegerType()); + BoxedType = NSNumberPointer; } if (!BoxingMethod) { Modified: cfe/trunk/test/SemaObjC/boxing-illegal-types.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/boxing-illegal-types.m?rev=156843&r1=156842&r2=156843&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/boxing-illegal-types.m (original) +++ cfe/trunk/test/SemaObjC/boxing-illegal-types.m Tue May 15 14:17:44 2012 @@ -1,5 +1,29 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef signed char BOOL; + + at interface NSNumber + at end + at interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; + at end + typedef struct { int x, y, z; } point; @@ -19,3 +43,16 @@ void testInvalid() { @(not_defined); // expected-error {{use of undeclared identifier 'not_defined'}} } + +enum MyEnum { + ME_foo +}; + +enum ForwE; + +void testEnum(void *p) { + enum MyEnum myen; + id box = @(myen); + box = @(ME_foo); + box = @(*(enum ForwE*)p); // expected-error {{incomplete type 'enum ForwE' used in a boxed expression}} +} Added: cfe/trunk/test/SemaObjCXX/boxing-illegal-types.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/boxing-illegal-types.mm?rev=156843&view=auto ============================================================================== --- cfe/trunk/test/SemaObjCXX/boxing-illegal-types.mm (added) +++ cfe/trunk/test/SemaObjCXX/boxing-illegal-types.mm Tue May 15 14:17:44 2012 @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wattributes %s + +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef signed char BOOL; + + at interface NSNumber + at end + at interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; + at end + +typedef struct { + int x, y, z; +} point; + +void testStruct() { + point p = { 0, 0, 0 }; + id boxed = @(p); // expected-error {{illegal type 'point' used in a boxed expression}} +} + +void testPointers() { + void *null = 0; + id boxed_null = @(null); // expected-error {{illegal type 'void *' used in a boxed expression}} + int numbers[] = { 0, 1, 2 }; + id boxed_numbers = @(numbers); // expected-error {{illegal type 'int *' used in a boxed expression}} +} + +void testInvalid() { + @(not_defined); // expected-error {{use of undeclared identifier 'not_defined'}} +} + +enum MyEnum { + ME_foo +}; + +enum ForwE; // expected-error {{ISO C++ forbids forward references to 'enum' types}} + +void testEnum(void *p) { + enum MyEnum myen; + id box = @(myen); + box = @(ME_foo); + box = @(*(enum ForwE*)p); // expected-error {{incomplete type 'enum ForwE' used in a boxed expression}} +} From akyrtzi at gmail.com Tue May 15 14:17:50 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 15 May 2012 19:17:50 -0000 Subject: [cfe-commits] r156844 - in /cfe/trunk: lib/Edit/RewriteObjCFoundationAPI.cpp test/ARCMT/objcmt-boxing.m test/ARCMT/objcmt-boxing.m.result test/ARCMT/objcmt-numeric-literals.m.result Message-ID: <20120515191750.51BFD2A6C065@llvm.org> Author: akirtzidis Date: Tue May 15 14:17:49 2012 New Revision: 156844 URL: http://llvm.org/viewvc/llvm-project?rev=156844&view=rev Log: [objcmt] Rewrite [NSNumber numberWith*] messages to the new @() boxing syntax. There are some caveats: -If an implicit cast (e.g. int -> float for numberWithFloat:) was required, the message will not get rewritten -If the message was with numberWithInteger:/numberWithUnsignedInteger:, which are very commonly used, be more liberal and allow the boxing syntax if the underlying type has same signedness and will not lose precision. Part of rdar://11438360 Added: cfe/trunk/test/ARCMT/objcmt-boxing.m cfe/trunk/test/ARCMT/objcmt-boxing.m.result Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp?rev=156844&r1=156843&r2=156844&view=diff ============================================================================== --- cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp (original) +++ cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Tue May 15 14:17:49 2012 @@ -209,6 +209,8 @@ const NSAPI &NS, Commit &commit); static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit); +static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit); bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { @@ -372,7 +374,7 @@ return true; } - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); } static bool rewriteToBoolLiteral(const ObjCMessageExpr *Msg, @@ -386,7 +388,7 @@ return true; } - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); } namespace { @@ -488,10 +490,10 @@ literalE = UOE->getSubExpr(); } - // Only integer and floating literals; non-literals or imaginary literal - // cannot be rewritten. + // Only integer and floating literals, otherwise try to rewrite to boxed + // expression. if (!isa(literalE) && !isa(literalE)) - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); ASTContext &Ctx = NS.getASTContext(); Selector Sel = Msg->getSelector(); @@ -511,7 +513,7 @@ case NSAPI::NSNumberWithShort: case NSAPI::NSNumberWithUnsignedShort: case NSAPI::NSNumberWithBool: - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); case NSAPI::NSNumberWithUnsignedInt: case NSAPI::NSNumberWithUnsignedInteger: @@ -551,15 +553,16 @@ } // We will need to modify the literal suffix to get the same type as the call. - // Don't even try if it came from a macro. + // Try with boxed expression if it came from a macro. if (ArgRange.getBegin().isMacroID()) - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); bool LitIsFloat = ArgTy->isFloatingType(); - // For a float passed to integer call, don't try rewriting. It is difficult - // and a very uncommon case anyway. + // For a float passed to integer call, don't try rewriting to objc literal. + // It is difficult and a very uncommon case anyway. + // But try with boxed expression. if (LitIsFloat && !CallIsFloating) - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); // Try to modify the literal make it the same type as the method call. // -Modify the suffix, and/or @@ -570,11 +573,11 @@ if (const IntegerLiteral *IntE = dyn_cast(literalE)) isIntZero = !IntE->getValue().getBoolValue(); if (!getLiteralInfo(ArgRange, LitIsFloat, isIntZero, Ctx, LitInfo)) - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); // Not easy to do int -> float with hex/octal and uncommon anyway. if (!LitIsFloat && CallIsFloating && (LitInfo.Hex || LitInfo.Octal)) - return false; + return rewriteToNumericBoxedExpression(Msg, NS, commit); SourceLocation LitB = LitInfo.WithoutSuffRange.getBegin(); SourceLocation LitE = LitInfo.WithoutSuffRange.getEnd(); @@ -672,3 +675,128 @@ commit.insertWrap("(", Range, ")"); commit.insertBefore(Range.getBegin(), "(id)"); } + +//===----------------------------------------------------------------------===// +// rewriteToNumericBoxedExpression. +//===----------------------------------------------------------------------===// + +static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit) { + if (Msg->getNumArgs() != 1) + return false; + + const Expr *Arg = Msg->getArg(0); + if (Arg->isTypeDependent()) + return false; + + ASTContext &Ctx = NS.getASTContext(); + Selector Sel = Msg->getSelector(); + llvm::Optional + MKOpt = NS.getNSNumberLiteralMethodKind(Sel); + if (!MKOpt) + return false; + NSAPI::NSNumberLiteralMethodKind MK = *MKOpt; + + const Expr *OrigArg = Arg->IgnoreImpCasts(); + QualType FinalTy = Arg->getType(); + QualType OrigTy = OrigArg->getType(); + uint64_t FinalTySize = Ctx.getTypeSize(FinalTy); + uint64_t OrigTySize = Ctx.getTypeSize(OrigTy); + + bool isTruncated = FinalTySize < OrigTySize; + bool needsCast = false; + + if (const ImplicitCastExpr *ICE = dyn_cast(Arg)) { + switch (ICE->getCastKind()) { + case CK_LValueToRValue: + case CK_NoOp: + case CK_UserDefinedConversion: + break; + + case CK_IntegralCast: { + if (MK == NSAPI::NSNumberWithBool && OrigTy->isBooleanType()) + break; + // Be more liberal with Integer/UnsignedInteger which are very commonly + // used. + if ((MK == NSAPI::NSNumberWithInteger || + MK == NSAPI::NSNumberWithUnsignedInteger) && + !isTruncated) { + if (OrigTy->getAs()) + break; + if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() && + OrigTySize >= Ctx.getTypeSize(Ctx.IntTy)) + break; + } + + needsCast = true; + break; + } + + case CK_PointerToBoolean: + case CK_IntegralToBoolean: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingToBoolean: + case CK_FloatingCast: + case CK_FloatingComplexToReal: + case CK_FloatingComplexToBoolean: + case CK_IntegralComplexToReal: + case CK_IntegralComplexToBoolean: + case CK_AtomicToNonAtomic: + needsCast = true; + break; + + case CK_Dependent: + case CK_BitCast: + case CK_LValueBitCast: + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToPointer: + case CK_NullToMemberPointer: + case CK_BaseToDerivedMemberPointer: + case CK_DerivedToBaseMemberPointer: + case CK_MemberPointerToBoolean: + case CK_ReinterpretMemberPointer: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_ToVoid: + case CK_VectorSplat: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + case CK_ObjCObjectLValueCast: + case CK_FloatingRealToComplex: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralRealToComplex: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + case CK_ARCProduceObject: + case CK_ARCConsumeObject: + case CK_ARCReclaimReturnedObject: + case CK_ARCExtendBlockObject: + case CK_NonAtomicToAtomic: + case CK_CopyAndAutoreleaseBlockObject: + return false; + } + } + + if (needsCast) + return false; + + SourceRange ArgRange = OrigArg->getSourceRange(); + commit.replaceWithInner(Msg->getSourceRange(), OrigArg->getSourceRange()); + + if (isa(OrigArg) || isa(OrigArg)) + commit.insertBefore(ArgRange.getBegin(), "@"); + else + commit.insertWrap("@(", ArgRange, ")"); + + return true; +} Added: cfe/trunk/test/ARCMT/objcmt-boxing.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m?rev=156844&view=auto ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-boxing.m (added) +++ cfe/trunk/test/ARCMT/objcmt-boxing.m Tue May 15 14:17:49 2012 @@ -0,0 +1,68 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c++ +// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c++ %s.result + +#define YES __objc_yes +#define NO __objc_no + +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef signed char BOOL; +#define nil ((void*) 0) + +#define INT_MIN (-__INT_MAX__ -1) + + at interface NSObject ++ (id)alloc; + at end + + at interface NSNumber : NSObject + at end + + at interface NSNumber (NSNumberCreation) +- (id)initWithChar:(char)value; +- (id)initWithUnsignedChar:(unsigned char)value; +- (id)initWithShort:(short)value; +- (id)initWithUnsignedShort:(unsigned short)value; +- (id)initWithInt:(int)value; +- (id)initWithUnsignedInt:(unsigned int)value; +- (id)initWithLong:(long)value; +- (id)initWithUnsignedLong:(unsigned long)value; +- (id)initWithLongLong:(long long)value; +- (id)initWithUnsignedLongLong:(unsigned long long)value; +- (id)initWithFloat:(float)value; +- (id)initWithDouble:(double)value; +- (id)initWithBool:(BOOL)value; +- (id)initWithInteger:(NSInteger)value; +- (id)initWithUnsignedInteger:(NSUInteger)value; + ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; + at end + +enum MyEnm { + ME_foo +}; + +void foo() { + [NSNumber numberWithInt:INT_MIN]; + bool cppb; + [NSNumber numberWithBool:cppb]; + MyEnm myenum; + [NSNumber numberWithInteger:myenum]; + [NSNumber numberWithInteger:ME_foo]; +} Added: cfe/trunk/test/ARCMT/objcmt-boxing.m.result URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m.result?rev=156844&view=auto ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-boxing.m.result (added) +++ cfe/trunk/test/ARCMT/objcmt-boxing.m.result Tue May 15 14:17:49 2012 @@ -0,0 +1,68 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c++ +// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c++ %s.result + +#define YES __objc_yes +#define NO __objc_no + +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef signed char BOOL; +#define nil ((void*) 0) + +#define INT_MIN (-__INT_MAX__ -1) + + at interface NSObject ++ (id)alloc; + at end + + at interface NSNumber : NSObject + at end + + at interface NSNumber (NSNumberCreation) +- (id)initWithChar:(char)value; +- (id)initWithUnsignedChar:(unsigned char)value; +- (id)initWithShort:(short)value; +- (id)initWithUnsignedShort:(unsigned short)value; +- (id)initWithInt:(int)value; +- (id)initWithUnsignedInt:(unsigned int)value; +- (id)initWithLong:(long)value; +- (id)initWithUnsignedLong:(unsigned long)value; +- (id)initWithLongLong:(long long)value; +- (id)initWithUnsignedLongLong:(unsigned long long)value; +- (id)initWithFloat:(float)value; +- (id)initWithDouble:(double)value; +- (id)initWithBool:(BOOL)value; +- (id)initWithInteger:(NSInteger)value; +- (id)initWithUnsignedInteger:(NSUInteger)value; + ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; + at end + +enum MyEnm { + ME_foo +}; + +void foo() { + @INT_MIN; + bool cppb; + @(cppb); + MyEnm myenum; + @(myenum); + @(ME_foo); +} Modified: cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result?rev=156844&r1=156843&r2=156844&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result (original) +++ cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result Tue May 15 14:17:49 2012 @@ -468,7 +468,7 @@ [NSNumber numberWithInteger:NO]; [NSNumber numberWithInteger:true]; [NSNumber numberWithInteger:false]; - [NSNumber numberWithInteger:VAL_INT]; + @VAL_INT; [NSNumber numberWithInteger:VAL_UINT]; [NSNumber numberWithUnsignedInteger:'a']; @@ -498,5 +498,5 @@ [NSNumber numberWithUnsignedInteger:true]; [NSNumber numberWithUnsignedInteger:false]; [NSNumber numberWithUnsignedInteger:VAL_INT]; - [NSNumber numberWithUnsignedInteger:VAL_UINT]; + @VAL_UINT; } From ganna at apple.com Tue May 15 14:21:57 2012 From: ganna at apple.com (Anna Zaks) Date: Tue, 15 May 2012 12:21:57 -0700 Subject: [cfe-commits] [PATCH] Add analyzer_assert for regression tests In-Reply-To: <603F2830-8617-434C-BBA8-659F26524A5B@belkadan.com> References: <881546B4-753E-499A-A279-04FD0F182FEF@belkadan.com> <6A305ACC-5BF0-4281-8B01-C3F3E4228F57@apple.com> <603F2830-8617-434C-BBA8-659F26524A5B@belkadan.com> Message-ID: <08B8B6C0-175A-4DDB-9E57-265C5B0AA986@apple.com> A couple of comments: 1) Maybe we could make the name of the checker more generic as it can easily be extended to provide info other that constraints. 2) I think C.addTransition() is a no-op in this case, so the call can be removed: + // These checks should have no effect on the surrounding environment + // (globals should not be evaluated, etc). + C.addTransition(); 3) Why not support these. They will just result in several diagnostics. + // A specific instantiation of an inlined function may have more constrained + // values than can generally be assumed. + if (LC->getParent() != 0) + return true; 4) Should this be an assert? + else + Msg = "INVALID"; 5) This one is the most important. I'd only change the test cases where you are absolutely sure that the constraint solver is the only thing that's being tested there and leave the rest. It is OK to have both types of tests and we don't want to decrease our coverage of testing for actual warnings. I see this enhancement as simplifying addition of this type of tests in the future; we don't need to convert all our tests to using it. Otherwise looks great! Thanks, Anna. On May 15, 2012, at 9:15 AM, Jordan Rose wrote: > All right, version 2, with your suggestions taken into account. What do you think? > > I went with clang_analyzer_eval because it's a little shorter, but it may be a bit less clear (does it eval integers as well?). The output is in all caps to try to avoid conflicts with legitimate warnings. > > Merging the constraint and taint testers would be possible, but it's something we can do later. > > In my working branch I've identified these files as systematically using null dereferencing and malloc leaks purely for error reporting: > > additive-folding-range-constraints.c > additive-folding.c > bstring.c > constant-folding.c > ptr-arith.c > string-fail.c > string.c (in this patch) > > (Many of those files were actually originally created or reformatted by me, so that's not surprising.) > > There are several more files where the policy is not as clear, but which should probably still be using this in at least one part of the test: > > array-struct-region.c (in this patch) > base-init.cpp > dynamic-cast.cpp (some null derefs remain, since it's about pointers anyway) > global-region-invalidation.c > initializer.cpp > inline.c > method-call-intra-p.cpp > method-call.cpp > objc-arc.m > reference.cpp > > Finally, some of the "ps" miscellaneous files also use null dereferencing and deadcode warnings, but since a lot of those are taken verbatim from PRs and Radars it's possible the particular form is what triggered the past bug. I left those alone, but I'm planning to go ahead and change the other two sets above as well. > > I'm a little concerned about blame churn for the less-systematic tests, but it still seems like the right thing to do moving forward. > > Jordy > > > > // Any signature with an integral type will do. > // 'bool' would be canonical in C++. > void clang_analyzer_eval(int); > > void testUnsigned (unsigned a) { > if (a > 0) > return; > > clang_analyzer_eval(a == 0); // expected-warning{{TRUE}} > } > > void testSigned (int a) { > if (a > 0) > return; > > clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} > } > > > On May 14, 2012, at 19:40, Anna Zaks wrote: > >> Jordy, >> >> I think having something like this is a great idea. >> >>> A downside I am realizing is that silent success means the output looks the same whether debug.Asserts is on or off...not sure yet what to do about that. >> >> How about having something like "clang_analyzer_check_expr()" that always produces a warning which tells us about the expression's state, like "true", "false", "unknown"? >> >> I've added a taint debug checker, which serves similar purpose. We could also use this to check taint or other info by appending another string to the warning message "true (tainted:true)", but possibly with better markup. >> >> A few minor comments: >> - I'd prefix these asserts with "clang_analyzer". >> - We should check for undefined here. This checker is not guaranteed to be run along with other checkers. >> >> Cheers, >> Anna. > From klimek at google.com Tue May 15 14:31:41 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 21:31:41 +0200 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> Message-ID: On Mon, May 14, 2012 at 10:15 AM, Manuel Klimek wrote: > On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc > wrote: >> >> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>> >>> + ? ?@property >>> + ? ?def translation_unit(self): >>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>> + ? ? ? ?return getattr(self, '_tu', None) >>> >>> What's the reason for the default value? Do we expect that people create >>> cursers via the lowlevel calls? Why would just return tu_ not work? >> >> Just defensive programming. If you return self._tu, that may raise an >> AttributeError if _tu is not set. Theoretically, the API should ensure that >> a TU is defined on all Cursor instances, so maybe an AttributeError would be >> acceptable. > > > I'd prefer that - to me defensive programming means to: > 1. never crash for invalid user input > 2. crash hard if there's an actual bug in the library > > If the cursor should never be generated by a user (-> the contract of the > library is to not break that), I think we should use _tu and have the > AttributeError thrown if it's not there. Or I'm also fine with putting in an > assert that checks that the attribute is there and delivers a nicer error in > case it's missing. > >>> >>> + ? ? ? ?# Store a reference to the TU in the Python object so it won't >>> get GC'd >>> + ? ? ? ?# before the Cursor. >>> + ? ? ? ?tu = None >>> + ? ? ? ?for arg in args: >>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>> + ? ? ? ? ? ? ? ?tu = arg >>> + ? ? ? ? ? ? ? ?break >>> + >>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>> + ? ? ? ? ? ? ? ?break >>> + >>> + ? ? ? ?assert tu is not None >>> + >>> + ? ? ? ?res._tu = tu >>> >>> That seems - odd. I can't find docs what from_result is supposed to do, >>> or what "args" are provided. But having to search through them for a TU >>> seems wrong - shouldn't they all have a TU? >> >> from_result is the errcheck function for the ctypes functions that return >> a Cursor. The 3rd argument to an errcheck function are the original >> arguments passed into the called function. ?For many of the functions, the >> original argument is a Cursor. However, clang_getTypeDeclaration takes a >> Type and clang_getTranslationUnitCursor receives a TranslationUnit. >> >> It is true that all of the functions today receive a single argument, so >> the iteration isn't required. However, that may change with the addition of >> new APIs in the future (this is how I coded it in my nearly feature-complete >> branch, so I'm guessing it is actually required from a future patch). > > > The question is: don't we just want to assert that all of those have a TU > (or are a TU)? ^ this question is still open I think... Cheers, /Manuel From gregory.szorc at gmail.com Tue May 15 14:40:41 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 15 May 2012 12:40:41 -0700 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> Message-ID: On Tue, May 15, 2012 at 12:31 PM, Manuel Klimek wrote: > On Mon, May 14, 2012 at 10:15 AM, Manuel Klimek wrote: >> On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc >> wrote: >>> >>> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>>> >>>> + ? ?@property >>>> + ? ?def translation_unit(self): >>>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>>> + ? ? ? ?return getattr(self, '_tu', None) >>>> >>>> What's the reason for the default value? Do we expect that people create >>>> cursers via the lowlevel calls? Why would just return tu_ not work? >>> >>> Just defensive programming. If you return self._tu, that may raise an >>> AttributeError if _tu is not set. Theoretically, the API should ensure that >>> a TU is defined on all Cursor instances, so maybe an AttributeError would be >>> acceptable. >> >> >> I'd prefer that - to me defensive programming means to: >> 1. never crash for invalid user input >> 2. crash hard if there's an actual bug in the library >> >> If the cursor should never be generated by a user (-> the contract of the >> library is to not break that), I think we should use _tu and have the >> AttributeError thrown if it's not there. Or I'm also fine with putting in an >> assert that checks that the attribute is there and delivers a nicer error in >> case it's missing. >> >>>> >>>> + ? ? ? ?# Store a reference to the TU in the Python object so it won't >>>> get GC'd >>>> + ? ? ? ?# before the Cursor. >>>> + ? ? ? ?tu = None >>>> + ? ? ? ?for arg in args: >>>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>>> + ? ? ? ? ? ? ? ?tu = arg >>>> + ? ? ? ? ? ? ? ?break >>>> + >>>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>>> + ? ? ? ? ? ? ? ?break >>>> + >>>> + ? ? ? ?assert tu is not None >>>> + >>>> + ? ? ? ?res._tu = tu >>>> >>>> That seems - odd. I can't find docs what from_result is supposed to do, >>>> or what "args" are provided. But having to search through them for a TU >>>> seems wrong - shouldn't they all have a TU? >>> >>> from_result is the errcheck function for the ctypes functions that return >>> a Cursor. The 3rd argument to an errcheck function are the original >>> arguments passed into the called function. ?For many of the functions, the >>> original argument is a Cursor. However, clang_getTypeDeclaration takes a >>> Type and clang_getTranslationUnitCursor receives a TranslationUnit. >>> >>> It is true that all of the functions today receive a single argument, so >>> the iteration isn't required. However, that may change with the addition of >>> new APIs in the future (this is how I coded it in my nearly feature-complete >>> branch, so I'm guessing it is actually required from a future patch). >> >> >> The question is: don't we just want to assert that all of those have a TU >> (or are a TU)? > > ^ this question is still open I think... I don't think it is. Both modified from_result functions now assert if a TU could not be found. Or, are you asking for something more? In the future, every live object will likely hold a reference to a TU. We aren't there quite yet. But, this patch is a step in the right direction. From daniel at zuster.org Tue May 15 14:45:08 2012 From: daniel at zuster.org (Daniel Dunbar) Date: Tue, 15 May 2012 12:45:08 -0700 Subject: [cfe-commits] r156180 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp In-Reply-To: <20120504171000.5A2F42A6C067@llvm.org> References: <20120504171000.5A2F42A6C067@llvm.org> Message-ID: Hey Doug, There is a test failing on this bot, looks most likely to be yours? http://lab.llvm.org:8011/builders/clang-x86_64-debian-selfhost-rel/builds/2943 Not sure if this is known... - Daniel On Fri, May 4, 2012 at 10:10 AM, Douglas Gregor wrote: > Author: dgregor > Date: Fri May ?4 12:09:59 2012 > New Revision: 156180 > > URL: http://llvm.org/viewvc/llvm-project?rev=156180&view=rev > Log: > Move Sema::RequireNonAbstractType() off of PartialDiagnostic. > > Modified: > ? ?cfe/trunk/include/clang/Sema/Sema.h > ? ?cfe/trunk/lib/Sema/SemaDeclCXX.cpp > ? ?cfe/trunk/lib/Sema/SemaExpr.cpp > ? ?cfe/trunk/lib/Sema/SemaExprCXX.cpp > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=156180&r1=156179&r2=156180&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Fri May ?4 12:09:59 2012 > @@ -4423,7 +4423,31 @@ > ? }; > > ? bool RequireNonAbstractType(SourceLocation Loc, QualType T, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const PartialDiagnostic &PD); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?TypeDiagnoser &Diagnoser); > + ?template > + ?bool RequireNonAbstractType(SourceLocation Loc, QualType T, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned DiagID, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const T1 &Arg1) { > + ? ?BoundTypeDiagnoser1 Diagnoser(DiagID, Arg1); > + ? ?return RequireNonAbstractType(Loc, T, Diagnoser); > + ?} > + > + ?template > + ?bool RequireNonAbstractType(SourceLocation Loc, QualType T, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned DiagID, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const T1 &Arg1, const T2 &Arg2) { > + ? ?BoundTypeDiagnoser2 Diagnoser(DiagID, Arg1, Arg2); > + ? ?return RequireNonAbstractType(Loc, T, Diagnoser); > + ?} > + > + ?template > + ?bool RequireNonAbstractType(SourceLocation Loc, QualType T, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned DiagID, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const T1 &Arg1, const T2 &Arg2, const T3 &Arg3) { > + ? ?BoundTypeDiagnoser3 Diagnoser(DiagID, Arg1, Arg2, Arg3); > + ? ?return RequireNonAbstractType(Loc, T, Diagnoser); > + ?} > + > ? void DiagnoseAbstractType(const CXXRecordDecl *RD); > > ? bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, > > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=156180&r1=156179&r2=156180&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri May ?4 12:09:59 2012 > @@ -3396,19 +3396,32 @@ > > ?bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned DiagID, AbstractDiagSelID SelID) { > - ?if (SelID == -1) > - ? ?return RequireNonAbstractType(Loc, T, PDiag(DiagID)); > - ?else > - ? ?return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID); > + ?class NonAbstractTypeDiagnoser : public TypeDiagnoser { > + ? ?unsigned DiagID; > + ? ?AbstractDiagSelID SelID; > + > + ?public: > + ? ?NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID) > + ? ? ?: TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { } > + > + ? ?virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { > + ? ? ?if (SelID == -1) > + ? ? ? ?S.Diag(Loc, DiagID) << T; > + ? ? ?else > + ? ? ? ?S.Diag(Loc, DiagID) << SelID << T; > + ? ?} > + ?} Diagnoser(DiagID, SelID); > + > + ?return RequireNonAbstractType(Loc, T, Diagnoser); > ?} > > ?bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const PartialDiagnostic &PD) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?TypeDiagnoser &Diagnoser) { > ? if (!getLangOpts().CPlusPlus) > ? ? return false; > > ? if (const ArrayType *AT = Context.getAsArrayType(T)) > - ? ?return RequireNonAbstractType(Loc, AT->getElementType(), PD); > + ? ?return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); > > ? if (const PointerType *PT = T->getAs()) { > ? ? // Find the innermost pointer type. > @@ -3416,7 +3429,7 @@ > ? ? ? PT = T; > > ? ? if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) > - ? ? ?return RequireNonAbstractType(Loc, AT->getElementType(), PD); > + ? ? ?return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); > ? } > > ? const RecordType *RT = T->getAs(); > @@ -3435,7 +3448,7 @@ > ? if (!RD->isAbstract()) > ? ? return false; > > - ?Diag(Loc, PD) << RD->getDeclName(); > + ?Diagnoser.diagnose(*this, Loc, T); > ? DiagnoseAbstractType(RD); > > ? return true; > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=156180&r1=156179&r2=156180&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri May ?4 12:09:59 2012 > @@ -9205,9 +9205,9 @@ > ? ? ? return ExprError(); > > ? ? if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(), > - ? ? ? ? ?TInfo->getType(), > - ? ? ? ? ?PDiag(diag::err_second_parameter_to_va_arg_abstract) > - ? ? ? ? ?<< TInfo->getTypeLoc().getSourceRange())) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TInfo->getType(), > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? diag::err_second_parameter_to_va_arg_abstract, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TInfo->getTypeLoc())) > ? ? ? return ExprError(); > > ? ? if (!TInfo->getType().isPODType(Context)) { > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=156180&r1=156179&r2=156180&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri May ?4 12:09:59 2012 > @@ -590,8 +590,7 @@ > ? ? ? return ExprError(); > > ? ? if (RequireNonAbstractType(ThrowLoc, E->getType(), > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PDiag(diag::err_throw_abstract_type) > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? << E->getSourceRange())) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? diag::err_throw_abstract_type, E)) > ? ? ? return ExprError(); > ? } > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From klimek at google.com Tue May 15 14:45:53 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 21:45:53 +0200 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> Message-ID: On Tue, May 15, 2012 at 9:40 PM, Gregory Szorc wrote: > On Tue, May 15, 2012 at 12:31 PM, Manuel Klimek wrote: >> On Mon, May 14, 2012 at 10:15 AM, Manuel Klimek wrote: >>> On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc >>> wrote: >>>> >>>> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>>>> >>>>> + ? ?@property >>>>> + ? ?def translation_unit(self): >>>>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>>>> + ? ? ? ?return getattr(self, '_tu', None) >>>>> >>>>> What's the reason for the default value? Do we expect that people create >>>>> cursers via the lowlevel calls? Why would just return tu_ not work? >>>> >>>> Just defensive programming. If you return self._tu, that may raise an >>>> AttributeError if _tu is not set. Theoretically, the API should ensure that >>>> a TU is defined on all Cursor instances, so maybe an AttributeError would be >>>> acceptable. >>> >>> >>> I'd prefer that - to me defensive programming means to: >>> 1. never crash for invalid user input >>> 2. crash hard if there's an actual bug in the library >>> >>> If the cursor should never be generated by a user (-> the contract of the >>> library is to not break that), I think we should use _tu and have the >>> AttributeError thrown if it's not there. Or I'm also fine with putting in an >>> assert that checks that the attribute is there and delivers a nicer error in >>> case it's missing. >>> >>>>> >>>>> + ? ? ? ?# Store a reference to the TU in the Python object so it won't >>>>> get GC'd >>>>> + ? ? ? ?# before the Cursor. >>>>> + ? ? ? ?tu = None >>>>> + ? ? ? ?for arg in args: >>>>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>>>> + ? ? ? ? ? ? ? ?tu = arg >>>>> + ? ? ? ? ? ? ? ?break >>>>> + >>>>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>>>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>>>> + ? ? ? ? ? ? ? ?break >>>>> + >>>>> + ? ? ? ?assert tu is not None >>>>> + >>>>> + ? ? ? ?res._tu = tu >>>>> >>>>> That seems - odd. I can't find docs what from_result is supposed to do, >>>>> or what "args" are provided. But having to search through them for a TU >>>>> seems wrong - shouldn't they all have a TU? >>>> >>>> from_result is the errcheck function for the ctypes functions that return >>>> a Cursor. The 3rd argument to an errcheck function are the original >>>> arguments passed into the called function. ?For many of the functions, the >>>> original argument is a Cursor. However, clang_getTypeDeclaration takes a >>>> Type and clang_getTranslationUnitCursor receives a TranslationUnit. >>>> >>>> It is true that all of the functions today receive a single argument, so >>>> the iteration isn't required. However, that may change with the addition of >>>> new APIs in the future (this is how I coded it in my nearly feature-complete >>>> branch, so I'm guessing it is actually required from a future patch). >>> >>> >>> The question is: don't we just want to assert that all of those have a TU >>> (or are a TU)? >> >> ^ this question is still open I think... > > I don't think it is. Both modified from_result functions now assert if > a TU could not be found. > > Or, are you asking for something more? In the future, every live > object will likely hold a reference to a TU. We aren't there quite > yet. But, this patch is a step in the right direction. Ah, ok, that was my question - why not every object has a TU and we can assert *for every object* that it has a TU. If that's a follow-up step, then LGTM. Cheers, /Manuel From gregory.szorc at gmail.com Tue May 15 14:51:02 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 15 May 2012 19:51:02 -0000 Subject: [cfe-commits] r156846 - in /cfe/trunk/bindings/python: clang/cindex.py tests/cindex/test_cursor.py tests/cindex/test_type.py Message-ID: <20120515195103.04E212A6C065@llvm.org> Author: gps Date: Tue May 15 14:51:02 2012 New Revision: 156846 URL: http://llvm.org/viewvc/llvm-project?rev=156846&view=rev Log: [clang.py] Store reference to TranslationUnit in Cursor and Type Modified: cfe/trunk/bindings/python/clang/cindex.py cfe/trunk/bindings/python/tests/cindex/test_cursor.py cfe/trunk/bindings/python/tests/cindex/test_type.py Modified: cfe/trunk/bindings/python/clang/cindex.py URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=156846&r1=156845&r2=156846&view=diff ============================================================================== --- cfe/trunk/bindings/python/clang/cindex.py (original) +++ cfe/trunk/bindings/python/clang/cindex.py Tue May 15 14:51:02 2012 @@ -929,7 +929,12 @@ @staticmethod def from_location(tu, location): - return Cursor_get(tu, location) + # We store a reference to the TU in the instance so the TU won't get + # collected before the cursor. + cursor = Cursor_get(tu, location) + cursor._tu = tu + + return cursor def __eq__(self, other): return Cursor_eq(self, other) @@ -1127,6 +1132,13 @@ return self._lexical_parent + @property + def translation_unit(self): + """Returns the TranslationUnit to which this Cursor belongs.""" + # If this triggers an AttributeError, the instance was not properly + # created. + return self._tu + def get_children(self): """Return an iterator for accessing the children of this cursor.""" @@ -1135,6 +1147,9 @@ # FIXME: Document this assertion in API. # FIXME: There should just be an isNull method. assert child != Cursor_null() + + # Create reference to TU so it isn't GC'd before Cursor. + child._tu = self._tu children.append(child) return 1 # continue children = [] @@ -1147,6 +1162,22 @@ # FIXME: There should just be an isNull method. if res == Cursor_null(): return None + + # Store a reference to the TU in the Python object so it won't get GC'd + # before the Cursor. + tu = None + for arg in args: + if isinstance(arg, TranslationUnit): + tu = arg + break + + if hasattr(arg, 'translation_unit'): + tu = arg.translation_unit + break + + assert tu is not None + + res._tu = tu return res @@ -1324,9 +1355,26 @@ return result + @property + def translation_unit(self): + """The TranslationUnit to which this Type is associated.""" + # If this triggers an AttributeError, the instance was not properly + # instantiated. + return self._tu + @staticmethod def from_result(res, fn, args): assert isinstance(res, Type) + + tu = None + for arg in args: + if hasattr(arg, 'translation_unit'): + tu = arg.translation_unit + break + + assert tu is not None + res._tu = tu + return res def get_canonical(self): Modified: cfe/trunk/bindings/python/tests/cindex/test_cursor.py URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/cindex/test_cursor.py?rev=156846&r1=156845&r2=156846&view=diff ============================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_cursor.py (original) +++ cfe/trunk/bindings/python/tests/cindex/test_cursor.py Tue May 15 14:51:02 2012 @@ -1,4 +1,7 @@ +import gc + from clang.cindex import CursorKind +from clang.cindex import TranslationUnit from clang.cindex import TypeKind from .util import get_cursor from .util import get_cursors @@ -38,6 +41,8 @@ tu_nodes = list(it) assert len(tu_nodes) == 3 + for cursor in tu_nodes: + assert cursor.translation_unit is not None assert tu_nodes[0] != tu_nodes[1] assert tu_nodes[0].kind == CursorKind.STRUCT_DECL @@ -47,6 +52,7 @@ assert tu_nodes[0].location.line == 4 assert tu_nodes[0].location.column == 8 assert tu_nodes[0].hash > 0 + assert tu_nodes[0].translation_unit is not None s0_nodes = list(tu_nodes[0].get_children()) assert len(s0_nodes) == 2 @@ -67,6 +73,23 @@ assert tu_nodes[2].displayname == 'f0(int, int)' assert tu_nodes[2].is_definition() == True +def test_references(): + """Ensure that references to TranslationUnit are kept.""" + tu = get_tu('int x;') + cursors = list(tu.cursor.get_children()) + assert len(cursors) > 0 + + cursor = cursors[0] + assert isinstance(cursor.translation_unit, TranslationUnit) + + # Delete reference to TU and perform a full GC. + del tu + gc.collect() + assert isinstance(cursor.translation_unit, TranslationUnit) + + # If the TU was destroyed, this should cause a segfault. + parent = cursor.semantic_parent + def test_canonical(): source = 'struct X; struct X; struct X { int member; };' tu = get_tu(source) Modified: cfe/trunk/bindings/python/tests/cindex/test_type.py URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/cindex/test_type.py?rev=156846&r1=156845&r2=156846&view=diff ============================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_type.py (original) +++ cfe/trunk/bindings/python/tests/cindex/test_type.py Tue May 15 14:51:02 2012 @@ -1,4 +1,7 @@ +import gc + from clang.cindex import CursorKind +from clang.cindex import TranslationUnit from clang.cindex import TypeKind from nose.tools import raises from .util import get_cursor @@ -28,6 +31,7 @@ assert teststruct is not None, "Could not find teststruct." fields = list(teststruct.get_children()) assert all(x.kind == CursorKind.FIELD_DECL for x in fields) + assert all(x.translation_unit is not None for x in fields) assert fields[0].spelling == 'a' assert not fields[0].type.is_const_qualified() @@ -72,6 +76,26 @@ assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT +def test_references(): + """Ensure that a Type maintains a reference to a TranslationUnit.""" + + tu = get_tu('int x;') + children = list(tu.cursor.get_children()) + assert len(children) > 0 + + cursor = children[0] + t = cursor.type + + assert isinstance(t.translation_unit, TranslationUnit) + + # Delete main TranslationUnit reference and force a GC. + del tu + gc.collect() + assert isinstance(t.translation_unit, TranslationUnit) + + # If the TU was destroyed, this should cause a segfault. + decl = t.get_declaration() + constarrayInput=""" struct teststruct { void *A[2]; From gregory.szorc at gmail.com Tue May 15 14:52:21 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 15 May 2012 12:52:21 -0700 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> Message-ID: On Tue, May 15, 2012 at 12:45 PM, Manuel Klimek wrote: > On Tue, May 15, 2012 at 9:40 PM, Gregory Szorc wrote: >> On Tue, May 15, 2012 at 12:31 PM, Manuel Klimek wrote: >>> On Mon, May 14, 2012 at 10:15 AM, Manuel Klimek wrote: >>>> On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc >>>> wrote: >>>>> >>>>> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>>>>> >>>>>> + ? ?@property >>>>>> + ? ?def translation_unit(self): >>>>>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>>>>> + ? ? ? ?return getattr(self, '_tu', None) >>>>>> >>>>>> What's the reason for the default value? Do we expect that people create >>>>>> cursers via the lowlevel calls? Why would just return tu_ not work? >>>>> >>>>> Just defensive programming. If you return self._tu, that may raise an >>>>> AttributeError if _tu is not set. Theoretically, the API should ensure that >>>>> a TU is defined on all Cursor instances, so maybe an AttributeError would be >>>>> acceptable. >>>> >>>> >>>> I'd prefer that - to me defensive programming means to: >>>> 1. never crash for invalid user input >>>> 2. crash hard if there's an actual bug in the library >>>> >>>> If the cursor should never be generated by a user (-> the contract of the >>>> library is to not break that), I think we should use _tu and have the >>>> AttributeError thrown if it's not there. Or I'm also fine with putting in an >>>> assert that checks that the attribute is there and delivers a nicer error in >>>> case it's missing. >>>> >>>>>> >>>>>> + ? ? ? ?# Store a reference to the TU in the Python object so it won't >>>>>> get GC'd >>>>>> + ? ? ? ?# before the Cursor. >>>>>> + ? ? ? ?tu = None >>>>>> + ? ? ? ?for arg in args: >>>>>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>>>>> + ? ? ? ? ? ? ? ?tu = arg >>>>>> + ? ? ? ? ? ? ? ?break >>>>>> + >>>>>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>>>>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>>>>> + ? ? ? ? ? ? ? ?break >>>>>> + >>>>>> + ? ? ? ?assert tu is not None >>>>>> + >>>>>> + ? ? ? ?res._tu = tu >>>>>> >>>>>> That seems - odd. I can't find docs what from_result is supposed to do, >>>>>> or what "args" are provided. But having to search through them for a TU >>>>>> seems wrong - shouldn't they all have a TU? >>>>> >>>>> from_result is the errcheck function for the ctypes functions that return >>>>> a Cursor. The 3rd argument to an errcheck function are the original >>>>> arguments passed into the called function. ?For many of the functions, the >>>>> original argument is a Cursor. However, clang_getTypeDeclaration takes a >>>>> Type and clang_getTranslationUnitCursor receives a TranslationUnit. >>>>> >>>>> It is true that all of the functions today receive a single argument, so >>>>> the iteration isn't required. However, that may change with the addition of >>>>> new APIs in the future (this is how I coded it in my nearly feature-complete >>>>> branch, so I'm guessing it is actually required from a future patch). >>>> >>>> >>>> The question is: don't we just want to assert that all of those have a TU >>>> (or are a TU)? >>> >>> ^ this question is still open I think... >> >> I don't think it is. Both modified from_result functions now assert if >> a TU could not be found. >> >> Or, are you asking for something more? In the future, every live >> object will likely hold a reference to a TU. We aren't there quite >> yet. But, this patch is a step in the right direction. > > Ah, ok, that was my question - why not every object has a TU and we > can assert *for every object* that it has a TU. If that's a follow-up > step, then LGTM. Well, in the case of from_result (or any errcheck function), not every argument to the original function may have a TU attached. e.g. integer arguments. Anyway... Committing to https://llvm.org/svn/llvm-project/cfe/trunk ... M bindings/python/clang/cindex.py M bindings/python/tests/cindex/test_cursor.py M bindings/python/tests/cindex/test_type.py Committed r156846 From klimek at google.com Tue May 15 14:55:04 2012 From: klimek at google.com (Manuel Klimek) Date: Tue, 15 May 2012 21:55:04 +0200 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> Message-ID: On Tue, May 15, 2012 at 9:52 PM, Gregory Szorc wrote: > On Tue, May 15, 2012 at 12:45 PM, Manuel Klimek wrote: >> On Tue, May 15, 2012 at 9:40 PM, Gregory Szorc wrote: >>> On Tue, May 15, 2012 at 12:31 PM, Manuel Klimek wrote: >>>> On Mon, May 14, 2012 at 10:15 AM, Manuel Klimek wrote: >>>>> On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc >>>>> wrote: >>>>>> >>>>>> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>>>>>> >>>>>>> + ? ?@property >>>>>>> + ? ?def translation_unit(self): >>>>>>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>>>>>> + ? ? ? ?return getattr(self, '_tu', None) >>>>>>> >>>>>>> What's the reason for the default value? Do we expect that people create >>>>>>> cursers via the lowlevel calls? Why would just return tu_ not work? >>>>>> >>>>>> Just defensive programming. If you return self._tu, that may raise an >>>>>> AttributeError if _tu is not set. Theoretically, the API should ensure that >>>>>> a TU is defined on all Cursor instances, so maybe an AttributeError would be >>>>>> acceptable. >>>>> >>>>> >>>>> I'd prefer that - to me defensive programming means to: >>>>> 1. never crash for invalid user input >>>>> 2. crash hard if there's an actual bug in the library >>>>> >>>>> If the cursor should never be generated by a user (-> the contract of the >>>>> library is to not break that), I think we should use _tu and have the >>>>> AttributeError thrown if it's not there. Or I'm also fine with putting in an >>>>> assert that checks that the attribute is there and delivers a nicer error in >>>>> case it's missing. >>>>> >>>>>>> >>>>>>> + ? ? ? ?# Store a reference to the TU in the Python object so it won't >>>>>>> get GC'd >>>>>>> + ? ? ? ?# before the Cursor. >>>>>>> + ? ? ? ?tu = None >>>>>>> + ? ? ? ?for arg in args: >>>>>>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>>>>>> + ? ? ? ? ? ? ? ?tu = arg >>>>>>> + ? ? ? ? ? ? ? ?break >>>>>>> + >>>>>>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>>>>>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>>>>>> + ? ? ? ? ? ? ? ?break >>>>>>> + >>>>>>> + ? ? ? ?assert tu is not None >>>>>>> + >>>>>>> + ? ? ? ?res._tu = tu >>>>>>> >>>>>>> That seems - odd. I can't find docs what from_result is supposed to do, >>>>>>> or what "args" are provided. But having to search through them for a TU >>>>>>> seems wrong - shouldn't they all have a TU? >>>>>> >>>>>> from_result is the errcheck function for the ctypes functions that return >>>>>> a Cursor. The 3rd argument to an errcheck function are the original >>>>>> arguments passed into the called function. ?For many of the functions, the >>>>>> original argument is a Cursor. However, clang_getTypeDeclaration takes a >>>>>> Type and clang_getTranslationUnitCursor receives a TranslationUnit. >>>>>> >>>>>> It is true that all of the functions today receive a single argument, so >>>>>> the iteration isn't required. However, that may change with the addition of >>>>>> new APIs in the future (this is how I coded it in my nearly feature-complete >>>>>> branch, so I'm guessing it is actually required from a future patch). >>>>> >>>>> >>>>> The question is: don't we just want to assert that all of those have a TU >>>>> (or are a TU)? >>>> >>>> ^ this question is still open I think... >>> >>> I don't think it is. Both modified from_result functions now assert if >>> a TU could not be found. >>> >>> Or, are you asking for something more? In the future, every live >>> object will likely hold a reference to a TU. We aren't there quite >>> yet. But, this patch is a step in the right direction. >> >> Ah, ok, that was my question - why not every object has a TU and we >> can assert *for every object* that it has a TU. If that's a follow-up >> step, then LGTM. > > Well, in the case of from_result (or any errcheck function), not every > argument to the original function may have a TU attached. e.g. integer > arguments. So that means we cannot even be sure that we'll always find a TU? Still trying to understand from_result better. Confused, /Manuel From fjahanian at apple.com Tue May 15 15:05:24 2012 From: fjahanian at apple.com (jahanian) Date: Tue, 15 May 2012 13:05:24 -0700 Subject: [cfe-commits] r156843 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExprObjC.cpp test/SemaObjC/boxing-illegal-types.m test/SemaObjCXX/boxing-illegal-types.mm In-Reply-To: <20120515191744.EDEBB2A6C065@llvm.org> References: <20120515191744.EDEBB2A6C065@llvm.org> Message-ID: Couple of comments. Documentation need be updated to document what the type of the enum expression will be; is it the underlying type or a promoted type? This will influence what method being selected. Please provide a CodeGenObjC test case showing the selected method. - fariborz On May 15, 2012, at 12:17 PM, Argyrios Kyrtzidis wrote: > Author: akirtzidis > Date: Tue May 15 14:17:44 2012 > New Revision: 156843 > > URL: http://llvm.org/viewvc/llvm-project?rev=156843&view=rev > Log: > Allow objc @() syntax for enum types. > > Previously we would reject it as illegal using a value of > enum type and on ObjC++ it was illegal to use an enumerator > as well. > > rdar://11454917 > > Added: > cfe/trunk/test/SemaObjCXX/boxing-illegal-types.mm > Modified: > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/lib/Sema/SemaExprObjC.cpp > cfe/trunk/test/SemaObjC/boxing-illegal-types.m From thakis at chromium.org Tue May 15 15:09:40 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 15 May 2012 13:09:40 -0700 Subject: [cfe-commits] r156821 - in /cfe/trunk: include/clang/Basic/Attr.td lib/AST/Decl.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGenCXX/visibility.cpp utils/TableGen/ClangAttrEmitter.cpp In-Reply-To: <20120515140956.7FABE2A6C065@llvm.org> References: <20120515140956.7FABE2A6C065@llvm.org> Message-ID: Hi Rafael, I have a reduced repro for the regression caused by this CL (as mentioned in IRC). I attached it to http://llvm.org/PR12835 Nico On Tue, May 15, 2012 at 7:09 AM, Rafael Espindola < rafael.espindola at gmail.com> wrote: > Author: rafael > Date: Tue May 15 09:09:55 2012 > New Revision: 156821 > > URL: http://llvm.org/viewvc/llvm-project?rev=156821&view=rev > Log: > Fix our handling of visibility in explicit template instantiations. > > * Don't copy the visibility attribute during instantiations. We have to be > able > to distinguish > > struct HIDDEN foo {}; > template > DEFAULT void bar() {} > template DEFAULT void bar(); > > from > > struct HIDDEN foo {}; > template > DEFAULT void bar() {} > template void bar(); > > * If an instantiation has an attribute, it takes precedence over an > attribute > in the template. > > * With instantiation attributes handled with the above logic, we can now > select the minimum visibility when looking at template arguments. > > Modified: > cfe/trunk/include/clang/Basic/Attr.td > cfe/trunk/lib/AST/Decl.cpp > cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > cfe/trunk/test/CodeGenCXX/visibility.cpp > cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp > > Modified: cfe/trunk/include/clang/Basic/Attr.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=156821&r1=156820&r2=156821&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/Attr.td (original) > +++ cfe/trunk/include/clang/Basic/Attr.td Tue May 15 09:09:55 2012 > @@ -93,6 +93,9 @@ > list Namespaces = []; > // Set to true for attributes with arguments which require delayed > parsing. > bit LateParsed = 0; > + // Set to false to prevent an attribute from being propagated from a > template > + // to the instantiation. > + bit Clone = 1; > // Set to true for attributes which must be instantiated within templates > bit TemplateDependent = 0; > // Set to true for attributes that have a corresponding AST node. > @@ -660,6 +663,7 @@ > } > > def Visibility : InheritableAttr { > + let Clone = 0; > let Spellings = ["visibility"]; > let Args = [EnumArgument<"Visibility", "VisibilityType", > ["default", "hidden", "internal", "protected"], > > Modified: cfe/trunk/lib/AST/Decl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=156821&r1=156820&r2=156821&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/Decl.cpp (original) > +++ cfe/trunk/lib/AST/Decl.cpp Tue May 15 09:09:55 2012 > @@ -158,14 +158,12 @@ > return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), > OnlyTemplate); > } > > -static bool shouldConsiderTemplateLV(const FunctionDecl *fn, > - const FunctionTemplateSpecializationInfo > *spec) { > - return !(spec->isExplicitSpecialization() && > - fn->hasAttr()); > +static bool shouldConsiderTemplateLV(const FunctionDecl *fn) { > + return !fn->hasAttr(); > } > > static bool shouldConsiderTemplateLV(const > ClassTemplateSpecializationDecl *d) { > - return !(d->isExplicitSpecialization() && d->hasAttr()); > + return !d->hasAttr(); > } > > static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, > @@ -376,7 +374,7 @@ > // this is an explicit specialization with a visibility attribute. > if (FunctionTemplateSpecializationInfo *specInfo > = > Function->getTemplateSpecializationInfo()) { > - if (shouldConsiderTemplateLV(Function, specInfo)) { > + if (shouldConsiderTemplateLV(Function)) { > LV.merge(getLVForDecl(specInfo->getTemplate(), > true)); > const TemplateArgumentList &templateArgs = > *specInfo->TemplateArguments; > @@ -407,8 +405,8 @@ > > // The arguments at which the template was instantiated. > const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); > - LV.merge(getLVForTemplateArgumentList(TemplateArgs, > - OnlyTemplate)); > + LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs, > + OnlyTemplate)); > } > } > > @@ -527,7 +525,7 @@ > // the template parameters and arguments. > if (FunctionTemplateSpecializationInfo *spec > = MD->getTemplateSpecializationInfo()) { > - if (shouldConsiderTemplateLV(MD, spec)) { > + if (shouldConsiderTemplateLV(MD)) { > > LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments, > OnlyTemplate)); > if (!OnlyTemplate) > > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=156821&r1=156820&r2=156821&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue May 15 09:09:55 > 2012 > @@ -102,7 +102,8 @@ > } else { > Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, > *this, > TemplateArgs); > - New->addAttr(NewAttr); > + if (NewAttr) > + New->addAttr(NewAttr); > } > } > } > > Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=156821&r1=156820&r2=156821&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/visibility.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/visibility.cpp Tue May 15 09:09:55 2012 > @@ -712,3 +712,55 @@ > // CHECK: define weak_odr hidden void > @_ZN6test363fooINS_2S1ENS_2S2EE3barEv > // CHECK-HIDDEN: define weak_odr hidden void > @_ZN6test363fooINS_2S1ENS_2S2EE3barEv > } > + > +namespace test37 { > + struct HIDDEN foo { > + }; > + template > + DEFAULT void bar() {} > + template DEFAULT void bar(); > + // CHECK: define weak_odr void @_ZN6test373barINS_3fooEEEvv > + // CHECK-HIDDEN: define weak_odr void @_ZN6test373barINS_3fooEEEvv > +} > + > +namespace test38 { > + template > + class DEFAULT foo { > + void bar() {} > + }; > + struct HIDDEN zed { > + }; > + template class foo; > + // CHECK: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv > + // CHECK-HIDDEN: define weak_odr hidden void > @_ZN6test383fooINS_3zedEE3barEv > +} > + > +namespace test39 { > + class DEFAULT default_t; > + class HIDDEN hidden_t; > + template class A { > + template class B { > + HIDDEN void hidden() {} > + void noattr() {} > + template void temp() {} > + }; > + }; > + template class DEFAULT A; > + template class DEFAULT A::B; > + template void A::B::temp(); > + template void A::B::temp(); > + > + // CHECK: define weak_odr hidden void > @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv > + // CHECK: define weak_odr void > @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv > + // CHECK: define weak_odr void > @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv > + > + // GCC produces a default for this one. Why? > + // CHECK: define weak_odr hidden void > @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv > + > + // CHECK-HIDDEN: define weak_odr hidden void > @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv > + // CHECK-HIDDEN: define weak_odr void > @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv > + // CHECK-HIDDEN: define weak_odr void > @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv > + > + // GCC produces a default for this one. Why? > + // CHECK-HIDDEN: define weak_odr hidden void > @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv > +} > > Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=156821&r1=156820&r2=156821&view=diff > > ============================================================================== > --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original) > +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Tue May 15 09:09:55 2012 > @@ -1004,6 +1004,14 @@ > continue; > > OS << " case attr::" << R.getName() << ": {\n"; > + bool ShouldClone = R.getValueAsBit("Clone"); > + > + if (!ShouldClone) { > + OS << " return NULL;\n"; > + OS << " }\n"; > + continue; > + } > + > OS << " const " << R.getName() << "Attr *A = cast<" > << R.getName() << "Attr>(At);\n"; > bool TDependent = R.getValueAsBit("TemplateDependent"); > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/59ea14d9/attachment-0001.html From dgregor at apple.com Tue May 15 15:09:08 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 13:09:08 -0700 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics In-Reply-To: References: Message-ID: <71F9C9BF-830D-4ADC-A751-0A9E4FCA9225@apple.com> On May 15, 2012, at 9:05 AM, Terry Long wrote: > Hi all, > > This patch mostly inspired by http://llvm.org/bugs/show_bug.cgi?id=9243 -- poor "duplicate case" diagnostic with enums > > Previously the diagnostic for duplicate case values in switch statements was always something like "duplicate case value '5'" > > What my patch changes: > When the duplicate case is exactly the same in textual representation (in source code), the diagnostic will use that exact text in the diagnostic. > e.g. using MyEnum twice gives the diagnostic "duplicate case value 'MyEnum'" > > If the textual representations differ, the new diagnostic explicitly states they are equal to the same value > e.g. using MyEnum (equal to 5) and 5, the diagnostic displays "duplicate case value: 'MyEnum' and '5' both equal '5'" > > The patch does the same for any valid expression in a case statement (including macros, const ints, char literals, etc.). I'm a bit uncomfortable with the textual approach here. Why not analyze the expressions to check whether they are references to named declarations, and use those names in the diagnostic? It won't catch some macro cases, but it's far simpler. - Doug From jediknil at belkadan.com Tue May 15 15:19:44 2012 From: jediknil at belkadan.com (Jordan Rose) Date: Tue, 15 May 2012 16:19:44 -0400 Subject: [cfe-commits] [PATCH] Add analyzer_assert for regression tests In-Reply-To: <08B8B6C0-175A-4DDB-9E57-265C5B0AA986@apple.com> References: <881546B4-753E-499A-A279-04FD0F182FEF@belkadan.com> <6A305ACC-5BF0-4281-8B01-C3F3E4228F57@apple.com> <603F2830-8617-434C-BBA8-659F26524A5B@belkadan.com> <08B8B6C0-175A-4DDB-9E57-265C5B0AA986@apple.com> Message-ID: <85DF843B-246E-4F10-A116-F2A43E396AA0@belkadan.com> On May 15, 2012, at 15:21, Anna Zaks wrote: > A couple of comments: > > 1) Maybe we could make the name of the checker more generic as it can easily be extended to provide info other that constraints. Hm. debug.StateInspection? debug.Reflection? debug.Introspection? > 2) I think C.addTransition() is a no-op in this case, so the call can be removed: > + // These checks should have no effect on the surrounding environment > + // (globals should not be evaluated, etc). > + C.addTransition(); Hm. Wasn't sure how that interacted with evalCall, but you're right. > 3) Why not support these. They will just result in several diagnostics. > + // A specific instantiation of an inlined function may have more constrained > + // values than can generally be assumed. > + if (LC->getParent() != 0) > + return true; I actually came across this when converting existing tests. Here's a trivial example where a constraint is generally unknowable but is known when inlined. void check(void *x) { clang_analyzer_check(x != 0); // expected-warning{{UNKNOWN}} } void test() { check(0); } For the case of TRUE or FALSE there would be no change, but UNKNOWN is a problem. (In the previous iteration, these were separated into analyzer_assert and analyzer_assert_unknown, but I don't think it's necessary to check that something is true generally /and/ in a specific inlined case.) > 4) Should this be an assert? > + else > + Msg = "INVALID"; I'm not sure. The analyzer will probably grind to a halt long before it gets here, but if someone ever /does/ make a logical mistake on the infrastructure that results in this situation (testing a constraint results in two infeasible states, even with a feasible base state), it might be nicer /not/ to stop analysis here. Since these are intended to go in regression tests, the fact that the test was known to work before might be useful knowledge, in which case it should go on being tested. I don't have a strong opinion here, but it doesn't seem to cost much. All we're doing is emitting a warning, not changing the state at all. > 5) This one is the most important. I'd only change the test cases where you are absolutely sure that the constraint solver is the only thing that's being tested there and leave the rest. It is OK to have both types of tests and we don't want to decrease our coverage of testing for actual warnings. I see this enhancement as simplifying addition of this type of tests in the future; we don't need to convert all our tests to using it. Okay, I'll stick to the systematically obvious ones, then (those that have a WARN macro or similar). Thanks! Jordy From akyrtzi at gmail.com Tue May 15 15:45:35 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 15 May 2012 20:45:35 -0000 Subject: [cfe-commits] r156851 - in /cfe/trunk: docs/ObjectiveCLiterals.html test/CodeGenObjC/boxing.m Message-ID: <20120515204535.72D742A6C065@llvm.org> Author: akirtzidis Date: Tue May 15 15:45:35 2012 New Revision: 156851 URL: http://llvm.org/viewvc/llvm-project?rev=156851&view=rev Log: Add documentation about boxing enum types and a codegen test to make sure we pick up the underlying type, per suggestion by Fariborz. No functionality change. Modified: cfe/trunk/docs/ObjectiveCLiterals.html cfe/trunk/test/CodeGenObjC/boxing.m Modified: cfe/trunk/docs/ObjectiveCLiterals.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ObjectiveCLiterals.html?rev=156851&r1=156850&r2=156851&view=diff ============================================================================== --- cfe/trunk/docs/ObjectiveCLiterals.html (original) +++ cfe/trunk/docs/ObjectiveCLiterals.html Tue May 15 15:45:35 2012 @@ -157,6 +157,18 @@ then the fixed underlying type will be used to select the correct NSNumber creation method.

+

+Boxing a value of enum type will result in a NSNumber pointer with a creation method according to the underlying type of the enum, +which can be a fixed underlying type or a compiler-defined +integer type capable of representing the values of all the members of the enumeration: +

+ +
+typedef enum : unsigned char { Red, Green, Blue } Color;
+Color col = Red;
+NSNumber *nsCol = @(col); // => [NSNumber numberWithUnsignedChar:]
+
+

Boxed C Strings

Modified: cfe/trunk/test/CodeGenObjC/boxing.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/boxing.m?rev=156851&r1=156850&r2=156851&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/boxing.m (original) +++ cfe/trunk/test/CodeGenObjC/boxing.m Tue May 15 15:45:35 2012 @@ -85,4 +85,11 @@ @((NSUInteger)i); // CHECK: load i8** [[stringWithUTF8StringSEL]] const char *s; @(s); + + typedef enum : NSInteger { Red, Green, Blue } Color; + // CHECK: load i8** [[WithIntegerSEL]] + @(Red); + Color col = Red; + // CHECK: load i8** [[WithIntegerSEL]] + @(col); } From kyrtzidis at apple.com Tue May 15 15:47:36 2012 From: kyrtzidis at apple.com (Argyrios Kyrtzidis) Date: Tue, 15 May 2012 13:47:36 -0700 Subject: [cfe-commits] r156843 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExprObjC.cpp test/SemaObjC/boxing-illegal-types.m test/SemaObjCXX/boxing-illegal-types.mm In-Reply-To: References: <20120515191744.EDEBB2A6C065@llvm.org> Message-ID: <60F8CE83-AA4D-4306-92D4-FF477E5C41D7@apple.com> On May 15, 2012, at 1:05 PM, jahanian wrote: > Couple of comments. > > Documentation need be updated to document what the type of the enum expression will be; is it the underlying type or > a promoted type? This will influence what method being selected. > > Please provide a CodeGenObjC test case showing the selected method. Both addressed in r156851, thanks for reviewing! > > - fariborz > > On May 15, 2012, at 12:17 PM, Argyrios Kyrtzidis wrote: > >> Author: akirtzidis >> Date: Tue May 15 14:17:44 2012 >> New Revision: 156843 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=156843&view=rev >> Log: >> Allow objc @() syntax for enum types. >> >> Previously we would reject it as illegal using a value of >> enum type and on ObjC++ it was illegal to use an enumerator >> as well. >> >> rdar://11454917 >> >> Added: >> cfe/trunk/test/SemaObjCXX/boxing-illegal-types.mm >> Modified: >> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> cfe/trunk/lib/Sema/SemaExprObjC.cpp >> cfe/trunk/test/SemaObjC/boxing-illegal-types.m > From dgregor at apple.com Tue May 15 15:52:33 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 13:52:33 -0700 Subject: [cfe-commits] r156180 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp In-Reply-To: References: <20120504171000.5A2F42A6C067@llvm.org> Message-ID: <90C9EFFA-3E8E-43C8-8F11-17955BF9B40A@apple.com> On May 15, 2012, at 12:45 PM, Daniel Dunbar wrote: > Hey Doug, > > There is a test failing on this bot, looks most likely to be yours? > http://lab.llvm.org:8011/builders/clang-x86_64-debian-selfhost-rel/builds/2943 > > Not sure if this is known? Frustrating. I can't reproduce this failure anywhere. - Doug > - Daniel > > On Fri, May 4, 2012 at 10:10 AM, Douglas Gregor wrote: >> Author: dgregor >> Date: Fri May 4 12:09:59 2012 >> New Revision: 156180 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=156180&view=rev >> Log: >> Move Sema::RequireNonAbstractType() off of PartialDiagnostic. >> >> Modified: >> cfe/trunk/include/clang/Sema/Sema.h >> cfe/trunk/lib/Sema/SemaDeclCXX.cpp >> cfe/trunk/lib/Sema/SemaExpr.cpp >> cfe/trunk/lib/Sema/SemaExprCXX.cpp >> >> Modified: cfe/trunk/include/clang/Sema/Sema.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=156180&r1=156179&r2=156180&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/Sema/Sema.h (original) >> +++ cfe/trunk/include/clang/Sema/Sema.h Fri May 4 12:09:59 2012 >> @@ -4423,7 +4423,31 @@ >> }; >> >> bool RequireNonAbstractType(SourceLocation Loc, QualType T, >> - const PartialDiagnostic &PD); >> + TypeDiagnoser &Diagnoser); >> + template >> + bool RequireNonAbstractType(SourceLocation Loc, QualType T, >> + unsigned DiagID, >> + const T1 &Arg1) { >> + BoundTypeDiagnoser1 Diagnoser(DiagID, Arg1); >> + return RequireNonAbstractType(Loc, T, Diagnoser); >> + } >> + >> + template >> + bool RequireNonAbstractType(SourceLocation Loc, QualType T, >> + unsigned DiagID, >> + const T1 &Arg1, const T2 &Arg2) { >> + BoundTypeDiagnoser2 Diagnoser(DiagID, Arg1, Arg2); >> + return RequireNonAbstractType(Loc, T, Diagnoser); >> + } >> + >> + template >> + bool RequireNonAbstractType(SourceLocation Loc, QualType T, >> + unsigned DiagID, >> + const T1 &Arg1, const T2 &Arg2, const T3 &Arg3) { >> + BoundTypeDiagnoser3 Diagnoser(DiagID, Arg1, Arg2, Arg3); >> + return RequireNonAbstractType(Loc, T, Diagnoser); >> + } >> + >> void DiagnoseAbstractType(const CXXRecordDecl *RD); >> >> bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, >> >> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=156180&r1=156179&r2=156180&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri May 4 12:09:59 2012 >> @@ -3396,19 +3396,32 @@ >> >> bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, >> unsigned DiagID, AbstractDiagSelID SelID) { >> - if (SelID == -1) >> - return RequireNonAbstractType(Loc, T, PDiag(DiagID)); >> - else >> - return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID); >> + class NonAbstractTypeDiagnoser : public TypeDiagnoser { >> + unsigned DiagID; >> + AbstractDiagSelID SelID; >> + >> + public: >> + NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID) >> + : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { } >> + >> + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { >> + if (SelID == -1) >> + S.Diag(Loc, DiagID) << T; >> + else >> + S.Diag(Loc, DiagID) << SelID << T; >> + } >> + } Diagnoser(DiagID, SelID); >> + >> + return RequireNonAbstractType(Loc, T, Diagnoser); >> } >> >> bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, >> - const PartialDiagnostic &PD) { >> + TypeDiagnoser &Diagnoser) { >> if (!getLangOpts().CPlusPlus) >> return false; >> >> if (const ArrayType *AT = Context.getAsArrayType(T)) >> - return RequireNonAbstractType(Loc, AT->getElementType(), PD); >> + return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); >> >> if (const PointerType *PT = T->getAs()) { >> // Find the innermost pointer type. >> @@ -3416,7 +3429,7 @@ >> PT = T; >> >> if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) >> - return RequireNonAbstractType(Loc, AT->getElementType(), PD); >> + return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); >> } >> >> const RecordType *RT = T->getAs(); >> @@ -3435,7 +3448,7 @@ >> if (!RD->isAbstract()) >> return false; >> >> - Diag(Loc, PD) << RD->getDeclName(); >> + Diagnoser.diagnose(*this, Loc, T); >> DiagnoseAbstractType(RD); >> >> return true; >> >> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=156180&r1=156179&r2=156180&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri May 4 12:09:59 2012 >> @@ -9205,9 +9205,9 @@ >> return ExprError(); >> >> if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(), >> - TInfo->getType(), >> - PDiag(diag::err_second_parameter_to_va_arg_abstract) >> - << TInfo->getTypeLoc().getSourceRange())) >> + TInfo->getType(), >> + diag::err_second_parameter_to_va_arg_abstract, >> + TInfo->getTypeLoc())) >> return ExprError(); >> >> if (!TInfo->getType().isPODType(Context)) { >> >> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=156180&r1=156179&r2=156180&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri May 4 12:09:59 2012 >> @@ -590,8 +590,7 @@ >> return ExprError(); >> >> if (RequireNonAbstractType(ThrowLoc, E->getType(), >> - PDiag(diag::err_throw_abstract_type) >> - << E->getSourceRange())) >> + diag::err_throw_abstract_type, E)) >> return ExprError(); >> } >> >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From dgregor at apple.com Tue May 15 16:00:28 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 21:00:28 -0000 Subject: [cfe-commits] r156853 - in /cfe/trunk: lib/Driver/Tools.cpp test/Driver/arclite-link.c Message-ID: <20120515210028.19D9C2A6C067@llvm.org> Author: dgregor Date: Tue May 15 16:00:27 2012 New Revision: 156853 URL: http://llvm.org/viewvc/llvm-project?rev=156853&view=rev Log: Add the Objective-C runtime linking arguments after user-specified linker arguments. Fixes . Modified: cfe/trunk/lib/Driver/Tools.cpp cfe/trunk/test/Driver/arclite-link.c Modified: cfe/trunk/lib/Driver/Tools.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=156853&r1=156852&r2=156853&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Tools.cpp (original) +++ cfe/trunk/lib/Driver/Tools.cpp Tue May 15 16:00:27 2012 @@ -4224,6 +4224,8 @@ // This is more complicated in gcc... CmdArgs.push_back("-lgomp"); + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -4246,8 +4248,6 @@ CmdArgs.push_back("-lobjc"); } - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); - if (LinkingOutput) { CmdArgs.push_back("-arch_multiple"); CmdArgs.push_back("-final_output"); Modified: cfe/trunk/test/Driver/arclite-link.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/arclite-link.c?rev=156853&r1=156852&r2=156853&view=diff ============================================================================== --- cfe/trunk/test/Driver/arclite-link.c (original) +++ cfe/trunk/test/Driver/arclite-link.c Tue May 15 16:00:27 2012 @@ -1,9 +1,10 @@ // RUN: touch %t.o -// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-OSX %s +// RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -lfoo -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-OSX %s // RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.8 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s // RUN: %clang -### -target i386-apple-darwin10 -fobjc-link-runtime -mmacosx-version-min=10.7 %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOARCLITE %s // RUN: %clang -### -target x86_64-apple-darwin10 -fobjc-link-runtime -nostdlib %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOSTDLIB %s +// CHECK-ARCLITE-OSX: -lfoo // CHECK-ARCLITE-OSX: libarclite_macosx.a // CHECK-ARCLITE-OSX: -framework // CHECK-ARCLITE-OSX: Foundation From richard-llvm at metafoo.co.uk Tue May 15 16:01:51 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 21:01:51 -0000 Subject: [cfe-commits] r156854 - in /cfe/trunk: lib/Parse/ParseDecl.cpp test/CXX/class/class.mem/p14.cpp test/Parser/cxx-undeclared-identifier.cpp test/SemaCXX/typo-correction.cpp Message-ID: <20120515210151.8E08D2A6C067@llvm.org> Author: rsmith Date: Tue May 15 16:01:51 2012 New Revision: 156854 URL: http://llvm.org/viewvc/llvm-project?rev=156854&view=rev Log: Don't use the implicit int rule for error recovery in C++. Instead, try to disambiguate whether the type name was forgotten or mistyped. Modified: cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/test/CXX/class/class.mem/p14.cpp cfe/trunk/test/Parser/cxx-undeclared-identifier.cpp cfe/trunk/test/SemaCXX/typo-correction.cpp Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=156854&r1=156853&r2=156854&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue May 15 16:01:51 2012 @@ -1638,12 +1638,13 @@ assert(!DS.hasTypeSpecifier() && "Type specifier checked above"); // Since we know that this either implicit int (which is rare) or an - // error, do lookahead to try to do better recovery. This never applies within - // a type specifier. - // FIXME: Don't bail out here in languages with no implicit int (like - // C++ with no -fms-extensions). This is much more likely to be an undeclared - // type or typo than a use of implicit int. + // error, do lookahead to try to do better recovery. This never applies + // within a type specifier. Outside of C++, we allow this even if the + // language doesn't "officially" support implicit int -- we support + // implicit int as an extension in C99 and C11. Allegedly, MS also + // supports implicit int in C++ mode. if (DSC != DSC_type_specifier && DSC != DSC_trailing && + (!getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt) && isValidAfterIdentifierInDeclarator(NextToken())) { // If this token is valid for implicit int, e.g. "static x = 4", then // we just avoid eating the identifier, so it will be parsed as the @@ -1651,6 +1652,13 @@ return false; } + if (getLangOpts().CPlusPlus && + DS.getStorageClassSpec() == DeclSpec::SCS_auto) { + // Don't require a type specifier if we have the 'auto' storage class + // specifier in C++98 -- we'll promote it to a type specifier. + return false; + } + // Otherwise, if we don't consume this token, we are going to emit an // error anyway. Try to recover from various common problems. Check // to see if this was a reference to a tag name without a tag specified. @@ -1699,6 +1707,47 @@ } } + if (DSC != DSC_type_specifier && DSC != DSC_trailing) { + // Look ahead to the next token to try to figure out what this declaration + // was supposed to be. + switch (NextToken().getKind()) { + case tok::comma: + case tok::equal: + case tok::kw_asm: + case tok::l_brace: + case tok::l_square: + case tok::semi: + // This looks like a variable declaration. The type is probably missing. + // We're done parsing decl-specifiers. + return false; + + case tok::l_paren: { + // static x(4); // 'x' is not a type + // x(int n); // 'x' is not a type + // x (*p)[]; // 'x' is a type + // + // Since we're in an error case (or the rare 'implicit int in C++' MS + // extension), we can afford to perform a tentative parse to determine + // which case we're in. + TentativeParsingAction PA(*this); + ConsumeToken(); + TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false); + PA.Revert(); + if (TPR == TPResult::False()) + return false; + // The identifier is followed by a parenthesized declarator. + // It's supposed to be a type. + break; + } + + default: + // This is probably supposed to be a type. This includes cases like: + // int f(itn); + // struct S { unsinged : 4; }; + break; + } + } + // This is almost certainly an invalid type name. Let the action emit a // diagnostic and attempt to recover. ParsedType T; Modified: cfe/trunk/test/CXX/class/class.mem/p14.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.mem/p14.cpp?rev=156854&r1=156853&r2=156854&view=diff ============================================================================== --- cfe/trunk/test/CXX/class/class.mem/p14.cpp (original) +++ cfe/trunk/test/CXX/class/class.mem/p14.cpp Tue May 15 16:01:51 2012 @@ -9,8 +9,9 @@ }; struct X1 { - int X1; - X1(); // expected-error{{declarator requires an identifier}} + int X1; // expected-note{{hidden by a non-type declaration of 'X1' here}} + X1(); // expected-error{{must use 'struct' tag to refer to type 'X1' in this scope}} \ + // expected-error{{expected member name or ';' after declaration specifiers}} }; struct X2 { Modified: cfe/trunk/test/Parser/cxx-undeclared-identifier.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-undeclared-identifier.cpp?rev=156854&r1=156853&r2=156854&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx-undeclared-identifier.cpp (original) +++ cfe/trunk/test/Parser/cxx-undeclared-identifier.cpp Tue May 15 16:01:51 2012 @@ -1,5 +1,17 @@ // RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s +namespace ImplicitInt { + static a(4); // expected-error {{requires a type specifier}} + b(int n); // expected-error {{requires a type specifier}} + c (*p)[]; // expected-error {{unknown type name 'c'}} + itn f(char *p, *q); // expected-error {{unknown type name 'itn'}} expected-error {{requires a type specifier}} + + struct S { + void f(); + }; + S::f() {} // expected-error {{requires a type specifier}} +} + // PR7180 int f(a::b::c); // expected-error {{use of undeclared identifier 'a'}} Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=156854&r1=156853&r2=156854&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/typo-correction.cpp (original) +++ cfe/trunk/test/SemaCXX/typo-correction.cpp Tue May 15 16:01:51 2012 @@ -190,3 +190,10 @@ }; test1::FooBar *b; // expected-error{{no type named 'FooBar' in namespace 'test1'; did you mean 'Foobar'?}} } + +namespace ImplicitInt { + void f(int, unsinged); // expected-error{{did you mean 'unsigned'}} + struct S { + unsinged : 4; // expected-error{{did you mean 'unsigned'}} + }; +} From dgregor at apple.com Tue May 15 16:11:37 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 14:11:37 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: On May 15, 2012, at 11:57 AM, David Blaikie wrote: > [-llvm-commits since it's not too relevant to that list at this point] > > On Tue, May 15, 2012 at 11:24 AM, Douglas Gregor wrote: >> >> On May 15, 2012, at 9:31 AM, David Blaikie wrote: >> >>> On Tue, May 15, 2012 at 9:19 AM, Douglas Gregor wrote: >>>> >>>> On May 6, 2012, at 7:02 PM, David Blaikie wrote: >>>> >>>>> This patch adds an iterator much like boost's transform_iterator >>>>> (without some extra bells & whistles) for use in some changes I'd like >>>>> to make to Clang to correct some misimplemented iterators there. >>>>> >>>>> A few gotchas that could be improved/changed depending on opinions: >>>>> * I may be playing a little loose with the return type of the functor >>>>> (see the example/motivating functor, to_pointer) - the return type >>>>> actually must be a reference, though the result_type provides the >>>>> underlying value type, not the reference type. If this is violated >>>>> Clang will emit a warning, but I could make it more robust with a >>>>> compile time assertion in the TransformIterator that the result_type >>>>> is actually a reference type, and strip that off to provide the >>>>> value_type of the TransformIterator. >>>> >>>> It's much more correct for the value and reference types of the iterator type to be, e.g., >>>> >>>> typedef typename Functor::result_type reference; >>>> typedef typename remove_reference::type value_type; >>>> >>>>> * I realize adding pointer-yness back onto an iterator over references >>>>> when the underlying data structure (in the Clang patch you can see >>>>> this situation) is a sequence of pointers may be a bit overkill - >>>>> though the alternatives are writing different algorithms in the two >>>>> cases where I've used TransformIterator, or having the decl_iterator >>>>> iterate over pointers (in which case I should probably change the >>>>> other iterators I've modified to iterate over pointers for symmetry). >>>> >>>> diff --git include/clang/AST/DeclBase.h include/clang/AST/DeclBase.h >>>> index 6aef681..0a16ea5 100644 >>>> --- include/clang/AST/DeclBase.h >>>> +++ include/clang/AST/DeclBase.h >>>> @@ -1175,17 +1175,18 @@ public: >>>> Decl *Current; >>>> >>>> public: >>>> - typedef Decl* value_type; >>>> - typedef Decl* reference; >>>> - typedef Decl* pointer; >>>> + typedef Decl value_type; >>>> + typedef value_type& reference; >>>> + typedef value_type* pointer; >>>> >>>> Since we tend to traffic in declaration pointers, not references, it's really beneficial to have value_type be Decl*. >>> >>> Fair enough - I was hoping to reduce the amount of pointers handed >>> around, but I realize in this case especially (where the underlying >>> sequence is a sequence of pointers) it's really an awkward fit. >> >> Why is reducing the number of pointers a specific goal? > > Evidently not something everyone finds to be a useful goal - and on > that basis perhaps I should just leave it alone. > > But for myself I find functions taking references (& locals that are > references) easier to read/reason about because it's clear that > they're not null. Trying to decide which functions are accepting > optional values and which ones aren't makes me pause a little - though > perhaps more out of habit than real curiosity about whether something > is null. If switching things to references causes pointer-habitual > people to have the same kind of pause then that's clearly not an > outright improvement. Unless we're seeing lots of problems due to the pointer-centric style, I don't see a motivation to make this kind of change in the code base. >>> This means killing off the op-> for these iterators though, right? Or >>> do you want to keep that as an excusable convenience? >> >> Honestly, I preferred the world back in its conveniently-inconsistent state where operator* returned a pointer and operator-> returned that same pointer, because being able to refer to Iter->getDeclName() rather than (*Iter)->getDeclName() is *really* convenient. > > It is convenient, certainly. Though I find op* returning T& to be > convenient/useful as well. In many cases we assign *i to a local > pointer (I'm not sure why - perhaps we should just have a better name > for the iterator and use that directly) & don't get the convenience of > op-> (I assume this code was written before the op-> was added, > actually) let alone the convenience of just using '.'. > > But if that's what you want, I can do that. "I.foo" vs. "I->foo" doesn't matter much to me, but "(*I)->foo" and "&*I" are really, really ugly. >> The inclusion of operator-> in the iterator concepts was a mistake. Nothing in the standard library actually depends on it, no sane algorithms need it, and it's a major PITA to implement for iterator adaptors (as you've noticed ). > > That's fine - though, since I want to replace > specific/filtered_decl_iterators with some generic adapters, those > adapters will need to provide the op-> convenience you want, whether > or not it was specified in the concept/standard. Yeah. >>> In which case my >>> change boils down to just changing the pointer typedefs to be Decl** >>> in these various iterator types. (& might make my planned work, >>> generalizing the filtering iterators, a bit weird - possibly providing >>> an op-> to the generic filtering iterators whenever the value type is >>> a pointer to match/support this oddity) >> >> Decl** won't always work, though. You'll almost certainly need a proxy. > > For the basic decl_iterators they do (because the underlying sequence > is Decl*) but for the specific/filtered, where it'd be SpecificDecl** > but we don't have a real SpecificDecl* to point to, it wouldn't and > I'd need a proxy. Are there other cases/reasons for needing a proxy > that you're referring to? I don't know of other cases, no. >>> Would you prefer the other iterators I changed >>> (specific_decl_iterator, filtered_decl_iterator) be switched to >>> pointer value_type too? >> >> I did prefer the pointer value_type; perhaps others want to weigh in. > > I'm fairly sure all 3 of these should be consistent, and that the > specific/filtered should be refactored into a common adapter > (typedef'd in place so clients of Decl wouldn't need to change, of > course). Generally I prefer references, but I realize they're not a > perfect fit. > > Yeah - I'd like to be able to get more discussion on this & other > stylistic (micro design?) aspects - I kind of feel like I'm just > throwing stuff up & seeing what's stuck after a few weeks. IRC is generally the best place for micro-design discussions. - Doug From chandlerc at google.com Tue May 15 16:23:59 2012 From: chandlerc at google.com (Chandler Carruth) Date: Tue, 15 May 2012 15:23:59 -0600 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: On Tue, May 15, 2012 at 3:11 PM, Douglas Gregor wrote: > > On May 15, 2012, at 11:57 AM, David Blaikie wrote: > > > [-llvm-commits since it's not too relevant to that list at this point] > > > > On Tue, May 15, 2012 at 11:24 AM, Douglas Gregor > wrote: > >> > >> On May 15, 2012, at 9:31 AM, David Blaikie wrote: > >> > >>> On Tue, May 15, 2012 at 9:19 AM, Douglas Gregor > wrote: > >>>> > >>>> On May 6, 2012, at 7:02 PM, David Blaikie wrote: > >>>> > >>>>> This patch adds an iterator much like boost's transform_iterator > >>>>> (without some extra bells & whistles) for use in some changes I'd > like > >>>>> to make to Clang to correct some misimplemented iterators there. > >>>>> > >>>>> A few gotchas that could be improved/changed depending on opinions: > >>>>> * I may be playing a little loose with the return type of the functor > >>>>> (see the example/motivating functor, to_pointer) - the return type > >>>>> actually must be a reference, though the result_type provides the > >>>>> underlying value type, not the reference type. If this is violated > >>>>> Clang will emit a warning, but I could make it more robust with a > >>>>> compile time assertion in the TransformIterator that the result_type > >>>>> is actually a reference type, and strip that off to provide the > >>>>> value_type of the TransformIterator. > >>>> > >>>> It's much more correct for the value and reference types of the > iterator type to be, e.g., > >>>> > >>>> typedef typename Functor::result_type reference; > >>>> typedef typename remove_reference::type value_type; > >>>> > >>>>> * I realize adding pointer-yness back onto an iterator over > references > >>>>> when the underlying data structure (in the Clang patch you can see > >>>>> this situation) is a sequence of pointers may be a bit overkill - > >>>>> though the alternatives are writing different algorithms in the two > >>>>> cases where I've used TransformIterator, or having the decl_iterator > >>>>> iterate over pointers (in which case I should probably change the > >>>>> other iterators I've modified to iterate over pointers for symmetry). > >>>> > >>>> diff --git include/clang/AST/DeclBase.h include/clang/AST/DeclBase.h > >>>> index 6aef681..0a16ea5 100644 > >>>> --- include/clang/AST/DeclBase.h > >>>> +++ include/clang/AST/DeclBase.h > >>>> @@ -1175,17 +1175,18 @@ public: > >>>> Decl *Current; > >>>> > >>>> public: > >>>> - typedef Decl* value_type; > >>>> - typedef Decl* reference; > >>>> - typedef Decl* pointer; > >>>> + typedef Decl value_type; > >>>> + typedef value_type& reference; > >>>> + typedef value_type* pointer; > >>>> > >>>> Since we tend to traffic in declaration pointers, not references, > it's really beneficial to have value_type be Decl*. > >>> > >>> Fair enough - I was hoping to reduce the amount of pointers handed > >>> around, but I realize in this case especially (where the underlying > >>> sequence is a sequence of pointers) it's really an awkward fit. > >> > >> Why is reducing the number of pointers a specific goal? > > > > Evidently not something everyone finds to be a useful goal - and on > > that basis perhaps I should just leave it alone. > > > > But for myself I find functions taking references (& locals that are > > references) easier to read/reason about because it's clear that > > they're not null. Trying to decide which functions are accepting > > optional values and which ones aren't makes me pause a little - though > > perhaps more out of habit than real curiosity about whether something > > is null. If switching things to references causes pointer-habitual > > people to have the same kind of pause then that's clearly not an > > outright improvement. > > Unless we're seeing lots of problems due to the pointer-centric style, I > don't see a motivation to make this kind of change in the code base. Since there was some mention of wanting other perspectives here, I wanted to chime in with my two cents... This seems like a lot of work and a disruptive change in API patterning, and I'm really not clear what problem it's trying to solve. My suspicion is that there isn't one other than a preference for references instead of pointers. I actually don't even agree with this movement. While yes, it is nice to use simpler constructs when there is no possibility of a null pointer, references aren't strictly superior. We can't assign to them to re-point them to other entities, which is a fundamental pattern in Clang and LLVM. I don't see soft "non-null" constraints as a sufficient reason to lose this. What's more, it is trivial to add non-null constraints to pointers. In fact, dyn_cast/cast/isa all provide such constraints. We could teach Clang about [[nonnull]] for parameters and get much more than a reference gives us: - Optimizing based on non-null-ness - Checking in non-optimized builds for non-null-ness - Still able to overwrite the argument within the funciton -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/8c7f19ab/attachment-0001.html From richard-llvm at metafoo.co.uk Tue May 15 16:29:55 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 21:29:55 -0000 Subject: [cfe-commits] r156856 - in /cfe/trunk: lib/Parse/ParseDecl.cpp test/SemaCXX/unknown-type-name.cpp Message-ID: <20120515212956.09E542A6C065@llvm.org> Author: rsmith Date: Tue May 15 16:29:55 2012 New Revision: 156856 URL: http://llvm.org/viewvc/llvm-project?rev=156856&view=rev Log: If we see a declaration which is either missing a type or has a malformed type, and the thing we have has a scope specifier, and we're in a context that doesn't allow declaring a qualified name, then the error is a malformed type, not a missing type. Modified: cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/test/SemaCXX/unknown-type-name.cpp Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=156856&r1=156855&r2=156856&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue May 15 16:29:55 2012 @@ -1707,7 +1707,10 @@ } } - if (DSC != DSC_type_specifier && DSC != DSC_trailing) { + // Determine whether this identifier could plausibly be the name of something + // being declared (with a missign type). + if (DSC != DSC_type_specifier && DSC != DSC_trailing && + (!SS || DSC == DSC_top_level || DSC == DSC_class)) { // Look ahead to the next token to try to figure out what this declaration // was supposed to be. switch (NextToken().getKind()) { Modified: cfe/trunk/test/SemaCXX/unknown-type-name.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unknown-type-name.cpp?rev=156856&r1=156855&r2=156856&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/unknown-type-name.cpp (original) +++ cfe/trunk/test/SemaCXX/unknown-type-name.cpp Tue May 15 16:29:55 2012 @@ -20,6 +20,8 @@ typedef T type; type f(); + + type g(); }; template @@ -27,3 +29,14 @@ template A::type A::f() { return type(); } // expected-error{{missing 'typename'}} + +template +void f(int, T::type) { } // expected-error{{missing 'typename'}} + +template +void f(int, T::type, int) { } // expected-error{{missing 'typename'}} + +// FIXME: We know which type specifier should have been specified here. Provide +// a fix-it to add 'typename A::type' +template +A::g() { } // expected-error{{requires a type specifier}} From dblaikie at gmail.com Tue May 15 16:33:58 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 14:33:58 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: On Tue, May 15, 2012 at 2:23 PM, Chandler Carruth wrote: > On Tue, May 15, 2012 at 3:11 PM, Douglas Gregor wrote: >> >> >> On May 15, 2012, at 11:57 AM, David Blaikie wrote: >> >> > [-llvm-commits since it's not too relevant to that list at this point] >> > >> > On Tue, May 15, 2012 at 11:24 AM, Douglas Gregor >> > wrote: >> >> >> >> On May 15, 2012, at 9:31 AM, David Blaikie wrote: >> >> >> >>> On Tue, May 15, 2012 at 9:19 AM, Douglas Gregor >> >>> wrote: >> >>>> >> >>>> On May 6, 2012, at 7:02 PM, David Blaikie wrote: >> >>>> >> >>>>> This patch adds an iterator much like boost's transform_iterator >> >>>>> (without some extra bells & whistles) for use in some changes I'd >> >>>>> like >> >>>>> to make to Clang to correct some misimplemented iterators there. >> >>>>> >> >>>>> A few gotchas that could be improved/changed depending on opinions: >> >>>>> * I may be playing a little loose with the return type of the >> >>>>> functor >> >>>>> (see the example/motivating functor, to_pointer) - the return type >> >>>>> actually must be a reference, though the result_type provides the >> >>>>> underlying value type, not the reference type. If this is violated >> >>>>> Clang will emit a warning, but I could make it more robust with a >> >>>>> compile time assertion in the TransformIterator that the result_type >> >>>>> is actually a reference type, and strip that off to provide the >> >>>>> value_type of the TransformIterator. >> >>>> >> >>>> It's much more correct for the value and reference types of the >> >>>> iterator type to be, e.g., >> >>>> >> >>>> ?typedef typename Functor::result_type reference; >> >>>> ?typedef typename remove_reference::type value_type; >> >>>> >> >>>>> * I realize adding pointer-yness back onto an iterator over >> >>>>> references >> >>>>> when the underlying data structure (in the Clang patch you can see >> >>>>> this situation) is a sequence of pointers may be a bit overkill - >> >>>>> though the alternatives are writing different algorithms in the two >> >>>>> cases where I've used TransformIterator, or having the decl_iterator >> >>>>> iterate over pointers (in which case I should probably change the >> >>>>> other iterators I've modified to iterate over pointers for >> >>>>> symmetry). >> >>>> >> >>>> diff --git include/clang/AST/DeclBase.h include/clang/AST/DeclBase.h >> >>>> index 6aef681..0a16ea5 100644 >> >>>> --- include/clang/AST/DeclBase.h >> >>>> +++ include/clang/AST/DeclBase.h >> >>>> @@ -1175,17 +1175,18 @@ public: >> >>>> ? ? Decl *Current; >> >>>> >> >>>> ? public: >> >>>> - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? value_type; >> >>>> - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? reference; >> >>>> - ? ?typedef Decl* ? ? ? ? ? ? ? ? ? ? pointer; >> >>>> + ? ?typedef Decl ? ? ? ? ? ? ? ? ? ? value_type; >> >>>> + ? ?typedef value_type& ? ? ? ? ? ? ?reference; >> >>>> + ? ?typedef value_type* ? ? ? ? ? ? ?pointer; >> >>>> >> >>>> Since we tend to traffic in declaration pointers, not references, >> >>>> it's really beneficial to have value_type be Decl*. >> >>> >> >>> Fair enough - I was hoping to reduce the amount of pointers handed >> >>> around, but I realize in this case especially (where the underlying >> >>> sequence is a sequence of pointers) it's really an awkward fit. >> >> >> >> Why is reducing the number of pointers a specific goal? >> > >> > Evidently not something everyone finds to be a useful goal - and on >> > that basis perhaps I should just leave it alone. >> > >> > But for myself I find functions taking references (& locals that are >> > references) easier to read/reason about because it's clear that >> > they're not null. Trying to decide which functions are accepting >> > optional values and which ones aren't makes me pause a little - though >> > perhaps more out of habit than real curiosity about whether something >> > is null. If switching things to references causes pointer-habitual >> > people to have the same kind of pause then that's clearly not an >> > outright improvement. >> >> Unless we're seeing lots of problems due to the pointer-centric style, I >> don't see a motivation to make this kind of change in the code base. > > > Since there was some mention of wanting other perspectives here, I wanted to > chime in with my two cents... Thanks > This seems like a lot of work and a disruptive change in API patterning, and > I'm really not clear what problem it's trying to solve. My suspicion is that > there isn't one other than a preference for references instead of pointers. Well the underlying problem was the inconsistency of the iterators in Decl/DeclBase. I wanted to rationalize their value/reference/pointer types so I could then extract the common filtering functionality out of filtered/specific_decl_iterator as a proof-of-concept for a general adapting/filtering iterator device which I could then re-use in my efforts to improve the CFG fidelity and -Wunreachable-code diagnostic. This particular path (generalizing the existing filtering iterators to a reusable adapter before reusing that in the new use case) was suggested by Ted Kremmenek & I was happy enough to have an excuse to tidy up some existing code. Then when I went to extract that filtering functionality I came across the fact that they weren't quite meeting the iterator requirements (specifically, value_type, reference, and pointer were all the same type) & so I set about fixing that. It could go either way - pointer value types or reference value types. I asked, I waited, and eventually Richard Smith chimed in to say he was OK with the reference version. Yes, my preference is towards the reference version because it seems to match the semantics (non-null-ness) and usage (iter->x) that's desired. > I actually don't even agree with this movement. While yes, it is nice to use > simpler constructs when there is no possibility of a null pointer, > references aren't strictly superior. We can't assign to them to re-point > them to other entities, which is a fundamental pattern in Clang and LLVM. I > don't see soft "non-null" constraints as a sufficient reason to lose this. I'm not suggesting losing that flexibility where it's desired/necessary. Indeed I think that helps readability to know which things are repointing over some algorithm & which things aren't. It's certainly not uncommon for algorithms/types to have pointers inside them that are reassigned to based on some ongoing algorithm or condition & those would have to remain pointers, certainly. > What's more, it is trivial to add non-null constraints to pointers. In fact, > dyn_cast/cast/isa all provide such constraints. We could teach Clang about > [[nonnull]] for parameters and get much more than a reference gives us: > > - Optimizing based on non-null-ness Clang doesn't optimize references on the basis of non-null-ness? For those things that need to be reassigned, but are guaranteed to never be null (I'm not sure we have (m)any of those - mostly if we're reassigning them, they start out/may be null for some time) > - Checking in non-optimized builds for non-null-ness Granted, adding this to reference usage might be a bit harder - knowing where checks are beneficial & where they aren't, but I imagine if we went all out with non-null annotations we might have some similar perf problems anyway. > - Still able to overwrite the argument within the funciton That usually seems to be a source of errors (as we've seen with people thinking they have an out parameter & assigning to the parameter directly, rather than the dereferenced parameter). Are there many deliberate uses of this in Clang? - David From chandlerc at google.com Tue May 15 16:37:47 2012 From: chandlerc at google.com (Chandler Carruth) Date: Tue, 15 May 2012 15:37:47 -0600 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: On Tue, May 15, 2012 at 3:33 PM, David Blaikie wrote: > > - Optimizing based on non-null-ness > > Clang doesn't optimize references on the basis of non-null-ness? For > those things that need to be reassigned, but are guaranteed to never > be null (I'm not sure we have (m)any of those - mostly if we're > reassigning them, they start out/may be null for some time) ... > > - Still able to overwrite the argument within the funciton > > That usually seems to be a source of errors (as we've seen with people > thinking they have an out parameter & assigning to the parameter > directly, rather than the dereferenced parameter). Are there many > deliberate uses of this in Clang? Yes, this is a very common pattern: void foo(Decl *D) { if (Decl *UnderlyingD = D->someWonkyMethod()) D = UnderlyingD; ... } -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/88b12867/attachment.html From richard-llvm at metafoo.co.uk Tue May 15 16:42:18 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 21:42:18 -0000 Subject: [cfe-commits] r156860 - /cfe/trunk/lib/Parse/ParseDecl.cpp Message-ID: <20120515214218.346632A6C065@llvm.org> Author: rsmith Date: Tue May 15 16:42:17 2012 New Revision: 156860 URL: http://llvm.org/viewvc/llvm-project?rev=156860&view=rev Log: Typo. Modified: cfe/trunk/lib/Parse/ParseDecl.cpp Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=156860&r1=156859&r2=156860&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue May 15 16:42:17 2012 @@ -1708,7 +1708,7 @@ } // Determine whether this identifier could plausibly be the name of something - // being declared (with a missign type). + // being declared (with a missing type). if (DSC != DSC_type_specifier && DSC != DSC_trailing && (!SS || DSC == DSC_top_level || DSC == DSC_class)) { // Look ahead to the next token to try to figure out what this declaration From dblaikie at gmail.com Tue May 15 16:47:59 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 14:47:59 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: On Tue, May 15, 2012 at 2:37 PM, Chandler Carruth wrote: > On Tue, May 15, 2012 at 3:33 PM, David Blaikie wrote: >> >> > - Optimizing based on non-null-ness >> >> Clang doesn't optimize references on the basis of non-null-ness? For >> those things that need to be reassigned, but are guaranteed to never >> be null (I'm not sure we have (m)any of those - mostly if we're >> reassigning them, they start out/may be null for some time) > > ... >> >> > - Still able to overwrite the argument within the funciton >> >> That usually seems to be a source of errors (as we've seen with people >> thinking they have an out parameter & assigning to the parameter >> directly, rather than the dereferenced parameter). Are there many >> deliberate uses of this in Clang? > > > Yes, this is a very common pattern: > > void foo(Decl *D) { > ? if (Decl *UnderlyingD = D->someWonkyMethod()) > ? ? D = UnderlyingD; Ah, right - I have seen a few of those. I think I only changed (locally, not committed) one or two when I got bored at one point & tried to push references further down through callers using the filtering iterators (you can see that in another patch I attached to the original review mail that Richard signed off on). From chandlerc at google.com Tue May 15 16:54:05 2012 From: chandlerc at google.com (Chandler Carruth) Date: Tue, 15 May 2012 15:54:05 -0600 Subject: [cfe-commits] r156813 - /cfe/trunk/lib/Driver/ToolChains.cpp In-Reply-To: <20120515112103.2B7052A6C065@llvm.org> References: <20120515112103.2B7052A6C065@llvm.org> Message-ID: On Tue, May 15, 2012 at 5:21 AM, Gabor Greif wrote: > Author: ggreif > Date: Tue May 15 06:21:03 2012 > New Revision: 156813 > > URL: http://llvm.org/viewvc/llvm-project?rev=156813&view=rev > Log: > add embedded linux variants that occur in the field > Please add test cases for these. > > Modified: > cfe/trunk/lib/Driver/ToolChains.cpp > > Modified: cfe/trunk/lib/Driver/ToolChains.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=156813&r1=156812&r2=156813&view=diff > > ============================================================================== > --- cfe/trunk/lib/Driver/ToolChains.cpp (original) > +++ cfe/trunk/lib/Driver/ToolChains.cpp Tue May 15 06:21:03 2012 > @@ -1146,7 +1146,8 @@ > "i586-redhat-linux", > "i386-redhat-linux", > "i586-suse-linux", > - "i486-slackware-linux" > + "i486-slackware-linux", > + "i686-montavista-linux" > }; > > static const char *const MIPSLibDirs[] = { "/lib" }; > @@ -1163,7 +1164,8 @@ > static const char *const PPCTriples[] = { > "powerpc-linux-gnu", > "powerpc-unknown-linux-gnu", > - "powerpc-suse-linux" > + "powerpc-suse-linux", > + "powerpc-montavista-linuxspe" > }; > static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; > static const char *const PPC64Triples[] = { > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/af16a4e2/attachment-0001.html From gregory.szorc at gmail.com Tue May 15 16:54:22 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 15 May 2012 14:54:22 -0700 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> Message-ID: On Tue, May 15, 2012 at 12:55 PM, Manuel Klimek wrote: > On Tue, May 15, 2012 at 9:52 PM, Gregory Szorc wrote: >> On Tue, May 15, 2012 at 12:45 PM, Manuel Klimek wrote: >>> On Tue, May 15, 2012 at 9:40 PM, Gregory Szorc wrote: >>>> On Tue, May 15, 2012 at 12:31 PM, Manuel Klimek wrote: >>>>> On Mon, May 14, 2012 at 10:15 AM, Manuel Klimek wrote: >>>>>> On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc >>>>>> wrote: >>>>>>> >>>>>>> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>>>>>>> >>>>>>>> + ? ?@property >>>>>>>> + ? ?def translation_unit(self): >>>>>>>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>>>>>>> + ? ? ? ?return getattr(self, '_tu', None) >>>>>>>> >>>>>>>> What's the reason for the default value? Do we expect that people create >>>>>>>> cursers via the lowlevel calls? Why would just return tu_ not work? >>>>>>> >>>>>>> Just defensive programming. If you return self._tu, that may raise an >>>>>>> AttributeError if _tu is not set. Theoretically, the API should ensure that >>>>>>> a TU is defined on all Cursor instances, so maybe an AttributeError would be >>>>>>> acceptable. >>>>>> >>>>>> >>>>>> I'd prefer that - to me defensive programming means to: >>>>>> 1. never crash for invalid user input >>>>>> 2. crash hard if there's an actual bug in the library >>>>>> >>>>>> If the cursor should never be generated by a user (-> the contract of the >>>>>> library is to not break that), I think we should use _tu and have the >>>>>> AttributeError thrown if it's not there. Or I'm also fine with putting in an >>>>>> assert that checks that the attribute is there and delivers a nicer error in >>>>>> case it's missing. >>>>>> >>>>>>>> >>>>>>>> + ? ? ? ?# Store a reference to the TU in the Python object so it won't >>>>>>>> get GC'd >>>>>>>> + ? ? ? ?# before the Cursor. >>>>>>>> + ? ? ? ?tu = None >>>>>>>> + ? ? ? ?for arg in args: >>>>>>>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>>>>>>> + ? ? ? ? ? ? ? ?tu = arg >>>>>>>> + ? ? ? ? ? ? ? ?break >>>>>>>> + >>>>>>>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>>>>>>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>>>>>>> + ? ? ? ? ? ? ? ?break >>>>>>>> + >>>>>>>> + ? ? ? ?assert tu is not None >>>>>>>> + >>>>>>>> + ? ? ? ?res._tu = tu >>>>>>>> >>>>>>>> That seems - odd. I can't find docs what from_result is supposed to do, >>>>>>>> or what "args" are provided. But having to search through them for a TU >>>>>>>> seems wrong - shouldn't they all have a TU? >>>>>>> >>>>>>> from_result is the errcheck function for the ctypes functions that return >>>>>>> a Cursor. The 3rd argument to an errcheck function are the original >>>>>>> arguments passed into the called function. ?For many of the functions, the >>>>>>> original argument is a Cursor. However, clang_getTypeDeclaration takes a >>>>>>> Type and clang_getTranslationUnitCursor receives a TranslationUnit. >>>>>>> >>>>>>> It is true that all of the functions today receive a single argument, so >>>>>>> the iteration isn't required. However, that may change with the addition of >>>>>>> new APIs in the future (this is how I coded it in my nearly feature-complete >>>>>>> branch, so I'm guessing it is actually required from a future patch). >>>>>> >>>>>> >>>>>> The question is: don't we just want to assert that all of those have a TU >>>>>> (or are a TU)? >>>>> >>>>> ^ this question is still open I think... >>>> >>>> I don't think it is. Both modified from_result functions now assert if >>>> a TU could not be found. >>>> >>>> Or, are you asking for something more? In the future, every live >>>> object will likely hold a reference to a TU. We aren't there quite >>>> yet. But, this patch is a step in the right direction. >>> >>> Ah, ok, that was my question - why not every object has a TU and we >>> can assert *for every object* that it has a TU. If that's a follow-up >>> step, then LGTM. >> >> Well, in the case of from_result (or any errcheck function), not every >> argument to the original function may have a TU attached. e.g. integer >> arguments. > > So that means we cannot even be sure that we'll always find a TU? > Still trying to understand from_result better. Don't feel bad. I was completely lost the first time I encountered these as well. The various from_result functions are registered as 'errcheck' functions for ctypes-registered functions. The function referenced by the 'errcheck' parameter of a ctypes function (if defined) is called by ctypes when the C function call has returned but before the result is passed to the original caller. In addition, the return value from the errcheck function is what is actually handed to the original caller. The errcheck function receives 3 arguments: the result from the C function call, a reference to the called function, and a tuple of arguments passed into the C function. Think of errcheck functions as hooks that allow you to perform additional validation and to modify the result of a low-level C function call. It is perfectly valid for them to raise an exception if the result is not what's expected, convert the C return value to something else (by not returning the first argument as-is), or perform modifications to the value returned from the C function call. If you wanted, you could even use these to aggregate "out" arguments from function calls into the return value. For example, for the function clang_getArgType(), the ctype function reference has: .argtypes = [Type, c_uint] .restype = Type .errcheck = Type.from_result When you call clang_getArgType(), ctypes will do some magic to convert the supplied arguments to the required types. When the C function has returned, it will invoke Type.from_result() with a Type instance, the ctype function instance, and a 2-tuple of (Type, c_uint). Honestly, we should probably have different errcheck functions for each function prototype. Then, we could make stronger assertions on the arguments. We cheat a little bit and use the same errcheck functions on each class. It does work. Does that help explain things? From dblaikie at gmail.com Tue May 15 16:57:38 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 21:57:38 -0000 Subject: [cfe-commits] r156861 - in /cfe/trunk: lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp test/SemaCXX/conversion.cpp Message-ID: <20120515215738.ECF6C2A6C065@llvm.org> Author: dblaikie Date: Tue May 15 16:57:38 2012 New Revision: 156861 URL: http://llvm.org/viewvc/llvm-project?rev=156861&view=rev Log: Don't warn when NULL is used within a macro but its conversion is outside a macro. This fixes the included test case & was reported by Nico Weber. It's a little bit nasty using the difference in the conversion context, but seems to me like a not unreasonable solution. I did have to fix up the conversion context for conditional operators (it seems correct to me to include the context for which we're actually doing the comparison - across all the nested conditionals, rather than the innermost conditional which might not actually have the problematic implicit conversion at all) and template default arguments (this is a bit of a hack, since we don't have the source location of the '=' anymore, so I just used the start of the parameter - open to suggestions there) Modified: cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/SemaCXX/conversion.cpp Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156861&r1=156860&r2=156861&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 16:57:38 2012 @@ -4250,9 +4250,10 @@ SourceLocation Loc = E->getSourceRange().getBegin(); if (Loc.isMacroID()) Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; - S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) - << T << clang::SourceRange(CC) - << FixItHint::CreateReplacement(Loc, S.getFixItZeroLiteralForType(T)); + if (!Loc.isMacroID() || CC.isMacroID()) + S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) + << T << clang::SourceRange(CC) + << FixItHint::CreateReplacement(Loc, S.getFixItZeroLiteralForType(T)); return; } @@ -4345,14 +4346,15 @@ return; } -void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T); +void CheckConditionalOperator(Sema &S, ConditionalOperator *E, + SourceLocation CC, QualType T); void CheckConditionalOperand(Sema &S, Expr *E, QualType T, SourceLocation CC, bool &ICContext) { E = E->IgnoreParenImpCasts(); if (isa(E)) - return CheckConditionalOperator(S, cast(E), T); + return CheckConditionalOperator(S, cast(E), CC, T); AnalyzeImplicitConversions(S, E, CC); if (E->getType() != T) @@ -4360,9 +4362,8 @@ return; } -void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) { - SourceLocation CC = E->getQuestionLoc(); - +void CheckConditionalOperator(Sema &S, ConditionalOperator *E, + SourceLocation CC, QualType T) { AnalyzeImplicitConversions(S, E->getCond(), CC); bool Suspicious = false; @@ -4404,7 +4405,7 @@ // were being fed directly into the output. if (isa(E)) { ConditionalOperator *CO = cast(E); - CheckConditionalOperator(S, CO, T); + CheckConditionalOperator(S, CO, CC, T); return; } Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=156861&r1=156860&r2=156861&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue May 15 16:57:38 2012 @@ -3314,7 +3314,7 @@ return ExprError(); Expr *Arg = Result.takeAs(); - CheckImplicitConversions(Arg, Arg->getExprLoc()); + CheckImplicitConversions(Arg, Param->getOuterLocStart()); // Build the default argument expression. return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg)); } Modified: cfe/trunk/test/SemaCXX/conversion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156861&r1=156860&r2=156861&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/conversion.cpp (original) +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 16:57:38 2012 @@ -73,13 +73,14 @@ // Use FileCheck to ensure we don't get any unnecessary macro-expansion notes // (that don't appear as 'real' notes & can't be seen/tested by -verify) // CHECK-NOT: note: - // CHECK: note: expanded from macro 'FNULL' -#define FNULL NULL - int a2 = FNULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} - // CHECK-NOT: note: // CHECK: note: expanded from macro 'FINIT' #define FINIT int a3 = NULL; FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}} + + // we don't catch the case of #define FOO NULL ... int i = FOO; but that seems a bit narrow anyway + // and avoiding that helps us skip these cases: +#define NULL_COND(cond) ((cond) ? &a : NULL) + bool bl2 = NULL_COND(true); // don't warn on NULL conversion through the conditional operator across a macro boundary } namespace test4 { From dblaikie at gmail.com Tue May 15 16:59:27 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 14:59:27 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 10:43 AM, David Blaikie wrote: > On Tue, May 15, 2012 at 10:39 AM, Nico Weber wrote: >> Hi David, >> >> as mentioned on the thread for this warning, with this change clang warns on > > Ah, right - sorry, I'd forgotten that even the NULL case had some > problems. I'll see what I can do to tidy this case up sooner rather > than later. Thanks for the reminder. I believe r156861 should help handle this case. Thanks again, - David >> >> #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ >> ? ? ? ? ? ? ? ? ? ? ? ? ? : NULL) >> >> // ... >> >> if ( ! YY_CURRENT_BUFFER ) { >> // ... >> } >> >> with this message: >> >> ./pp_lex.cpp:784:10: error: implicit conversion of NULL constant to 'bool' >> [-Werror,-Wnull-conversion] >> ? ? ? ? ? ? ? ? if ( ! YY_CURRENT_BUFFER ) { >> ? ? ? ? ? ? ? ? ? ? ? ?^~~~~~~~~~~~~~~~~ >> ./pp_lex.cpp:295:29: note: expanded from macro 'YY_CURRENT_BUFFER' >> ? ? ? ? ? ? ? ? ? ? ? ? ? : NULL) >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^ >> >> >> This looks like valid code to me. >> >> Nico >> >> On Tue, May 15, 2012 at 9:56 AM, David Blaikie wrote: >>> >>> Author: dblaikie >>> Date: Tue May 15 11:56:36 2012 >>> New Revision: 156826 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev >>> Log: >>> Improve some of the conversion warnings to fire on conversion to bool. >>> >>> Moves the bool bail-out down a little in SemaChecking - so now >>> -Wnull-conversion and -Wliteral-conversion can fire when the target type >>> is >>> bool. >>> >>> Also improve the wording/details in the -Wliteral-conversion warning to >>> match >>> the -Wconstant-conversion. >>> >>> Modified: >>> ? ?cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>> ? ?cfe/trunk/lib/Sema/SemaChecking.cpp >>> ? ?cfe/trunk/test/Analysis/array-struct-region.c >>> ? ?cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >>> ? ?cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >>> ? ?cfe/trunk/test/PCH/exprs.h >>> ? ?cfe/trunk/test/Sema/array-init.c >>> ? ?cfe/trunk/test/Sema/knr-def-call.c >>> ? ?cfe/trunk/test/SemaCXX/bool.cpp >>> ? ?cfe/trunk/test/SemaCXX/conversion.cpp >>> ? ?cfe/trunk/test/SemaCXX/expressions.cpp >>> ? ?cfe/trunk/test/SemaCXX/overload-call.cpp >>> ? ?cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >>> ? ?cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >>> >>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 >>> 11:56:36 2012 >>> @@ -1781,8 +1781,7 @@ >>> ? "implicit truncation from %2 to bitfield changes value from %0 to %1">, >>> ? InGroup; >>> ?def warn_impcast_literal_float_to_integer : Warning< >>> - ?"implicit conversion turns literal floating-point number into integer: >>> " >>> - ?"%0 to %1">, >>> + ?"implicit conversion from %0 to %1 changes value from %2 to %3">, >>> ? InGroup; >>> ?def warn_impcast_string_literal_to_bool : Warning< >>> ? "implicit conversion turns string literal into bool: %0 to %1">, >>> >>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) >>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 >>> @@ -22,6 +22,7 @@ >>> ?#include "clang/AST/CharUnits.h" >>> ?#include "clang/AST/DeclCXX.h" >>> ?#include "clang/AST/DeclObjC.h" >>> +#include "clang/AST/Expr.h" >>> ?#include "clang/AST/ExprCXX.h" >>> ?#include "clang/AST/ExprObjC.h" >>> ?#include "clang/AST/EvaluatedExprVisitor.h" >>> @@ -4081,8 +4082,17 @@ >>> ? ? ? == llvm::APFloat::opOK && isExact) >>> ? ? return; >>> >>> >>> + ?SmallString<16> PrettySourceValue; >>> + ?Value.toString(PrettySourceValue); >>> + ?std::string PrettyTargetValue; >>> + ?if (T->isSpecificBuiltinType(BuiltinType::Bool)) >>> + ? ?PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; >>> + ?else >>> + ? ?PrettyTargetValue = IntegerValue.toString(10); >>> + >>> ? S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) >>> - ? ?<< FL->getType() << T << FL->getSourceRange() << >>> SourceRange(CContext); >>> + ? ?<< FL->getType() << T.getUnqualifiedType() << PrettySourceValue >>> + ? ?<< PrettyTargetValue << FL->getSourceRange() << >>> SourceRange(CContext); >>> ?} >>> >>> ?std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) >>> { >>> @@ -4149,7 +4159,6 @@ >>> ? ? ? ? } >>> ? ? ? } >>> ? ? } >>> - ? ?return; // Other casts to bool are not checked. >>> ? } >>> >>> ? // Strip vector types. >>> @@ -4213,7 +4222,7 @@ >>> ? ? } >>> >>> ? ? // If the target is integral, always warn. >>> - ? ?if ((TargetBT && TargetBT->isInteger())) { >>> + ? ?if (TargetBT && TargetBT->isInteger()) { >>> ? ? ? if (S.SourceMgr.isInSystemMacro(CC)) >>> ? ? ? ? return; >>> >>> @@ -4247,6 +4256,11 @@ >>> ? ? return; >>> ? } >>> >>> + ?// TODO: remove this early return once the false positives for >>> constant->bool >>> + ?// in templates, macros, etc, are reduced or removed. >>> + ?if (Target->isSpecificBuiltinType(BuiltinType::Bool)) >>> + ? ?return; >>> + >>> ? IntRange SourceRange = GetExprRange(S.Context, E); >>> ? IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, >>> Target); >>> >>> >>> Modified: cfe/trunk/test/Analysis/array-struct-region.c >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/Analysis/array-struct-region.c (original) >>> +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 11:56:36 2012 >>> @@ -25,8 +25,8 @@ >>> ?} >>> >>> ?void nested_compound_literals(int rad) { >>> - ?int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, ?// >>> expected-warning 6 {{implicit conversion turns literal floating-point number >>> into integer}} >>> - ? ? ? ? ? ? ? ? ? {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >>> expected-warning 6 {{implicit conversion turns literal floating-point number >>> into integer}} >>> + ?int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, ?// >>> expected-warning 6 {{implicit conversion from 'double' to 'int' changes >>> value from}} >>> + ? ? ? ? ? ? ? ? ? {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >>> expected-warning 6 {{implicit conversion from 'double' to 'int' changes >>> value from}} >>> ? int a; >>> >>> ? for (a = 0; a < 6; ++a) { >>> >>> Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp (original) >>> +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May 15 >>> 11:56:36 2012 >>> @@ -4,7 +4,7 @@ >>> >>> ?bool b = !0; >>> >>> -bool b2 = !1.2; >>> +bool b2 = !1.2; //expected-warning{{implicit conversion from 'double' to >>> 'bool' changes value from 1.2 to true}} >>> >>> ?bool b3 = !4; >>> >>> >>> Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) >>> +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 2012 >>> @@ -14,7 +14,7 @@ >>> ?}; >>> >>> ?template >>> -T X0::value = 3.14; // expected-warning{{implicit conversion turns >>> literal floating-point number into integer}} >>> +T X0::value = 3.14; // expected-warning{{implicit conversion from >>> 'double' to 'int' changes value from 3.14 to 3}} >>> >>> ?template struct X0; // expected-note{{previous explicit >>> instantiation}} \ >>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? expected-note{{requested here}} >>> >>> Modified: cfe/trunk/test/PCH/exprs.h >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/PCH/exprs.h (original) >>> +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 >>> @@ -87,7 +87,7 @@ >>> ? int x; >>> ? float y; >>> ?} designated_inits[3] = { [0].y = 17, >>> - ? ? ? ? ? ? ? ? ? ? ? ? ?[2].x = 12.3, // expected-warning {{implicit >>> conversion turns literal floating-point number into integer}} >>> + ? ? ? ? ? ? ? ? ? ? ? ? ?[2].x = 12.3, // expected-warning {{implicit >>> conversion from 'double' to 'int' changes value from 12.3 to 12}} >>> ? ? ? ? ? ? ? ? ? ? ? ? ? 3.5 }; >>> >>> ?// TypesCompatibleExpr >>> >>> Modified: cfe/trunk/test/Sema/array-init.c >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/Sema/array-init.c (original) >>> +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 >>> @@ -50,7 +50,7 @@ >>> >>> ? static long x2[3] = { 1.0, >>> ? ? ? ? ? ? ? ? ? ? ? ? "abc", // expected-warning{{incompatible pointer >>> to integer conversion initializing 'long' with an expression of type 'char >>> [4]'}} >>> - ? ? ? ? ? ? ? ? ? ? ? ? 5.8 }; // expected-warning {{implicit conversion >>> turns literal floating-point number into integer}} >>> + ? ? ? ? ? ? ? ? ? ? ? ? 5.8 }; // expected-warning {{implicit conversion >>> from 'double' to 'long' changes value from 5.8 to 5}} >>> ?} >>> >>> ?void test() { >>> >>> Modified: cfe/trunk/test/Sema/knr-def-call.c >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/Sema/knr-def-call.c (original) >>> +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 >>> @@ -36,6 +36,6 @@ >>> ?} >>> >>> ?void use_proto() { >>> - ?proto(42.1); // expected-warning{{implicit conversion turns literal >>> floating-point number into integer}} >>> - ?(&proto)(42.1); // expected-warning{{implicit conversion turns literal >>> floating-point number into integer}} >>> + ?proto(42.1); // expected-warning{{implicit conversion from 'double' to >>> 'int' changes value from 42.1 to 42}} >>> + ?(&proto)(42.1); // expected-warning{{implicit conversion from 'double' >>> to 'int' changes value from 42.1 to 42}} >>> ?} >>> >>> Modified: cfe/trunk/test/SemaCXX/bool.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCXX/bool.cpp (original) >>> +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 >>> @@ -1,4 +1,4 @@ >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >>> >>> ?// Bool literals can be enum values. >>> ?enum { >>> >>> Modified: cfe/trunk/test/SemaCXX/conversion.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCXX/conversion.cpp (original) >>> +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 >>> @@ -65,7 +65,7 @@ >>> ? int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL >>> constant to 'int'}} >>> ? int d; >>> ? d = ((((NULL)))); // expected-warning {{implicit conversion of NULL >>> constant to 'int'}} >>> - ?bool bl = NULL; // FIXME: this should warn but we currently suppress a >>> bunch of conversion-to-bool warnings including this one >>> + ?bool bl = NULL; // expected-warning {{implicit conversion of NULL >>> constant to 'bool'}} >>> ? char ch = NULL; // expected-warning {{implicit conversion of NULL >>> constant to 'char'}} >>> ? unsigned char uch = NULL; // expected-warning {{implicit conversion of >>> NULL constant to 'unsigned char'}} >>> ? short sh = NULL; // expected-warning {{implicit conversion of NULL >>> constant to 'short'}} >>> @@ -104,3 +104,12 @@ >>> ? ? tmpl2(); >>> ? } >>> ?} >>> + >>> +namespace test5 { >>> + ?template >>> + ?void func() { >>> + ? ?bool b = I; >>> + ?} >>> + >>> + ?template void func<3>(); >>> +} >>> >>> Modified: cfe/trunk/test/SemaCXX/expressions.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCXX/expressions.cpp (original) >>> +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 >>> @@ -1,4 +1,4 @@ >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >>> >>> ?void choice(int); >>> ?int choice(bool); >>> >>> Modified: cfe/trunk/test/SemaCXX/overload-call.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) >>> +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 2012 >>> @@ -233,7 +233,7 @@ >>> >>> ?void intref_test() { >>> ? float* ir1 = intref(5); >>> - ?float* ir2 = intref(5.5); // expected-warning{{implicit conversion >>> turns literal floating-point number into integer}} >>> + ?float* ir2 = intref(5.5); // expected-warning{{implicit conversion from >>> 'double' to 'int' changes value from 5.5 to 5}} >>> ?} >>> >>> ?void derived5(C&); // expected-note{{candidate function not viable: >>> cannot bind base class object of type 'A' to derived class reference 'C &' >>> for 1st argument}} >>> >>> Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) >>> +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 11:56:36 >>> 2012 >>> @@ -5,29 +5,29 @@ >>> ?// Warn when a literal float or double is assigned or bound to an >>> integer. >>> ?void test0() { >>> ? // Float >>> - ?int y0 = 1.2222F; // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> - ?int y1 = (1.2222F); // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> - ?int y2 = (((1.2222F))); // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> - ?int y3 = 12E-1F; // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> - ?int y4 = 1.23E1F; // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> + ?int y0 = 1.2222F; // expected-warning {{implicit conversion from >>> 'float' to 'int' changes value from 1.2222 to 1}} >>> + ?int y1 = (1.2222F); // expected-warning {{implicit conversion from >>> 'float' to 'int' changes value from 1.2222 to 1}} >>> + ?int y2 = (((1.2222F))); // expected-warning {{implicit conversion from >>> 'float' to 'int' changes value from 1.2222 to 1}} >>> + ?int y3 = 12E-1F; // expected-warning {{implicit conversion from 'float' >>> to 'int' changes value from 1.2 to 1}} >>> + ?int y4 = 1.23E1F; // expected-warning {{implicit conversion from >>> 'float' to 'int' changes value from 12.3 to 12}} >>> ? // Double >>> - ?int y5 = 1.2222; // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> - ?int y6 = 12E-1; // expected-warning {{implicit conversion turns literal >>> floating-point number into integer}} >>> - ?int y7 = 1.23E1; // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> - ?int y8 = (1.23E1); // expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> + ?int y5 = 1.2222; // expected-warning {{implicit conversion from >>> 'double' to 'int' changes value from 1.2222 to 1}} >>> + ?int y6 = 12E-1; // expected-warning {{implicit conversion from 'double' >>> to 'int' changes value from 1.2 to 1}} >>> + ?int y7 = 1.23E1; // expected-warning {{implicit conversion from >>> 'double' to 'int' changes value from 12.3 to 12}} >>> + ?int y8 = (1.23E1); // expected-warning {{implicit conversion from >>> 'double' to 'int' changes value from 12.3 to 12}} >>> >>> ? // Test assignment to an existing variable. >>> - ?y8 = 2.22F; // expected-warning {{implicit conversion turns literal >>> floating-point number into integer}} >>> + ?y8 = 2.22F; // expected-warning {{implicit conversion from 'float' to >>> 'int' changes value from 2.22 to 2}} >>> >>> ? // Test direct initialization. >>> - ?int y9(1.23F); // expected-warning {{implicit conversion turns literal >>> floating-point number into integer}} >>> + ?int y9(1.23F); // expected-warning {{implicit conversion from 'float' >>> to 'int' changes value from 1.23 to 1}} >>> >>> ? // Test passing a literal floating-point value to a function that takes >>> an integer. >>> - ?foo(1.2F); // expected-warning {{implicit conversion turns literal >>> floating-point number into integer}} >>> + ?foo(1.2F); // expected-warning {{implicit conversion from 'float' to >>> 'int' changes value from 1.2 to 1}} >>> >>> - ?int y10 = -1.2F; ?// expected-warning {{implicit conversion turns >>> literal floating-point number into integer}} >>> + ?int y10 = -1.2F; ?// expected-warning {{implicit conversion from >>> 'float' to 'int' changes value from 1.2 to 1}} >>> >>> - ?// -Wconversion-literal does NOT catch const values. >>> + ?// -Wliteral-conversion does NOT catch const values. >>> ? // (-Wconversion DOES catch them.) >>> ? static const float sales_tax_rate = .095F; >>> ? int z = sales_tax_rate; >>> >>> Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original) >>> +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue May 15 >>> 11:56:36 2012 >>> @@ -60,7 +60,7 @@ >>> >>> ?void test_X1(X1 x1) { >>> ? float *fp1 = x1.f1<>(17); >>> - ?float *fp2 = x1.f1(3.14); // expected-warning {{implicit >>> conversion turns literal floating-point number into integer}} >>> + ?float *fp2 = x1.f1(3.14); // expected-warning {{implicit >>> conversion from 'double' to 'int' changes value from 3.14 to 3}} >>> ? int *ip1 = x1.f1(17); >>> ? float *ip2 = x1.f1(3.14); >>> >>> >>> >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> >> From chandlerc at google.com Tue May 15 17:07:41 2012 From: chandlerc at google.com (Chandler Carruth) Date: Tue, 15 May 2012 16:07:41 -0600 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: On Tue, May 15, 2012 at 3:33 PM, David Blaikie wrote: > > This seems like a lot of work and a disruptive change in API patterning, > and > > I'm really not clear what problem it's trying to solve. My suspicion is > that > > there isn't one other than a preference for references instead of > pointers. > > Well the underlying problem was the inconsistency of the iterators in > Decl/DeclBase. I wanted to rationalize their value/reference/pointer > types so I could then extract the common filtering functionality out > of filtered/specific_decl_iterator as a proof-of-concept for a general > adapting/filtering iterator device which I could then re-use in my > efforts to improve the CFG fidelity and -Wunreachable-code diagnostic. > This particular path (generalizing the existing filtering iterators to > a reusable adapter before reusing that in the new use case) was > suggested by Ted Kremmenek & I was happy enough to have an excuse to > tidy up some existing code. > Ok, but again, this is a disruptive change in API patterning. I don't think the inconsistency you point out really justifies the churn without some more compelling problem that it solves. That said, I'd be interested in Ted's perspective here. I also don't see why its necessary to change the pointer / reference semantics in order to factor out common iterator infrastructure, so I'm not really clear why one is blocked on the other. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/e8badca0/attachment.html From macmantrl at me.com Tue May 15 17:09:23 2012 From: macmantrl at me.com (Terry Long) Date: Tue, 15 May 2012 18:09:23 -0400 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics In-Reply-To: References: Message-ID: <86651C4D-12F9-4640-A3EE-BEB07AC70D15@me.com> > I like this a lot! How does it fare against more complicated macros, though? As is it doesn't display very helpful diagnostics for complicated macros like these, and even crashes on some. A good reason not to try to do textual parsing. > > #define CASE1 case 1 > #define CASE(x) case x > #define MULTI_CASE(x,y) case x: case y: > > switch (x) { > CASE1: break; > CASE(1U): break; > MULTI_CASE(2,2): break; > case 2: break; > } > > As for multi-line case statements, I'd be inclined to simply fall back to the dumb version of the warning, rather than trying to format it nicely in the output. We already have a note showing where the relevant code is. And I wouldn't be worried about casts -- if they're there, the user probably thought they were making a difference. (I'd actually be more worried about things like parens, but I'd err on the side of including them anyway.) > > Jordy > > > On May 15, 2012, at 12:05, Terry Long wrote: > >> Hi all, >> >> This patch mostly inspired by http://llvm.org/bugs/show_bug.cgi?id=9243 -- poor "duplicate case" diagnostic with enums >> >> Previously the diagnostic for duplicate case values in switch statements was always something like "duplicate case value '5'" >> >> What my patch changes: >> When the duplicate case is exactly the same in textual representation (in source code), the diagnostic will use that exact text in the diagnostic. >> e.g. using MyEnum twice gives the diagnostic "duplicate case value 'MyEnum'" >> >> If the textual representations differ, the new diagnostic explicitly states they are equal to the same value >> e.g. using MyEnum (equal to 5) and 5, the diagnostic displays "duplicate case value: 'MyEnum' and '5' both equal '5'" >> >> The patch does the same for any valid expression in a case statement (including macros, const ints, char literals, etc.). >> >> Concerns with my patch: >> 1. Multiline case statements, although unusual, will be printed out in the diagnostic exactly as they appear in the source. I'm not sure if this is a real issue. Possible solution would be checking if it spans multiple lines. If so, the diagnostic could be "duplicate case value: both expressions equal 'x'". >> e.g. >> case 1 + >> 2 + >> 3: >> >> 2. If a case statement includes a cast, the cast will also be included in the diagnostic. Sometimes this inclusion is helpful, for example in situations where the cast will cause an overflow (such as "(char)256" and "0"). Other times it is irrelevant, such as "(int)7" and "7", where a simple diagnostic of "duplicate case value '7'" makes more sense. I'm also not sure if this is an issue. >> >> >> Thanks! >> >> Terry Long >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > From thakis at chromium.org Tue May 15 17:16:15 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 15 May 2012 15:16:15 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 2:59 PM, David Blaikie wrote: > On Tue, May 15, 2012 at 10:43 AM, David Blaikie > wrote: > > On Tue, May 15, 2012 at 10:39 AM, Nico Weber > wrote: > >> Hi David, > >> > >> as mentioned on the thread for this warning, with this change clang > warns on > > > > Ah, right - sorry, I'd forgotten that even the NULL case had some > > problems. I'll see what I can do to tidy this case up sooner rather > > than later. Thanks for the reminder. > > I believe r156861 should help handle this case. The warnings on lines with `if ( ! YY_CURRENT_BUFFER)` lines are gone, but `if (YY_CURRENT_BUFFER)` still warns: hummer:src thakis$ /Users/thakis/src/llvm-svn/Release+Asserts/bin/clang++ --version clang version 3.2 (trunk 156862) Target: x86_64-apple-darwin10.8.0 Thread model: posix $ ... glsl_lexer.cpp:2778:7: error: implicit conversion of NULL constant to 'bool' [-Werror,-Wnull-conversion] if ( YY_CURRENT_BUFFER ) ^~~~~~~~~~~~~~~~~ glsl_lexer.cpp:273:29: note: expanded from macro 'YY_CURRENT_BUFFER' : NULL) ^ > Thanks again, > > - David > > >> > >> #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ > >> ? > yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ > >> : NULL) > >> > >> // ... > >> > >> if ( ! YY_CURRENT_BUFFER ) { > >> // ... > >> } > >> > >> with this message: > >> > >> ./pp_lex.cpp:784:10: error: implicit conversion of NULL constant to > 'bool' > >> [-Werror,-Wnull-conversion] > >> if ( ! YY_CURRENT_BUFFER ) { > >> ^~~~~~~~~~~~~~~~~ > >> ./pp_lex.cpp:295:29: note: expanded from macro 'YY_CURRENT_BUFFER' > >> : NULL) > >> ^ > >> > >> > >> This looks like valid code to me. > >> > >> Nico > >> > >> On Tue, May 15, 2012 at 9:56 AM, David Blaikie > wrote: > >>> > >>> Author: dblaikie > >>> Date: Tue May 15 11:56:36 2012 > >>> New Revision: 156826 > >>> > >>> URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev > >>> Log: > >>> Improve some of the conversion warnings to fire on conversion to bool. > >>> > >>> Moves the bool bail-out down a little in SemaChecking - so now > >>> -Wnull-conversion and -Wliteral-conversion can fire when the target > type > >>> is > >>> bool. > >>> > >>> Also improve the wording/details in the -Wliteral-conversion warning to > >>> match > >>> the -Wconstant-conversion. > >>> > >>> Modified: > >>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > >>> cfe/trunk/lib/Sema/SemaChecking.cpp > >>> cfe/trunk/test/Analysis/array-struct-region.c > >>> cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp > >>> cfe/trunk/test/CXX/temp/temp.spec/p5.cpp > >>> cfe/trunk/test/PCH/exprs.h > >>> cfe/trunk/test/Sema/array-init.c > >>> cfe/trunk/test/Sema/knr-def-call.c > >>> cfe/trunk/test/SemaCXX/bool.cpp > >>> cfe/trunk/test/SemaCXX/conversion.cpp > >>> cfe/trunk/test/SemaCXX/expressions.cpp > >>> cfe/trunk/test/SemaCXX/overload-call.cpp > >>> cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp > >>> cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > >>> > >>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > >>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 > >>> 11:56:36 2012 > >>> @@ -1781,8 +1781,7 @@ > >>> "implicit truncation from %2 to bitfield changes value from %0 to > %1">, > >>> InGroup; > >>> def warn_impcast_literal_float_to_integer : Warning< > >>> - "implicit conversion turns literal floating-point number into > integer: > >>> " > >>> - "%0 to %1">, > >>> + "implicit conversion from %0 to %1 changes value from %2 to %3">, > >>> InGroup; > >>> def warn_impcast_string_literal_to_bool : Warning< > >>> "implicit conversion turns string literal into bool: %0 to %1">, > >>> > >>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) > >>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 > >>> @@ -22,6 +22,7 @@ > >>> #include "clang/AST/CharUnits.h" > >>> #include "clang/AST/DeclCXX.h" > >>> #include "clang/AST/DeclObjC.h" > >>> +#include "clang/AST/Expr.h" > >>> #include "clang/AST/ExprCXX.h" > >>> #include "clang/AST/ExprObjC.h" > >>> #include "clang/AST/EvaluatedExprVisitor.h" > >>> @@ -4081,8 +4082,17 @@ > >>> == llvm::APFloat::opOK && isExact) > >>> return; > >>> > >>> > >>> + SmallString<16> PrettySourceValue; > >>> + Value.toString(PrettySourceValue); > >>> + std::string PrettyTargetValue; > >>> + if (T->isSpecificBuiltinType(BuiltinType::Bool)) > >>> + PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; > >>> + else > >>> + PrettyTargetValue = IntegerValue.toString(10); > >>> + > >>> S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) > >>> - << FL->getType() << T << FL->getSourceRange() << > >>> SourceRange(CContext); > >>> + << FL->getType() << T.getUnqualifiedType() << PrettySourceValue > >>> + << PrettyTargetValue << FL->getSourceRange() << > >>> SourceRange(CContext); > >>> } > >>> > >>> std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange > Range) > >>> { > >>> @@ -4149,7 +4159,6 @@ > >>> } > >>> } > >>> } > >>> - return; // Other casts to bool are not checked. > >>> } > >>> > >>> // Strip vector types. > >>> @@ -4213,7 +4222,7 @@ > >>> } > >>> > >>> // If the target is integral, always warn. > >>> - if ((TargetBT && TargetBT->isInteger())) { > >>> + if (TargetBT && TargetBT->isInteger()) { > >>> if (S.SourceMgr.isInSystemMacro(CC)) > >>> return; > >>> > >>> @@ -4247,6 +4256,11 @@ > >>> return; > >>> } > >>> > >>> + // TODO: remove this early return once the false positives for > >>> constant->bool > >>> + // in templates, macros, etc, are reduced or removed. > >>> + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) > >>> + return; > >>> + > >>> IntRange SourceRange = GetExprRange(S.Context, E); > >>> IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, > >>> Target); > >>> > >>> > >>> Modified: cfe/trunk/test/Analysis/array-struct-region.c > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/Analysis/array-struct-region.c (original) > >>> +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 11:56:36 > 2012 > >>> @@ -25,8 +25,8 @@ > >>> } > >>> > >>> void nested_compound_literals(int rad) { > >>> - int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // > >>> expected-warning 6 {{implicit conversion turns literal floating-point > number > >>> into integer}} > >>> - {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // > >>> expected-warning 6 {{implicit conversion turns literal floating-point > number > >>> into integer}} > >>> + int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // > >>> expected-warning 6 {{implicit conversion from 'double' to 'int' changes > >>> value from}} > >>> + {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // > >>> expected-warning 6 {{implicit conversion from 'double' to 'int' changes > >>> value from}} > >>> int a; > >>> > >>> for (a = 0; a < 6; ++a) { > >>> > >>> Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp (original) > >>> +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May 15 > >>> 11:56:36 2012 > >>> @@ -4,7 +4,7 @@ > >>> > >>> bool b = !0; > >>> > >>> -bool b2 = !1.2; > >>> +bool b2 = !1.2; //expected-warning{{implicit conversion from 'double' > to > >>> 'bool' changes value from 1.2 to true}} > >>> > >>> bool b3 = !4; > >>> > >>> > >>> Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) > >>> +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 2012 > >>> @@ -14,7 +14,7 @@ > >>> }; > >>> > >>> template > >>> -T X0::value = 3.14; // expected-warning{{implicit conversion turns > >>> literal floating-point number into integer}} > >>> +T X0::value = 3.14; // expected-warning{{implicit conversion from > >>> 'double' to 'int' changes value from 3.14 to 3}} > >>> > >>> template struct X0; // expected-note{{previous explicit > >>> instantiation}} \ > >>> expected-note{{requested here}} > >>> > >>> Modified: cfe/trunk/test/PCH/exprs.h > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/PCH/exprs.h (original) > >>> +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 > >>> @@ -87,7 +87,7 @@ > >>> int x; > >>> float y; > >>> } designated_inits[3] = { [0].y = 17, > >>> - [2].x = 12.3, // expected-warning {{implicit > >>> conversion turns literal floating-point number into integer}} > >>> + [2].x = 12.3, // expected-warning {{implicit > >>> conversion from 'double' to 'int' changes value from 12.3 to 12}} > >>> 3.5 }; > >>> > >>> // TypesCompatibleExpr > >>> > >>> Modified: cfe/trunk/test/Sema/array-init.c > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/Sema/array-init.c (original) > >>> +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 > >>> @@ -50,7 +50,7 @@ > >>> > >>> static long x2[3] = { 1.0, > >>> "abc", // expected-warning{{incompatible > pointer > >>> to integer conversion initializing 'long' with an expression of type > 'char > >>> [4]'}} > >>> - 5.8 }; // expected-warning {{implicit > conversion > >>> turns literal floating-point number into integer}} > >>> + 5.8 }; // expected-warning {{implicit > conversion > >>> from 'double' to 'long' changes value from 5.8 to 5}} > >>> } > >>> > >>> void test() { > >>> > >>> Modified: cfe/trunk/test/Sema/knr-def-call.c > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/Sema/knr-def-call.c (original) > >>> +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 > >>> @@ -36,6 +36,6 @@ > >>> } > >>> > >>> void use_proto() { > >>> - proto(42.1); // expected-warning{{implicit conversion turns literal > >>> floating-point number into integer}} > >>> - (&proto)(42.1); // expected-warning{{implicit conversion turns > literal > >>> floating-point number into integer}} > >>> + proto(42.1); // expected-warning{{implicit conversion from 'double' > to > >>> 'int' changes value from 42.1 to 42}} > >>> + (&proto)(42.1); // expected-warning{{implicit conversion from > 'double' > >>> to 'int' changes value from 42.1 to 42}} > >>> } > >>> > >>> Modified: cfe/trunk/test/SemaCXX/bool.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/SemaCXX/bool.cpp (original) > >>> +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 > >>> @@ -1,4 +1,4 @@ > >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s > >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s > >>> > >>> // Bool literals can be enum values. > >>> enum { > >>> > >>> Modified: cfe/trunk/test/SemaCXX/conversion.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/SemaCXX/conversion.cpp (original) > >>> +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 > >>> @@ -65,7 +65,7 @@ > >>> int c = ((((NULL)))); // expected-warning {{implicit conversion of > NULL > >>> constant to 'int'}} > >>> int d; > >>> d = ((((NULL)))); // expected-warning {{implicit conversion of NULL > >>> constant to 'int'}} > >>> - bool bl = NULL; // FIXME: this should warn but we currently > suppress a > >>> bunch of conversion-to-bool warnings including this one > >>> + bool bl = NULL; // expected-warning {{implicit conversion of NULL > >>> constant to 'bool'}} > >>> char ch = NULL; // expected-warning {{implicit conversion of NULL > >>> constant to 'char'}} > >>> unsigned char uch = NULL; // expected-warning {{implicit conversion > of > >>> NULL constant to 'unsigned char'}} > >>> short sh = NULL; // expected-warning {{implicit conversion of NULL > >>> constant to 'short'}} > >>> @@ -104,3 +104,12 @@ > >>> tmpl2(); > >>> } > >>> } > >>> + > >>> +namespace test5 { > >>> + template > >>> + void func() { > >>> + bool b = I; > >>> + } > >>> + > >>> + template void func<3>(); > >>> +} > >>> > >>> Modified: cfe/trunk/test/SemaCXX/expressions.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/SemaCXX/expressions.cpp (original) > >>> +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 > >>> @@ -1,4 +1,4 @@ > >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s > >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s > >>> > >>> void choice(int); > >>> int choice(bool); > >>> > >>> Modified: cfe/trunk/test/SemaCXX/overload-call.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) > >>> +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 2012 > >>> @@ -233,7 +233,7 @@ > >>> > >>> void intref_test() { > >>> float* ir1 = intref(5); > >>> - float* ir2 = intref(5.5); // expected-warning{{implicit conversion > >>> turns literal floating-point number into integer}} > >>> + float* ir2 = intref(5.5); // expected-warning{{implicit conversion > from > >>> 'double' to 'int' changes value from 5.5 to 5}} > >>> } > >>> > >>> void derived5(C&); // expected-note{{candidate function not viable: > >>> cannot bind base class object of type 'A' to derived class reference > 'C &' > >>> for 1st argument}} > >>> > >>> Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) > >>> +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 > 11:56:36 > >>> 2012 > >>> @@ -5,29 +5,29 @@ > >>> // Warn when a literal float or double is assigned or bound to an > >>> integer. > >>> void test0() { > >>> // Float > >>> - int y0 = 1.2222F; // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> - int y1 = (1.2222F); // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> - int y2 = (((1.2222F))); // expected-warning {{implicit conversion > turns > >>> literal floating-point number into integer}} > >>> - int y3 = 12E-1F; // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> - int y4 = 1.23E1F; // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> + int y0 = 1.2222F; // expected-warning {{implicit conversion from > >>> 'float' to 'int' changes value from 1.2222 to 1}} > >>> + int y1 = (1.2222F); // expected-warning {{implicit conversion from > >>> 'float' to 'int' changes value from 1.2222 to 1}} > >>> + int y2 = (((1.2222F))); // expected-warning {{implicit conversion > from > >>> 'float' to 'int' changes value from 1.2222 to 1}} > >>> + int y3 = 12E-1F; // expected-warning {{implicit conversion from > 'float' > >>> to 'int' changes value from 1.2 to 1}} > >>> + int y4 = 1.23E1F; // expected-warning {{implicit conversion from > >>> 'float' to 'int' changes value from 12.3 to 12}} > >>> // Double > >>> - int y5 = 1.2222; // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> - int y6 = 12E-1; // expected-warning {{implicit conversion turns > literal > >>> floating-point number into integer}} > >>> - int y7 = 1.23E1; // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> - int y8 = (1.23E1); // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> + int y5 = 1.2222; // expected-warning {{implicit conversion from > >>> 'double' to 'int' changes value from 1.2222 to 1}} > >>> + int y6 = 12E-1; // expected-warning {{implicit conversion from > 'double' > >>> to 'int' changes value from 1.2 to 1}} > >>> + int y7 = 1.23E1; // expected-warning {{implicit conversion from > >>> 'double' to 'int' changes value from 12.3 to 12}} > >>> + int y8 = (1.23E1); // expected-warning {{implicit conversion from > >>> 'double' to 'int' changes value from 12.3 to 12}} > >>> > >>> // Test assignment to an existing variable. > >>> - y8 = 2.22F; // expected-warning {{implicit conversion turns literal > >>> floating-point number into integer}} > >>> + y8 = 2.22F; // expected-warning {{implicit conversion from 'float' > to > >>> 'int' changes value from 2.22 to 2}} > >>> > >>> // Test direct initialization. > >>> - int y9(1.23F); // expected-warning {{implicit conversion turns > literal > >>> floating-point number into integer}} > >>> + int y9(1.23F); // expected-warning {{implicit conversion from > 'float' > >>> to 'int' changes value from 1.23 to 1}} > >>> > >>> // Test passing a literal floating-point value to a function that > takes > >>> an integer. > >>> - foo(1.2F); // expected-warning {{implicit conversion turns literal > >>> floating-point number into integer}} > >>> + foo(1.2F); // expected-warning {{implicit conversion from 'float' to > >>> 'int' changes value from 1.2 to 1}} > >>> > >>> - int y10 = -1.2F; // expected-warning {{implicit conversion turns > >>> literal floating-point number into integer}} > >>> + int y10 = -1.2F; // expected-warning {{implicit conversion from > >>> 'float' to 'int' changes value from 1.2 to 1}} > >>> > >>> - // -Wconversion-literal does NOT catch const values. > >>> + // -Wliteral-conversion does NOT catch const values. > >>> // (-Wconversion DOES catch them.) > >>> static const float sales_tax_rate = .095F; > >>> int z = sales_tax_rate; > >>> > >>> Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > >>> URL: > >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> > >>> > ============================================================================== > >>> --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > (original) > >>> +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue > May 15 > >>> 11:56:36 2012 > >>> @@ -60,7 +60,7 @@ > >>> > >>> void test_X1(X1 x1) { > >>> float *fp1 = x1.f1<>(17); > >>> - float *fp2 = x1.f1(3.14); // expected-warning {{implicit > >>> conversion turns literal floating-point number into integer}} > >>> + float *fp2 = x1.f1(3.14); // expected-warning {{implicit > >>> conversion from 'double' to 'int' changes value from 3.14 to 3}} > >>> int *ip1 = x1.f1(17); > >>> float *ip2 = x1.f1(3.14); > >>> > >>> > >>> > >>> _______________________________________________ > >>> cfe-commits mailing list > >>> cfe-commits at cs.uiuc.edu > >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > >> > >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/a8da2e29/attachment-0001.html From akyrtzi at gmail.com Tue May 15 17:22:10 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 15 May 2012 22:22:10 -0000 Subject: [cfe-commits] r156868 - in /cfe/trunk: include/clang/AST/NSAPI.h lib/AST/NSAPI.cpp lib/Edit/RewriteObjCFoundationAPI.cpp test/ARCMT/objcmt-boxing.m test/ARCMT/objcmt-boxing.m.result Message-ID: <20120515222210.613ED2A6C067@llvm.org> Author: akirtzidis Date: Tue May 15 17:22:10 2012 New Revision: 156868 URL: http://llvm.org/viewvc/llvm-project?rev=156868&view=rev Log: [objcmt] Rewrite messages to NSString's stringWithUTF8String:/stringWithCString: to use the @() boxing syntax. It will also rewrite uses of stringWithCString:encoding: where the encoding that is used is NSASCIIStringEncoding or NSUTF8StringEncoding. rdar://11438360 Modified: cfe/trunk/include/clang/AST/NSAPI.h cfe/trunk/lib/AST/NSAPI.cpp cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp cfe/trunk/test/ARCMT/objcmt-boxing.m cfe/trunk/test/ARCMT/objcmt-boxing.m.result Modified: cfe/trunk/include/clang/AST/NSAPI.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NSAPI.h?rev=156868&r1=156867&r2=156868&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/NSAPI.h (original) +++ cfe/trunk/include/clang/AST/NSAPI.h Tue May 15 17:22:10 2012 @@ -16,6 +16,7 @@ namespace clang { class ASTContext; class QualType; + class Expr; // \brief Provides info and caches identifiers/selectors for NSFoundation API. class NSAPI { @@ -37,15 +38,33 @@ enum NSStringMethodKind { NSStr_stringWithString, + NSStr_stringWithUTF8String, + NSStr_stringWithCStringEncoding, + NSStr_stringWithCString, NSStr_initWithString }; - static const unsigned NumNSStringMethods = 2; + static const unsigned NumNSStringMethods = 5; IdentifierInfo *getNSClassId(NSClassIdKindKind K) const; /// \brief The Objective-C NSString selectors. Selector getNSStringSelector(NSStringMethodKind MK) const; + /// \brief Return NSStringMethodKind if \param Sel is such a selector. + llvm::Optional getNSStringMethodKind(Selector Sel) const; + + /// \brief Returns true if the expression \param E is a reference of + /// "NSUTF8StringEncoding" enum constant. + bool isNSUTF8StringEncodingConstant(const Expr *E) const { + return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId); + } + + /// \brief Returns true if the expression \param E is a reference of + /// "NSASCIIStringEncoding" enum constant. + bool isNSASCIIStringEncodingConstant(const Expr *E) const { + return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId); + } + /// \brief Enumerates the NSArray methods used to generate literals. enum NSArrayMethodKind { NSArr_array, @@ -138,6 +157,8 @@ private: bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const; + bool isObjCEnumerator(const Expr *E, + StringRef name, IdentifierInfo *&II) const; ASTContext &Ctx; @@ -156,6 +177,7 @@ mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods]; mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId; + mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId; }; } // end namespace clang Modified: cfe/trunk/lib/AST/NSAPI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?rev=156868&r1=156867&r2=156868&view=diff ============================================================================== --- cfe/trunk/lib/AST/NSAPI.cpp (original) +++ cfe/trunk/lib/AST/NSAPI.cpp Tue May 15 17:22:10 2012 @@ -9,11 +9,13 @@ #include "clang/AST/NSAPI.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" using namespace clang; NSAPI::NSAPI(ASTContext &ctx) - : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0) { + : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0), + NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) { } IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { @@ -40,6 +42,21 @@ case NSStr_stringWithString: Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString")); break; + case NSStr_stringWithUTF8String: + Sel = Ctx.Selectors.getUnarySelector( + &Ctx.Idents.get("stringWithUTF8String")); + break; + case NSStr_stringWithCStringEncoding: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("stringWithCString"), + &Ctx.Idents.get("encoding") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSStr_stringWithCString: + Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString")); + break; case NSStr_initWithString: Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString")); break; @@ -50,6 +67,17 @@ return NSStringSelectors[MK]; } +llvm::Optional +NSAPI::getNSStringMethodKind(Selector Sel) const { + for (unsigned i = 0; i != NumNSStringMethods; ++i) { + NSStringMethodKind MK = NSStringMethodKind(i); + if (Sel == getNSStringSelector(MK)) + return MK; + } + + return llvm::Optional(); +} + Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { if (NSArraySelectors[MK].isNull()) { Selector Sel; @@ -353,3 +381,21 @@ return false; } + +bool NSAPI::isObjCEnumerator(const Expr *E, + StringRef name, IdentifierInfo *&II) const { + if (!Ctx.getLangOpts().ObjC1) + return false; + if (!E) + return false; + + if (!II) + II = &Ctx.Idents.get(name); + + if (const DeclRefExpr *DRE = dyn_cast(E->IgnoreParenImpCasts())) + if (const EnumConstantDecl * + EnumD = dyn_cast_or_null(DRE->getDecl())) + return EnumD->getIdentifier() == II; + + return false; +} Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp?rev=156868&r1=156867&r2=156868&view=diff ============================================================================== --- cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp (original) +++ cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Tue May 15 17:22:10 2012 @@ -211,6 +211,8 @@ const NSAPI &NS, Commit &commit); static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit); +static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit); bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { @@ -224,6 +226,8 @@ return rewriteToDictionaryLiteral(Msg, NS, commit); if (II == NS.getNSClassId(NSAPI::ClassId_NSNumber)) return rewriteToNumberLiteral(Msg, NS, commit); + if (II == NS.getNSClassId(NSAPI::ClassId_NSString)) + return rewriteToStringBoxedExpression(Msg, NS, commit); return false; } @@ -791,7 +795,7 @@ return false; SourceRange ArgRange = OrigArg->getSourceRange(); - commit.replaceWithInner(Msg->getSourceRange(), OrigArg->getSourceRange()); + commit.replaceWithInner(Msg->getSourceRange(), ArgRange); if (isa(OrigArg) || isa(OrigArg)) commit.insertBefore(ArgRange.getBegin(), "@"); @@ -800,3 +804,68 @@ return true; } + +//===----------------------------------------------------------------------===// +// rewriteToStringBoxedExpression. +//===----------------------------------------------------------------------===// + +static bool doRewriteToUTF8StringBoxedExpressionHelper( + const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit) { + const Expr *Arg = Msg->getArg(0); + if (Arg->isTypeDependent()) + return false; + + const Expr *OrigArg = Arg->IgnoreImpCasts(); + QualType OrigTy = OrigArg->getType(); + + if (const StringLiteral * + StrE = dyn_cast(OrigArg->IgnoreParens())) { + commit.replaceWithInner(Msg->getSourceRange(), StrE->getSourceRange()); + commit.insert(StrE->getLocStart(), "@"); + return true; + } + + ASTContext &Ctx = NS.getASTContext(); + + if (const PointerType *PT = OrigTy->getAs()) { + QualType PointeeType = PT->getPointeeType(); + if (Ctx.hasSameUnqualifiedType(PointeeType, Ctx.CharTy)) { + SourceRange ArgRange = OrigArg->getSourceRange(); + commit.replaceWithInner(Msg->getSourceRange(), ArgRange); + + if (isa(OrigArg) || isa(OrigArg)) + commit.insertBefore(ArgRange.getBegin(), "@"); + else + commit.insertWrap("@(", ArgRange, ")"); + + return true; + } + } + + return false; +} + +static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg, + const NSAPI &NS, Commit &commit) { + Selector Sel = Msg->getSelector(); + + if (Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithUTF8String) || + Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithCString)) { + if (Msg->getNumArgs() != 1) + return false; + return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit); + } + + if (Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithCStringEncoding)) { + if (Msg->getNumArgs() != 2) + return false; + + const Expr *encodingArg = Msg->getArg(1); + if (NS.isNSUTF8StringEncodingConstant(encodingArg) || + NS.isNSASCIIStringEncodingConstant(encodingArg)) + return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit); + } + + return false; +} Modified: cfe/trunk/test/ARCMT/objcmt-boxing.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m?rev=156868&r1=156867&r2=156868&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-boxing.m (original) +++ cfe/trunk/test/ARCMT/objcmt-boxing.m Tue May 15 17:22:10 2012 @@ -54,6 +54,22 @@ + (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; @end +enum { + NSASCIIStringEncoding = 1, + NSUTF8StringEncoding = 4, + NSUnicodeStringEncoding = 10 +}; +typedef NSUInteger NSStringEncoding; + + at interface NSString : NSObject + at end + + at interface NSString (NSStringExtensionMethods) ++ (id)stringWithUTF8String:(const char *)nullTerminatedCString; ++ (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc; ++ (id)stringWithCString:(const char *)bytes; + at end + enum MyEnm { ME_foo }; @@ -66,3 +82,17 @@ [NSNumber numberWithInteger:myenum]; [NSNumber numberWithInteger:ME_foo]; } + +void boxString() { + NSString *s = [NSString stringWithUTF8String:"box"]; + const char *cstr1; + char *cstr2; + s = [NSString stringWithUTF8String:cstr1]; + s = [NSString stringWithUTF8String:cstr2]; + s = [NSString stringWithCString:cstr1 encoding:NSASCIIStringEncoding]; + s = [NSString stringWithCString:cstr1 encoding:NSUTF8StringEncoding]; + s = [NSString stringWithCString:cstr1 encoding: NSUnicodeStringEncoding]; + NSStringEncoding encode; + s = [NSString stringWithCString:cstr1 encoding:encode]; + s = [NSString stringWithCString:cstr1]; +} Modified: cfe/trunk/test/ARCMT/objcmt-boxing.m.result URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m.result?rev=156868&r1=156867&r2=156868&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-boxing.m.result (original) +++ cfe/trunk/test/ARCMT/objcmt-boxing.m.result Tue May 15 17:22:10 2012 @@ -54,6 +54,22 @@ + (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value; @end +enum { + NSASCIIStringEncoding = 1, + NSUTF8StringEncoding = 4, + NSUnicodeStringEncoding = 10 +}; +typedef NSUInteger NSStringEncoding; + + at interface NSString : NSObject + at end + + at interface NSString (NSStringExtensionMethods) ++ (id)stringWithUTF8String:(const char *)nullTerminatedCString; ++ (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc; ++ (id)stringWithCString:(const char *)bytes; + at end + enum MyEnm { ME_foo }; @@ -66,3 +82,17 @@ @(myenum); @(ME_foo); } + +void boxString() { + NSString *s = @"box"; + const char *cstr1; + char *cstr2; + s = @(cstr1); + s = @(cstr2); + s = @(cstr1); + s = @(cstr1); + s = [NSString stringWithCString:cstr1 encoding: NSUnicodeStringEncoding]; + NSStringEncoding encode; + s = [NSString stringWithCString:cstr1 encoding:encode]; + s = @(cstr1); +} From ganna at apple.com Tue May 15 17:25:25 2012 From: ganna at apple.com (Anna Zaks) Date: Tue, 15 May 2012 15:25:25 -0700 Subject: [cfe-commits] [PATCH] Add analyzer_assert for regression tests In-Reply-To: <85DF843B-246E-4F10-A116-F2A43E396AA0@belkadan.com> References: <881546B4-753E-499A-A279-04FD0F182FEF@belkadan.com> <6A305ACC-5BF0-4281-8B01-C3F3E4228F57@apple.com> <603F2830-8617-434C-BBA8-659F26524A5B@belkadan.com> <08B8B6C0-175A-4DDB-9E57-265C5B0AA986@apple.com> <85DF843B-246E-4F10-A116-F2A43E396AA0@belkadan.com> Message-ID: <02322A8B-EFCD-4501-B532-774E9B89E1CA@apple.com> On May 15, 2012, at 1:19 PM, Jordan Rose wrote: > > On May 15, 2012, at 15:21, Anna Zaks wrote: > >> A couple of comments: >> >> 1) Maybe we could make the name of the checker more generic as it can easily be extended to provide info other that constraints. > > Hm. debug.StateInspection? debug.Reflection? debug.Introspection? debug.ExprInspection? > > >> 2) I think C.addTransition() is a no-op in this case, so the call can be removed: >> + // These checks should have no effect on the surrounding environment >> + // (globals should not be evaluated, etc). >> + C.addTransition(); > > Hm. Wasn't sure how that interacted with evalCall, but you're right. > > >> 3) Why not support these. They will just result in several diagnostics. >> + // A specific instantiation of an inlined function may have more constrained >> + // values than can generally be assumed. >> + if (LC->getParent() != 0) >> + return true; > > I actually came across this when converting existing tests. Here's a trivial example where a constraint is generally unknowable but is known when inlined. > (As I said before, we should probably not convert such cases - that most likely is not a constraint test.) > void check(void *x) { > clang_analyzer_check(x != 0); // expected-warning{{UNKNOWN}} > } > > void test() { > check(0); > } > > For the case of TRUE or FALSE there would be no change, but UNKNOWN is a problem. (In the previous iteration, these were separated into analyzer_assert and analyzer_assert_unknown, but I don't think it's necessary to check that something is true generally /and/ in a specific inlined case.) This checker might be useful to debug in presence of IPA. I though it's just the matter of having extra diagnostics - one per frame in which the call is evaluated. But maybe I am missing something.. > > >> 4) Should this be an assert? >> + else >> + Msg = "INVALID"; > > I'm not sure. The analyzer will probably grind to a halt long before it gets here, but if someone ever /does/ make a logical mistake on the infrastructure that results in this situation (testing a constraint results in two infeasible states, even with a feasible base state), it might be nicer /not/ to stop analysis here. Since these are intended to go in regression tests, the fact that the test was known to work before might be useful knowledge, in which case it should go on being tested. > Are there cases where an expression is known to be "INVALID"? If someone introduces this issue we should detect ASAP and fix immediately, no? > I don't have a strong opinion here, but it doesn't seem to cost much. All we're doing is emitting a warning, not changing the state at all. It's better to stop with an assert and bring attention to this right away. You could run the checker on large codebases to find out if these cases are ever possible. > > >> 5) This one is the most important. I'd only change the test cases where you are absolutely sure that the constraint solver is the only thing that's being tested there and leave the rest. It is OK to have both types of tests and we don't want to decrease our coverage of testing for actual warnings. I see this enhancement as simplifying addition of this type of tests in the future; we don't need to convert all our tests to using it. > > Okay, I'll stick to the systematically obvious ones, then (those that have a WARN macro or similar). > > Thanks! > Jordy From macmantrl at me.com Tue May 15 17:28:45 2012 From: macmantrl at me.com (Terry Long) Date: Tue, 15 May 2012 18:28:45 -0400 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics In-Reply-To: <71F9C9BF-830D-4ADC-A751-0A9E4FCA9225@apple.com> References: <71F9C9BF-830D-4ADC-A751-0A9E4FCA9225@apple.com> Message-ID: Am 15.05.2012 um 16:09 schrieb Douglas Gregor > > > I'm a bit uncomfortable with the textual approach here. Why not analyze the expressions to check whether they are references to named declarations, and use those names in the diagnostic? It won't catch some macro cases, but it's far simpler. I was also uncomfortable with the textual approach, and in fact I first tried seeing if the case expression was a DeclRefExpr that refers to a valid NamedDecl. The problem I found with that approach was that it was not catching very many situations. Doing it that way only works for enums as far as I can tell. Macros, const ints, case overflows, casting, and more complicated expressions (like "case 2+2") are not DeclRefExprs, and I don't see any obvious way to grab the necessary diagnostic info without using a textual approach. To be safer and simpler, it's probably best to only do these smart diagnostics for enums (through DeclRefExpr), unless someone has any suggestions for a better way to do all of this. -Terry From ganna at apple.com Tue May 15 17:31:56 2012 From: ganna at apple.com (Anna Zaks) Date: Tue, 15 May 2012 22:31:56 -0000 Subject: [cfe-commits] r156870 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp test/Analysis/unused-ivars.m Message-ID: <20120515223156.8D6B72A6C065@llvm.org> Author: zaks Date: Tue May 15 17:31:56 2012 New Revision: 156870 URL: http://llvm.org/viewvc/llvm-project?rev=156870&view=rev Log: [analyzer] Fix a regression in ObjCUnusedIVars checker. We can no longer rely on children iterator to visit all the AST tree children of an expression (OpaqueValueExpr has no children). Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp cfe/trunk/test/Analysis/unused-ivars.m Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp?rev=156870&r1=156869&r2=156870&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp Tue May 15 17:31:56 2012 @@ -47,6 +47,15 @@ return; } + if (const PseudoObjectExpr *POE = dyn_cast(S)) + for (PseudoObjectExpr::const_semantics_iterator + i = POE->semantics_begin(), e = POE->semantics_end(); i != e; ++i) { + const Expr *sub = *i; + if (const OpaqueValueExpr *OVE = dyn_cast(sub)) + sub = OVE->getSourceExpr(); + Scan(M, sub); + } + for (Stmt::const_child_iterator I=S->child_begin(),E=S->child_end(); I!=E;++I) Scan(M, *I); } Modified: cfe/trunk/test/Analysis/unused-ivars.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/unused-ivars.m?rev=156870&r1=156869&r2=156870&view=diff ============================================================================== --- cfe/trunk/test/Analysis/unused-ivars.m (original) +++ cfe/trunk/test/Analysis/unused-ivars.m Tue May 15 17:31:56 2012 @@ -108,3 +108,24 @@ @implementation RDar8481311 @end + + at class NSString; + at interface Radar11059352_1 { + at private + NSString *_pathString; +} + at property (readonly, strong) NSString *pathString; + at end + + at interface Radar11059352 { + at private +Radar11059352_1 *_workspacePath; +} + at end + + at implementation Radar11059352 + +- (void)useWorkspace { + NSString *workspacePathString = _workspacePath.pathString; +} + at end \ No newline at end of file From fjahanian at apple.com Tue May 15 17:37:05 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Tue, 15 May 2012 22:37:05 -0000 Subject: [cfe-commits] r156871 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaObjCProperty.cpp test/SemaObjC/property-impl-misuse.m test/SemaObjC/property-typecheck-1.m Message-ID: <20120515223705.1BDB32A6C065@llvm.org> Author: fjahanian Date: Tue May 15 17:37:04 2012 New Revision: 156871 URL: http://llvm.org/viewvc/llvm-project?rev=156871&view=rev Log: objective-c: perform strict type checking on property type and its accessor type and issue error if types are incompatible, instead of crashing in IRgen. // rdar://1105153 Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaObjCProperty.cpp cfe/trunk/test/SemaObjC/property-impl-misuse.m cfe/trunk/test/SemaObjC/property-typecheck-1.m Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156871&r1=156870&r2=156871&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 17:37:04 2012 @@ -685,6 +685,8 @@ def error_property_ivar_type : Error< "type of property %0 (%1) does not match type of ivar %2 (%3)">; +def error_property_accessor_type : Error< + "type of property %0 (%1) does not match type of accessor %2 (%3)">; def error_ivar_in_superclass_use : Error< "property %0 attempting to use ivar %1 declared in super class %2">; def error_weak_property : Error< Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=156871&r1=156870&r2=156871&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original) +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Tue May 15 17:37:04 2012 @@ -1050,21 +1050,42 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, ObjCMethodDecl *GetterMethod, SourceLocation Loc) { - if (GetterMethod && - !Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(), - property->getType().getNonReferenceType())) { - AssignConvertType result = Incompatible; - if (property->getType()->isObjCObjectPointerType()) - result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), - property->getType()); - if (result != Compatible) { - Diag(Loc, diag::warn_accessor_property_type_mismatch) - << property->getDeclName() - << GetterMethod->getSelector(); - Diag(GetterMethod->getLocation(), diag::note_declared_at); - return true; + if (!GetterMethod) + return false; + QualType GetterType = GetterMethod->getResultType().getNonReferenceType(); + QualType PropertyIvarType = property->getType().getNonReferenceType(); + bool compat = Context.hasSameType(PropertyIvarType, GetterType); + if (!compat) { + if (isa(PropertyIvarType) && + isa(GetterType)) + compat = + Context.canAssignObjCInterfaces( + PropertyIvarType->getAs(), + GetterType->getAs()); + else if (CheckAssignmentConstraints(Loc, PropertyIvarType, GetterType) + != Compatible) { + Diag(Loc, diag::error_property_accessor_type) + << property->getDeclName() << PropertyIvarType + << GetterMethod->getSelector() << GetterType; + Diag(GetterMethod->getLocation(), diag::note_declared_at); + return true; + } else { + compat = true; + QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); + QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType(); + if (lhsType != rhsType && lhsType->isArithmeticType()) + compat = false; } } + + if (!compat) { + Diag(Loc, diag::warn_accessor_property_type_mismatch) + << property->getDeclName() + << GetterMethod->getSelector(); + Diag(GetterMethod->getLocation(), diag::note_declared_at); + return true; + } + return false; } Modified: cfe/trunk/test/SemaObjC/property-impl-misuse.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-impl-misuse.m?rev=156871&r1=156870&r2=156871&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/property-impl-misuse.m (original) +++ cfe/trunk/test/SemaObjC/property-impl-misuse.m Tue May 15 17:37:04 2012 @@ -34,3 +34,16 @@ self.gradientStyle; // expected-error {{property 'gradientStyle' not found on object of type 'Class'}} } @end + +// rdar://1105153 + at interface rdar1105153 + at property int P; // expected-error {{type of property 'P' ('int') does not match type of accessor 'P' ('void')}} +- (void)P; // expected-note {{declared here}} + + at property int P1; // expected-warning {{type of property 'P1' does not match type of accessor 'P1'}} +- (double) P1; // expected-note {{declared here}} + + at property int P2; // expected-error {{type of property 'P2' ('int') does not match type of accessor 'P2' ('double *')}} +- (double*)P2; // expected-note {{declared here}} + + at end Modified: cfe/trunk/test/SemaObjC/property-typecheck-1.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-typecheck-1.m?rev=156871&r1=156870&r2=156871&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/property-typecheck-1.m (original) +++ cfe/trunk/test/SemaObjC/property-typecheck-1.m Tue May 15 17:37:04 2012 @@ -73,11 +73,11 @@ NSArray* first; } - at property (readonly) NSArray* pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}} - at property (readonly) NSMutableArray* first; + at property (readonly) NSArray* pieces; + at property (readonly) NSMutableArray* first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}} -- (NSMutableArray*) pieces; // expected-note {{declared here}} // expected-note {{declared here}} -- (NSArray*) first; +- (NSMutableArray*) pieces; +- (NSArray*) first; // expected-note 2 {{declared here}} @end @interface Class2 { @@ -90,12 +90,12 @@ - (id) lastPiece { - return container.pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}} + return container.pieces; } - (id)firstPeice { - return container.first; + return container.first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}} } @end From dgregor at apple.com Tue May 15 17:41:11 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 15:41:11 -0700 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics In-Reply-To: References: <71F9C9BF-830D-4ADC-A751-0A9E4FCA9225@apple.com> Message-ID: <30EDA624-D310-4EEA-A69C-CB0DDDD23D3B@apple.com> On May 15, 2012, at 3:28 PM, Terry Long wrote: > > Am 15.05.2012 um 16:09 schrieb Douglas Gregor >> >> >> I'm a bit uncomfortable with the textual approach here. Why not analyze the expressions to check whether they are references to named declarations, and use those names in the diagnostic? It won't catch some macro cases, but it's far simpler. > > I was also uncomfortable with the textual approach, and in fact I first tried seeing if the case expression was a DeclRefExpr that refers to a valid NamedDecl. The problem I found with that approach was that it was not catching very many situations. Doing it that way only works for enums as far as I can tell. Macros, const ints, case overflows, casting, and more complicated expressions (like "case 2+2") are not DeclRefExprs, and I don't see any obvious way to grab the necessary diagnostic info without using a textual approach. You can look through implicit conversions (e.g., promotions) and parentheses to find the underlying expression. We'll get a DeclRefExpr for enumerators and variables that are constant ("const int x = 17;"), which are presumably the common cases. We won't get macros, of course, but we might not want to: it's probably more useful to show the value we get when the macro is expanded, and let the macro-substitution backtrace show how we got there. - Doug From fjahanian at apple.com Tue May 15 17:42:31 2012 From: fjahanian at apple.com (jahanian) Date: Tue, 15 May 2012 15:42:31 -0700 Subject: [cfe-commits] r156871 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaObjCProperty.cpp test/SemaObjC/property-impl-misuse.m test/SemaObjC/property-typecheck-1.m In-Reply-To: <20120515223705.1BDB32A6C065@llvm.org> References: <20120515223705.1BDB32A6C065@llvm.org> Message-ID: <7F0B8610-337E-40BA-9DB8-D67535176971@apple.com> On May 15, 2012, at 3:37 PM, Fariborz Jahanian wrote: > Author: fjahanian > Date: Tue May 15 17:37:04 2012 > New Revision: 156871 > > URL: http://llvm.org/viewvc/llvm-project?rev=156871&view=rev > Log: > objective-c: perform strict type checking on property > type and its accessor type and issue error if types > are incompatible, instead of crashing in IRgen. > // rdar://1105153 // rdar://11054153 - Fariborz From dblaikie at gmail.com Tue May 15 17:44:05 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 15:44:05 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: On Tue, May 15, 2012 at 3:07 PM, Chandler Carruth wrote: > On Tue, May 15, 2012 at 3:33 PM, David Blaikie wrote: >> >> > This seems like a lot of work and a disruptive change in API patterning, >> > and >> > I'm really not clear what problem it's trying to solve. My suspicion is >> > that >> > there isn't one other than a preference for references instead of >> > pointers. >> >> Well the underlying problem was the inconsistency of the iterators in >> Decl/DeclBase. I wanted to rationalize their value/reference/pointer >> types so I could then extract the common filtering functionality out >> of filtered/specific_decl_iterator as a proof-of-concept for a general >> adapting/filtering iterator device which I could then re-use in my >> efforts to improve the CFG fidelity and -Wunreachable-code diagnostic. >> This particular path (generalizing the existing filtering iterators to >> a reusable adapter before reusing that in the new use case) was >> suggested by Ted Kremmenek & I was happy enough to have an excuse to >> tidy up some existing code. > > > Ok, but again, this is a disruptive change in API patterning. I don't think > the inconsistency you point out really justifies the churn without some more > compelling problem that it solves. That said, I'd be interested in Ted's > perspective here. To be clear - I don't think Ted has a dog in this race (or hasn't expressed it, at least - though I wouldn't mind having a few more opinions on the issue since we've all got to work with the code base) - his involvement was just to say "yeah, we should probably factor out the common filtering iteration functionality first (before using it for the CFG)". > I also don't see why its necessary to change the pointer / reference > semantics in order to factor out common iterator infrastructure, so I'm not > really clear why one is blocked on the other. It's not - I just had to choose one way or the other, and without much in the way of feedback after a few weeks, it ended up tipping slightly towards value semantics so I carried along with that. Happy to change it over if that's the prevailing preference. - David From meadori at gmail.com Tue May 15 17:46:19 2012 From: meadori at gmail.com (Meador Inge) Date: Tue, 15 May 2012 17:46:19 -0500 Subject: [cfe-commits] [PATCH] PR 12746: Code generation of variables reference expressions when mixing blocks and lambdas In-Reply-To: References: Message-ID: Ping. On Tue, May 8, 2012 at 8:18 PM, Meador Inge wrote: > Hi All, > > In PR 12746 a failing assertion was reported when mixing blocks and lambdas. > The original reproduction case looked something like: > > void foo(int *x) > { > ?^() { > ? ?[&]() { > ? ? ?return x == 0; > ? ?}(); > ?}(); > } > > The following assert in 'clang::CodeGenFunction::EmitDeclRefLValue' was failing > because the variable declaration referenced in 'E' was not in the 'LocalDeclMap' > and was not marked as referring to an enclosing local: > > ? ? ?assert(isa(CurCodeDecl) && E->refersToEnclosingLocal()); > > This problem has been fixed by ensuring that the 'DeclRefExpr' gets marked as > referring to an enclosing local as it should be. > > While investigating this issue I noticed that the reverse nesting fails too, > but for a different reason: > > void foo(int *x) > { > ?[&]() { > ? ?^() { > ? ? ?return x == 0; > ? ?}(); > ?}(); > } > > This time 'clang::CodeGen::CodeGenFunction::EmitBlockLiteral' goes to lookup > the capture information for the nested parameter 'x', but crashes because it > is actually nested in a lambda and the ?'BlockInfo' is NULL. ?This was fixed by > adding a check to ensure 'BlockInfo' is not NULL. > > OK? > > -- Meador > > P.S. ?If it is OK, then can someone commit for me? ?(I don't have > commit rights.) -- # Meador From meadori at gmail.com Tue May 15 17:55:41 2012 From: meadori at gmail.com (Meador Inge) Date: Tue, 15 May 2012 17:55:41 -0500 Subject: [cfe-commits] [PATCH] Fix ASTReader handling of ImportDecls Message-ID: Hi All, I came across this bug while hacking on another C FE issue. 'void ASTDeclReader::VisitImportDecl' bumps the current index one too many. OK? P.S. If it is OK, then can someone commit it for me. I don't have write access. -- # Meador -------------- next part -------------- A non-text attachment was scrubbed... Name: ast-import-decl.patch Type: application/octet-stream Size: 1499 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/82857226/attachment.obj From dgregor at apple.com Tue May 15 18:00:05 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 16:00:05 -0700 Subject: [cfe-commits] [patch] TransformIterator (motivating use case in Clang) In-Reply-To: References: <668FA4CE-BFBB-4300-BC12-9042C33BF012@apple.com> Message-ID: <7FB539AF-679F-4FE9-8D17-BEA2E47AE5BD@apple.com> On May 15, 2012, at 3:44 PM, David Blaikie wrote: > On Tue, May 15, 2012 at 3:07 PM, Chandler Carruth wrote: >> On Tue, May 15, 2012 at 3:33 PM, David Blaikie wrote: >>> >>>> This seems like a lot of work and a disruptive change in API patterning, >>>> and >>>> I'm really not clear what problem it's trying to solve. My suspicion is >>>> that >>>> there isn't one other than a preference for references instead of >>>> pointers. >>> >>> Well the underlying problem was the inconsistency of the iterators in >>> Decl/DeclBase. I wanted to rationalize their value/reference/pointer >>> types so I could then extract the common filtering functionality out >>> of filtered/specific_decl_iterator as a proof-of-concept for a general >>> adapting/filtering iterator device which I could then re-use in my >>> efforts to improve the CFG fidelity and -Wunreachable-code diagnostic. >>> This particular path (generalizing the existing filtering iterators to >>> a reusable adapter before reusing that in the new use case) was >>> suggested by Ted Kremmenek & I was happy enough to have an excuse to >>> tidy up some existing code. >> >> >> Ok, but again, this is a disruptive change in API patterning. I don't think >> the inconsistency you point out really justifies the churn without some more >> compelling problem that it solves. That said, I'd be interested in Ted's >> perspective here. > > To be clear - I don't think Ted has a dog in this race (or hasn't > expressed it, at least - though I wouldn't mind having a few more > opinions on the issue since we've all got to work with the code base) > - his involvement was just to say "yeah, we should probably factor out > the common filtering iteration functionality first (before using it > for the CFG)". > >> I also don't see why its necessary to change the pointer / reference >> semantics in order to factor out common iterator infrastructure, so I'm not >> really clear why one is blocked on the other. > > It's not - I just had to choose one way or the other, and without much > in the way of feedback after a few weeks, it ended up tipping slightly > towards value semantics so I carried along with that. Happy to change > it over if that's the prevailing preference. It makes sense to factor out the filtering-iterator functionality, but I'd rather not have to restyle the code base to do it. - Doug From akyrtzi at gmail.com Tue May 15 17:59:54 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 15 May 2012 22:59:54 -0000 Subject: [cfe-commits] r156873 - /cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Message-ID: <20120515225955.A76A82A6C065@llvm.org> Author: akirtzidis Date: Tue May 15 17:59:54 2012 New Revision: 156873 URL: http://llvm.org/viewvc/llvm-project?rev=156873&view=rev Log: [objcmt] When using NSNumber numberWithInteger:/numberWithUnsignedInteger: be more liberal in rewriting when the parameter is an enum constant. Part of rdar://11438360 Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp?rev=156873&r1=156872&r2=156873&view=diff ============================================================================== --- cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp (original) +++ cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Tue May 15 17:59:54 2012 @@ -684,6 +684,14 @@ // rewriteToNumericBoxedExpression. //===----------------------------------------------------------------------===// +static bool isEnumConstant(const Expr *E) { + if (const DeclRefExpr *DRE = dyn_cast(E->IgnoreParenImpCasts())) + if (const ValueDecl *VD = DRE->getDecl()) + return isa(VD); + + return false; +} + static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { if (Msg->getNumArgs() != 1) @@ -725,7 +733,7 @@ if ((MK == NSAPI::NSNumberWithInteger || MK == NSAPI::NSNumberWithUnsignedInteger) && !isTruncated) { - if (OrigTy->getAs()) + if (OrigTy->getAs() || isEnumConstant(OrigArg)) break; if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() && OrigTySize >= Ctx.getTypeSize(Ctx.IntTy)) From rtrieu at google.com Tue May 15 18:10:42 2012 From: rtrieu at google.com (Richard Trieu) Date: Tue, 15 May 2012 16:10:42 -0700 Subject: [cfe-commits] [Patch] Add a warning to catch enums with all elements having the same value Message-ID: Add -Wunique-enum which will warn on enums with at least 2 elements such that all elements are the same value. This will catch enums such as: enum A { FIRST = 1, SECOND = 1 }; -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/65648768/attachment.html -------------- next part -------------- A non-text attachment was scrubbed... Name: unique-enum.patch Type: application/octet-stream Size: 3800 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/65648768/attachment.obj From ganna at apple.com Tue May 15 18:12:53 2012 From: ganna at apple.com (Anna Zaks) Date: Tue, 15 May 2012 23:12:53 -0000 Subject: [cfe-commits] r156875 - /cfe/trunk/test/Analysis/dead-stores.m Message-ID: <20120515231253.BB0A72A6C065@llvm.org> Author: zaks Date: Tue May 15 18:12:53 2012 New Revision: 156875 URL: http://llvm.org/viewvc/llvm-project?rev=156875&view=rev Log: [analyzer] Add a test for dead stores, which uses OpaqueValExpr. Modified: cfe/trunk/test/Analysis/dead-stores.m Modified: cfe/trunk/test/Analysis/dead-stores.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.m?rev=156875&r1=156874&r2=156875&view=diff ============================================================================== --- cfe/trunk/test/Analysis/dead-stores.m (original) +++ cfe/trunk/test/Analysis/dead-stores.m Tue May 15 18:12:53 2012 @@ -88,3 +88,23 @@ RDar10591355 *p = rdar10591355_aux(); ^{ (void) p.x; }(); } + + at interface Radar11059352_1 { + at private + int *_pathString; +} + at property int *pathString; + at end + at interface Radar11059352 { + at private +Radar11059352_1 *_Path; +} + at end + at implementation Radar11059352 + +- (int*)usePath { + Radar11059352_1 *xxxxx = _Path; // no warning + int *wp = xxxxx.pathString; + return wp; +} + at end From bob.wilson at apple.com Tue May 15 18:40:53 2012 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 15 May 2012 16:40:53 -0700 Subject: [cfe-commits] r156630 - in /cfe/trunk: include/clang/Basic/BuiltinsHexagon.def lib/CodeGen/CGBuiltin.cpp In-Reply-To: <950A8AB2-80A5-4E92-859D-544170B70562@apple.com> References: <20120511193909.11C6D2A6C065@llvm.org> <000001cd2ff3$632f3910$298dab30$@codeaurora.org> <950A8AB2-80A5-4E92-859D-544170B70562@apple.com> Message-ID: On May 11, 2012, at 11:13 PM, John McCall wrote: > On May 11, 2012, at 8:57 PM, Sirish Pande wrote: >> I would love to have a macro-generated switch statement - but that would >> require a target dependent file - which I don't think clang folks would like >> in lib/CodeGen. Since most of the architectures are doing the same thing, I >> adopted the style. But it's a pain for me as well. The whole switch block is >> auto-generated by my other script, and I have to copy/paste. So yes, I would >> love to have macro generated switch case. Clang folks, can I have a target >> dependent file there? > > I have nothing against macro metaprogramming and would much prefer a > macro-generated switch over this enormous blob of code. > > Bob, you had some experience doing this with the Neon intrinsics; is there > reusable infrastructure there, or at least useful lessons that apply? This should really be handled with TableGen, especially because the Hexagon builtins look simpler than Neon, at least in the sense that they appear to be mapped one-to-one to LLVM intrinsics without a lot of special cases. It might need a custom TableGen backend, but it should be a very simple one. Look at the include/clang/Basic/arm_neon.td file and utils/TableGen/NeonEmitter.* files. You can see some examples of how the results are used in lib/Sema/SemaChecking.cpp -- look for the includes of clang/Basic/arm_neon.inc. From macmantrl at me.com Tue May 15 18:50:58 2012 From: macmantrl at me.com (Terry Long) Date: Tue, 15 May 2012 19:50:58 -0400 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics In-Reply-To: <30EDA624-D310-4EEA-A69C-CB0DDDD23D3B@apple.com> References: <71F9C9BF-830D-4ADC-A751-0A9E4FCA9225@apple.com> <30EDA624-D310-4EEA-A69C-CB0DDDD23D3B@apple.com> Message-ID: <6BEC7EB8-4287-432C-BE37-910310ABB544@me.com> Attached is a new version of the patch for review. I have removed all of the textual parsing and replaced it with code that finds a DeclRefExpr if it exists. Unfortunately, this will catch a lot less cases, but at least it will catch some common ones and display them nicely. -Terry -------------- next part -------------- A non-text attachment was scrubbed... Name: PR9243v2.patch Type: application/octet-stream Size: 4328 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/9b7f8382/attachment.obj -------------- next part -------------- Am 15.05.2012 um 18:41 schrieb Douglas Gregor: > > On May 15, 2012, at 3:28 PM, Terry Long wrote: > >> >> Am 15.05.2012 um 16:09 schrieb Douglas Gregor >>> >>> >>> I'm a bit uncomfortable with the textual approach here. Why not analyze the expressions to check whether they are references to named declarations, and use those names in the diagnostic? It won't catch some macro cases, but it's far simpler. >> >> I was also uncomfortable with the textual approach, and in fact I first tried seeing if the case expression was a DeclRefExpr that refers to a valid NamedDecl. The problem I found with that approach was that it was not catching very many situations. Doing it that way only works for enums as far as I can tell. Macros, const ints, case overflows, casting, and more complicated expressions (like "case 2+2") are not DeclRefExprs, and I don't see any obvious way to grab the necessary diagnostic info without using a textual approach. > > > You can look through implicit conversions (e.g., promotions) and parentheses to find the underlying expression. We'll get a DeclRefExpr for enumerators and variables that are constant ("const int x = 17;"), which are presumably the common cases. We won't get macros, of course, but we might not want to: it's probably more useful to show the value we get when the macro is expanded, and let the macro-substitution backtrace show how we got there. > > - Doug From akyrtzi at gmail.com Tue May 15 19:21:21 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Wed, 16 May 2012 00:21:21 -0000 Subject: [cfe-commits] r156880 - in /cfe/trunk: lib/Edit/RewriteObjCFoundationAPI.cpp test/ARCMT/objcmt-boxing.m test/ARCMT/objcmt-boxing.m.result Message-ID: <20120516002121.DDDE02A6C065@llvm.org> Author: akirtzidis Date: Tue May 15 19:21:21 2012 New Revision: 156880 URL: http://llvm.org/viewvc/llvm-project?rev=156880&view=rev Log: [objcmt] Accept char arrays for rewriting to @() syntax. Part of rdar://11438360 Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp cfe/trunk/test/ARCMT/objcmt-boxing.m cfe/trunk/test/ARCMT/objcmt-boxing.m.result Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp?rev=156880&r1=156879&r2=156880&view=diff ============================================================================== --- cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp (original) +++ cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Tue May 15 19:21:21 2012 @@ -824,8 +824,12 @@ if (Arg->isTypeDependent()) return false; + ASTContext &Ctx = NS.getASTContext(); + const Expr *OrigArg = Arg->IgnoreImpCasts(); QualType OrigTy = OrigArg->getType(); + if (OrigTy->isArrayType()) + OrigTy = Ctx.getArrayDecayedType(OrigTy); if (const StringLiteral * StrE = dyn_cast(OrigArg->IgnoreParens())) { @@ -834,8 +838,6 @@ return true; } - ASTContext &Ctx = NS.getASTContext(); - if (const PointerType *PT = OrigTy->getAs()) { QualType PointeeType = PT->getPointeeType(); if (Ctx.hasSameUnqualifiedType(PointeeType, Ctx.CharTy)) { Modified: cfe/trunk/test/ARCMT/objcmt-boxing.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m?rev=156880&r1=156879&r2=156880&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-boxing.m (original) +++ cfe/trunk/test/ARCMT/objcmt-boxing.m Tue May 15 19:21:21 2012 @@ -95,4 +95,7 @@ NSStringEncoding encode; s = [NSString stringWithCString:cstr1 encoding:encode]; s = [NSString stringWithCString:cstr1]; + + static const char strarr[] = "coolbox"; + s = [NSString stringWithUTF8String:strarr]; } Modified: cfe/trunk/test/ARCMT/objcmt-boxing.m.result URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m.result?rev=156880&r1=156879&r2=156880&view=diff ============================================================================== --- cfe/trunk/test/ARCMT/objcmt-boxing.m.result (original) +++ cfe/trunk/test/ARCMT/objcmt-boxing.m.result Tue May 15 19:21:21 2012 @@ -95,4 +95,7 @@ NSStringEncoding encode; s = [NSString stringWithCString:cstr1 encoding:encode]; s = @(cstr1); + + static const char strarr[] = "coolbox"; + s = @(strarr); } From akyrtzi at gmail.com Tue May 15 19:50:02 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Wed, 16 May 2012 00:50:02 -0000 Subject: [cfe-commits] r156890 - in /cfe/trunk: include/clang/AST/ExprObjC.h include/clang/Sema/Sema.h lib/Parse/ParseObjc.cpp lib/Sema/SemaExprObjC.cpp lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp tools/libclang/IndexBody.cpp Message-ID: <20120516005003.327E92A6C065@llvm.org> Author: akirtzidis Date: Tue May 15 19:50:02 2012 New Revision: 156890 URL: http://llvm.org/viewvc/llvm-project?rev=156890&view=rev Log: [libclang/AST] Index references of protocols in "@protocol(...)" syntax. To do that, keep track of the location of the protocol id in the ObjCProtocolExpr AST node. rdar://11190837 Modified: cfe/trunk/include/clang/AST/ExprObjC.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseObjc.cpp cfe/trunk/lib/Sema/SemaExprObjC.cpp cfe/trunk/lib/Serialization/ASTReaderStmt.cpp cfe/trunk/lib/Serialization/ASTWriterStmt.cpp cfe/trunk/tools/libclang/IndexBody.cpp Modified: cfe/trunk/include/clang/AST/ExprObjC.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=156890&r1=156889&r2=156890&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprObjC.h (original) +++ cfe/trunk/include/clang/AST/ExprObjC.h Tue May 15 19:50:02 2012 @@ -421,19 +421,20 @@ /// The return type is "Protocol*". class ObjCProtocolExpr : public Expr { ObjCProtocolDecl *TheProtocol; - SourceLocation AtLoc, RParenLoc; + SourceLocation AtLoc, ProtoLoc, RParenLoc; public: ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, - SourceLocation at, SourceLocation rp) + SourceLocation at, SourceLocation protoLoc, SourceLocation rp) : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, false, false), - TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {} + TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {} explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} ObjCProtocolDecl *getProtocol() const { return TheProtocol; } void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } + SourceLocation getProtocolIdLoc() const { return ProtoLoc; } SourceLocation getAtLoc() const { return AtLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } @@ -450,6 +451,9 @@ // Iterators child_range children() { return child_range(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// ObjCIvarRefExpr - A reference to an ObjC instance variable. Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=156890&r1=156889&r2=156890&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue May 15 19:50:02 2012 @@ -4096,6 +4096,7 @@ SourceLocation AtLoc, SourceLocation ProtoLoc, SourceLocation LParenLoc, + SourceLocation ProtoIdLoc, SourceLocation RParenLoc); //===--------------------------------------------------------------------===// Modified: cfe/trunk/lib/Parse/ParseObjc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=156890&r1=156889&r2=156890&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseObjc.cpp (original) +++ cfe/trunk/lib/Parse/ParseObjc.cpp Tue May 15 19:50:02 2012 @@ -2743,12 +2743,13 @@ return ExprError(Diag(Tok, diag::err_expected_ident)); IdentifierInfo *protocolId = Tok.getIdentifierInfo(); - ConsumeToken(); + SourceLocation ProtoIdLoc = ConsumeToken(); T.consumeClose(); return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, T.getOpenLocation(), + ProtoIdLoc, T.getCloseLocation())); } Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=156890&r1=156889&r2=156890&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue May 15 19:50:02 2012 @@ -1012,8 +1012,9 @@ SourceLocation AtLoc, SourceLocation ProtoLoc, SourceLocation LParenLoc, + SourceLocation ProtoIdLoc, SourceLocation RParenLoc) { - ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoLoc); + ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc); if (!PDecl) { Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; return true; @@ -1023,7 +1024,7 @@ if (Ty.isNull()) return true; Ty = Context.getObjCObjectPointerType(Ty); - return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc); + return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc); } /// Try to capture an implicit reference to 'self'. Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=156890&r1=156889&r2=156890&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue May 15 19:50:02 2012 @@ -873,6 +873,7 @@ VisitExpr(E); E->setProtocol(ReadDeclAs(Record, Idx)); E->setAtLoc(ReadSourceLocation(Record, Idx)); + E->ProtoLoc = ReadSourceLocation(Record, Idx); E->setRParenLoc(ReadSourceLocation(Record, Idx)); } Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=156890&r1=156889&r2=156890&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue May 15 19:50:02 2012 @@ -837,6 +837,7 @@ VisitExpr(E); Writer.AddDeclRef(E->getProtocol(), Record); Writer.AddSourceLocation(E->getAtLoc(), Record); + Writer.AddSourceLocation(E->ProtoLoc, Record); Writer.AddSourceLocation(E->getRParenLoc(), Record); Code = serialization::EXPR_OBJC_PROTOCOL_EXPR; } Modified: cfe/trunk/tools/libclang/IndexBody.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=156890&r1=156889&r2=156890&view=diff ============================================================================== --- cfe/trunk/tools/libclang/IndexBody.cpp (original) +++ cfe/trunk/tools/libclang/IndexBody.cpp Tue May 15 19:50:02 2012 @@ -90,6 +90,12 @@ return true; } + bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { + IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), + Parent, ParentDC, E, CXIdxEntityRef_Direct); + return true; + } + bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { if (ObjCMethodDecl *MD = E->getBoxingMethod()) IndexCtx.handleReference(MD, E->getLocStart(), From richard at metafoo.co.uk Tue May 15 20:12:11 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Tue, 15 May 2012 18:12:11 -0700 Subject: [cfe-commits] Handle missing 'typename' in function template definitions Message-ID: Hi, The attached patch allows Clang to recover better from a missing 'typename' keyword in a function template definition: :1:29: error: missing 'typename' prior to dependent type name 'T::type' template void f(T::type) {} ^~~~~~~ typename With this patch, we carry on disambiguating past such a situation. If we can't disambiguate the declaration in some other way, the absence of 'typename' is used to infer that we have a variable declaration. I've also extended the disambiguation code to inspect the token immediately after the parameter-declaration-clause to disambiguate (in the above case, the {token is used to disambiguate, and more generally we will also look for an exception-specification, ref-qualifier, cv-qualifier, etc., which cannot appear after a parenthesized initializer in a variable declaration). Does this seem like a reasonable approach? Thanks! Richard -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/fe07d693/attachment.html -------------- next part -------------- A non-text attachment was scrubbed... Name: missing-typename.diff Type: application/octet-stream Size: 10532 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/fe07d693/attachment.obj From rtrieu at google.com Tue May 15 20:43:52 2012 From: rtrieu at google.com (Richard Trieu) Date: Tue, 15 May 2012 18:43:52 -0700 Subject: [cfe-commits] [Patch] -Wextra-semi for semi-colon warnings with fixit for removal Message-ID: This patch will group the extra semi-colon warnings together under -Wextra-semi. A warning for the optional semi-colon after a function definition has also been added. A fixit has been added for the removal of the semi-colons. Also, contiguous semi-colons on a line will only produce one warning. Previously, each semi-colon got its own warning. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/b677dca8/attachment-0001.html -------------- next part -------------- A non-text attachment was scrubbed... Name: extra-semi4.patch Type: application/octet-stream Size: 8973 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/b677dca8/attachment-0001.obj From jediknil at belkadan.com Tue May 15 20:51:53 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Tue, 15 May 2012 21:51:53 -0400 Subject: [cfe-commits] [Patch] Add a warning to catch enums with all elements having the same value In-Reply-To: References: Message-ID: <0FA771F0-B74A-4F77-9070-4526D0CAFE75@belkadan.com> Interesting. This seems hard to do by accident, but there are very few circumstances I can think of where you'd do it on purpose, so... + // Keep track of whether every enum element is the same value. + if (AllElementsEqual && i > 0) { + if (InitVal.getBitWidth() > LastVal.getBitWidth()) + AllElementsEqual = InitVal == LastVal.extend(InitVal.getBitWidth()); + else if (InitVal.getBitWidth() < LastVal.getBitWidth()) + AllElementsEqual = InitVal.extend(LastVal.getBitWidth()) == LastVal; + else + AllElementsEqual = InitVal == LastVal; + } This will crash if the two values have the same bit width, but different signedness. I'm not sure if you can do that with enums, but... (This is the sort of problem that APSIntType in the static analyzer Core library is supposed to make simpler.) Also, as is right now the two tests can be embedded in the same file, using "-x c++". However, if we want to test this with C++11's fixed-underlying-type enums, that's a case for keeping separate files. Jordy On May 15, 2012, at 19:10, Richard Trieu wrote: > Add -Wunique-enum which will warn on enums with at least 2 elements such that all elements are the same value. This will catch enums such as: > > enum A { > FIRST = 1, > SECOND = 1 > }; > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From rafael.espindola at gmail.com Tue May 15 21:10:38 2012 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Wed, 16 May 2012 02:10:38 -0000 Subject: [cfe-commits] r156897 - in /cfe/trunk: lib/AST/Decl.cpp test/CodeGenCXX/visibility.cpp Message-ID: <20120516021038.9E49F2A6C065@llvm.org> Author: rafael Date: Tue May 15 21:10:38 2012 New Revision: 156897 URL: http://llvm.org/viewvc/llvm-project?rev=156897&view=rev Log: Fix the visibility of instantiations of static data members. Fixes pr12835. Modified: cfe/trunk/lib/AST/Decl.cpp cfe/trunk/test/CodeGenCXX/visibility.cpp Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=156897&r1=156896&r2=156897&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Tue May 15 21:10:38 2012 @@ -633,9 +633,19 @@ llvm::Optional NamedDecl::getExplicitVisibility() const { // Use the most recent declaration of a variable. - if (const VarDecl *var = dyn_cast(this)) - return getVisibilityOf(var->getMostRecentDecl()); + if (const VarDecl *Var = dyn_cast(this)) { + if (llvm::Optional V = + getVisibilityOf(Var->getMostRecentDecl())) + return V; + + if (Var->isStaticDataMember()) { + VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom); + } + return llvm::Optional(); + } // Use the most recent declaration of a function, and also handle // function template specializations. if (const FunctionDecl *fn = dyn_cast(this)) { Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=156897&r1=156896&r2=156897&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/visibility.cpp (original) +++ cfe/trunk/test/CodeGenCXX/visibility.cpp Tue May 15 21:10:38 2012 @@ -54,6 +54,18 @@ // CHECK-HIDDEN: @_ZN6test299data_rectE = global } +namespace test40 { + template + struct foo { + DEFAULT static int bar; + }; + template + int foo::bar; + template struct foo; + // CHECK: _ZN6test403fooIiE3barE = weak_odr global + // CHECK-HIDDEN: _ZN6test403fooIiE3barE = weak_odr global +} + // CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10 // CHECK: @_ZN5Test71aE = hidden global // CHECK: @_ZN5Test71bE = global From rtrieu at google.com Tue May 15 21:25:40 2012 From: rtrieu at google.com (Richard Trieu) Date: Tue, 15 May 2012 19:25:40 -0700 Subject: [cfe-commits] [Patch] Add a warning to catch enums with all elements having the same value In-Reply-To: <0FA771F0-B74A-4F77-9070-4526D0CAFE75@belkadan.com> References: <0FA771F0-B74A-4F77-9070-4526D0CAFE75@belkadan.com> Message-ID: On Tue, May 15, 2012 at 6:51 PM, Jordy Rose wrote: > Interesting. This seems hard to do by accident, but there are very few > circumstances I can think of where you'd do it on purpose, so... > > + // Keep track of whether every enum element is the same value. > + if (AllElementsEqual && i > 0) { > + if (InitVal.getBitWidth() > LastVal.getBitWidth()) > + AllElementsEqual = InitVal == > LastVal.extend(InitVal.getBitWidth()); > + else if (InitVal.getBitWidth() < LastVal.getBitWidth()) > + AllElementsEqual = InitVal.extend(LastVal.getBitWidth()) == > LastVal; > + else > + AllElementsEqual = InitVal == LastVal; > + } > > This will crash if the two values have the same bit width, but different > signedness. I'm not sure if you can do that with enums, but... > I tried sticking some negative values in there, but didn't see any crashing. Do you have an example of this happening? > > (This is the sort of problem that APSIntType in the static analyzer Core > library is supposed to make simpler.) > > Also, as is right now the two tests can be embedded in the same file, > using "-x c++". However, if we want to test this with C++11's > fixed-underlying-type enums, that's a case for keeping separate files. > > Jordy > > > On May 15, 2012, at 19:10, Richard Trieu wrote: > > > Add -Wunique-enum which will warn on enums with at least 2 elements such > that all elements are the same value. This will catch enums such as: > > > > enum A { > > FIRST = 1, > > SECOND = 1 > > }; > > _______________________________________________ > > cfe-commits mailing list > > cfe-commits at cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/491de907/attachment.html From jediknil at belkadan.com Tue May 15 21:37:18 2012 From: jediknil at belkadan.com (Jordan Rose) Date: Tue, 15 May 2012 22:37:18 -0400 Subject: [cfe-commits] [PATCH] Add analyzer_assert for regression tests In-Reply-To: <02322A8B-EFCD-4501-B532-774E9B89E1CA@apple.com> References: <881546B4-753E-499A-A279-04FD0F182FEF@belkadan.com> <6A305ACC-5BF0-4281-8B01-C3F3E4228F57@apple.com> <603F2830-8617-434C-BBA8-659F26524A5B@belkadan.com> <08B8B6C0-175A-4DDB-9E57-265C5B0AA986@apple.com> <85DF843B-246E-4F10-A116-F2A43E396AA0@belkadan.com> <02322A8B-EFCD-4501-B532-774E9B89E1CA@apple.com> Message-ID: On May 15, 2012, at 18:25, Anna Zaks wrote: >> For the case of TRUE or FALSE there would be no change, but UNKNOWN is a problem. (In the previous iteration, these were separated into analyzer_assert and analyzer_assert_unknown, but I don't think it's necessary to check that something is true generally /and/ in a specific inlined case.) > This checker might be useful to debug in presence of IPA. I though it's just the matter of having extra diagnostics - one per frame in which the call is evaluated. But maybe I am missing something.. Here is the actual case that came up (from dynamic-cast.cpp): void testDynCastMostLikelyWillFail(C *c) { B *b = 0; b = dynamic_cast(c); clang_analyzer_eval(b); // expected-warning{{UNKNOWN}} } class M : public B, public C {}; void callTestDynCastMostLikelyWillFail() { M m; testDynCastMostLikelyWillFail(&m); } This seems like a reasonable use of clang_analyzer_eval to me -- the main thing being tested is that we haven't mistakenly assumed that 'c' is or isn't a 'B*'. When the call below is inlined, however, we know the cast succeeds. While I'm going to follow your suggestion and not change dynamic-cast right now, this doesn't actually allow us to make useful assertions within inlined functions. Anything that ought to be true or false in the general case will be in the specific case as well, and as shown above, UNKNOWNs can change into knowns. And any function that gets inlined is still analyzed separately, at least for now. (I remember you were working on that already.) On the other hand, the /calling/ function is perfectly able to assert results about the callee, which can be used to test specific cases. I think we should leave it as is, at least for now. I'll clean up everything else and check it in, then! Jordy From thakis at chromium.org Tue May 15 22:34:41 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 15 May 2012 20:34:41 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 3:16 PM, Nico Weber wrote: > On Tue, May 15, 2012 at 2:59 PM, David Blaikie wrote: > >> On Tue, May 15, 2012 at 10:43 AM, David Blaikie >> wrote: >> > On Tue, May 15, 2012 at 10:39 AM, Nico Weber >> wrote: >> >> Hi David, >> >> >> >> as mentioned on the thread for this warning, with this change clang >> warns on >> > >> > Ah, right - sorry, I'd forgotten that even the NULL case had some >> > problems. I'll see what I can do to tidy this case up sooner rather >> > than later. Thanks for the reminder. >> >> I believe r156861 should help handle this case. > > > The warnings on lines with `if ( ! YY_CURRENT_BUFFER)` lines are gone, but > `if (YY_CURRENT_BUFFER)` still warns: > > hummer:src thakis$ /Users/thakis/src/llvm-svn/Release+Asserts/bin/clang++ > --version > clang version 3.2 (trunk 156862) > Target: x86_64-apple-darwin10.8.0 > Thread model: posix > > $ ... > glsl_lexer.cpp:2778:7: error: implicit conversion of NULL constant to > 'bool' [-Werror,-Wnull-conversion] > if ( YY_CURRENT_BUFFER ) > ^~~~~~~~~~~~~~~~~ > glsl_lexer.cpp:273:29: note: expanded from macro 'YY_CURRENT_BUFFER' > : NULL) > ^ > If this is taking a while to fix, would you mind reverting this in the meantime? > > > > > >> Thanks again, >> >> - David >> >> >> >> >> #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ >> >> ? >> yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ >> >> : NULL) >> >> >> >> // ... >> >> >> >> if ( ! YY_CURRENT_BUFFER ) { >> >> // ... >> >> } >> >> >> >> with this message: >> >> >> >> ./pp_lex.cpp:784:10: error: implicit conversion of NULL constant to >> 'bool' >> >> [-Werror,-Wnull-conversion] >> >> if ( ! YY_CURRENT_BUFFER ) { >> >> ^~~~~~~~~~~~~~~~~ >> >> ./pp_lex.cpp:295:29: note: expanded from macro 'YY_CURRENT_BUFFER' >> >> : NULL) >> >> ^ >> >> >> >> >> >> This looks like valid code to me. >> >> >> >> Nico >> >> >> >> On Tue, May 15, 2012 at 9:56 AM, David Blaikie >> wrote: >> >>> >> >>> Author: dblaikie >> >>> Date: Tue May 15 11:56:36 2012 >> >>> New Revision: 156826 >> >>> >> >>> URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev >> >>> Log: >> >>> Improve some of the conversion warnings to fire on conversion to bool. >> >>> >> >>> Moves the bool bail-out down a little in SemaChecking - so now >> >>> -Wnull-conversion and -Wliteral-conversion can fire when the target >> type >> >>> is >> >>> bool. >> >>> >> >>> Also improve the wording/details in the -Wliteral-conversion warning >> to >> >>> match >> >>> the -Wconstant-conversion. >> >>> >> >>> Modified: >> >>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> >>> cfe/trunk/lib/Sema/SemaChecking.cpp >> >>> cfe/trunk/test/Analysis/array-struct-region.c >> >>> cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >> >>> cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >> >>> cfe/trunk/test/PCH/exprs.h >> >>> cfe/trunk/test/Sema/array-init.c >> >>> cfe/trunk/test/Sema/knr-def-call.c >> >>> cfe/trunk/test/SemaCXX/bool.cpp >> >>> cfe/trunk/test/SemaCXX/conversion.cpp >> >>> cfe/trunk/test/SemaCXX/expressions.cpp >> >>> cfe/trunk/test/SemaCXX/overload-call.cpp >> >>> cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >> >>> cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >> >>> >> >>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >> >>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 >> >>> 11:56:36 2012 >> >>> @@ -1781,8 +1781,7 @@ >> >>> "implicit truncation from %2 to bitfield changes value from %0 to >> %1">, >> >>> InGroup; >> >>> def warn_impcast_literal_float_to_integer : Warning< >> >>> - "implicit conversion turns literal floating-point number into >> integer: >> >>> " >> >>> - "%0 to %1">, >> >>> + "implicit conversion from %0 to %1 changes value from %2 to %3">, >> >>> InGroup; >> >>> def warn_impcast_string_literal_to_bool : Warning< >> >>> "implicit conversion turns string literal into bool: %0 to %1">, >> >>> >> >>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) >> >>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 >> >>> @@ -22,6 +22,7 @@ >> >>> #include "clang/AST/CharUnits.h" >> >>> #include "clang/AST/DeclCXX.h" >> >>> #include "clang/AST/DeclObjC.h" >> >>> +#include "clang/AST/Expr.h" >> >>> #include "clang/AST/ExprCXX.h" >> >>> #include "clang/AST/ExprObjC.h" >> >>> #include "clang/AST/EvaluatedExprVisitor.h" >> >>> @@ -4081,8 +4082,17 @@ >> >>> == llvm::APFloat::opOK && isExact) >> >>> return; >> >>> >> >>> >> >>> + SmallString<16> PrettySourceValue; >> >>> + Value.toString(PrettySourceValue); >> >>> + std::string PrettyTargetValue; >> >>> + if (T->isSpecificBuiltinType(BuiltinType::Bool)) >> >>> + PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; >> >>> + else >> >>> + PrettyTargetValue = IntegerValue.toString(10); >> >>> + >> >>> S.Diag(FL->getExprLoc(), >> diag::warn_impcast_literal_float_to_integer) >> >>> - << FL->getType() << T << FL->getSourceRange() << >> >>> SourceRange(CContext); >> >>> + << FL->getType() << T.getUnqualifiedType() << PrettySourceValue >> >>> + << PrettyTargetValue << FL->getSourceRange() << >> >>> SourceRange(CContext); >> >>> } >> >>> >> >>> std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange >> Range) >> >>> { >> >>> @@ -4149,7 +4159,6 @@ >> >>> } >> >>> } >> >>> } >> >>> - return; // Other casts to bool are not checked. >> >>> } >> >>> >> >>> // Strip vector types. >> >>> @@ -4213,7 +4222,7 @@ >> >>> } >> >>> >> >>> // If the target is integral, always warn. >> >>> - if ((TargetBT && TargetBT->isInteger())) { >> >>> + if (TargetBT && TargetBT->isInteger()) { >> >>> if (S.SourceMgr.isInSystemMacro(CC)) >> >>> return; >> >>> >> >>> @@ -4247,6 +4256,11 @@ >> >>> return; >> >>> } >> >>> >> >>> + // TODO: remove this early return once the false positives for >> >>> constant->bool >> >>> + // in templates, macros, etc, are reduced or removed. >> >>> + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) >> >>> + return; >> >>> + >> >>> IntRange SourceRange = GetExprRange(S.Context, E); >> >>> IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, >> >>> Target); >> >>> >> >>> >> >>> Modified: cfe/trunk/test/Analysis/array-struct-region.c >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/Analysis/array-struct-region.c (original) >> >>> +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 11:56:36 >> 2012 >> >>> @@ -25,8 +25,8 @@ >> >>> } >> >>> >> >>> void nested_compound_literals(int rad) { >> >>> - int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // >> >>> expected-warning 6 {{implicit conversion turns literal floating-point >> number >> >>> into integer}} >> >>> - {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >> >>> expected-warning 6 {{implicit conversion turns literal floating-point >> number >> >>> into integer}} >> >>> + int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // >> >>> expected-warning 6 {{implicit conversion from 'double' to 'int' >> changes >> >>> value from}} >> >>> + {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >> >>> expected-warning 6 {{implicit conversion from 'double' to 'int' >> changes >> >>> value from}} >> >>> int a; >> >>> >> >>> for (a = 0; a < 6; ++a) { >> >>> >> >>> Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp (original) >> >>> +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May 15 >> >>> 11:56:36 2012 >> >>> @@ -4,7 +4,7 @@ >> >>> >> >>> bool b = !0; >> >>> >> >>> -bool b2 = !1.2; >> >>> +bool b2 = !1.2; //expected-warning{{implicit conversion from >> 'double' to >> >>> 'bool' changes value from 1.2 to true}} >> >>> >> >>> bool b3 = !4; >> >>> >> >>> >> >>> Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) >> >>> +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 2012 >> >>> @@ -14,7 +14,7 @@ >> >>> }; >> >>> >> >>> template >> >>> -T X0::value = 3.14; // expected-warning{{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> +T X0::value = 3.14; // expected-warning{{implicit conversion from >> >>> 'double' to 'int' changes value from 3.14 to 3}} >> >>> >> >>> template struct X0; // expected-note{{previous explicit >> >>> instantiation}} \ >> >>> expected-note{{requested here}} >> >>> >> >>> Modified: cfe/trunk/test/PCH/exprs.h >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/PCH/exprs.h (original) >> >>> +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 >> >>> @@ -87,7 +87,7 @@ >> >>> int x; >> >>> float y; >> >>> } designated_inits[3] = { [0].y = 17, >> >>> - [2].x = 12.3, // expected-warning >> {{implicit >> >>> conversion turns literal floating-point number into integer}} >> >>> + [2].x = 12.3, // expected-warning >> {{implicit >> >>> conversion from 'double' to 'int' changes value from 12.3 to 12}} >> >>> 3.5 }; >> >>> >> >>> // TypesCompatibleExpr >> >>> >> >>> Modified: cfe/trunk/test/Sema/array-init.c >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/Sema/array-init.c (original) >> >>> +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 >> >>> @@ -50,7 +50,7 @@ >> >>> >> >>> static long x2[3] = { 1.0, >> >>> "abc", // expected-warning{{incompatible >> pointer >> >>> to integer conversion initializing 'long' with an expression of type >> 'char >> >>> [4]'}} >> >>> - 5.8 }; // expected-warning {{implicit >> conversion >> >>> turns literal floating-point number into integer}} >> >>> + 5.8 }; // expected-warning {{implicit >> conversion >> >>> from 'double' to 'long' changes value from 5.8 to 5}} >> >>> } >> >>> >> >>> void test() { >> >>> >> >>> Modified: cfe/trunk/test/Sema/knr-def-call.c >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/Sema/knr-def-call.c (original) >> >>> +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 >> >>> @@ -36,6 +36,6 @@ >> >>> } >> >>> >> >>> void use_proto() { >> >>> - proto(42.1); // expected-warning{{implicit conversion turns literal >> >>> floating-point number into integer}} >> >>> - (&proto)(42.1); // expected-warning{{implicit conversion turns >> literal >> >>> floating-point number into integer}} >> >>> + proto(42.1); // expected-warning{{implicit conversion from >> 'double' to >> >>> 'int' changes value from 42.1 to 42}} >> >>> + (&proto)(42.1); // expected-warning{{implicit conversion from >> 'double' >> >>> to 'int' changes value from 42.1 to 42}} >> >>> } >> >>> >> >>> Modified: cfe/trunk/test/SemaCXX/bool.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/SemaCXX/bool.cpp (original) >> >>> +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 >> >>> @@ -1,4 +1,4 @@ >> >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s >> >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >> >>> >> >>> // Bool literals can be enum values. >> >>> enum { >> >>> >> >>> Modified: cfe/trunk/test/SemaCXX/conversion.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/SemaCXX/conversion.cpp (original) >> >>> +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 >> >>> @@ -65,7 +65,7 @@ >> >>> int c = ((((NULL)))); // expected-warning {{implicit conversion of >> NULL >> >>> constant to 'int'}} >> >>> int d; >> >>> d = ((((NULL)))); // expected-warning {{implicit conversion of NULL >> >>> constant to 'int'}} >> >>> - bool bl = NULL; // FIXME: this should warn but we currently >> suppress a >> >>> bunch of conversion-to-bool warnings including this one >> >>> + bool bl = NULL; // expected-warning {{implicit conversion of NULL >> >>> constant to 'bool'}} >> >>> char ch = NULL; // expected-warning {{implicit conversion of NULL >> >>> constant to 'char'}} >> >>> unsigned char uch = NULL; // expected-warning {{implicit conversion >> of >> >>> NULL constant to 'unsigned char'}} >> >>> short sh = NULL; // expected-warning {{implicit conversion of NULL >> >>> constant to 'short'}} >> >>> @@ -104,3 +104,12 @@ >> >>> tmpl2(); >> >>> } >> >>> } >> >>> + >> >>> +namespace test5 { >> >>> + template >> >>> + void func() { >> >>> + bool b = I; >> >>> + } >> >>> + >> >>> + template void func<3>(); >> >>> +} >> >>> >> >>> Modified: cfe/trunk/test/SemaCXX/expressions.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/SemaCXX/expressions.cpp (original) >> >>> +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 >> >>> @@ -1,4 +1,4 @@ >> >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s >> >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >> >>> >> >>> void choice(int); >> >>> int choice(bool); >> >>> >> >>> Modified: cfe/trunk/test/SemaCXX/overload-call.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) >> >>> +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 2012 >> >>> @@ -233,7 +233,7 @@ >> >>> >> >>> void intref_test() { >> >>> float* ir1 = intref(5); >> >>> - float* ir2 = intref(5.5); // expected-warning{{implicit conversion >> >>> turns literal floating-point number into integer}} >> >>> + float* ir2 = intref(5.5); // expected-warning{{implicit conversion >> from >> >>> 'double' to 'int' changes value from 5.5 to 5}} >> >>> } >> >>> >> >>> void derived5(C&); // expected-note{{candidate function not viable: >> >>> cannot bind base class object of type 'A' to derived class reference >> 'C &' >> >>> for 1st argument}} >> >>> >> >>> Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) >> >>> +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 >> 11:56:36 >> >>> 2012 >> >>> @@ -5,29 +5,29 @@ >> >>> // Warn when a literal float or double is assigned or bound to an >> >>> integer. >> >>> void test0() { >> >>> // Float >> >>> - int y0 = 1.2222F; // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> - int y1 = (1.2222F); // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> - int y2 = (((1.2222F))); // expected-warning {{implicit conversion >> turns >> >>> literal floating-point number into integer}} >> >>> - int y3 = 12E-1F; // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> - int y4 = 1.23E1F; // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> + int y0 = 1.2222F; // expected-warning {{implicit conversion from >> >>> 'float' to 'int' changes value from 1.2222 to 1}} >> >>> + int y1 = (1.2222F); // expected-warning {{implicit conversion from >> >>> 'float' to 'int' changes value from 1.2222 to 1}} >> >>> + int y2 = (((1.2222F))); // expected-warning {{implicit conversion >> from >> >>> 'float' to 'int' changes value from 1.2222 to 1}} >> >>> + int y3 = 12E-1F; // expected-warning {{implicit conversion from >> 'float' >> >>> to 'int' changes value from 1.2 to 1}} >> >>> + int y4 = 1.23E1F; // expected-warning {{implicit conversion from >> >>> 'float' to 'int' changes value from 12.3 to 12}} >> >>> // Double >> >>> - int y5 = 1.2222; // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> - int y6 = 12E-1; // expected-warning {{implicit conversion turns >> literal >> >>> floating-point number into integer}} >> >>> - int y7 = 1.23E1; // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> - int y8 = (1.23E1); // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> + int y5 = 1.2222; // expected-warning {{implicit conversion from >> >>> 'double' to 'int' changes value from 1.2222 to 1}} >> >>> + int y6 = 12E-1; // expected-warning {{implicit conversion from >> 'double' >> >>> to 'int' changes value from 1.2 to 1}} >> >>> + int y7 = 1.23E1; // expected-warning {{implicit conversion from >> >>> 'double' to 'int' changes value from 12.3 to 12}} >> >>> + int y8 = (1.23E1); // expected-warning {{implicit conversion from >> >>> 'double' to 'int' changes value from 12.3 to 12}} >> >>> >> >>> // Test assignment to an existing variable. >> >>> - y8 = 2.22F; // expected-warning {{implicit conversion turns literal >> >>> floating-point number into integer}} >> >>> + y8 = 2.22F; // expected-warning {{implicit conversion from 'float' >> to >> >>> 'int' changes value from 2.22 to 2}} >> >>> >> >>> // Test direct initialization. >> >>> - int y9(1.23F); // expected-warning {{implicit conversion turns >> literal >> >>> floating-point number into integer}} >> >>> + int y9(1.23F); // expected-warning {{implicit conversion from >> 'float' >> >>> to 'int' changes value from 1.23 to 1}} >> >>> >> >>> // Test passing a literal floating-point value to a function that >> takes >> >>> an integer. >> >>> - foo(1.2F); // expected-warning {{implicit conversion turns literal >> >>> floating-point number into integer}} >> >>> + foo(1.2F); // expected-warning {{implicit conversion from 'float' >> to >> >>> 'int' changes value from 1.2 to 1}} >> >>> >> >>> - int y10 = -1.2F; // expected-warning {{implicit conversion turns >> >>> literal floating-point number into integer}} >> >>> + int y10 = -1.2F; // expected-warning {{implicit conversion from >> >>> 'float' to 'int' changes value from 1.2 to 1}} >> >>> >> >>> - // -Wconversion-literal does NOT catch const values. >> >>> + // -Wliteral-conversion does NOT catch const values. >> >>> // (-Wconversion DOES catch them.) >> >>> static const float sales_tax_rate = .095F; >> >>> int z = sales_tax_rate; >> >>> >> >>> Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >> >>> URL: >> >>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff >> >>> >> >>> >> ============================================================================== >> >>> --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >> (original) >> >>> +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue >> May 15 >> >>> 11:56:36 2012 >> >>> @@ -60,7 +60,7 @@ >> >>> >> >>> void test_X1(X1 x1) { >> >>> float *fp1 = x1.f1<>(17); >> >>> - float *fp2 = x1.f1(3.14); // expected-warning {{implicit >> >>> conversion turns literal floating-point number into integer}} >> >>> + float *fp2 = x1.f1(3.14); // expected-warning {{implicit >> >>> conversion from 'double' to 'int' changes value from 3.14 to 3}} >> >>> int *ip1 = x1.f1(17); >> >>> float *ip2 = x1.f1(3.14); >> >>> >> >>> >> >>> >> >>> _______________________________________________ >> >>> cfe-commits mailing list >> >>> cfe-commits at cs.uiuc.edu >> >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> >> >> >> >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/e3931c89/attachment-0001.html From jediknil at belkadan.com Tue May 15 22:44:46 2012 From: jediknil at belkadan.com (Jordan Rose) Date: Tue, 15 May 2012 23:44:46 -0400 Subject: [cfe-commits] [Patch] Add a warning to catch enums with all elements having the same value In-Reply-To: References: <0FA771F0-B74A-4F77-9070-4526D0CAFE75@belkadan.com> Message-ID: <79E139EF-CCAC-4BBD-9E0D-66E36CD28604@belkadan.com> On May 15, 2012, at 22:25, Richard Trieu wrote: > On Tue, May 15, 2012 at 6:51 PM, Jordy Rose wrote: >> This will crash if the two values have the same bit width, but different signedness. I'm not sure if you can do that with enums, but... >> > I tried sticking some negative values in there, but didn't see any crashing. Do you have an example of this happening? I meant signed vs. unsigned, but it looks like the EnumConstantDecls should already have a consistent type by this point. I can't get it to trigger in C or C++ mode. Sorry for crying wolf! Jordy From dblaikie at gmail.com Tue May 15 23:20:05 2012 From: dblaikie at gmail.com (David Blaikie) Date: Wed, 16 May 2012 04:20:05 -0000 Subject: [cfe-commits] r156901 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/ParseStmt.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/conversion.cpp Message-ID: <20120516042005.1E5D62A6C065@llvm.org> Author: dblaikie Date: Tue May 15 23:20:04 2012 New Revision: 156901 URL: http://llvm.org/viewvc/llvm-project?rev=156901&view=rev Log: Include the correct conversion context locations for condition expressions. This improves the conversion diagnostics (by correctly pointing to the loop construct for conversions that may've been caused by the contextual conversion to bool caused by a condition expression) and also causes the NULL conversion warnings to be correctly suppressed when crossing a macro boundary in such a context. (previously, since the conversion context location was incorrect, the suppression could not be performed) Reported by Nico Weber as feedback to r156826. Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/SemaCXX/conversion.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=156901&r1=156900&r2=156901&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue May 15 23:20:04 2012 @@ -2402,7 +2402,10 @@ }; FullExprArg MakeFullExpr(Expr *Arg) { - return FullExprArg(ActOnFinishFullExpr(Arg).release()); + return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); + } + FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { + return FullExprArg(ActOnFinishFullExpr(Arg, CC).release()); } StmtResult ActOnExprStmt(FullExprArg Expr); @@ -3795,7 +3798,11 @@ Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt); ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr); - ExprResult ActOnFinishFullExpr(Expr *Expr); + ExprResult ActOnFinishFullExpr(Expr *Expr) { + return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() + : SourceLocation()); + } + ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC); StmtResult ActOnFinishFullStmt(Stmt *Stmt); // Marks SS invalid if it represents an incomplete type. Modified: cfe/trunk/lib/Parse/ParseStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=156901&r1=156900&r2=156901&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue May 15 23:20:04 2012 @@ -948,7 +948,7 @@ if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) return StmtError(); - FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get())); + FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc)); // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1174,7 +1174,7 @@ if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) return StmtError(); - FullExprArg FullCond(Actions.MakeFullExpr(Cond.get())); + FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1451,7 +1451,7 @@ Second.get()); } SecondPartIsInvalid = Second.isInvalid(); - SecondPart = Actions.MakeFullExpr(Second.get()); + SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc); } if (Tok.isNot(tok::semi)) { Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=156901&r1=156900&r2=156901&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue May 15 23:20:04 2012 @@ -5310,7 +5310,7 @@ return Owned(E); } -ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { +ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) { ExprResult FullExpr = Owned(FE); if (!FullExpr.get()) @@ -5336,7 +5336,7 @@ if (FullExpr.isInvalid()) return ExprError(); - CheckImplicitConversions(FullExpr.get(), FullExpr.get()->getExprLoc()); + CheckImplicitConversions(FullExpr.get(), CC); return MaybeCreateExprWithCleanups(FullExpr); } Modified: cfe/trunk/test/SemaCXX/conversion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156901&r1=156900&r2=156901&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/conversion.cpp (original) +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 23:20:04 2012 @@ -81,6 +81,14 @@ // and avoiding that helps us skip these cases: #define NULL_COND(cond) ((cond) ? &a : NULL) bool bl2 = NULL_COND(true); // don't warn on NULL conversion through the conditional operator across a macro boundary + if (NULL_COND(true)) + ; + while (NULL_COND(true)) + ; + for (; NULL_COND(true); ) + ; + do ; + while(NULL_COND(true)); } namespace test4 { From dblaikie at gmail.com Tue May 15 23:25:43 2012 From: dblaikie at gmail.com (David Blaikie) Date: Tue, 15 May 2012 21:25:43 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 8:34 PM, Nico Weber wrote: > On Tue, May 15, 2012 at 3:16 PM, Nico Weber wrote: >> >> On Tue, May 15, 2012 at 2:59 PM, David Blaikie wrote: >>> >>> On Tue, May 15, 2012 at 10:43 AM, David Blaikie >>> wrote: >>> > On Tue, May 15, 2012 at 10:39 AM, Nico Weber >>> > wrote: >>> >> Hi David, >>> >> >>> >> as mentioned on the thread for this warning, with this change clang >>> >> warns on >>> > >>> > Ah, right - sorry, I'd forgotten that even the NULL case had some >>> > problems. I'll see what I can do to tidy this case up sooner rather >>> > than later. Thanks for the reminder. >>> >>> I believe r156861 should help handle this case. >> >> >> The warnings on lines with `if ( ! YY_CURRENT_BUFFER)` lines are gone, but >> `if (YY_CURRENT_BUFFER)` still warns: >> >> hummer:src thakis$ ?/Users/thakis/src/llvm-svn/Release+Asserts/bin/clang++ >> ?--version >> clang version 3.2 (trunk 156862) >> Target: x86_64-apple-darwin10.8.0 >> Thread model: posix >> >> $ ... >> glsl_lexer.cpp:2778:7: error: implicit conversion of NULL constant to >> 'bool' [-Werror,-Wnull-conversion] >> ? ? ? ? if ( YY_CURRENT_BUFFER ) >> ? ? ? ? ? ? ?^~~~~~~~~~~~~~~~~ >> glsl_lexer.cpp:273:29: note: expanded from macro 'YY_CURRENT_BUFFER' >> ? ? ? ? ? ? ? ? ? ? ? ? ? : NULL) >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^ > > > If this is taking a while to fix, would you mind reverting this in the > meantime? Sorry for the delay - r156901 has a variety of conditional test cases & I believe addresses the issues. After readding the various macros to the preprocessed file you sent, it seems to not trigger these warnings anymore. Thanks again, - David > >> >> >> >> >> >>> >>> Thanks again, >>> >>> - David >>> >>> >> >>> >> #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ >>> >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? >>> >> yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ >>> >> ? ? ? ? ? ? ? ? ? ? ? ? ? : NULL) >>> >> >>> >> // ... >>> >> >>> >> if ( ! YY_CURRENT_BUFFER ) { >>> >> // ... >>> >> } >>> >> >>> >> with this message: >>> >> >>> >> ./pp_lex.cpp:784:10: error: implicit conversion of NULL constant to >>> >> 'bool' >>> >> [-Werror,-Wnull-conversion] >>> >> ? ? ? ? ? ? ? ? if ( ! YY_CURRENT_BUFFER ) { >>> >> ? ? ? ? ? ? ? ? ? ? ? ?^~~~~~~~~~~~~~~~~ >>> >> ./pp_lex.cpp:295:29: note: expanded from macro 'YY_CURRENT_BUFFER' >>> >> ? ? ? ? ? ? ? ? ? ? ? ? ? : NULL) >>> >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^ >>> >> >>> >> >>> >> This looks like valid code to me. >>> >> >>> >> Nico >>> >> >>> >> On Tue, May 15, 2012 at 9:56 AM, David Blaikie >>> >> wrote: >>> >>> >>> >>> Author: dblaikie >>> >>> Date: Tue May 15 11:56:36 2012 >>> >>> New Revision: 156826 >>> >>> >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev >>> >>> Log: >>> >>> Improve some of the conversion warnings to fire on conversion to >>> >>> bool. >>> >>> >>> >>> Moves the bool bail-out down a little in SemaChecking - so now >>> >>> -Wnull-conversion and -Wliteral-conversion can fire when the target >>> >>> type >>> >>> is >>> >>> bool. >>> >>> >>> >>> Also improve the wording/details in the -Wliteral-conversion warning >>> >>> to >>> >>> match >>> >>> the -Wconstant-conversion. >>> >>> >>> >>> Modified: >>> >>> ? ?cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>> >>> ? ?cfe/trunk/lib/Sema/SemaChecking.cpp >>> >>> ? ?cfe/trunk/test/Analysis/array-struct-region.c >>> >>> ? ?cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >>> >>> ? ?cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >>> >>> ? ?cfe/trunk/test/PCH/exprs.h >>> >>> ? ?cfe/trunk/test/Sema/array-init.c >>> >>> ? ?cfe/trunk/test/Sema/knr-def-call.c >>> >>> ? ?cfe/trunk/test/SemaCXX/bool.cpp >>> >>> ? ?cfe/trunk/test/SemaCXX/conversion.cpp >>> >>> ? ?cfe/trunk/test/SemaCXX/expressions.cpp >>> >>> ? ?cfe/trunk/test/SemaCXX/overload-call.cpp >>> >>> ? ?cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >>> >>> ? ?cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >>> >>> >>> >>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >>> >>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 >>> >>> 11:56:36 2012 >>> >>> @@ -1781,8 +1781,7 @@ >>> >>> ? "implicit truncation from %2 to bitfield changes value from %0 to >>> >>> %1">, >>> >>> ? InGroup; >>> >>> ?def warn_impcast_literal_float_to_integer : Warning< >>> >>> - ?"implicit conversion turns literal floating-point number into >>> >>> integer: >>> >>> " >>> >>> - ?"%0 to %1">, >>> >>> + ?"implicit conversion from %0 to %1 changes value from %2 to %3">, >>> >>> ? InGroup; >>> >>> ?def warn_impcast_string_literal_to_bool : Warning< >>> >>> ? "implicit conversion turns string literal into bool: %0 to %1">, >>> >>> >>> >>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) >>> >>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 >>> >>> @@ -22,6 +22,7 @@ >>> >>> ?#include "clang/AST/CharUnits.h" >>> >>> ?#include "clang/AST/DeclCXX.h" >>> >>> ?#include "clang/AST/DeclObjC.h" >>> >>> +#include "clang/AST/Expr.h" >>> >>> ?#include "clang/AST/ExprCXX.h" >>> >>> ?#include "clang/AST/ExprObjC.h" >>> >>> ?#include "clang/AST/EvaluatedExprVisitor.h" >>> >>> @@ -4081,8 +4082,17 @@ >>> >>> ? ? ? == llvm::APFloat::opOK && isExact) >>> >>> ? ? return; >>> >>> >>> >>> >>> >>> + ?SmallString<16> PrettySourceValue; >>> >>> + ?Value.toString(PrettySourceValue); >>> >>> + ?std::string PrettyTargetValue; >>> >>> + ?if (T->isSpecificBuiltinType(BuiltinType::Bool)) >>> >>> + ? ?PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; >>> >>> + ?else >>> >>> + ? ?PrettyTargetValue = IntegerValue.toString(10); >>> >>> + >>> >>> ? S.Diag(FL->getExprLoc(), >>> >>> diag::warn_impcast_literal_float_to_integer) >>> >>> - ? ?<< FL->getType() << T << FL->getSourceRange() << >>> >>> SourceRange(CContext); >>> >>> + ? ?<< FL->getType() << T.getUnqualifiedType() << PrettySourceValue >>> >>> + ? ?<< PrettyTargetValue << FL->getSourceRange() << >>> >>> SourceRange(CContext); >>> >>> ?} >>> >>> >>> >>> ?std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange >>> >>> Range) >>> >>> { >>> >>> @@ -4149,7 +4159,6 @@ >>> >>> ? ? ? ? } >>> >>> ? ? ? } >>> >>> ? ? } >>> >>> - ? ?return; // Other casts to bool are not checked. >>> >>> ? } >>> >>> >>> >>> ? // Strip vector types. >>> >>> @@ -4213,7 +4222,7 @@ >>> >>> ? ? } >>> >>> >>> >>> ? ? // If the target is integral, always warn. >>> >>> - ? ?if ((TargetBT && TargetBT->isInteger())) { >>> >>> + ? ?if (TargetBT && TargetBT->isInteger()) { >>> >>> ? ? ? if (S.SourceMgr.isInSystemMacro(CC)) >>> >>> ? ? ? ? return; >>> >>> >>> >>> @@ -4247,6 +4256,11 @@ >>> >>> ? ? return; >>> >>> ? } >>> >>> >>> >>> + ?// TODO: remove this early return once the false positives for >>> >>> constant->bool >>> >>> + ?// in templates, macros, etc, are reduced or removed. >>> >>> + ?if (Target->isSpecificBuiltinType(BuiltinType::Bool)) >>> >>> + ? ?return; >>> >>> + >>> >>> ? IntRange SourceRange = GetExprRange(S.Context, E); >>> >>> ? IntRange TargetRange = >>> >>> IntRange::forTargetOfCanonicalType(S.Context, >>> >>> Target); >>> >>> >>> >>> >>> >>> Modified: cfe/trunk/test/Analysis/array-struct-region.c >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/Analysis/array-struct-region.c (original) >>> >>> +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 11:56:36 >>> >>> 2012 >>> >>> @@ -25,8 +25,8 @@ >>> >>> ?} >>> >>> >>> >>> ?void nested_compound_literals(int rad) { >>> >>> - ?int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, ?// >>> >>> expected-warning 6 {{implicit conversion turns literal floating-point >>> >>> number >>> >>> into integer}} >>> >>> - ? ? ? ? ? ? ? ? ? {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >>> >>> expected-warning 6 {{implicit conversion turns literal floating-point >>> >>> number >>> >>> into integer}} >>> >>> + ?int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, ?// >>> >>> expected-warning 6 {{implicit conversion from 'double' to 'int' >>> >>> changes >>> >>> value from}} >>> >>> + ? ? ? ? ? ? ? ? ? {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // >>> >>> expected-warning 6 {{implicit conversion from 'double' to 'int' >>> >>> changes >>> >>> value from}} >>> >>> ? int a; >>> >>> >>> >>> ? for (a = 0; a < 6; ++a) { >>> >>> >>> >>> Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp >>> >>> (original) >>> >>> +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May >>> >>> 15 >>> >>> 11:56:36 2012 >>> >>> @@ -4,7 +4,7 @@ >>> >>> >>> >>> ?bool b = !0; >>> >>> >>> >>> -bool b2 = !1.2; >>> >>> +bool b2 = !1.2; //expected-warning{{implicit conversion from >>> >>> 'double' to >>> >>> 'bool' changes value from 1.2 to true}} >>> >>> >>> >>> ?bool b3 = !4; >>> >>> >>> >>> >>> >>> Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) >>> >>> +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 2012 >>> >>> @@ -14,7 +14,7 @@ >>> >>> ?}; >>> >>> >>> >>> ?template >>> >>> -T X0::value = 3.14; // expected-warning{{implicit conversion >>> >>> turns >>> >>> literal floating-point number into integer}} >>> >>> +T X0::value = 3.14; // expected-warning{{implicit conversion from >>> >>> 'double' to 'int' changes value from 3.14 to 3}} >>> >>> >>> >>> ?template struct X0; // expected-note{{previous explicit >>> >>> instantiation}} \ >>> >>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? expected-note{{requested here}} >>> >>> >>> >>> Modified: cfe/trunk/test/PCH/exprs.h >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/PCH/exprs.h (original) >>> >>> +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 >>> >>> @@ -87,7 +87,7 @@ >>> >>> ? int x; >>> >>> ? float y; >>> >>> ?} designated_inits[3] = { [0].y = 17, >>> >>> - ? ? ? ? ? ? ? ? ? ? ? ? ?[2].x = 12.3, // expected-warning >>> >>> {{implicit >>> >>> conversion turns literal floating-point number into integer}} >>> >>> + ? ? ? ? ? ? ? ? ? ? ? ? ?[2].x = 12.3, // expected-warning >>> >>> {{implicit >>> >>> conversion from 'double' to 'int' changes value from 12.3 to 12}} >>> >>> ? ? ? ? ? ? ? ? ? ? ? ? ? 3.5 }; >>> >>> >>> >>> ?// TypesCompatibleExpr >>> >>> >>> >>> Modified: cfe/trunk/test/Sema/array-init.c >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/Sema/array-init.c (original) >>> >>> +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 >>> >>> @@ -50,7 +50,7 @@ >>> >>> >>> >>> ? static long x2[3] = { 1.0, >>> >>> ? ? ? ? ? ? ? ? ? ? ? ? "abc", // expected-warning{{incompatible >>> >>> pointer >>> >>> to integer conversion initializing 'long' with an expression of type >>> >>> 'char >>> >>> [4]'}} >>> >>> - ? ? ? ? ? ? ? ? ? ? ? ? 5.8 }; // expected-warning {{implicit >>> >>> conversion >>> >>> turns literal floating-point number into integer}} >>> >>> + ? ? ? ? ? ? ? ? ? ? ? ? 5.8 }; // expected-warning {{implicit >>> >>> conversion >>> >>> from 'double' to 'long' changes value from 5.8 to 5}} >>> >>> ?} >>> >>> >>> >>> ?void test() { >>> >>> >>> >>> Modified: cfe/trunk/test/Sema/knr-def-call.c >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/Sema/knr-def-call.c (original) >>> >>> +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 >>> >>> @@ -36,6 +36,6 @@ >>> >>> ?} >>> >>> >>> >>> ?void use_proto() { >>> >>> - ?proto(42.1); // expected-warning{{implicit conversion turns >>> >>> literal >>> >>> floating-point number into integer}} >>> >>> - ?(&proto)(42.1); // expected-warning{{implicit conversion turns >>> >>> literal >>> >>> floating-point number into integer}} >>> >>> + ?proto(42.1); // expected-warning{{implicit conversion from >>> >>> 'double' to >>> >>> 'int' changes value from 42.1 to 42}} >>> >>> + ?(&proto)(42.1); // expected-warning{{implicit conversion from >>> >>> 'double' >>> >>> to 'int' changes value from 42.1 to 42}} >>> >>> ?} >>> >>> >>> >>> Modified: cfe/trunk/test/SemaCXX/bool.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/SemaCXX/bool.cpp (original) >>> >>> +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 >>> >>> @@ -1,4 +1,4 @@ >>> >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s >>> >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >>> >>> >>> >>> ?// Bool literals can be enum values. >>> >>> ?enum { >>> >>> >>> >>> Modified: cfe/trunk/test/SemaCXX/conversion.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/SemaCXX/conversion.cpp (original) >>> >>> +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 >>> >>> @@ -65,7 +65,7 @@ >>> >>> ? int c = ((((NULL)))); // expected-warning {{implicit conversion of >>> >>> NULL >>> >>> constant to 'int'}} >>> >>> ? int d; >>> >>> ? d = ((((NULL)))); // expected-warning {{implicit conversion of NULL >>> >>> constant to 'int'}} >>> >>> - ?bool bl = NULL; // FIXME: this should warn but we currently >>> >>> suppress a >>> >>> bunch of conversion-to-bool warnings including this one >>> >>> + ?bool bl = NULL; // expected-warning {{implicit conversion of NULL >>> >>> constant to 'bool'}} >>> >>> ? char ch = NULL; // expected-warning {{implicit conversion of NULL >>> >>> constant to 'char'}} >>> >>> ? unsigned char uch = NULL; // expected-warning {{implicit conversion >>> >>> of >>> >>> NULL constant to 'unsigned char'}} >>> >>> ? short sh = NULL; // expected-warning {{implicit conversion of NULL >>> >>> constant to 'short'}} >>> >>> @@ -104,3 +104,12 @@ >>> >>> ? ? tmpl2(); >>> >>> ? } >>> >>> ?} >>> >>> + >>> >>> +namespace test5 { >>> >>> + ?template >>> >>> + ?void func() { >>> >>> + ? ?bool b = I; >>> >>> + ?} >>> >>> + >>> >>> + ?template void func<3>(); >>> >>> +} >>> >>> >>> >>> Modified: cfe/trunk/test/SemaCXX/expressions.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/SemaCXX/expressions.cpp (original) >>> >>> +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 >>> >>> @@ -1,4 +1,4 @@ >>> >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s >>> >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s >>> >>> >>> >>> ?void choice(int); >>> >>> ?int choice(bool); >>> >>> >>> >>> Modified: cfe/trunk/test/SemaCXX/overload-call.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) >>> >>> +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 2012 >>> >>> @@ -233,7 +233,7 @@ >>> >>> >>> >>> ?void intref_test() { >>> >>> ? float* ir1 = intref(5); >>> >>> - ?float* ir2 = intref(5.5); // expected-warning{{implicit conversion >>> >>> turns literal floating-point number into integer}} >>> >>> + ?float* ir2 = intref(5.5); // expected-warning{{implicit conversion >>> >>> from >>> >>> 'double' to 'int' changes value from 5.5 to 5}} >>> >>> ?} >>> >>> >>> >>> ?void derived5(C&); // expected-note{{candidate function not viable: >>> >>> cannot bind base class object of type 'A' to derived class reference >>> >>> 'C &' >>> >>> for 1st argument}} >>> >>> >>> >>> Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) >>> >>> +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 >>> >>> 11:56:36 >>> >>> 2012 >>> >>> @@ -5,29 +5,29 @@ >>> >>> ?// Warn when a literal float or double is assigned or bound to an >>> >>> integer. >>> >>> ?void test0() { >>> >>> ? // Float >>> >>> - ?int y0 = 1.2222F; // expected-warning {{implicit conversion turns >>> >>> literal floating-point number into integer}} >>> >>> - ?int y1 = (1.2222F); // expected-warning {{implicit conversion >>> >>> turns >>> >>> literal floating-point number into integer}} >>> >>> - ?int y2 = (((1.2222F))); // expected-warning {{implicit conversion >>> >>> turns >>> >>> literal floating-point number into integer}} >>> >>> - ?int y3 = 12E-1F; // expected-warning {{implicit conversion turns >>> >>> literal floating-point number into integer}} >>> >>> - ?int y4 = 1.23E1F; // expected-warning {{implicit conversion turns >>> >>> literal floating-point number into integer}} >>> >>> + ?int y0 = 1.2222F; // expected-warning {{implicit conversion from >>> >>> 'float' to 'int' changes value from 1.2222 to 1}} >>> >>> + ?int y1 = (1.2222F); // expected-warning {{implicit conversion from >>> >>> 'float' to 'int' changes value from 1.2222 to 1}} >>> >>> + ?int y2 = (((1.2222F))); // expected-warning {{implicit conversion >>> >>> from >>> >>> 'float' to 'int' changes value from 1.2222 to 1}} >>> >>> + ?int y3 = 12E-1F; // expected-warning {{implicit conversion from >>> >>> 'float' >>> >>> to 'int' changes value from 1.2 to 1}} >>> >>> + ?int y4 = 1.23E1F; // expected-warning {{implicit conversion from >>> >>> 'float' to 'int' changes value from 12.3 to 12}} >>> >>> ? // Double >>> >>> - ?int y5 = 1.2222; // expected-warning {{implicit conversion turns >>> >>> literal floating-point number into integer}} >>> >>> - ?int y6 = 12E-1; // expected-warning {{implicit conversion turns >>> >>> literal >>> >>> floating-point number into integer}} >>> >>> - ?int y7 = 1.23E1; // expected-warning {{implicit conversion turns >>> >>> literal floating-point number into integer}} >>> >>> - ?int y8 = (1.23E1); // expected-warning {{implicit conversion turns >>> >>> literal floating-point number into integer}} >>> >>> + ?int y5 = 1.2222; // expected-warning {{implicit conversion from >>> >>> 'double' to 'int' changes value from 1.2222 to 1}} >>> >>> + ?int y6 = 12E-1; // expected-warning {{implicit conversion from >>> >>> 'double' >>> >>> to 'int' changes value from 1.2 to 1}} >>> >>> + ?int y7 = 1.23E1; // expected-warning {{implicit conversion from >>> >>> 'double' to 'int' changes value from 12.3 to 12}} >>> >>> + ?int y8 = (1.23E1); // expected-warning {{implicit conversion from >>> >>> 'double' to 'int' changes value from 12.3 to 12}} >>> >>> >>> >>> ? // Test assignment to an existing variable. >>> >>> - ?y8 = 2.22F; // expected-warning {{implicit conversion turns >>> >>> literal >>> >>> floating-point number into integer}} >>> >>> + ?y8 = 2.22F; // expected-warning {{implicit conversion from 'float' >>> >>> to >>> >>> 'int' changes value from 2.22 to 2}} >>> >>> >>> >>> ? // Test direct initialization. >>> >>> - ?int y9(1.23F); // expected-warning {{implicit conversion turns >>> >>> literal >>> >>> floating-point number into integer}} >>> >>> + ?int y9(1.23F); // expected-warning {{implicit conversion from >>> >>> 'float' >>> >>> to 'int' changes value from 1.23 to 1}} >>> >>> >>> >>> ? // Test passing a literal floating-point value to a function that >>> >>> takes >>> >>> an integer. >>> >>> - ?foo(1.2F); // expected-warning {{implicit conversion turns literal >>> >>> floating-point number into integer}} >>> >>> + ?foo(1.2F); // expected-warning {{implicit conversion from 'float' >>> >>> to >>> >>> 'int' changes value from 1.2 to 1}} >>> >>> >>> >>> - ?int y10 = -1.2F; ?// expected-warning {{implicit conversion turns >>> >>> literal floating-point number into integer}} >>> >>> + ?int y10 = -1.2F; ?// expected-warning {{implicit conversion from >>> >>> 'float' to 'int' changes value from 1.2 to 1}} >>> >>> >>> >>> - ?// -Wconversion-literal does NOT catch const values. >>> >>> + ?// -Wliteral-conversion does NOT catch const values. >>> >>> ? // (-Wconversion DOES catch them.) >>> >>> ? static const float sales_tax_rate = .095F; >>> >>> ? int z = sales_tax_rate; >>> >>> >>> >>> Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >>> >>> URL: >>> >>> >>> >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff >>> >>> >>> >>> >>> >>> ============================================================================== >>> >>> --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp >>> >>> (original) >>> >>> +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue >>> >>> May 15 >>> >>> 11:56:36 2012 >>> >>> @@ -60,7 +60,7 @@ >>> >>> >>> >>> ?void test_X1(X1 x1) { >>> >>> ? float *fp1 = x1.f1<>(17); >>> >>> - ?float *fp2 = x1.f1(3.14); // expected-warning {{implicit >>> >>> conversion turns literal floating-point number into integer}} >>> >>> + ?float *fp2 = x1.f1(3.14); // expected-warning {{implicit >>> >>> conversion from 'double' to 'int' changes value from 3.14 to 3}} >>> >>> ? int *ip1 = x1.f1(17); >>> >>> ? float *ip2 = x1.f1(3.14); >>> >>> >>> >>> >>> >>> >>> >>> _______________________________________________ >>> >>> cfe-commits mailing list >>> >>> cfe-commits at cs.uiuc.edu >>> >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >>> >> >>> >> >> >> > From thakis at chromium.org Wed May 16 00:22:53 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 15 May 2012 22:22:53 -0700 Subject: [cfe-commits] r156826 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Analysis/array-struct-region.c test/CXX/expr/expr.unary/expr.unary.op/p6.cpp test/CXX/temp/temp.spec/p5.cpp test/PCH/exprs.h test/Sem In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 9:25 PM, David Blaikie wrote: > On Tue, May 15, 2012 at 8:34 PM, Nico Weber wrote: > > On Tue, May 15, 2012 at 3:16 PM, Nico Weber wrote: > >> > >> On Tue, May 15, 2012 at 2:59 PM, David Blaikie > wrote: > >>> > >>> On Tue, May 15, 2012 at 10:43 AM, David Blaikie > >>> wrote: > >>> > On Tue, May 15, 2012 at 10:39 AM, Nico Weber > >>> > wrote: > >>> >> Hi David, > >>> >> > >>> >> as mentioned on the thread for this warning, with this change clang > >>> >> warns on > >>> > > >>> > Ah, right - sorry, I'd forgotten that even the NULL case had some > >>> > problems. I'll see what I can do to tidy this case up sooner rather > >>> > than later. Thanks for the reminder. > >>> > >>> I believe r156861 should help handle this case. > >> > >> > >> The warnings on lines with `if ( ! YY_CURRENT_BUFFER)` lines are gone, > but > >> `if (YY_CURRENT_BUFFER)` still warns: > >> > >> hummer:src thakis$ > /Users/thakis/src/llvm-svn/Release+Asserts/bin/clang++ > >> --version > >> clang version 3.2 (trunk 156862) > >> Target: x86_64-apple-darwin10.8.0 > >> Thread model: posix > >> > >> $ ... > >> glsl_lexer.cpp:2778:7: error: implicit conversion of NULL constant to > >> 'bool' [-Werror,-Wnull-conversion] > >> if ( YY_CURRENT_BUFFER ) > >> ^~~~~~~~~~~~~~~~~ > >> glsl_lexer.cpp:273:29: note: expanded from macro 'YY_CURRENT_BUFFER' > >> : NULL) > >> ^ > > > > > > If this is taking a while to fix, would you mind reverting this in the > > meantime? > > Sorry for the delay - r156901 has a variety of conditional test cases > & I believe addresses the issues. After readding the various macros to > the preprocessed file you sent, it seems to not trigger these warnings > anymore. > Confirmed, thanks :-) > > Thanks again, > - David > > > > >> > >> > >> > >> > >> > >>> > >>> Thanks again, > >>> > >>> - David > >>> > >>> >> > >>> >> #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ > >>> >> ? > >>> >> yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ > >>> >> : NULL) > >>> >> > >>> >> // ... > >>> >> > >>> >> if ( ! YY_CURRENT_BUFFER ) { > >>> >> // ... > >>> >> } > >>> >> > >>> >> with this message: > >>> >> > >>> >> ./pp_lex.cpp:784:10: error: implicit conversion of NULL constant to > >>> >> 'bool' > >>> >> [-Werror,-Wnull-conversion] > >>> >> if ( ! YY_CURRENT_BUFFER ) { > >>> >> ^~~~~~~~~~~~~~~~~ > >>> >> ./pp_lex.cpp:295:29: note: expanded from macro 'YY_CURRENT_BUFFER' > >>> >> : NULL) > >>> >> ^ > >>> >> > >>> >> > >>> >> This looks like valid code to me. > >>> >> > >>> >> Nico > >>> >> > >>> >> On Tue, May 15, 2012 at 9:56 AM, David Blaikie > >>> >> wrote: > >>> >>> > >>> >>> Author: dblaikie > >>> >>> Date: Tue May 15 11:56:36 2012 > >>> >>> New Revision: 156826 > >>> >>> > >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=156826&view=rev > >>> >>> Log: > >>> >>> Improve some of the conversion warnings to fire on conversion to > >>> >>> bool. > >>> >>> > >>> >>> Moves the bool bail-out down a little in SemaChecking - so now > >>> >>> -Wnull-conversion and -Wliteral-conversion can fire when the target > >>> >>> type > >>> >>> is > >>> >>> bool. > >>> >>> > >>> >>> Also improve the wording/details in the -Wliteral-conversion > warning > >>> >>> to > >>> >>> match > >>> >>> the -Wconstant-conversion. > >>> >>> > >>> >>> Modified: > >>> >>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > >>> >>> cfe/trunk/lib/Sema/SemaChecking.cpp > >>> >>> cfe/trunk/test/Analysis/array-struct-region.c > >>> >>> cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp > >>> >>> cfe/trunk/test/CXX/temp/temp.spec/p5.cpp > >>> >>> cfe/trunk/test/PCH/exprs.h > >>> >>> cfe/trunk/test/Sema/array-init.c > >>> >>> cfe/trunk/test/Sema/knr-def-call.c > >>> >>> cfe/trunk/test/SemaCXX/bool.cpp > >>> >>> cfe/trunk/test/SemaCXX/conversion.cpp > >>> >>> cfe/trunk/test/SemaCXX/expressions.cpp > >>> >>> cfe/trunk/test/SemaCXX/overload-call.cpp > >>> >>> cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp > >>> >>> cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > >>> >>> > >>> >>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > >>> >>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 15 > >>> >>> 11:56:36 2012 > >>> >>> @@ -1781,8 +1781,7 @@ > >>> >>> "implicit truncation from %2 to bitfield changes value from %0 to > >>> >>> %1">, > >>> >>> InGroup; > >>> >>> def warn_impcast_literal_float_to_integer : Warning< > >>> >>> - "implicit conversion turns literal floating-point number into > >>> >>> integer: > >>> >>> " > >>> >>> - "%0 to %1">, > >>> >>> + "implicit conversion from %0 to %1 changes value from %2 to > %3">, > >>> >>> InGroup; > >>> >>> def warn_impcast_string_literal_to_bool : Warning< > >>> >>> "implicit conversion turns string literal into bool: %0 to %1">, > >>> >>> > >>> >>> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) > >>> >>> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue May 15 11:56:36 2012 > >>> >>> @@ -22,6 +22,7 @@ > >>> >>> #include "clang/AST/CharUnits.h" > >>> >>> #include "clang/AST/DeclCXX.h" > >>> >>> #include "clang/AST/DeclObjC.h" > >>> >>> +#include "clang/AST/Expr.h" > >>> >>> #include "clang/AST/ExprCXX.h" > >>> >>> #include "clang/AST/ExprObjC.h" > >>> >>> #include "clang/AST/EvaluatedExprVisitor.h" > >>> >>> @@ -4081,8 +4082,17 @@ > >>> >>> == llvm::APFloat::opOK && isExact) > >>> >>> return; > >>> >>> > >>> >>> > >>> >>> + SmallString<16> PrettySourceValue; > >>> >>> + Value.toString(PrettySourceValue); > >>> >>> + std::string PrettyTargetValue; > >>> >>> + if (T->isSpecificBuiltinType(BuiltinType::Bool)) > >>> >>> + PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; > >>> >>> + else > >>> >>> + PrettyTargetValue = IntegerValue.toString(10); > >>> >>> + > >>> >>> S.Diag(FL->getExprLoc(), > >>> >>> diag::warn_impcast_literal_float_to_integer) > >>> >>> - << FL->getType() << T << FL->getSourceRange() << > >>> >>> SourceRange(CContext); > >>> >>> + << FL->getType() << T.getUnqualifiedType() << > PrettySourceValue > >>> >>> + << PrettyTargetValue << FL->getSourceRange() << > >>> >>> SourceRange(CContext); > >>> >>> } > >>> >>> > >>> >>> std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange > >>> >>> Range) > >>> >>> { > >>> >>> @@ -4149,7 +4159,6 @@ > >>> >>> } > >>> >>> } > >>> >>> } > >>> >>> - return; // Other casts to bool are not checked. > >>> >>> } > >>> >>> > >>> >>> // Strip vector types. > >>> >>> @@ -4213,7 +4222,7 @@ > >>> >>> } > >>> >>> > >>> >>> // If the target is integral, always warn. > >>> >>> - if ((TargetBT && TargetBT->isInteger())) { > >>> >>> + if (TargetBT && TargetBT->isInteger()) { > >>> >>> if (S.SourceMgr.isInSystemMacro(CC)) > >>> >>> return; > >>> >>> > >>> >>> @@ -4247,6 +4256,11 @@ > >>> >>> return; > >>> >>> } > >>> >>> > >>> >>> + // TODO: remove this early return once the false positives for > >>> >>> constant->bool > >>> >>> + // in templates, macros, etc, are reduced or removed. > >>> >>> + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) > >>> >>> + return; > >>> >>> + > >>> >>> IntRange SourceRange = GetExprRange(S.Context, E); > >>> >>> IntRange TargetRange = > >>> >>> IntRange::forTargetOfCanonicalType(S.Context, > >>> >>> Target); > >>> >>> > >>> >>> > >>> >>> Modified: cfe/trunk/test/Analysis/array-struct-region.c > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/Analysis/array-struct-region.c (original) > >>> >>> +++ cfe/trunk/test/Analysis/array-struct-region.c Tue May 15 > 11:56:36 > >>> >>> 2012 > >>> >>> @@ -25,8 +25,8 @@ > >>> >>> } > >>> >>> > >>> >>> void nested_compound_literals(int rad) { > >>> >>> - int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, > // > >>> >>> expected-warning 6 {{implicit conversion turns literal > floating-point > >>> >>> number > >>> >>> into integer}} > >>> >>> - {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; > // > >>> >>> expected-warning 6 {{implicit conversion turns literal > floating-point > >>> >>> number > >>> >>> into integer}} > >>> >>> + int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, > // > >>> >>> expected-warning 6 {{implicit conversion from 'double' to 'int' > >>> >>> changes > >>> >>> value from}} > >>> >>> + {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; > // > >>> >>> expected-warning 6 {{implicit conversion from 'double' to 'int' > >>> >>> changes > >>> >>> value from}} > >>> >>> int a; > >>> >>> > >>> >>> for (a = 0; a < 6; ++a) { > >>> >>> > >>> >>> Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp > >>> >>> (original) > >>> >>> +++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp Tue May > >>> >>> 15 > >>> >>> 11:56:36 2012 > >>> >>> @@ -4,7 +4,7 @@ > >>> >>> > >>> >>> bool b = !0; > >>> >>> > >>> >>> -bool b2 = !1.2; > >>> >>> +bool b2 = !1.2; //expected-warning{{implicit conversion from > >>> >>> 'double' to > >>> >>> 'bool' changes value from 1.2 to true}} > >>> >>> > >>> >>> bool b3 = !4; > >>> >>> > >>> >>> > >>> >>> Modified: cfe/trunk/test/CXX/temp/temp.spec/p5.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/p5.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/CXX/temp/temp.spec/p5.cpp (original) > >>> >>> +++ cfe/trunk/test/CXX/temp/temp.spec/p5.cpp Tue May 15 11:56:36 > 2012 > >>> >>> @@ -14,7 +14,7 @@ > >>> >>> }; > >>> >>> > >>> >>> template > >>> >>> -T X0::value = 3.14; // expected-warning{{implicit conversion > >>> >>> turns > >>> >>> literal floating-point number into integer}} > >>> >>> +T X0::value = 3.14; // expected-warning{{implicit conversion > from > >>> >>> 'double' to 'int' changes value from 3.14 to 3}} > >>> >>> > >>> >>> template struct X0; // expected-note{{previous explicit > >>> >>> instantiation}} \ > >>> >>> expected-note{{requested here}} > >>> >>> > >>> >>> Modified: cfe/trunk/test/PCH/exprs.h > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/exprs.h?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/PCH/exprs.h (original) > >>> >>> +++ cfe/trunk/test/PCH/exprs.h Tue May 15 11:56:36 2012 > >>> >>> @@ -87,7 +87,7 @@ > >>> >>> int x; > >>> >>> float y; > >>> >>> } designated_inits[3] = { [0].y = 17, > >>> >>> - [2].x = 12.3, // expected-warning > >>> >>> {{implicit > >>> >>> conversion turns literal floating-point number into integer}} > >>> >>> + [2].x = 12.3, // expected-warning > >>> >>> {{implicit > >>> >>> conversion from 'double' to 'int' changes value from 12.3 to 12}} > >>> >>> 3.5 }; > >>> >>> > >>> >>> // TypesCompatibleExpr > >>> >>> > >>> >>> Modified: cfe/trunk/test/Sema/array-init.c > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/Sema/array-init.c (original) > >>> >>> +++ cfe/trunk/test/Sema/array-init.c Tue May 15 11:56:36 2012 > >>> >>> @@ -50,7 +50,7 @@ > >>> >>> > >>> >>> static long x2[3] = { 1.0, > >>> >>> "abc", // expected-warning{{incompatible > >>> >>> pointer > >>> >>> to integer conversion initializing 'long' with an expression of > type > >>> >>> 'char > >>> >>> [4]'}} > >>> >>> - 5.8 }; // expected-warning {{implicit > >>> >>> conversion > >>> >>> turns literal floating-point number into integer}} > >>> >>> + 5.8 }; // expected-warning {{implicit > >>> >>> conversion > >>> >>> from 'double' to 'long' changes value from 5.8 to 5}} > >>> >>> } > >>> >>> > >>> >>> void test() { > >>> >>> > >>> >>> Modified: cfe/trunk/test/Sema/knr-def-call.c > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/Sema/knr-def-call.c (original) > >>> >>> +++ cfe/trunk/test/Sema/knr-def-call.c Tue May 15 11:56:36 2012 > >>> >>> @@ -36,6 +36,6 @@ > >>> >>> } > >>> >>> > >>> >>> void use_proto() { > >>> >>> - proto(42.1); // expected-warning{{implicit conversion turns > >>> >>> literal > >>> >>> floating-point number into integer}} > >>> >>> - (&proto)(42.1); // expected-warning{{implicit conversion turns > >>> >>> literal > >>> >>> floating-point number into integer}} > >>> >>> + proto(42.1); // expected-warning{{implicit conversion from > >>> >>> 'double' to > >>> >>> 'int' changes value from 42.1 to 42}} > >>> >>> + (&proto)(42.1); // expected-warning{{implicit conversion from > >>> >>> 'double' > >>> >>> to 'int' changes value from 42.1 to 42}} > >>> >>> } > >>> >>> > >>> >>> Modified: cfe/trunk/test/SemaCXX/bool.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bool.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/SemaCXX/bool.cpp (original) > >>> >>> +++ cfe/trunk/test/SemaCXX/bool.cpp Tue May 15 11:56:36 2012 > >>> >>> @@ -1,4 +1,4 @@ > >>> >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s > >>> >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion > %s > >>> >>> > >>> >>> // Bool literals can be enum values. > >>> >>> enum { > >>> >>> > >>> >>> Modified: cfe/trunk/test/SemaCXX/conversion.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/SemaCXX/conversion.cpp (original) > >>> >>> +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 11:56:36 2012 > >>> >>> @@ -65,7 +65,7 @@ > >>> >>> int c = ((((NULL)))); // expected-warning {{implicit conversion > of > >>> >>> NULL > >>> >>> constant to 'int'}} > >>> >>> int d; > >>> >>> d = ((((NULL)))); // expected-warning {{implicit conversion of > NULL > >>> >>> constant to 'int'}} > >>> >>> - bool bl = NULL; // FIXME: this should warn but we currently > >>> >>> suppress a > >>> >>> bunch of conversion-to-bool warnings including this one > >>> >>> + bool bl = NULL; // expected-warning {{implicit conversion of > NULL > >>> >>> constant to 'bool'}} > >>> >>> char ch = NULL; // expected-warning {{implicit conversion of NULL > >>> >>> constant to 'char'}} > >>> >>> unsigned char uch = NULL; // expected-warning {{implicit > conversion > >>> >>> of > >>> >>> NULL constant to 'unsigned char'}} > >>> >>> short sh = NULL; // expected-warning {{implicit conversion of > NULL > >>> >>> constant to 'short'}} > >>> >>> @@ -104,3 +104,12 @@ > >>> >>> tmpl2(); > >>> >>> } > >>> >>> } > >>> >>> + > >>> >>> +namespace test5 { > >>> >>> + template > >>> >>> + void func() { > >>> >>> + bool b = I; > >>> >>> + } > >>> >>> + > >>> >>> + template void func<3>(); > >>> >>> +} > >>> >>> > >>> >>> Modified: cfe/trunk/test/SemaCXX/expressions.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/expressions.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/SemaCXX/expressions.cpp (original) > >>> >>> +++ cfe/trunk/test/SemaCXX/expressions.cpp Tue May 15 11:56:36 2012 > >>> >>> @@ -1,4 +1,4 @@ > >>> >>> -// RUN: %clang_cc1 -fsyntax-only -verify %s > >>> >>> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion > %s > >>> >>> > >>> >>> void choice(int); > >>> >>> int choice(bool); > >>> >>> > >>> >>> Modified: cfe/trunk/test/SemaCXX/overload-call.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) > >>> >>> +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue May 15 11:56:36 > 2012 > >>> >>> @@ -233,7 +233,7 @@ > >>> >>> > >>> >>> void intref_test() { > >>> >>> float* ir1 = intref(5); > >>> >>> - float* ir2 = intref(5.5); // expected-warning{{implicit > conversion > >>> >>> turns literal floating-point number into integer}} > >>> >>> + float* ir2 = intref(5.5); // expected-warning{{implicit > conversion > >>> >>> from > >>> >>> 'double' to 'int' changes value from 5.5 to 5}} > >>> >>> } > >>> >>> > >>> >>> void derived5(C&); // expected-note{{candidate function not > viable: > >>> >>> cannot bind base class object of type 'A' to derived class > reference > >>> >>> 'C &' > >>> >>> for 1st argument}} > >>> >>> > >>> >>> Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) > >>> >>> +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Tue May 15 > >>> >>> 11:56:36 > >>> >>> 2012 > >>> >>> @@ -5,29 +5,29 @@ > >>> >>> // Warn when a literal float or double is assigned or bound to an > >>> >>> integer. > >>> >>> void test0() { > >>> >>> // Float > >>> >>> - int y0 = 1.2222F; // expected-warning {{implicit conversion > turns > >>> >>> literal floating-point number into integer}} > >>> >>> - int y1 = (1.2222F); // expected-warning {{implicit conversion > >>> >>> turns > >>> >>> literal floating-point number into integer}} > >>> >>> - int y2 = (((1.2222F))); // expected-warning {{implicit > conversion > >>> >>> turns > >>> >>> literal floating-point number into integer}} > >>> >>> - int y3 = 12E-1F; // expected-warning {{implicit conversion turns > >>> >>> literal floating-point number into integer}} > >>> >>> - int y4 = 1.23E1F; // expected-warning {{implicit conversion > turns > >>> >>> literal floating-point number into integer}} > >>> >>> + int y0 = 1.2222F; // expected-warning {{implicit conversion from > >>> >>> 'float' to 'int' changes value from 1.2222 to 1}} > >>> >>> + int y1 = (1.2222F); // expected-warning {{implicit conversion > from > >>> >>> 'float' to 'int' changes value from 1.2222 to 1}} > >>> >>> + int y2 = (((1.2222F))); // expected-warning {{implicit > conversion > >>> >>> from > >>> >>> 'float' to 'int' changes value from 1.2222 to 1}} > >>> >>> + int y3 = 12E-1F; // expected-warning {{implicit conversion from > >>> >>> 'float' > >>> >>> to 'int' changes value from 1.2 to 1}} > >>> >>> + int y4 = 1.23E1F; // expected-warning {{implicit conversion from > >>> >>> 'float' to 'int' changes value from 12.3 to 12}} > >>> >>> // Double > >>> >>> - int y5 = 1.2222; // expected-warning {{implicit conversion turns > >>> >>> literal floating-point number into integer}} > >>> >>> - int y6 = 12E-1; // expected-warning {{implicit conversion turns > >>> >>> literal > >>> >>> floating-point number into integer}} > >>> >>> - int y7 = 1.23E1; // expected-warning {{implicit conversion turns > >>> >>> literal floating-point number into integer}} > >>> >>> - int y8 = (1.23E1); // expected-warning {{implicit conversion > turns > >>> >>> literal floating-point number into integer}} > >>> >>> + int y5 = 1.2222; // expected-warning {{implicit conversion from > >>> >>> 'double' to 'int' changes value from 1.2222 to 1}} > >>> >>> + int y6 = 12E-1; // expected-warning {{implicit conversion from > >>> >>> 'double' > >>> >>> to 'int' changes value from 1.2 to 1}} > >>> >>> + int y7 = 1.23E1; // expected-warning {{implicit conversion from > >>> >>> 'double' to 'int' changes value from 12.3 to 12}} > >>> >>> + int y8 = (1.23E1); // expected-warning {{implicit conversion > from > >>> >>> 'double' to 'int' changes value from 12.3 to 12}} > >>> >>> > >>> >>> // Test assignment to an existing variable. > >>> >>> - y8 = 2.22F; // expected-warning {{implicit conversion turns > >>> >>> literal > >>> >>> floating-point number into integer}} > >>> >>> + y8 = 2.22F; // expected-warning {{implicit conversion from > 'float' > >>> >>> to > >>> >>> 'int' changes value from 2.22 to 2}} > >>> >>> > >>> >>> // Test direct initialization. > >>> >>> - int y9(1.23F); // expected-warning {{implicit conversion turns > >>> >>> literal > >>> >>> floating-point number into integer}} > >>> >>> + int y9(1.23F); // expected-warning {{implicit conversion from > >>> >>> 'float' > >>> >>> to 'int' changes value from 1.23 to 1}} > >>> >>> > >>> >>> // Test passing a literal floating-point value to a function that > >>> >>> takes > >>> >>> an integer. > >>> >>> - foo(1.2F); // expected-warning {{implicit conversion turns > literal > >>> >>> floating-point number into integer}} > >>> >>> + foo(1.2F); // expected-warning {{implicit conversion from > 'float' > >>> >>> to > >>> >>> 'int' changes value from 1.2 to 1}} > >>> >>> > >>> >>> - int y10 = -1.2F; // expected-warning {{implicit conversion > turns > >>> >>> literal floating-point number into integer}} > >>> >>> + int y10 = -1.2F; // expected-warning {{implicit conversion from > >>> >>> 'float' to 'int' changes value from 1.2 to 1}} > >>> >>> > >>> >>> - // -Wconversion-literal does NOT catch const values. > >>> >>> + // -Wliteral-conversion does NOT catch const values. > >>> >>> // (-Wconversion DOES catch them.) > >>> >>> static const float sales_tax_rate = .095F; > >>> >>> int z = sales_tax_rate; > >>> >>> > >>> >>> Modified: > cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > >>> >>> URL: > >>> >>> > >>> >>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=156826&r1=156825&r2=156826&view=diff > >>> >>> > >>> >>> > >>> >>> > ============================================================================== > >>> >>> --- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp > >>> >>> (original) > >>> >>> +++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Tue > >>> >>> May 15 > >>> >>> 11:56:36 2012 > >>> >>> @@ -60,7 +60,7 @@ > >>> >>> > >>> >>> void test_X1(X1 x1) { > >>> >>> float *fp1 = x1.f1<>(17); > >>> >>> - float *fp2 = x1.f1(3.14); // expected-warning {{implicit > >>> >>> conversion turns literal floating-point number into integer}} > >>> >>> + float *fp2 = x1.f1(3.14); // expected-warning {{implicit > >>> >>> conversion from 'double' to 'int' changes value from 3.14 to 3}} > >>> >>> int *ip1 = x1.f1(17); > >>> >>> float *ip2 = x1.f1(3.14); > >>> >>> > >>> >>> > >>> >>> > >>> >>> _______________________________________________ > >>> >>> cfe-commits mailing list > >>> >>> cfe-commits at cs.uiuc.edu > >>> >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > >>> >> > >>> >> > >> > >> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120515/306e4d8c/attachment-0001.html From dgregor at apple.com Wed May 16 00:32:58 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 05:32:58 -0000 Subject: [cfe-commits] r156904 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaStmt.cpp test/Sema/switch.c Message-ID: <20120516053258.9C4032A6C065@llvm.org> Author: dgregor Date: Wed May 16 00:32:58 2012 New Revision: 156904 URL: http://llvm.org/viewvc/llvm-project?rev=156904&view=rev Log: Produce more useful 'duplicate case' diagnostics. Fixes PR9243, from Terry Long! Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaStmt.cpp cfe/trunk/test/Sema/switch.c Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=156904&r1=156903&r2=156904&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May 16 00:32:58 2012 @@ -5229,6 +5229,8 @@ "overflow converting case value to switch condition type (%0 to %1)">, InGroup>; def err_duplicate_case : Error<"duplicate case value '%0'">; +def err_duplicate_case_differing_expr : Error< + "duplicate case value: '%0' and '%1' both equal '%2'">; def warn_case_empty_range : Warning<"empty case range specified">; def warn_missing_case_for_condition : Warning<"no case matching constant switch condition '%0'">; Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=156904&r1=156903&r2=156904&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed May 16 00:32:58 2012 @@ -768,8 +768,29 @@ if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) { // If we have a duplicate, report it. - Diag(CaseVals[i].second->getLHS()->getLocStart(), - diag::err_duplicate_case) << CaseVals[i].first.toString(10); + // First, determine if either case value has a name + StringRef PrevString, CurrString; + Expr *PrevCase = CaseVals[i-1].second->getLHS()->IgnoreParenCasts(); + Expr *CurrCase = CaseVals[i].second->getLHS()->IgnoreParenCasts(); + if (DeclRefExpr *DeclRef = dyn_cast(PrevCase)) { + PrevString = DeclRef->getDecl()->getName(); + } + if (DeclRefExpr *DeclRef = dyn_cast(CurrCase)) { + CurrString = DeclRef->getDecl()->getName(); + } + std::string CaseValStr = CaseVals[i-1].first.toString(10); + + if (PrevString == CurrString) + Diag(CaseVals[i].second->getLHS()->getLocStart(), + diag::err_duplicate_case) << + (PrevString.empty() ? CaseValStr : PrevString.str()); + else + Diag(CaseVals[i].second->getLHS()->getLocStart(), + diag::err_duplicate_case_differing_expr) << + (PrevString.empty() ? CaseValStr : PrevString.str()) << + (CurrString.empty() ? CaseValStr : CurrString.str()) << + CaseValStr; + Diag(CaseVals[i-1].second->getLHS()->getLocStart(), diag::note_duplicate_case_prev); // FIXME: We really want to remove the bogus case stmt from the Modified: cfe/trunk/test/Sema/switch.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/switch.c?rev=156904&r1=156903&r2=156904&view=diff ============================================================================== --- cfe/trunk/test/Sema/switch.c (original) +++ cfe/trunk/test/Sema/switch.c Wed May 16 00:32:58 2012 @@ -9,7 +9,7 @@ switch (X) { case 42: ; // expected-note {{previous case}} case 5000000000LL: // expected-warning {{overflow}} - case 42: // expected-error {{duplicate case value}} + case 42: // expected-error {{duplicate case value '42'}} ; case 100 ... 99: ; // expected-warning {{empty case range}} @@ -320,3 +320,32 @@ break; } } + +// PR9243 +#define TEST19MACRO 5 +void test19(int i) { + enum { + kTest19Enum1 = 7, + kTest19Enum2 = 7 + }; + const int a = 3; + switch (i) { + case 5: // expected-note {{previous case}} + case TEST19MACRO: // expected-error {{duplicate case value '5'}} + + case 7: // expected-note {{previous case}} + case kTest19Enum1: // expected-error {{duplicate case value: '7' and 'kTest19Enum1' both equal '7'}} \ + // expected-note {{previous case}} + case kTest19Enum1: // expected-error {{duplicate case value 'kTest19Enum1'}} \ + // expected-note {{previous case}} + case kTest19Enum2: // expected-error {{duplicate case value: 'kTest19Enum1' and 'kTest19Enum2' both equal '7'}} \ + // expected-note {{previous case}} + case (int)kTest19Enum2: //expected-error {{duplicate case value 'kTest19Enum2'}} + + case 3: // expected-note {{previous case}} + case a: // expected-error {{duplicate case value: '3' and 'a' both equal '3'}} \ + // expected-note {{previous case}} + case a: // expected-error {{duplicate case value 'a'}} + break; + } +} From dgregor at apple.com Wed May 16 00:36:06 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 15 May 2012 22:36:06 -0700 Subject: [cfe-commits] [PATCH] more useful 'duplicate case' diagnostics In-Reply-To: <6BEC7EB8-4287-432C-BE37-910310ABB544@me.com> References: <71F9C9BF-830D-4ADC-A751-0A9E4FCA9225@apple.com> <30EDA624-D310-4EEA-A69C-CB0DDDD23D3B@apple.com> <6BEC7EB8-4287-432C-BE37-910310ABB544@me.com> Message-ID: On May 15, 2012, at 4:50 PM, Terry Long wrote: > Attached is a new version of the patch for review. > I have removed all of the textual parsing and replaced it with code that finds a DeclRefExpr if it exists. > Unfortunately, this will catch a lot less cases, but at least it will catch some common ones and display them nicely. I like this patch a lot, and I think it's a good trade-off between complexity and functionality. Thank you! Committed as r156904. - Doug > -Terry > > > > Am 15.05.2012 um 18:41 schrieb Douglas Gregor: > >> >> On May 15, 2012, at 3:28 PM, Terry Long wrote: >> >>> >>> Am 15.05.2012 um 16:09 schrieb Douglas Gregor >>>> >>>> >>>> I'm a bit uncomfortable with the textual approach here. Why not analyze the expressions to check whether they are references to named declarations, and use those names in the diagnostic? It won't catch some macro cases, but it's far simpler. >>> >>> I was also uncomfortable with the textual approach, and in fact I first tried seeing if the case expression was a DeclRefExpr that refers to a valid NamedDecl. The problem I found with that approach was that it was not catching very many situations. Doing it that way only works for enums as far as I can tell. Macros, const ints, case overflows, casting, and more complicated expressions (like "case 2+2") are not DeclRefExprs, and I don't see any obvious way to grab the necessary diagnostic info without using a textual approach. >> >> >> You can look through implicit conversions (e.g., promotions) and parentheses to find the underlying expression. We'll get a DeclRefExpr for enumerators and variables that are constant ("const int x = 17;"), which are presumably the common cases. We won't get macros, of course, but we might not want to: it's probably more useful to show the value we get when the macro is expanded, and let the macro-substitution backtrace show how we got there. >> >> - Doug > From jediknil at belkadan.com Wed May 16 00:40:49 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 16 May 2012 01:40:49 -0400 Subject: [cfe-commits] r156904 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaStmt.cpp test/Sema/switch.c In-Reply-To: <20120516053258.9C4032A6C065@llvm.org> References: <20120516053258.9C4032A6C065@llvm.org> Message-ID: <77679894-69F4-44E3-95D5-4178F03E6651@belkadan.com> On May 16, 2012, at 1:32, Douglas Gregor wrote: > Modified: cfe/trunk/lib/Sema/SemaStmt.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=156904&r1=156903&r2=156904&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) > +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed May 16 00:32:58 2012 > @@ -768,8 +768,29 @@ > > if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) { > // If we have a duplicate, report it. > - Diag(CaseVals[i].second->getLHS()->getLocStart(), > - diag::err_duplicate_case) << CaseVals[i].first.toString(10); > + // First, determine if either case value has a name > + StringRef PrevString, CurrString; > + Expr *PrevCase = CaseVals[i-1].second->getLHS()->IgnoreParenCasts(); > + Expr *CurrCase = CaseVals[i].second->getLHS()->IgnoreParenCasts(); > + if (DeclRefExpr *DeclRef = dyn_cast(PrevCase)) { > + PrevString = DeclRef->getDecl()->getName(); > + } > + if (DeclRefExpr *DeclRef = dyn_cast(CurrCase)) { > + CurrString = DeclRef->getDecl()->getName(); > + } > + std::string CaseValStr = CaseVals[i-1].first.toString(10); Just saw this earlier today. APSInt has a toString method that takes a SmallString to print to (and defaults to base 10). SmallString<16> CaseValStr; CaseVals[i-1].first.toString(CaseValStr); Sorry for not getting that in before the commit! Jordy From kcc at google.com Wed May 16 01:36:00 2012 From: kcc at google.com (Kostya Serebryany) Date: Wed, 16 May 2012 06:36:00 -0000 Subject: [cfe-commits] r156906 - in /cfe/trunk: lib/Driver/Tools.cpp runtime/compiler-rt/Makefile Message-ID: <20120516063601.056AA2A6C065@llvm.org> Author: kcc Date: Wed May 16 01:36:00 2012 New Revision: 156906 URL: http://llvm.org/viewvc/llvm-project?rev=156906&view=rev Log: [tsan] add ThreadSanitizer linker flags on Linux and also copy the tsan-rt into the appropriate place at build time Modified: cfe/trunk/lib/Driver/Tools.cpp cfe/trunk/runtime/compiler-rt/Makefile Modified: cfe/trunk/lib/Driver/Tools.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=156906&r1=156905&r2=156906&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Tools.cpp (original) +++ cfe/trunk/lib/Driver/Tools.cpp Wed May 16 01:36:00 2012 @@ -1304,6 +1304,27 @@ } } +/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux). +/// This needs to be called before we add the C run-time (malloc, etc). +static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + if (!Args.hasFlag(options::OPT_fthread_sanitizer, + options::OPT_fno_thread_sanitizer, false)) + return; + if (!Args.hasArg(options::OPT_shared)) { + // LibTsan is "libclang_rt.tsan-.a" in the Linux library + // resource directory. + SmallString<128> LibTsan(TC.getDriver().ResourceDir); + llvm::sys::path::append(LibTsan, "lib", "linux", + (Twine("libclang_rt.tsan-") + + TC.getArchName() + ".a")); + CmdArgs.push_back(Args.MakeArgString(LibTsan)); + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-ldl"); + CmdArgs.push_back("-export-dynamic"); + } +} + static bool shouldUseFramePointer(const ArgList &Args, const llvm::Triple &Triple) { if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, @@ -5330,6 +5351,7 @@ // Call this before we add the C run-time. addAsanRTLinux(getToolChain(), Args, CmdArgs); + addTsanRTLinux(getToolChain(), Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { Modified: cfe/trunk/runtime/compiler-rt/Makefile URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/runtime/compiler-rt/Makefile?rev=156906&r1=156905&r2=156906&view=diff ============================================================================== --- cfe/trunk/runtime/compiler-rt/Makefile (original) +++ cfe/trunk/runtime/compiler-rt/Makefile Wed May 16 01:36:00 2012 @@ -90,7 +90,7 @@ endif ifeq ($(ARCH),x86_64) RuntimeLibrary.linux.Configs += \ - full-x86_64 profile-x86_64 asan-x86_64 + full-x86_64 profile-x86_64 asan-x86_64 tsan-x86_64 endif endif From kcc at google.com Wed May 16 01:43:23 2012 From: kcc at google.com (Kostya Serebryany) Date: Wed, 16 May 2012 10:43:23 +0400 Subject: [cfe-commits] ThreadSanitizer library and linker flags: please review In-Reply-To: References: Message-ID: Thanks! r156906. --kcc On Tue, May 15, 2012 at 9:03 PM, Chandler Carruth wrote: > Looks good. > > On Tue, May 15, 2012 at 9:38 AM, Kostya Serebryany wrote: > >> Hello, >> >> Please review the following patch which adds ThreadSanitizer (tsan) >> linker flags on Linux >> and also copies the tsan-rt into the appropriate place at build time. >> This mimics similar parts related to AddressSanitizer. >> >> http://codereview.appspot.com/6197087/ >> >> Thanks, >> >> --kcc >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120516/2d42dce1/attachment.html From chandlerc at google.com Wed May 16 03:02:39 2012 From: chandlerc at google.com (Chandler Carruth) Date: Wed, 16 May 2012 02:02:39 -0600 Subject: [cfe-commits] r156901 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/ParseStmt.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/conversion.cpp In-Reply-To: <20120516042005.1E5D62A6C065@llvm.org> References: <20120516042005.1E5D62A6C065@llvm.org> Message-ID: I have to ask: why do we bother warning about 'if (NULL) {...}'? It seems obvious and valid code, with no plausible typo or mistake in it. I don't understand why we need such heavy machinery merely to suppress this *iff* the NULL comes out of some other macro... But I've not followed all of the discussion, so perhaps I'm just missing context. On Tue, May 15, 2012 at 10:20 PM, David Blaikie wrote: > Author: dblaikie > Date: Tue May 15 23:20:04 2012 > New Revision: 156901 > > URL: http://llvm.org/viewvc/llvm-project?rev=156901&view=rev > Log: > Include the correct conversion context locations for condition expressions. > > This improves the conversion diagnostics (by correctly pointing to the loop > construct for conversions that may've been caused by the contextual > conversion > to bool caused by a condition expression) and also causes the NULL > conversion > warnings to be correctly suppressed when crossing a macro boundary in such > a > context. (previously, since the conversion context location was incorrect, > the > suppression could not be performed) > > Reported by Nico Weber as feedback to r156826. > > Modified: > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/Parse/ParseStmt.cpp > cfe/trunk/lib/Sema/SemaExprCXX.cpp > cfe/trunk/test/SemaCXX/conversion.cpp > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=156901&r1=156900&r2=156901&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Tue May 15 23:20:04 2012 > @@ -2402,7 +2402,10 @@ > }; > > FullExprArg MakeFullExpr(Expr *Arg) { > - return FullExprArg(ActOnFinishFullExpr(Arg).release()); > + return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); > + } > + FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { > + return FullExprArg(ActOnFinishFullExpr(Arg, CC).release()); > } > > StmtResult ActOnExprStmt(FullExprArg Expr); > @@ -3795,7 +3798,11 @@ > Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt); > ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr); > > - ExprResult ActOnFinishFullExpr(Expr *Expr); > + ExprResult ActOnFinishFullExpr(Expr *Expr) { > + return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() > + : SourceLocation()); > + } > + ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC); > StmtResult ActOnFinishFullStmt(Stmt *Stmt); > > // Marks SS invalid if it represents an incomplete type. > > Modified: cfe/trunk/lib/Parse/ParseStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=156901&r1=156900&r2=156901&view=diff > > ============================================================================== > --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) > +++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue May 15 23:20:04 2012 > @@ -948,7 +948,7 @@ > if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) > return StmtError(); > > - FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get())); > + FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc)); > > // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if > // there is no compound stmt. C90 does not have this clause. We only > do this > @@ -1174,7 +1174,7 @@ > if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) > return StmtError(); > > - FullExprArg FullCond(Actions.MakeFullExpr(Cond.get())); > + FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); > > // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if > // there is no compound stmt. C90 does not have this clause. We only > do this > @@ -1451,7 +1451,7 @@ > Second.get()); > } > SecondPartIsInvalid = Second.isInvalid(); > - SecondPart = Actions.MakeFullExpr(Second.get()); > + SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc); > } > > if (Tok.isNot(tok::semi)) { > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=156901&r1=156900&r2=156901&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue May 15 23:20:04 2012 > @@ -5310,7 +5310,7 @@ > return Owned(E); > } > > -ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { > +ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) { > ExprResult FullExpr = Owned(FE); > > if (!FullExpr.get()) > @@ -5336,7 +5336,7 @@ > if (FullExpr.isInvalid()) > return ExprError(); > > - CheckImplicitConversions(FullExpr.get(), FullExpr.get()->getExprLoc()); > + CheckImplicitConversions(FullExpr.get(), CC); > return MaybeCreateExprWithCleanups(FullExpr); > } > > > Modified: cfe/trunk/test/SemaCXX/conversion.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion.cpp?rev=156901&r1=156900&r2=156901&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/conversion.cpp (original) > +++ cfe/trunk/test/SemaCXX/conversion.cpp Tue May 15 23:20:04 2012 > @@ -81,6 +81,14 @@ > // and avoiding that helps us skip these cases: > #define NULL_COND(cond) ((cond) ? &a : NULL) > bool bl2 = NULL_COND(true); // don't warn on NULL conversion through the > conditional operator across a macro boundary > + if (NULL_COND(true)) > + ; > + while (NULL_COND(true)) > + ; > + for (; NULL_COND(true); ) > + ; > + do ; > + while(NULL_COND(true)); > } > > namespace test4 { > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120516/bc7af1b9/attachment-0001.html From kcc at google.com Wed May 16 03:14:36 2012 From: kcc at google.com (Kostya Serebryany) Date: Wed, 16 May 2012 08:14:36 -0000 Subject: [cfe-commits] r156910 - /cfe/trunk/docs/ThreadSanitizer.html Message-ID: <20120516081436.512AE2A6C065@llvm.org> Author: kcc Date: Wed May 16 03:14:36 2012 New Revision: 156910 URL: http://llvm.org/viewvc/llvm-project?rev=156910&view=rev Log: [tsan] first version of ThreadSanitizer docs Added: cfe/trunk/docs/ThreadSanitizer.html Added: cfe/trunk/docs/ThreadSanitizer.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ThreadSanitizer.html?rev=156910&view=auto ============================================================================== --- cfe/trunk/docs/ThreadSanitizer.html (added) +++ cfe/trunk/docs/ThreadSanitizer.html Wed May 16 03:14:36 2012 @@ -0,0 +1,125 @@ + + + + + + ThreadSanitizer, a race detector + + + + + + + + +

+ +

ThreadSanitizer

+ + +

Introduction

+ThreadSanitizer is a tool that detects data races.
+It consists of a compiler instrumentation module and a run-time library.
+Typical slowdown introduced by ThreadSanitizer is 5x-15x (TODO: these numbers are +aproximate so far). + +

How to build

+Follow the clang build instructions.
+Note: CMake build does not work yet. +See bug 12272. + +

Supported Platforms

+ThreadSanitizer is supported on Linux x86_64 (tested on Ubuntu 10.04).
+Support for MacOS 10.7 (64-bit only) is planed for late 2012.
+Support for 32-bit platforms is problematic and not yet planed. + + + +

Usage

+Simply compile your program with -faddress-sanitizer -fPIE and link it +with -faddress-sanitizer -pie.
+To get a reasonable performance add -O1 or higher.
+Use -g to get file names and line numbers in the warning messages.
+ +Example: +
+% cat projects/compiler-rt/lib/tsan/output_tests/tiny_race.c
+#include 
+int Global;
+void *Thread1(void *x) {
+  Global = 42;
+  return x;
+}
+int main() {
+  pthread_t t;
+  pthread_create(&t, NULL, Thread1, NULL);
+  Global = 43;
+  pthread_join(t, NULL);
+  return Global;
+}
+
+ +
+% clang -fthread-sanitizer -g -O1 tiny_race.c -fPIE -pie
+
+ +If a bug is detected, the program will print an error message to stderr. +Currently, ThreadSanitizer symbolizes its output using an external +addr2line +process (this will be fixed in future). +
+% TSAN_OPTIONS=strip_path_prefix=`pwd`/  # Don't print full paths.
+% ./a.out 2> log
+% cat log
+WARNING: ThreadSanitizer: data race (pid=19219)
+  Write of size 4 at 0x7fcf47b21bc0 by thread 1:
+    #0 Thread1 tiny_race.c:4 (exe+0x00000000a360)
+  Previous write of size 4 at 0x7fcf47b21bc0 by main thread:
+    #0 main tiny_race.c:10 (exe+0x00000000a3b4)
+  Thread 1 (running) created at:
+    #0 pthread_create ??:0 (exe+0x00000000c790)
+    #1 main tiny_race.c:9 (exe+0x00000000a3a4)
+
+ + +

Limitations

+
    +
  • ThreadSanitizer uses more real memory than a native run. +At the default settings the memory overhead is 9x plus 9Mb per each thread. +Settings with 5x and 3x overhead (but less accurate analysis) are also available. +
  • ThreadSanitizer maps (but not reserves) a lot of virtual address space. +This means that tools like ulimit may not work as usually expected. +
  • Static linking is not supported. +
  • ThreadSanitizer requires -fPIE -pie +
+ + +

Current Status

+ThreadSanitizer is in alpha stage. +It is known to work on large C++ programs using pthreads, but we do not promise +anything (yet).
+C++11 threading is not yet supported. + +We are actively working on enhancing the tool -- stay tuned. +Any help, especially in the form of minimized standalone tests is more than welcome. + +

More Information

+http://code.google.com/p/thread-sanitizer. + + +
+ + From chandlerc at gmail.com Wed May 16 03:18:59 2012 From: chandlerc at gmail.com (Chandler Carruth) Date: Wed, 16 May 2012 08:18:59 -0000 Subject: [cfe-commits] r156911 - /cfe/trunk/www/get_started.html Message-ID: <20120516081859.2F98A2A6C065@llvm.org> Author: chandlerc Date: Wed May 16 03:18:58 2012 New Revision: 156911 URL: http://llvm.org/viewvc/llvm-project?rev=156911&view=rev Log: Clarify how libstdc++ and other bits of the system toolchain are found on Linux in the getting started documentation. Patch by Nathan Ridge. Modified: cfe/trunk/www/get_started.html Modified: cfe/trunk/www/get_started.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/get_started.html?rev=156911&r1=156910&r2=156911&view=diff ============================================================================== --- cfe/trunk/www/get_started.html (original) +++ cfe/trunk/www/get_started.html Wed May 16 03:18:58 2012 @@ -83,15 +83,12 @@
  • If you intend to work on Clang C++ support, you may need to tell it how - to find your C++ standard library headers. If Clang cannot find your - system libstdc++ headers, please follow these instructions: -
      -
    • 'gcc -v -x c++ /dev/null -fsyntax-only' to get the - path.
    • -
    • Look for the comment "FIXME: temporary hack: - hard-coded paths" in clang/lib/Frontend/InitHeaderSearch.cpp and - change the lines below to include that path.
    • -
    + to find your C++ standard library headers. In general, Clang will detect + the best version of libstdc++ headers available and use them - it will + look both for system installations of libstdc++ as well as installations + adjacent to Clang itself. If your configuration fits neither of these + scenarios, you can use the --with-gcc-toolchain configure option + to tell Clang where the gcc containing the desired libstdc++ is installed.
  • Try it out (assuming you add llvm/Debug+Asserts/bin to your path):
      From kcc at google.com Wed May 16 03:19:13 2012 From: kcc at google.com (Kostya Serebryany) Date: Wed, 16 May 2012 08:19:13 -0000 Subject: [cfe-commits] r156912 - /cfe/trunk/docs/ThreadSanitizer.html Message-ID: <20120516081913.6355D2A6C065@llvm.org> Author: kcc Date: Wed May 16 03:19:13 2012 New Revision: 156912 URL: http://llvm.org/viewvc/llvm-project?rev=156912&view=rev Log: [tsan] fix typo Modified: cfe/trunk/docs/ThreadSanitizer.html Modified: cfe/trunk/docs/ThreadSanitizer.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ThreadSanitizer.html?rev=156912&r1=156911&r2=156912&view=diff ============================================================================== --- cfe/trunk/docs/ThreadSanitizer.html (original) +++ cfe/trunk/docs/ThreadSanitizer.html Wed May 16 03:19:13 2012 @@ -49,8 +49,8 @@

      Usage

      -Simply compile your program with -faddress-sanitizer -fPIE and link it -with -faddress-sanitizer -pie.
      +Simply compile your program with -fthread-sanitizer -fPIE and link it +with -fthread-sanitizer -pie.
      To get a reasonable performance add -O1 or higher.
      Use -g to get file names and line numbers in the warning messages.
      From klimek at google.com Wed May 16 04:12:07 2012 From: klimek at google.com (Manuel Klimek) Date: Wed, 16 May 2012 11:12:07 +0200 Subject: [cfe-commits] [PATCH 1/4] [clang.py] Store reference to TranslationUnit in Cursor and Type In-Reply-To: References: <4FB07FFA.5000702@gmail.com> Message-ID: On Tue, May 15, 2012 at 11:54 PM, Gregory Szorc wrote: > On Tue, May 15, 2012 at 12:55 PM, Manuel Klimek wrote: >> On Tue, May 15, 2012 at 9:52 PM, Gregory Szorc wrote: >>> On Tue, May 15, 2012 at 12:45 PM, Manuel Klimek wrote: >>>> On Tue, May 15, 2012 at 9:40 PM, Gregory Szorc wrote: >>>>> On Tue, May 15, 2012 at 12:31 PM, Manuel Klimek wrote: >>>>>> On Mon, May 14, 2012 at 10:15 AM, Manuel Klimek wrote: >>>>>>> On Mon, May 14, 2012 at 5:46 AM, Gregory Szorc >>>>>>> wrote: >>>>>>>> >>>>>>>> On 5/13/12 1:00 AM, Manuel Klimek wrote: >>>>>>>>> >>>>>>>>> + ? ?@property >>>>>>>>> + ? ?def translation_unit(self): >>>>>>>>> + ? ? ? ?"""Returns the TranslationUnit to which this Cursor belongs.""" >>>>>>>>> + ? ? ? ?return getattr(self, '_tu', None) >>>>>>>>> >>>>>>>>> What's the reason for the default value? Do we expect that people create >>>>>>>>> cursers via the lowlevel calls? Why would just return tu_ not work? >>>>>>>> >>>>>>>> Just defensive programming. If you return self._tu, that may raise an >>>>>>>> AttributeError if _tu is not set. Theoretically, the API should ensure that >>>>>>>> a TU is defined on all Cursor instances, so maybe an AttributeError would be >>>>>>>> acceptable. >>>>>>> >>>>>>> >>>>>>> I'd prefer that - to me defensive programming means to: >>>>>>> 1. never crash for invalid user input >>>>>>> 2. crash hard if there's an actual bug in the library >>>>>>> >>>>>>> If the cursor should never be generated by a user (-> the contract of the >>>>>>> library is to not break that), I think we should use _tu and have the >>>>>>> AttributeError thrown if it's not there. Or I'm also fine with putting in an >>>>>>> assert that checks that the attribute is there and delivers a nicer error in >>>>>>> case it's missing. >>>>>>> >>>>>>>>> >>>>>>>>> + ? ? ? ?# Store a reference to the TU in the Python object so it won't >>>>>>>>> get GC'd >>>>>>>>> + ? ? ? ?# before the Cursor. >>>>>>>>> + ? ? ? ?tu = None >>>>>>>>> + ? ? ? ?for arg in args: >>>>>>>>> + ? ? ? ? ? ?if isinstance(arg, TranslationUnit): >>>>>>>>> + ? ? ? ? ? ? ? ?tu = arg >>>>>>>>> + ? ? ? ? ? ? ? ?break >>>>>>>>> + >>>>>>>>> + ? ? ? ? ? ?if hasattr(arg, 'translation_unit'): >>>>>>>>> + ? ? ? ? ? ? ? ?tu = arg.translation_unit >>>>>>>>> + ? ? ? ? ? ? ? ?break >>>>>>>>> + >>>>>>>>> + ? ? ? ?assert tu is not None >>>>>>>>> + >>>>>>>>> + ? ? ? ?res._tu = tu >>>>>>>>> >>>>>>>>> That seems - odd. I can't find docs what from_result is supposed to do, >>>>>>>>> or what "args" are provided. But having to search through them for a TU >>>>>>>>> seems wrong - shouldn't they all have a TU? >>>>>>>> >>>>>>>> from_result is the errcheck function for the ctypes functions that return >>>>>>>> a Cursor. The 3rd argument to an errcheck function are the original >>>>>>>> arguments passed into the called function. ?For many of the functions, the >>>>>>>> original argument is a Cursor. However, clang_getTypeDeclaration takes a >>>>>>>> Type and clang_getTranslationUnitCursor receives a TranslationUnit. >>>>>>>> >>>>>>>> It is true that all of the functions today receive a single argument, so >>>>>>>> the iteration isn't required. However, that may change with the addition of >>>>>>>> new APIs in the future (this is how I coded it in my nearly feature-complete >>>>>>>> branch, so I'm guessing it is actually required from a future patch). >>>>>>> >>>>>>> >>>>>>> The question is: don't we just want to assert that all of those have a TU >>>>>>> (or are a TU)? >>>>>> >>>>>> ^ this question is still open I think... >>>>> >>>>> I don't think it is. Both modified from_result functions now assert if >>>>> a TU could not be found. >>>>> >>>>> Or, are you asking for something more? In the future, every live >>>>> object will likely hold a reference to a TU. We aren't there quite >>>>> yet. But, this patch is a step in the right direction. >>>> >>>> Ah, ok, that was my question - why not every object has a TU and we >>>> can assert *for every object* that it has a TU. If that's a follow-up >>>> step, then LGTM. >>> >>> Well, in the case of from_result (or any errcheck function), not every >>> argument to the original function may have a TU attached. e.g. integer >>> arguments. >> >> So that means we cannot even be sure that we'll always find a TU? >> Still trying to understand from_result better. > > Don't feel bad. I was completely lost the first time I encountered > these as well. > > The various from_result functions are registered as 'errcheck' > functions for ctypes-registered functions. The function referenced by > the 'errcheck' parameter of a ctypes function (if defined) is called > by ctypes when the C function call has returned but before the result > is passed to the original caller. In addition, the return value from > the errcheck function is what is actually handed to the original > caller. > > The errcheck function receives 3 arguments: the result from the C > function call, a reference to the called function, and a tuple of > arguments passed into the C function. > > Think of errcheck functions as hooks that allow you to perform > additional validation and to modify the result of a low-level C > function call. It is perfectly valid for them to raise an exception if > the result is not what's expected, convert the C return value to > something else (by not returning the first argument as-is), or perform > modifications to the value returned from the C function call. If you > wanted, you could even use these to aggregate "out" arguments from > function calls into the return value. > > For example, for the function clang_getArgType(), the ctype function > reference has: > > .argtypes = [Type, c_uint] > .restype = Type > .errcheck = Type.from_result > > When you call clang_getArgType(), ctypes will do some magic to convert > the supplied arguments to the required types. When the C function has > returned, it will invoke Type.from_result() with a Type instance, the > ctype function instance, and a 2-tuple of (Type, c_uint). > > Honestly, we should probably have different errcheck functions for > each function prototype. Then, we could make stronger assertions on > the arguments. We cheat a little bit and use the same errcheck > functions on each class. It does work. > > Does that help explain things? Yes, thanks. I'm not sure the answer to my question is hidden in there: If the arguments don't have a TU, but we need the result to have a TU, we're basically screwed, right? So wouldn't it make sense to make everything that depends on the TU "living" to be created by calls into the TU? I'm probably still missing something here... ;) Cheers, /Manuel From benny.kra at googlemail.com Wed May 16 07:19:08 2012 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Wed, 16 May 2012 12:19:08 -0000 Subject: [cfe-commits] r156914 - /cfe/trunk/lib/Sema/SemaDeclAttr.cpp Message-ID: <20120516121908.8F9722A6C065@llvm.org> Author: d0k Date: Wed May 16 07:19:08 2012 New Revision: 156914 URL: http://llvm.org/viewvc/llvm-project?rev=156914&view=rev Log: Factor sema for attributes unavailable and deprecated into a common function. No functionality change. Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=156914&r1=156913&r2=156914&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed May 16 07:19:08 2012 @@ -1642,47 +1642,28 @@ priority)); } -static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) { +template +static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr, + const char *Name) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } - - // Handle the case where deprecated attribute has a text message. + + // Handle the case where the attribute has a text message. StringRef Str; if (NumArgs == 1) { StringLiteral *SE = dyn_cast(Attr.getArg(0)); if (!SE) { S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) - << "deprecated"; + << Name; return; } Str = SE->getString(); } - D->addAttr(::new (S.Context) DeprecatedAttr(Attr.getRange(), S.Context, Str)); -} - -static void handleUnavailableAttr(Sema &S, Decl *D, const AttributeList &Attr) { - unsigned NumArgs = Attr.getNumArgs(); - if (NumArgs > 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; - return; - } - - // Handle the case where unavailable attribute has a text message. - StringRef Str; - if (NumArgs == 1) { - StringLiteral *SE = dyn_cast(Attr.getArg(0)); - if (!SE) { - S.Diag(Attr.getArg(0)->getLocStart(), - diag::err_attribute_not_string) << "unavailable"; - return; - } - Str = SE->getString(); - } - D->addAttr(::new (S.Context) UnavailableAttr(Attr.getRange(), S.Context, Str)); + D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str)); } static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, @@ -3849,7 +3830,9 @@ case AttributeList::AT_common: handleCommonAttr (S, D, Attr); break; case AttributeList::AT_constant: handleConstantAttr (S, D, Attr); break; case AttributeList::AT_constructor: handleConstructorAttr (S, D, Attr); break; - case AttributeList::AT_deprecated: handleDeprecatedAttr (S, D, Attr); break; + case AttributeList::AT_deprecated: + handleAttrWithMessage(S, D, Attr, "deprecated"); + break; case AttributeList::AT_destructor: handleDestructorAttr (S, D, Attr); break; case AttributeList::AT_ext_vector_type: handleExtVectorTypeAttr(S, scope, D, Attr); @@ -3915,7 +3898,9 @@ case AttributeList::AT_packed: handlePackedAttr (S, D, Attr); break; case AttributeList::AT_ms_struct: handleMsStructAttr (S, D, Attr); break; case AttributeList::AT_section: handleSectionAttr (S, D, Attr); break; - case AttributeList::AT_unavailable: handleUnavailableAttr (S, D, Attr); break; + case AttributeList::AT_unavailable: + handleAttrWithMessage(S, D, Attr, "unavailable"); + break; case AttributeList::AT_objc_arc_weak_reference_unavailable: handleArcWeakrefUnavailableAttr (S, D, Attr); break; From benny.kra at googlemail.com Wed May 16 07:44:25 2012 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Wed, 16 May 2012 12:44:25 -0000 Subject: [cfe-commits] r156916 - /cfe/trunk/lib/Sema/SemaDeclAttr.cpp Message-ID: <20120516124425.6691F2A6C065@llvm.org> Author: d0k Date: Wed May 16 07:44:25 2012 New Revision: 156916 URL: http://llvm.org/viewvc/llvm-project?rev=156916&view=rev Log: StringSwitchify. No functionality change. Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=156916&r1=156915&r2=156916&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed May 16 07:44:25 2012 @@ -2489,26 +2489,19 @@ /// getFormatAttrKind - Map from format attribute names to supported format /// types. static FormatAttrKind getFormatAttrKind(StringRef Format) { - // Check for formats that get handled specially. - if (Format == "NSString") - return NSStringFormat; - if (Format == "CFString") - return CFStringFormat; - if (Format == "strftime") - return StrftimeFormat; - - // Otherwise, check for supported formats. - if (Format == "scanf" || Format == "printf" || Format == "printf0" || - Format == "strfmon" || Format == "cmn_err" || Format == "vcmn_err" || - Format == "zcmn_err" || - Format == "kprintf") // OpenBSD. - return SupportedFormat; - - if (Format == "gcc_diag" || Format == "gcc_cdiag" || - Format == "gcc_cxxdiag" || Format == "gcc_tdiag") - return IgnoredFormat; - - return InvalidFormat; + return llvm::StringSwitch(Format) + // Check for formats that get handled specially. + .Case("NSString", NSStringFormat) + .Case("CFString", CFStringFormat) + .Case("strftime", StrftimeFormat) + + // Otherwise, check for supported formats. + .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) + .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) + .Case("kprintf", SupportedFormat) // OpenBSD. + + .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) + .Default(InvalidFormat); } /// Handle __attribute__((init_priority(priority))) attributes based on From jediknil at belkadan.com Wed May 16 11:01:11 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 16 May 2012 16:01:11 -0000 Subject: [cfe-commits] r156920 - in /cfe/trunk/test/Analysis: additive-folding-range-constraints.c additive-folding.cpp array-struct-region.c base-init.cpp bstring.c constant-folding.c initializer.cpp method-call.cpp ptr-arith.c string-fail.c string.c Message-ID: <20120516160111.6AA102A6C066@llvm.org> Author: jrose Date: Wed May 16 11:01:10 2012 New Revision: 156920 URL: http://llvm.org/viewvc/llvm-project?rev=156920&view=rev Log: [analyzer] Convert many existing tests to use clang_analyzer_eval. Modified: cfe/trunk/test/Analysis/additive-folding-range-constraints.c cfe/trunk/test/Analysis/additive-folding.cpp cfe/trunk/test/Analysis/array-struct-region.c cfe/trunk/test/Analysis/base-init.cpp cfe/trunk/test/Analysis/bstring.c cfe/trunk/test/Analysis/constant-folding.c cfe/trunk/test/Analysis/initializer.cpp cfe/trunk/test/Analysis/method-call.cpp cfe/trunk/test/Analysis/ptr-arith.c cfe/trunk/test/Analysis/string-fail.c cfe/trunk/test/Analysis/string.c Modified: cfe/trunk/test/Analysis/additive-folding-range-constraints.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/additive-folding-range-constraints.c?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/additive-folding-range-constraints.c (original) +++ cfe/trunk/test/Analysis/additive-folding-range-constraints.c Wed May 16 11:01:10 2012 @@ -1,10 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=range %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range %s + +void clang_analyzer_eval(int); -// These are used to trigger warnings. -typedef typeof(sizeof(int)) size_t; -void *malloc(size_t); -void free(void *); -#define NULL ((void*)0) #define UINT_MAX (~0U) #define INT_MAX (UINT_MAX & (UINT_MAX >> 1)) #define INT_MIN (-INT_MAX - 1) @@ -14,43 +11,27 @@ // solution range across an overflow boundary (Min for <, Max for >). // This corresponds to one set of branches in RangeConstraintManager. void smallAdjustmentGT (unsigned a) { - void *b = NULL; if (a+2 > 1) - b = malloc(1); - if (a == UINT_MAX-1 || a == UINT_MAX) - return; // no-warning - else if (a < UINT_MAX-1) - free(b); - return; // no-warning + clang_analyzer_eval(a < UINT_MAX-1); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a == UINT_MAX-1 || a == UINT_MAX); // expected-warning{{TRUE}} } void smallAdjustmentGE (unsigned a) { - void *b = NULL; if (a+2 >= 1) - b = malloc(1); - if (a == UINT_MAX-1) - return; // no-warning - else if (a < UINT_MAX-1 || a == UINT_MAX) - free(b); - return; // no-warning + clang_analyzer_eval(a < UINT_MAX-1 || a == UINT_MAX); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a == UINT_MAX-1); // expected-warning{{TRUE}} } void smallAdjustmentLT (unsigned a) { - void *b = NULL; if (a+1 < 2) - b = malloc(1); - if (a == 0 || a == UINT_MAX) - free(b); - return; // no-warning + clang_analyzer_eval(a == 0 || a == UINT_MAX); // expected-warning{{TRUE}} } void smallAdjustmentLE (unsigned a) { - void *b = NULL; if (a+1 <= 2) - b = malloc(1); - if (a == 0 || a == 1 || a == UINT_MAX) - free(b); - return; // no-warning + clang_analyzer_eval(a == 0 || a == 1 || a == UINT_MAX); // expected-warning{{TRUE}} } @@ -58,154 +39,102 @@ // comparison value over an overflow boundary (Min for <, Max for >). // This corresponds to one set of branches in RangeConstraintManager. void largeAdjustmentGT (unsigned a) { - void *b = NULL; if (a-2 > UINT_MAX-1) - b = malloc(1); - if (a == 1 || a == 0) - free(b); - else if (a > 1) - free(b); - return; // no-warning + clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a != 1); // expected-warning{{TRUE}} } void largeAdjustmentGE (unsigned a) { - void *b = NULL; if (a-2 >= UINT_MAX-1) - b = malloc(1); - if (a > 1) - return; // no-warning - else if (a == 1 || a == 0) - free(b); - return; // no-warning + clang_analyzer_eval(a == 1 || a == 0); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a > 1); // expected-warning{{TRUE}} } void largeAdjustmentLT (unsigned a) { - void *b = NULL; if (a+2 < 1) - b = malloc(1); - if (a == UINT_MAX-1 || a == UINT_MAX) - free(b); - else if (a < UINT_MAX-1) - return; // no-warning - return; // no-warning + clang_analyzer_eval(a == UINT_MAX-1); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a != UINT_MAX-1); // expected-warning{{TRUE}} } void largeAdjustmentLE (unsigned a) { - void *b = NULL; if (a+2 <= 1) - b = malloc(1); - if (a < UINT_MAX-1) - return; // no-warning - else if (a == UINT_MAX-1 || a == UINT_MAX) - free(b); - return; // no-warning + clang_analyzer_eval(a == UINT_MAX-1 || a == UINT_MAX); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a < UINT_MAX-1); // expected-warning{{TRUE}} } // Test the nine cases in RangeConstraintManager's pinning logic. +// For out-of-range tautologies, it may be the negation that actually +// triggers the case in question. void mixedComparisons1(signed char a) { // Case 1: The range is entirely below the symbol's range. int min = INT_MIN; - if ((a - 2) < (min + 5LL)) - return; // expected-warning{{never executed}} + clang_analyzer_eval((a - 2) >= (min + 5LL)); // expected-warning{{TRUE}} - if (a == 0) - return; // no-warning - if (a == 0x7F) - return; // no-warning - if (a == -0x80) - return; // no-warning - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}} } void mixedComparisons2(signed char a) { // Case 2: Only the lower end of the range is outside. + clang_analyzer_eval((a - 5) < (-0x81LL)); // expected-warning{{UNKNOWN}} + if ((a - 5) < (-0x81LL)) { - if (a == 0) - return; // expected-warning{{never executed}} - if (a == 0x7F) - return; // expected-warning{{never executed}} - if (a == -0x80) - return; // no-warning - return; // no-warning - } else { - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{FALSE}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{FALSE}} + clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}} } } void mixedComparisons3(signed char a) { // Case 3: The entire symbol range is covered. - if ((a - 0x200) < -0x100LL) { - if (a == 0) - return; // no-warning - if (a == 0x7F) - return; // no-warning - if (a == -0x80) - return; // no-warning - return; // no-warning - } else { - return; // expected-warning{{never executed}} - } + clang_analyzer_eval((a - 0x200) < -0x100LL); // expected-warning{{TRUE}} + + clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}} } void mixedComparisons4(signed char a) { // Case 4: The range wraps around, but the lower wrap is out-of-range. + clang_analyzer_eval((a - 5) > 0LL); // expected-warning{{UNKNOWN}} + if ((a - 5) > 0LL) { - if (a == 0) - return; // expected-warning{{never executed}} - if (a == 0x7F) - return; // no-warning - if (a == -0x80) - return; // expected-warning{{never executed}} - return; // no-warning - } else { - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{FALSE}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == -0x80); // expected-warning{{FALSE}} } } void mixedComparisons5(signed char a) { - // Case 5a: The range is inside and does not wrap. - if ((a + 5) == 0LL) { - if (a == 0) - return; // expected-warning{{never executed}} - if (a == 0x7F) - return; // expected-warning{{never executed}} - if (a == -0x80) - return; // expected-warning{{never executed}} - return; // no-warning - } else { - return; // no-warning - } -} + // Case 5: The range is inside and may or may not wrap. + clang_analyzer_eval((a + 5) == 0LL); // expected-warning{{UNKNOWN}} -void mixedComparisons5Wrap(signed char a) { - // Case 5b: The range is inside and does wrap. - if ((a + 5) != 0LL) { - if (a == 0) - return; // no-warning - if (a == 0x7F) - return; // no-warning - if (a == -0x80) - return; // no-warning - return; // no-warning - } else { - return; // no-warning + if ((a + 5) == 0LL) { + clang_analyzer_eval(a == 0); // expected-warning{{FALSE}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{FALSE}} + clang_analyzer_eval(a == -0x80); // expected-warning{{FALSE}} + } else { + clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}} } } void mixedComparisons6(signed char a) { // Case 6: Only the upper end of the range is outside. + clang_analyzer_eval((a + 5) > 0x81LL); // expected-warning{{UNKNOWN}} + if ((a + 5) > 0x81LL) { - if (a == 0) - return; // expected-warning{{never executed}} - if (a == 0x7F) - return; // no-warning - if (a == -0x80) - return; // expected-warning{{never executed}} - return; // no-warning - } else { - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{FALSE}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == -0x80); // expected-warning{{FALSE}} } } @@ -213,30 +142,21 @@ // Case 7: The range wraps around but is entirely outside the symbol's range. int min = INT_MIN; - if ((a + 2) < (min + 5LL)) - return; // expected-warning{{never executed}} + clang_analyzer_eval((a + 2) >= (min + 5LL)); // expected-warning{{TRUE}} - if (a == 0) - return; // no-warning - if (a == 0x7F) - return; // no-warning - if (a == -0x80) - return; // no-warning - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}} } void mixedComparisons8(signed char a) { // Case 8: The range wraps, but the upper wrap is out of range. + clang_analyzer_eval((a + 5) < 0LL); // expected-warning{{UNKNOWN}} + if ((a + 5) < 0LL) { - if (a == 0) - return; // expected-warning{{never executed}} - if (a == 0x7F) - return; // expected-warning{{never executed}} - if (a == -0x80) - return; // no-warning - return; // no-warning - } else { - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{FALSE}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{FALSE}} + clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}} } } @@ -244,14 +164,9 @@ // Case 9: The range is entirely above the symbol's range. int max = INT_MAX; - if ((a + 2) > (max - 5LL)) - return; // expected-warning{{never executed}} + clang_analyzer_eval((a + 2) <= (max - 5LL)); // expected-warning{{TRUE}} - if (a == 0) - return; // no-warning - if (a == 0x7F) - return; // no-warning - if (a == -0x80) - return; // no-warning - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}} } Modified: cfe/trunk/test/Analysis/additive-folding.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/additive-folding.cpp?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/additive-folding.cpp (original) +++ cfe/trunk/test/Analysis/additive-folding.cpp Wed May 16 11:01:10 2012 @@ -1,11 +1,8 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=basic %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=range %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=basic -Wno-tautological-compare %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range -Wno-tautological-compare %s + +void clang_analyzer_eval(bool); -// These are used to trigger warnings. -typedef typeof(sizeof(int)) size_t; -void *malloc(size_t); -void free(void *); -#define NULL ((void*)0) #define UINT_MAX (~0U) #define INT_MAX (UINT_MAX & (UINT_MAX >> 1)) #define INT_MIN (-INT_MAX - 1) @@ -18,10 +15,7 @@ int b = a + 1; --b; - void *buf = malloc(1); - if (a != 0 && b == 0) - return; // expected-warning{{never executed}} - free(buf); + clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}} } void oneLongExpression (int a) { @@ -29,26 +23,17 @@ // the first term is on the left. int b = 15 + a + 15 - 10 - 20; - void *buf = malloc(1); - if (a != 0 && b == 0) - return; // expected-warning{{never executed}} - free(buf); + clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}} } void mixedTypes (int a) { - void *buf = malloc(1); - // Different additive types should not cause crashes when constant-folding. // This is part of PR7406. int b = a + 1LL; - if (a != 0 && (b-1) == 0) // not crash - return; // expected-warning{{never executed}} + clang_analyzer_eval(a != 0 && (b-1) == 0); // not crash, expected-warning{{FALSE}} int c = a + 1U; - if (a != 0 && (c-1) == 0) // not crash - return; // expected-warning{{never executed}} - - free(buf); + clang_analyzer_eval(a != 0 && (c-1) == 0); // not crash, expected-warning{{FALSE}} } //--------------- @@ -57,206 +42,101 @@ // Equality and inequality only void eq_ne (unsigned a) { - void *b = NULL; - if (a == UINT_MAX) - b = malloc(1); - if (a+1 != 0) - return; // no-warning - if (a-1 != UINT_MAX-1) - return; // no-warning - free(b); -} - -void ne_eq (unsigned a) { - void *b = NULL; - if (a != UINT_MAX) - b = malloc(1); - if (a+1 == 0) - return; // no-warning - if (a-1 == UINT_MAX-1) - return; // no-warning - free(b); + if (a == UINT_MAX) { + clang_analyzer_eval(a+1 == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(a-1 == UINT_MAX-1); // expected-warning{{TRUE}} + } else { + clang_analyzer_eval(a+1 != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(a-1 != UINT_MAX-1); // expected-warning{{TRUE}} + } } // Mixed typed inequalities (part of PR7406) // These should not crash. void mixed_eq_ne (int a) { - void *b = NULL; - if (a == 1) - b = malloc(1); - if (a+1U != 2) - return; // no-warning - if (a-1U != 0) - return; // expected-warning{{never executed}} - free(b); -} - -void mixed_ne_eq (int a) { - void *b = NULL; - if (a != 1) - b = malloc(1); - if (a+1U == 2) - return; // no-warning - if (a-1U == 0) - return; // expected-warning{{never executed}} - free(b); + if (a == 1) { + clang_analyzer_eval(a+1U == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a-1U == 0); // expected-warning{{TRUE}} + } else { + clang_analyzer_eval(a+1U != 2); // expected-warning{{TRUE}} + clang_analyzer_eval(a-1U != 0); // expected-warning{{TRUE}} + } } // Simple order comparisons with no adjustment void baselineGT (unsigned a) { - void *b = NULL; if (a > 0) - b = malloc(1); - if (a == 0) - return; // no-warning - free(b); + clang_analyzer_eval(a != 0); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a == 0); // expected-warning{{TRUE}} } void baselineGE (unsigned a) { - void *b = NULL; if (a >= UINT_MAX) - b = malloc(1); - if (a == UINT_MAX) - free(b); - return; // no-warning + clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}} } void baselineLT (unsigned a) { - void *b = NULL; if (a < UINT_MAX) - b = malloc(1); - if (a == UINT_MAX) - return; // no-warning - free(b); + clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}} } void baselineLE (unsigned a) { - void *b = NULL; if (a <= 0) - b = malloc(1); - if (a == 0) - free(b); - return; // no-warning + clang_analyzer_eval(a == 0); // expected-warning{{TRUE}} + else + clang_analyzer_eval(a != 0); // expected-warning{{TRUE}} } // Adjustment gives each of these an extra solution! void adjustedGT (unsigned a) { - void *b = NULL; - if (a-1 > UINT_MAX-1) - b = malloc(1); - return; // expected-warning{{leak}} + clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}} } void adjustedGE (unsigned a) { - void *b = NULL; + clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}} + if (a-1 >= UINT_MAX-1) - b = malloc(1); - if (a == UINT_MAX) - free(b); - return; // expected-warning{{leak}} + clang_analyzer_eval(a == UINT_MAX); // expected-warning{{UNKNOWN}} } void adjustedLT (unsigned a) { - void *b = NULL; - if (a+1 < 1) - b = malloc(1); - return; // expected-warning{{leak}} + clang_analyzer_eval(a+1 < 1); // expected-warning{{UNKNOWN}} } void adjustedLE (unsigned a) { - void *b = NULL; + clang_analyzer_eval(a+1 <= 1); // expected-warning{{UNKNOWN}} + if (a+1 <= 1) - b = malloc(1); - if (a == 0) - free(b); - return; // expected-warning{{leak}} + clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}} } // Tautologies -void tautologyGT (unsigned a) { - void *b = malloc(1); - if (a > UINT_MAX) - return; // no-warning - free(b); -} - -void tautologyGE (unsigned a) { - void *b = malloc(1); - if (a >= 0) // expected-warning{{always true}} - free(b); - return; // no-warning -} - -void tautologyLT (unsigned a) { - void *b = malloc(1); - if (a < 0) // expected-warning{{always false}} - return; // expected-warning{{never executed}} - free(b); -} - -void tautologyLE (unsigned a) { - void *b = malloc(1); - if (a <= UINT_MAX) - free(b); - return; // no-warning +// The negative forms are exercised as well +// because clang_analyzer_eval tests both possibilities. +void tautologies(unsigned a) { + clang_analyzer_eval(a <= UINT_MAX); // expected-warning{{TRUE}} + clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}} } // Tautologies from outside the range of the symbol -void tautologyOutsideGT(unsigned char a) { - void *b = malloc(1); - if (a > 0x100) - return; // expected-warning{{never executed}} - if (a > -1) - free(b); - return; // no-warning -} - -void tautologyOutsideGE(unsigned char a) { - void *b = malloc(1); - if (a >= 0x100) - return; // expected-warning{{never executed}} - if (a >= -1) - free(b); - return; // no-warning -} - -void tautologyOutsideLT(unsigned char a) { - void *b = malloc(1); - if (a < -1) - return; // expected-warning{{never executed}} - if (a < 0x100) - free(b); - return; // no-warning -} - -void tautologyOutsideLE (unsigned char a) { - void *b = malloc(1); - if (a <= -1) - return; // expected-warning{{never executed}} - if (a <= 0x100) - free(b); - return; // no-warning -} - -void tautologyOutsideEQ(unsigned char a) { - if (a == 0x100) - malloc(1); // expected-warning{{never executed}} - if (a == -1) - malloc(1); // expected-warning{{never executed}} -} - -void tautologyOutsideNE(unsigned char a) { - void *sentinel = malloc(1); - if (a != 0x100) - free(sentinel); - - sentinel = malloc(1); - if (a != -1) - free(sentinel); +void tautologiesOutside(unsigned char a) { + clang_analyzer_eval(a <= 0x100); // expected-warning{{TRUE}} + clang_analyzer_eval(a < 0x100); // expected-warning{{TRUE}} + + clang_analyzer_eval(a != 0x100); // expected-warning{{TRUE}} + clang_analyzer_eval(a != -1); // expected-warning{{TRUE}} + + clang_analyzer_eval(a > -1); // expected-warning{{TRUE}} + clang_analyzer_eval(a >= -1); // expected-warning{{TRUE}} } @@ -267,64 +147,32 @@ int min = INT_MIN; int b = a + 1; - if (a == max && b != min) - return; // expected-warning{{never executed}} -} - -void mixedWraparoundGT(int a) { - int max = INT_MAX; - - if ((a + 2) > (max + 1LL)) - return; // expected-warning{{never executed}} + clang_analyzer_eval(a == max && b != min); // expected-warning{{FALSE}} } -void mixedWraparoundGE(int a) { +void mixedWraparoundLE_GT(int a) { int max = INT_MAX; int min = INT_MIN; - if ((a + 2) >= (max + 1LL)) - return; // expected-warning{{never executed}} - - void *sentinel = malloc(1); - if ((a - 2LL) >= min) - free(sentinel); - return; // expected-warning{{leak}} + clang_analyzer_eval((a + 2) <= (max + 1LL)); // expected-warning{{TRUE}} + clang_analyzer_eval((a - 2) > (min - 1LL)); // expected-warning{{TRUE}} + clang_analyzer_eval((a + 2LL) <= max); // expected-warning{{UNKNOWN}} } -void mixedWraparoundLT(int a) { - int min = INT_MIN; - - if ((a - 2) < (min - 1LL)) - return; // expected-warning{{never executed}} -} - -void mixedWraparoundLE(int a) { +void mixedWraparoundGE_LT(int a) { int max = INT_MAX; int min = INT_MIN; - if ((a - 2) <= (min - 1LL)) - return; // expected-warning{{never executed}} - - void *sentinel = malloc(1); - if ((a + 2LL) <= max) - free(sentinel); - return; // expected-warning{{leak}} + clang_analyzer_eval((a + 2) < (max + 1LL)); // expected-warning{{TRUE}} + clang_analyzer_eval((a - 2) >= (min - 1LL)); // expected-warning{{TRUE}} + clang_analyzer_eval((a - 2LL) >= min); // expected-warning{{UNKNOWN}} } -void mixedWraparoundEQ(int a) { +void mixedWraparoundEQ_NE(int a) { int max = INT_MAX; - if ((a + 2) == (max + 1LL)) - return; // expected-warning{{never executed}} -} - -void mixedWraparoundNE(int a) { - int max = INT_MAX; - - void *sentinel = malloc(1); - if ((a + 2) != (max + 1LL)) - free(sentinel); - return; // no-warning + clang_analyzer_eval((a + 2) != (max + 1LL)); // expected-warning{{TRUE}} + clang_analyzer_eval((a + 2LL) == (max + 1LL)); // expected-warning{{UNKNOWN}} } @@ -332,10 +180,9 @@ void mixedSignedness(int a, unsigned b) { int sMin = INT_MIN; unsigned uMin = INT_MIN; - if (a == sMin && a != uMin) - return; // expected-warning{{never executed}} - if (b == uMin && b != sMin) - return; // expected-warning{{never executed}} + + clang_analyzer_eval(a == sMin && a != uMin); // expected-warning{{FALSE}} + clang_analyzer_eval(b == uMin && b != sMin); // expected-warning{{FALSE}} } @@ -365,16 +212,12 @@ // turning the symbol into a ConcreteInt, rather than ExprEngine. // Test relational operators. - if ((local + 1) < 2) - malloc(1); // expected-warning{{never executed}} - if (2 > (local + 1)) - malloc(1); // expected-warning{{never executed}} + clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}} + clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}} // Test equality operators. - if ((local + 1) == 1) - malloc(1); // expected-warning{{never executed}} - if (1 == (local + 1)) - malloc(1); // expected-warning{{never executed}} + clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}} + clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}} } void PR12206_truncation(signed char x) { @@ -393,24 +236,19 @@ signed int value = 1 + (1 << 8); // Test relational operators. - if ((local + 1) >= value) - malloc(1); // expected-warning{{never executed}} - if (value <= (local + 1)) - malloc(1); // expected-warning{{never executed}} + clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}} + clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}} // Test equality operators. - if ((local + 1) == value) - malloc(1); // expected-warning{{never executed}} - if (value == (local + 1)) - malloc(1); // expected-warning{{never executed}} + clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}} + clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}} } void multiplicativeSanityTest(int x) { // At one point we were ignoring the *4 completely -- the constraint manager - // would see x < 8 and then declare the next part unreachable. + // would see x < 8 and then declare the assertion to be known false. if (x*4 < 8) return; - if (x == 3) - malloc(1); - return; // expected-warning{{leak}} + + clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}} } Modified: cfe/trunk/test/Analysis/array-struct-region.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct-region.c?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/array-struct-region.c (original) +++ cfe/trunk/test/Analysis/array-struct-region.c Wed May 16 11:01:10 2012 @@ -1,25 +1,21 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,experimental.deadcode.UnreachableCode -analyzer-store=region -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,experimental.deadcode.UnreachableCode -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify %s + +void clang_analyzer_eval(int); int string_literal_init() { char a[] = "abc"; char b[2] = "abc"; // expected-warning{{too long}} char c[5] = "abc"; - if (a[1] != 'b') - return 0; // expected-warning{{never executed}} - if (b[1] != 'b') - return 0; // expected-warning{{never executed}} - if (c[1] != 'b') - return 0; // expected-warning{{never executed}} - - if (a[3] != 0) - return 0; // expected-warning{{never executed}} - if (c[3] != 0) - return 0; // expected-warning{{never executed}} + clang_analyzer_eval(a[1] == 'b'); // expected-warning{{TRUE}} + clang_analyzer_eval(b[1] == 'b'); // expected-warning{{TRUE}} + clang_analyzer_eval(c[1] == 'b'); // expected-warning{{TRUE}} + + clang_analyzer_eval(a[3] == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(c[3] == 0); // expected-warning{{TRUE}} - if (c[4] != 0) - return 0; // expected-warning{{never executed}} + clang_analyzer_eval(c[4] == 0); // expected-warning{{TRUE}} return 42; } @@ -48,13 +44,16 @@ void struct_as_array() { - struct simple { int x; }; + struct simple { int x; int y; }; struct simple a; struct simple *p = &a; + p->x = 5; - if (!p[0].x) - return; // expected-warning{{never executed}} - if (p[0].x) - return; // no-warning + clang_analyzer_eval(a.x == 5); // expected-warning{{TRUE}} + clang_analyzer_eval(p[0].x == 5); // expected-warning{{TRUE}} + + p[0].y = 5; + clang_analyzer_eval(a.y == 5); // expected-warning{{TRUE}} + clang_analyzer_eval(p->y == 5); // expected-warning{{TRUE}} } Modified: cfe/trunk/test/Analysis/base-init.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/base-init.cpp?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/base-init.cpp (original) +++ cfe/trunk/test/Analysis/base-init.cpp Wed May 16 11:01:10 2012 @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -analyzer-inline-call -cfg-add-initializers -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -analyzer-ipa=inlining -cfg-add-initializers -verify %s // XFAIL: * +void clang_analyzer_eval(bool); + class A { int x; public: @@ -24,8 +26,5 @@ void f() { B b; - if (b.getx() != 0) { - int *p = 0; - *p = 0; // no-warning - } + clang_analyzer_eval(b.getx() == 0); // expected-warning{{TRUE}} } Modified: cfe/trunk/test/Analysis/bstring.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/bstring.c?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/bstring.c (original) +++ cfe/trunk/test/Analysis/bstring.c Wed May 16 11:01:10 2012 @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring.NullArg,experimental.unix.cstring.OutOfBounds,experimental.unix.cstring.BufferOverlap,experimental.unix.cstring.NotNullTerminated -analyzer-store=region -Wno-null-dereference -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s //===----------------------------------------------------------------------=== // Declarations @@ -26,6 +26,8 @@ typedef typeof(sizeof(int)) size_t; +void clang_analyzer_eval(int); + //===----------------------------------------------------------------------=== // memcpy() //===----------------------------------------------------------------------=== @@ -52,12 +54,11 @@ memcpy(dst, src, 4); // no-warning - if (memcpy(dst, src, 4) != dst) { - (void)*(char*)0; // no-warning - } + clang_analyzer_eval(memcpy(dst, src, 4) == dst); // expected-warning{{TRUE}} - if (dst[0] != 0) - (void)*(char*)0; // expected-warning{{null}} + // If we actually model the copy, we can make this known. + // The important thing for now is that the old value has been invalidated. + clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} } void memcpy1 () { @@ -138,14 +139,13 @@ void memcpy_unknown_size (size_t n) { char a[4], b[4] = {1}; - if (memcpy(a, b, n) != a) - (void)*(char*)0; // no-warning + clang_analyzer_eval(memcpy(a, b, n) == a); // expected-warning{{TRUE}} } void memcpy_unknown_size_warn (size_t n) { char a[4]; - if (memcpy(a, 0, n) != a) // expected-warning{{Null pointer argument in call to memory copy function}} - (void)*(char*)0; // no-warning + void *result = memcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}} + clang_analyzer_eval(result == a); // no-warning (above is fatal) } //===----------------------------------------------------------------------=== @@ -174,12 +174,11 @@ mempcpy(dst, src, 4); // no-warning - if (mempcpy(dst, src, 4) != &dst[4]) { - (void)*(char*)0; // no-warning - } + clang_analyzer_eval(mempcpy(dst, src, 4) == &dst[4]); // expected-warning{{TRUE}} - if (dst[0] != 0) - (void)*(char*)0; // expected-warning{{null}} + // If we actually model the copy, we can make this known. + // The important thing for now is that the old value has been invalidated. + clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} } void mempcpy1 () { @@ -260,8 +259,8 @@ void mempcpy_unknown_size_warn (size_t n) { char a[4]; - if (mempcpy(a, 0, n) != a) // expected-warning{{Null pointer argument in call to memory copy function}} - (void)*(char*)0; // no-warning + void *result = mempcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}} + clang_analyzer_eval(result == a); // no-warning (above is fatal) } void mempcpy_unknownable_size (char *src, float n) { @@ -295,12 +294,11 @@ memmove(dst, src, 4); // no-warning - if (memmove(dst, src, 4) != dst) { - (void)*(char*)0; // no-warning - } + clang_analyzer_eval(memmove(dst, src, 4) == dst); // expected-warning{{TRUE}} - if (dst[0] != 0) - (void)*(char*)0; // expected-warning{{null}} + // If we actually model the copy, we can make this known. + // The important thing for now is that the old value has been invalidated. + clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} } void memmove1 () { @@ -327,7 +325,7 @@ // __builtin_bcmp is not defined with const in Builtins.def. int bcmp(/*const*/ void *s1, /*const*/ void *s2, size_t n); #define memcmp bcmp - +// #else /* VARIANT */ #define memcmp BUILTIN(memcmp) @@ -360,34 +358,32 @@ void memcmp3 () { char a[] = {1, 2, 3, 4}; - if (memcmp(a, a, 4)) - (void)*(char*)0; // no-warning + clang_analyzer_eval(memcmp(a, a, 4) == 0); // expected-warning{{TRUE}} } void memcmp4 (char *input) { char a[] = {1, 2, 3, 4}; - if (memcmp(a, input, 4)) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(memcmp(a, input, 4) == 0); // expected-warning{{UNKNOWN}} } void memcmp5 (char *input) { char a[] = {1, 2, 3, 4}; - if (memcmp(a, 0, 0)) // no-warning - (void)*(char*)0; // no-warning - if (memcmp(0, a, 0)) // no-warning - (void)*(char*)0; // no-warning - if (memcmp(a, input, 0)) // no-warning - (void)*(char*)0; // no-warning + clang_analyzer_eval(memcmp(a, 0, 0) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(memcmp(0, a, 0) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(memcmp(a, input, 0) == 0); // expected-warning{{TRUE}} } void memcmp6 (char *a, char *b, size_t n) { int result = memcmp(a, b, n); if (result != 0) - return; - if (n == 0) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(n != 0); // expected-warning{{TRUE}} + // else + // analyzer_assert_unknown(n == 0); + + // We can't do the above comparison because n has already been constrained. + // On one path n == 0, on the other n != 0. } int memcmp7 (char *a, size_t x, size_t y, size_t n) { @@ -411,8 +407,9 @@ bcopy(src, dst, 4); // no-warning - if (dst[0] != 0) - (void)*(char*)0; // expected-warning{{null}} + // If we actually model the copy, we can make this known. + // The important thing for now is that the old value has been invalidated. + clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}} } void bcopy1 () { Modified: cfe/trunk/test/Analysis/constant-folding.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/constant-folding.c?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/constant-folding.c (original) +++ cfe/trunk/test/Analysis/constant-folding.c Wed May 16 11:01:10 2012 @@ -1,7 +1,6 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode -Wno-null-dereference -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s -// Trigger a warning if the analyzer reaches this point in the control flow. -#define WARN ((void)*(char*)0) +void clang_analyzer_eval(int); // There should be no warnings unless otherwise indicated. @@ -9,73 +8,71 @@ // Sema can already catch the simple comparison a==a, // since that's usually a logic error (and not path-dependent). int b = a; - if (!(b==a)) WARN; // expected-warning{{never executed}} - if (!(b>=a)) WARN; // expected-warning{{never executed}} - if (!(b<=a)) WARN; // expected-warning{{never executed}} - if (b!=a) WARN; // expected-warning{{never executed}} - if (b>a) WARN; // expected-warning{{never executed}} - if (b= a); // expected-warning{{TRUE}} + clang_analyzer_eval(b <= a); // expected-warning{{TRUE}} + clang_analyzer_eval(b != a); // expected-warning{{FALSE}} + clang_analyzer_eval(b > a); // expected-warning{{FALSE}} + clang_analyzer_eval(b < a); // expected-warning{{FALSE}} } void testSelfOperations (int a) { - if ((a|a) != a) WARN; // expected-warning{{never executed}} - if ((a&a) != a) WARN; // expected-warning{{never executed}} - if ((a^a) != 0) WARN; // expected-warning{{never executed}} - if ((a-a) != 0) WARN; // expected-warning{{never executed}} + clang_analyzer_eval((a|a) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a&a) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a^a) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval((a-a) == 0); // expected-warning{{TRUE}} } void testIdempotent (int a) { - if ((a*1) != a) WARN; // expected-warning{{never executed}} - if ((a/1) != a) WARN; // expected-warning{{never executed}} - if ((a+0) != a) WARN; // expected-warning{{never executed}} - if ((a-0) != a) WARN; // expected-warning{{never executed}} - if ((a<<0) != a) WARN; // expected-warning{{never executed}} - if ((a>>0) != a) WARN; // expected-warning{{never executed}} - if ((a^0) != a) WARN; // expected-warning{{never executed}} - if ((a&(~0)) != a) WARN; // expected-warning{{never executed}} - if ((a|0) != a) WARN; // expected-warning{{never executed}} + clang_analyzer_eval((a*1) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a/1) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a+0) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a-0) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a<<0) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a>>0) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a^0) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a&(~0)) == a); // expected-warning{{TRUE}} + clang_analyzer_eval((a|0) == a); // expected-warning{{TRUE}} } void testReductionToConstant (int a) { - if ((a*0) != 0) WARN; // expected-warning{{never executed}} - if ((a&0) != 0) WARN; // expected-warning{{never executed}} - if ((a|(~0)) != (~0)) WARN; // expected-warning{{never executed}} + clang_analyzer_eval((a*0) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval((a&0) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval((a|(~0)) == (~0)); // expected-warning{{TRUE}} } void testSymmetricIntSymOperations (int a) { - if ((2+a) != (a+2)) WARN; // expected-warning{{never executed}} - if ((2*a) != (a*2)) WARN; // expected-warning{{never executed}} - if ((2&a) != (a&2)) WARN; // expected-warning{{never executed}} - if ((2^a) != (a^2)) WARN; // expected-warning{{never executed}} - if ((2|a) != (a|2)) WARN; // expected-warning{{never executed}} + clang_analyzer_eval((2+a) == (a+2)); // expected-warning{{TRUE}} + clang_analyzer_eval((2*a) == (a*2)); // expected-warning{{TRUE}} + clang_analyzer_eval((2&a) == (a&2)); // expected-warning{{TRUE}} + clang_analyzer_eval((2^a) == (a^2)); // expected-warning{{TRUE}} + clang_analyzer_eval((2|a) == (a|2)); // expected-warning{{TRUE}} } void testAsymmetricIntSymOperations (int a) { - if (((~0) >> a) != (~0)) WARN; // expected-warning{{never executed}} - if ((0 >> a) != 0) WARN; // expected-warning{{never executed}} - if ((0 << a) != 0) WARN; // expected-warning{{never executed}} + clang_analyzer_eval(((~0) >> a) == (~0)); // expected-warning{{TRUE}} + clang_analyzer_eval((0 >> a) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval((0 << a) == 0); // expected-warning{{TRUE}} // Unsigned right shift shifts in zeroes. - if ((((unsigned)(~0)) >> ((unsigned) a)) != ((unsigned)(~0))) - WARN; // expected-warning{{}} + clang_analyzer_eval(((~0U) >> a) != (~0U)); // expected-warning{{UNKNOWN}} } void testLocations (char *a) { char *b = a; - if (!(b==a)) WARN; // expected-warning{{never executed}} - if (!(b>=a)) WARN; // expected-warning{{never executed}} - if (!(b<=a)) WARN; // expected-warning{{never executed}} - if (b!=a) WARN; // expected-warning{{never executed}} - if (b>a) WARN; // expected-warning{{never executed}} - if (b= a); // expected-warning{{TRUE}} + clang_analyzer_eval(b <= a); // expected-warning{{TRUE}} + clang_analyzer_eval(b != a); // expected-warning{{FALSE}} + clang_analyzer_eval(b > a); // expected-warning{{FALSE}} + clang_analyzer_eval(b < a); // expected-warning{{FALSE}} } void testMixedTypeComparisons (char a, unsigned long b) { if (a != 0) return; if (b != 0x100) return; - if (a > b) WARN; // expected-warning{{never executed}} - if (b < a) WARN; // expected-warning{{never executed}} - if (a == b) WARN; // expected-warning{{never executed}} + clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} + clang_analyzer_eval(b >= a); // expected-warning{{TRUE}} + clang_analyzer_eval(a != b); // expected-warning{{TRUE}} } Modified: cfe/trunk/test/Analysis/initializer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/initializer.cpp?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/initializer.cpp (original) +++ cfe/trunk/test/Analysis/initializer.cpp Wed May 16 11:01:10 2012 @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -cfg-add-initializers -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -cfg-add-initializers -verify %s + +void clang_analyzer_eval(bool); class A { int x; @@ -7,8 +9,5 @@ }; A::A() : x(0) { - if (x != 0) { - int *p = 0; - *p = 0; // no-warning - } + clang_analyzer_eval(x == 0); // expected-warning{{TRUE}} } Modified: cfe/trunk/test/Analysis/method-call.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/method-call.cpp?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/method-call.cpp (original) +++ cfe/trunk/test/Analysis/method-call.cpp Wed May 16 11:01:10 2012 @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -analyzer-store region -verify %s // XFAIL: * +void clang_analyzer_eval(bool); + struct A { int x; A(int a) { x = a; } @@ -9,33 +11,15 @@ void f1() { A x(3); - if (x.getx() == 3) { - int *p = 0; - *p = 3; // expected-warning{{Dereference of null pointer}} - } else { - int *p = 0; - *p = 3; // no-warning - } + clang_analyzer_eval(x.getx() == 3); // expected-warning{{TRUE}} } void f2() { const A &x = A(3); - if (x.getx() == 3) { - int *p = 0; - *p = 3; // expected-warning{{Dereference of null pointer}} - } else { - int *p = 0; - *p = 3; // no-warning - } + clang_analyzer_eval(x.getx() == 3); // expected-warning{{TRUE}} } void f3() { const A &x = (A)3; - if (x.getx() == 3) { - int *p = 0; - *p = 3; // expected-warning{{Dereference of null pointer}} - } else { - int *p = 0; - *p = 3; // no-warning - } + clang_analyzer_eval(x.getx() == 3); // expected-warning{{TRUE}} } Modified: cfe/trunk/test/Analysis/ptr-arith.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/ptr-arith.c?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/ptr-arith.c (original) +++ cfe/trunk/test/Analysis/ptr-arith.c Wed May 16 11:01:10 2012 @@ -1,8 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s -// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub -analyzer-store=region -verify -triple i686-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s +// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 %s -// Used to trigger warnings for unreachable paths. -#define WARN do { int a, b; int c = &b-&a; } while (0) +void clang_analyzer_eval(int); void f1() { int a[10]; @@ -67,111 +66,48 @@ void null_operand(int *a) { start: // LHS is a label, RHS is NULL - if (&&start == 0) - WARN; // no-warning - if (&&start < 0) - WARN; // no-warning - if (&&start <= 0) - WARN; // no-warning - if (!(&&start != 0)) - WARN; // no-warning - if (!(&&start > 0)) - WARN; // no-warning - if (!(&&start >= 0)) - WARN; // no-warning - if (!(&&start - 0)) - WARN; // no-warning + clang_analyzer_eval(&&start != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(&&start >= 0); // expected-warning{{TRUE}} + clang_analyzer_eval(&&start > 0); // expected-warning{{TRUE}} + clang_analyzer_eval((&&start - 0) != 0); // expected-warning{{TRUE}} // LHS is a non-symbolic value, RHS is NULL - if (&a == 0) - WARN; // no-warning - if (&a < 0) - WARN; // no-warning - if (&a <= 0) - WARN; // no-warning - if (!(&a != 0)) - WARN; // no-warning - if (!(&a > 0)) - WARN; // no-warning - if (!(&a >= 0)) - WARN; // no-warning - - if (!(&a - 0)) // expected-warning{{Pointer arithmetic done on non-array variables}} - WARN; // no-warning + clang_analyzer_eval(&a != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(&a >= 0); // expected-warning{{TRUE}} + clang_analyzer_eval(&a > 0); // expected-warning{{TRUE}} + clang_analyzer_eval((&a - 0) != 0); // expected-warning{{TRUE}} expected-warning{{Pointer arithmetic done on non-array variables}} // LHS is NULL, RHS is non-symbolic // The same code is used for labels and non-symbolic values. - if (0 == &a) - WARN; // no-warning - if (0 > &a) - WARN; // no-warning - if (0 >= &a) - WARN; // no-warning - if (!(0 != &a)) - WARN; // no-warning - if (!(0 < &a)) - WARN; // no-warning - if (!(0 <= &a)) - WARN; // no-warning + clang_analyzer_eval(0 != &a); // expected-warning{{TRUE}} + clang_analyzer_eval(0 <= &a); // expected-warning{{TRUE}} + clang_analyzer_eval(0 < &a); // expected-warning{{TRUE}} // LHS is a symbolic value, RHS is NULL - if (a == 0) - WARN; // expected-warning{{}} - if (a < 0) - WARN; // no-warning - if (a <= 0) - WARN; // expected-warning{{}} - if (!(a != 0)) - WARN; // expected-warning{{}} - if (!(a > 0)) - WARN; // expected-warning{{}} - if (!(a >= 0)) - WARN; // no-warning - if (!(a - 0)) - WARN; // expected-warning{{}} + clang_analyzer_eval(a != 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}} + clang_analyzer_eval(a <= 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval((a - 0) != 0); // expected-warning{{UNKNOWN}} // LHS is NULL, RHS is a symbolic value - if (0 == a) - WARN; // expected-warning{{}} - if (0 > a) - WARN; // no-warning - if (0 >= a) - WARN; // expected-warning{{}} - if (!(0 != a)) - WARN; // expected-warning{{}} - if (!(0 < a)) - WARN; // expected-warning{{}} - if (!(0 <= a)) - WARN; // no-warning + clang_analyzer_eval(0 != a); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(0 <= a); // expected-warning{{TRUE}} + clang_analyzer_eval(0 < a); // expected-warning{{UNKNOWN}} } void const_locs() { char *a = (char*)0x1000; char *b = (char*)0x1100; start: - if (a==b) - WARN; // no-warning - if (!(a!=b)) - WARN; // no-warning - if (a>b) - WARN; // no-warning - if (b=b) - WARN; // no-warning - if (b<=a) - WARN; // no-warning - if (b-a != 0x100) - WARN; // no-warning - - if (&&start == a) - WARN; // expected-warning{{}} - if (a == &&start) - WARN; // expected-warning{{}} - if (&a == (char**)a) - WARN; // expected-warning{{}} - if ((char**)a == &a) - WARN; // expected-warning{{}} + clang_analyzer_eval(a != b); // expected-warning{{TRUE}} + clang_analyzer_eval(a < b); // expected-warning{{TRUE}} + clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} + clang_analyzer_eval((b-a) == 0x100); // expected-warning{{TRUE}} + + clang_analyzer_eval(&&start == a); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == &&start); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(&a == (char**)a); // expected-warning{{UNKNOWN}} + clang_analyzer_eval((char**)a == &a); // expected-warning{{UNKNOWN}} } void array_matching_types() { @@ -179,20 +115,10 @@ int *a = &array[2]; int *b = &array[5]; - if (a==b) - WARN; // no-warning - if (!(a!=b)) - WARN; // no-warning - if (a>b) - WARN; // no-warning - if (b=b) - WARN; // no-warning - if (b<=a) - WARN; // no-warning - if ((b-a) == 0) - WARN; // no-warning + clang_analyzer_eval(a != b); // expected-warning{{TRUE}} + clang_analyzer_eval(a < b); // expected-warning{{TRUE}} + clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} + clang_analyzer_eval((b-a) != 0); // expected-warning{{TRUE}} } // This takes a different code path than array_matching_types() @@ -201,49 +127,22 @@ int *a = &array[2]; char *b = (char*)&array[5]; - if (a==b) // expected-warning{{comparison of distinct pointer types}} - WARN; // no-warning - if (!(a!=b)) // expected-warning{{comparison of distinct pointer types}} - WARN; // no-warning - if (a>b) // expected-warning{{comparison of distinct pointer types}} - WARN; // no-warning - if (b=b) // expected-warning{{comparison of distinct pointer types}} - WARN; // no-warning - if (b<=a) // expected-warning{{comparison of distinct pointer types}} - WARN; // no-warning + clang_analyzer_eval(a != b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}} + clang_analyzer_eval(a < b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}} + clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}} } struct test { int x; int y; }; void struct_fields() { struct test a, b; - if (&a.x == &a.y) - WARN; // no-warning - if (!(&a.x != &a.y)) - WARN; // no-warning - if (&a.x > &a.y) - WARN; // no-warning - if (&a.y < &a.x) - WARN; // no-warning - if (&a.x >= &a.y) - WARN; // no-warning - if (&a.y <= &a.x) - WARN; // no-warning - - if (&a.x == &b.x) - WARN; // no-warning - if (!(&a.x != &b.x)) - WARN; // no-warning - if (&a.x > &b.x) - WARN; // expected-warning{{}} - if (&b.x < &a.x) - WARN; // expected-warning{{}} - if (&a.x >= &b.x) - WARN; // expected-warning{{}} - if (&b.x <= &a.x) - WARN; // expected-warning{{}} + clang_analyzer_eval(&a.x != &a.y); // expected-warning{{TRUE}} + clang_analyzer_eval(&a.x < &a.y); // expected-warning{{TRUE}} + clang_analyzer_eval(&a.x <= &a.y); // expected-warning{{TRUE}} + + clang_analyzer_eval(&a.x != &b.x); // expected-warning{{TRUE}} + clang_analyzer_eval(&a.x > &b.x); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(&a.x >= &b.x); // expected-warning{{UNKNOWN}} } void mixed_region_types() { @@ -251,35 +150,17 @@ int array[2]; void *a = &array, *b = &s; - if (&a == &b) - WARN; // no-warning - if (!(&a != &b)) - WARN; // no-warning - if (&a > &b) - WARN; // expected-warning{{}} - if (&b < &a) - WARN; // expected-warning{{}} - if (&a >= &b) - WARN; // expected-warning{{}} - if (&b <= &a) - WARN; // expected-warning{{}} + clang_analyzer_eval(&a != &b); // expected-warning{{TRUE}} + clang_analyzer_eval(&a > &b); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(&a >= &b); // expected-warning{{UNKNOWN}} } void symbolic_region(int *p) { int a; - if (&a == p) - WARN; // no-warning - if (&a != p) - WARN; // expected-warning{{}} - if (&a > p) - WARN; // expected-warning{{}} - if (&a < p) - WARN; // expected-warning{{}} - if (&a >= p) - WARN; // expected-warning{{}} - if (&a <= p) - WARN; // expected-warning{{}} + clang_analyzer_eval(&a != p); // expected-warning{{TRUE}} + clang_analyzer_eval(&a > p); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(&a >= p); // expected-warning{{UNKNOWN}} } void PR7527 (int *p) { Modified: cfe/trunk/test/Analysis/string-fail.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string-fail.c?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/string-fail.c (original) +++ cfe/trunk/test/Analysis/string-fail.c Wed May 16 11:01:10 2012 @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.unix.CString,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,experimental.unix.CString,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s // XFAIL: * // This file is for tests that may eventually go into string.c, or may be @@ -32,6 +32,7 @@ #define NULL 0 typedef typeof(sizeof(int)) size_t; +void clang_analyzer_eval(int); //===----------------------------------------------------------------------=== // strnlen() @@ -43,8 +44,7 @@ void strnlen_liveness(const char *x) { if (strnlen(x, 10) < 5) return; - if (strnlen(x, 10) < 5) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strnlen(x, 10) < 5); // expected-warning{{FALSE}} } void strnlen_subregion() { @@ -57,43 +57,43 @@ size_t a = strnlen(z.a, 10); z.b[0] = 5; size_t b = strnlen(z.a, 10); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} use_two_stringsn(&z); size_t c = strnlen(z.a, 10); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } extern void use_stringn(char *); void strnlen_argument(char *x) { size_t a = strnlen(x, 10); size_t b = strnlen(x, 10); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} use_stringn(x); size_t c = strnlen(x, 10); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } extern char global_strn[]; void strnlen_global() { size_t a = strnlen(global_strn, 10); size_t b = strnlen(global_strn, 10); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} // Call a function with unknown effects, which should invalidate globals. use_stringn(0); size_t c = strnlen(global_strn, 10); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } void strnlen_indirect(char *x) { @@ -101,13 +101,13 @@ char *p = x; char **p2 = &p; size_t b = strnlen(x, 10); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} extern void use_stringn_ptr(char*const*); use_stringn_ptr(p2); size_t c = strnlen(x, 10); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } Modified: cfe/trunk/test/Analysis/string.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156920&r1=156919&r2=156920&view=diff ============================================================================== --- cfe/trunk/test/Analysis/string.c (original) +++ cfe/trunk/test/Analysis/string.c Wed May 16 11:01:10 2012 @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=experimental.security.taint,core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s +// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s +// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s +// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=experimental.security.taint,core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s //===----------------------------------------------------------------------=== // Declarations @@ -26,6 +26,9 @@ #define NULL 0 typedef typeof(sizeof(int)) size_t; + +void clang_analyzer_eval(int); + int scanf(const char *restrict format, ...); //===----------------------------------------------------------------------=== @@ -36,23 +39,20 @@ size_t strlen(const char *s); void strlen_constant0() { - if (strlen("123") != 3) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen("123") == 3); // expected-warning{{TRUE}} } void strlen_constant1() { const char *a = "123"; - if (strlen(a) != 3) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}} } void strlen_constant2(char x) { char a[] = "123"; - if (strlen(a) != 3) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}} + a[0] = x; - if (strlen(a) != 3) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(strlen(a) == 3); // expected-warning{{UNKNOWN}} } size_t strlen_null() { @@ -78,43 +78,46 @@ size_t a = strlen(z.a); z.b[0] = 5; size_t b = strlen(z.a); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} use_two_strings(&z); size_t c = strlen(z.a); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } extern void use_string(char *); void strlen_argument(char *x) { size_t a = strlen(x); size_t b = strlen(x); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} use_string(x); size_t c = strlen(x); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } extern char global_str[]; void strlen_global() { size_t a = strlen(global_str); size_t b = strlen(global_str); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) { + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} + // Make sure clang_analyzer_eval does not invalidate globals. + clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}} + } // Call a function with unknown effects, which should invalidate globals. use_string(0); size_t c = strlen(global_str); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } void strlen_indirect(char *x) { @@ -122,15 +125,15 @@ char *p = x; char **p2 = &p; size_t b = strlen(x); - if (a == 0 && b != 0) - (void)*(char*)0; // expected-warning{{never executed}} + if (a == 0) + clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} extern void use_string_ptr(char*const*); use_string_ptr(p2); size_t c = strlen(x); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } void strlen_indirect2(char *x) { @@ -141,15 +144,14 @@ use_string_ptr2(p2); size_t c = strlen(x); - if (a == 0 && c != 0) - (void)*(char*)0; // expected-warning{{null}} + if (a == 0) + clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} } void strlen_liveness(const char *x) { if (strlen(x) < 5) return; - if (strlen(x) < 5) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}} } //===----------------------------------------------------------------------=== @@ -159,43 +161,35 @@ size_t strnlen(const char *s, size_t maxlen); void strnlen_constant0() { - if (strnlen("123", 10) != 3) - (void)*(char*)0; // expected-warning{{never executed}} + clang_analyzer_eval(strnlen("123", 10) == 3); // expected-warning{{TRUE}} } void strnlen_constant1() { const char *a = "123"; - if (strnlen(a, 10) != 3) - (void)*(char*)0; // expected-warning{{never executed}} + clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}} } void strnlen_constant2(char x) { char a[] = "123"; - if (strnlen(a, 10) != 3) - (void)*(char*)0; // expected-warning{{never executed}} + clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}} a[0] = x; - if (strnlen(a, 10) != 3) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{UNKNOWN}} } void strnlen_constant4() { - if (strnlen("123456", 3) != 3) - (void)*(char*)0; // expected-warning{{never executed}} + clang_analyzer_eval(strnlen("123456", 3) == 3); // expected-warning{{TRUE}} } void strnlen_constant5() { const char *a = "123456"; - if (strnlen(a, 3) != 3) - (void)*(char*)0; // expected-warning{{never executed}} + clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}} } void strnlen_constant6(char x) { char a[] = "123456"; - if (strnlen(a, 3) != 3) - (void)*(char*)0; // expected-warning{{never executed}} + clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}} a[0] = x; - if (strnlen(a, 3) != 3) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{UNKNOWN}} } size_t strnlen_null() { @@ -212,10 +206,8 @@ } void strnlen_zero() { - if (strnlen("abc", 0) != 0) - (void)*(char*)0; // expected-warning{{never executed}} - if (strnlen(NULL, 0) != 0) // no-warning - (void)*(char*)0; // no-warning + clang_analyzer_eval(strnlen("abc", 0) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(strnlen(NULL, 0) == 0); // expected-warning{{TRUE}} } size_t strnlen_compound_literal() { @@ -230,40 +222,26 @@ } void strnlen_is_not_strlen(char *x) { - if (strnlen(x, 10) != strlen(x)) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(strnlen(x, 10) == strlen(x)); // expected-warning{{UNKNOWN}} } void strnlen_at_limit(char *x) { size_t len = strnlen(x, 10); - if (len > 10) - (void)*(char*)0; // expected-warning{{never executed}} - if (len == 10) - (void)*(char*)0; // expected-warning{{null}} -} - -void strnlen_less_than_limit(char *x) { - size_t len = strnlen(x, 10); - if (len > 10) - (void)*(char*)0; // expected-warning{{never executed}} - if (len < 10) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}} + clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}} } void strnlen_at_actual(size_t limit) { size_t len = strnlen("abc", limit); - if (len > 3) - (void)*(char*)0; // expected-warning{{never executed}} - if (len == 3) - (void)*(char*)0; // expected-warning{{null}} -} - -void strnlen_less_than_actual(size_t limit) { - size_t len = strnlen("abc", limit); - if (len > 3) - (void)*(char*)0; // expected-warning{{never executed}} - if (len < 3) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}} + // This is due to eager assertion in strnlen. + if (limit == 0) { + clang_analyzer_eval(len == 0); // expected-warning{{TRUE}} + } else { + clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}} + } } //===----------------------------------------------------------------------=== @@ -304,14 +282,9 @@ void strcpy_effects(char *x, char *y) { char a = x[0]; - if (strcpy(x, y) != x) - (void)*(char*)0; // no-warning - - if (strlen(x) != strlen(y)) - (void)*(char*)0; // no-warning - - if (a != x[0]) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}} + clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}} + clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} } void strcpy_overflow(char *y) { @@ -348,14 +321,9 @@ void stpcpy_effect(char *x, char *y) { char a = x[0]; - if (stpcpy(x, y) != &x[strlen(y)]) - (void)*(char*)0; // no-warning - - if (strlen(x) != strlen(y)) - (void)*(char*)0; // no-warning - - if (a != x[0]) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(stpcpy(x, y) == &x[strlen(y)]); // expected-warning{{TRUE}} + clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}} + clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} } void stpcpy_overflow(char *y) { @@ -409,11 +377,8 @@ if (strlen(y) != 4) return; - if (strcat(x, y) != x) - (void)*(char*)0; // no-warning - - if ((int)strlen(x) != (orig_len + strlen(y))) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcat(x, y) == x); // expected-warning{{TRUE}} + clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} } void strcat_overflow_0(char *y) { @@ -442,29 +407,25 @@ void strcat_symbolic_dst_length(char *dst) { strcat(dst, "1234"); - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} } void strcat_symbolic_src_length(char *src) { char dst[8] = "1234"; strcat(dst, src); - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} } void strcat_symbolic_dst_length_taint(char *dst) { scanf("%s", dst); // Taint data. strcat(dst, "1234"); - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} } void strcat_unknown_src_length(char *src, int offset) { char dst[8] = "1234"; strcat(dst, &src[offset]); - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} } // There is no strcat_unknown_dst_length because if we can't get a symbolic @@ -513,14 +474,9 @@ void strncpy_effects(char *x, char *y) { char a = x[0]; - if (strncpy(x, y, 5) != x) - (void)*(char*)0; // no-warning - - if (strlen(x) != strlen(y)) - (void)*(char*)0; // expected-warning{{null}} - - if (a != x[0]) - (void)*(char*)0; // expected-warning{{null}} + clang_analyzer_eval(strncpy(x, y, 5) == x); // expected-warning{{TRUE}} + clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} } void strncpy_overflow(char *y) { @@ -562,8 +518,7 @@ // strncpy does not null-terminate, so we have no idea what the strlen is // after this. - if (strlen(x) > 4) - (void)*(int*)0; // expected-warning{{null}} + clang_analyzer_eval(strlen(x) > 4); // expected-warning{{UNKNOWN}} } void strncpy_exactly_matching_buffer2(char *y) { @@ -574,8 +529,7 @@ strncpy(x, y, 4); // no-warning // This time, we know that y fits in x anyway. - if (strlen(x) > 3) - (void)*(int*)0; // no-warning + clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{TRUE}} } void strncpy_zero(char *src) { @@ -628,11 +582,8 @@ if (strlen(y) != 4) return; - if (strncat(x, y, strlen(y)) != x) - (void)*(char*)0; // no-warning - - if (strlen(x) != orig_len + strlen(y)) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncat(x, y, strlen(y)) == x); // expected-warning{{TRUE}} + clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} } void strncat_overflow_0(char *y) { @@ -672,15 +623,13 @@ void strncat_symbolic_dst_length(char *dst) { strncat(dst, "1234", 5); - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} } void strncat_symbolic_src_length(char *src) { char dst[8] = "1234"; strncat(dst, src, 3); - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} char dst2[8] = "1234"; strncat(dst2, src, 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}} @@ -689,8 +638,7 @@ void strncat_unknown_src_length(char *src, int offset) { char dst[8] = "1234"; strncat(dst, &src[offset], 3); - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} char dst2[8] = "1234"; strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}} @@ -703,20 +651,18 @@ char dst[6] = "1234"; char src[] = "567"; strncat(dst, src, limit); // no-warning - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning - if (strlen(dst) == 4) - (void)*(char*)0; // expected-warning{{null}} + + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} + clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}} } void strncat_unknown_limit(float limit) { char dst[6] = "1234"; char src[] = "567"; strncat(dst, src, (size_t)limit); // no-warning - if (strlen(dst) < 4) - (void)*(char*)0; // no-warning - if (strlen(dst) == 4) - (void)*(char*)0; // expected-warning{{null}} + + clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} + clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}} } void strncat_too_big(char *dst, char *src) { @@ -746,41 +692,35 @@ int strcmp(const char * s1, const char * s2); void strcmp_constant0() { - if (strcmp("123", "123") != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}} } void strcmp_constant_and_var_0() { char *x = "123"; - if (strcmp(x, "123") != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}} } void strcmp_constant_and_var_1() { char *x = "123"; - if (strcmp("123", x) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}} } void strcmp_0() { char *x = "123"; char *y = "123"; - if (strcmp(x, y) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}} } void strcmp_1() { char *x = "234"; char *y = "123"; - if (strcmp(x, y) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}} } void strcmp_2() { char *x = "123"; char *y = "234"; - if (strcmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}} } void strcmp_null_0() { @@ -798,39 +738,33 @@ void strcmp_diff_length_0() { char *x = "12345"; char *y = "234"; - if (strcmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}} } void strcmp_diff_length_1() { char *x = "123"; char *y = "23456"; - if (strcmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}} } void strcmp_diff_length_2() { char *x = "12345"; char *y = "123"; - if (strcmp(x, y) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}} } void strcmp_diff_length_3() { char *x = "123"; char *y = "12345"; - if (strcmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}} } void strcmp_embedded_null () { - if (strcmp("\0z", "\0y") != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}} } void strcmp_unknown_arg (char *unknown) { - if (strcmp(unknown, unknown) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}} } //===----------------------------------------------------------------------=== @@ -841,41 +775,35 @@ int strncmp(const char *s1, const char *s2, size_t n); void strncmp_constant0() { - if (strncmp("123", "123", 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}} } void strncmp_constant_and_var_0() { char *x = "123"; - if (strncmp(x, "123", 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}} } void strncmp_constant_and_var_1() { char *x = "123"; - if (strncmp("123", x, 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}} } void strncmp_0() { char *x = "123"; char *y = "123"; - if (strncmp(x, y, 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}} } void strncmp_1() { char *x = "234"; char *y = "123"; - if (strncmp(x, y, 3) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}} } void strncmp_2() { char *x = "123"; char *y = "234"; - if (strncmp(x, y, 3) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}} } void strncmp_null_0() { @@ -893,55 +821,47 @@ void strncmp_diff_length_0() { char *x = "12345"; char *y = "234"; - if (strncmp(x, y, 5) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}} } void strncmp_diff_length_1() { char *x = "123"; char *y = "23456"; - if (strncmp(x, y, 5) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}} } void strncmp_diff_length_2() { char *x = "12345"; char *y = "123"; - if (strncmp(x, y, 5) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 5) == 1); // expected-warning{{TRUE}} } void strncmp_diff_length_3() { char *x = "123"; char *y = "12345"; - if (strncmp(x, y, 5) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}} } void strncmp_diff_length_4() { char *x = "123"; char *y = "12345"; - if (strncmp(x, y, 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}} } void strncmp_diff_length_5() { char *x = "012"; char *y = "12345"; - if (strncmp(x, y, 3) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}} } void strncmp_diff_length_6() { char *x = "234"; char *y = "12345"; - if (strncmp(x, y, 3) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}} } void strncmp_embedded_null () { - if (strncmp("ab\0zz", "ab\0yy", 4) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}} } //===----------------------------------------------------------------------=== @@ -952,41 +872,35 @@ int strcasecmp(const char *s1, const char *s2); void strcasecmp_constant0() { - if (strcasecmp("abc", "Abc") != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}} } void strcasecmp_constant_and_var_0() { char *x = "abc"; - if (strcasecmp(x, "Abc") != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}} } void strcasecmp_constant_and_var_1() { char *x = "abc"; - if (strcasecmp("Abc", x) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}} } void strcasecmp_0() { char *x = "abc"; char *y = "Abc"; - if (strcasecmp(x, y) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}} } void strcasecmp_1() { char *x = "Bcd"; char *y = "abc"; - if (strcasecmp(x, y) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}} } void strcasecmp_2() { char *x = "abc"; char *y = "Bcd"; - if (strcasecmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}} } void strcasecmp_null_0() { @@ -1004,34 +918,29 @@ void strcasecmp_diff_length_0() { char *x = "abcde"; char *y = "aBd"; - if (strcasecmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}} } void strcasecmp_diff_length_1() { char *x = "abc"; char *y = "aBdef"; - if (strcasecmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}} } void strcasecmp_diff_length_2() { char *x = "aBcDe"; char *y = "abc"; - if (strcasecmp(x, y) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}} } void strcasecmp_diff_length_3() { char *x = "aBc"; char *y = "abcde"; - if (strcasecmp(x, y) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}} } void strcasecmp_embedded_null () { - if (strcasecmp("ab\0zz", "ab\0yy") != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}} } //===----------------------------------------------------------------------=== @@ -1042,41 +951,35 @@ int strncasecmp(const char *s1, const char *s2, size_t n); void strncasecmp_constant0() { - if (strncasecmp("abc", "Abc", 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}} } void strncasecmp_constant_and_var_0() { char *x = "abc"; - if (strncasecmp(x, "Abc", 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}} } void strncasecmp_constant_and_var_1() { char *x = "abc"; - if (strncasecmp("Abc", x, 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}} } void strncasecmp_0() { char *x = "abc"; char *y = "Abc"; - if (strncasecmp(x, y, 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}} } void strncasecmp_1() { char *x = "Bcd"; char *y = "abc"; - if (strncasecmp(x, y, 3) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}} } void strncasecmp_2() { char *x = "abc"; char *y = "Bcd"; - if (strncasecmp(x, y, 3) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}} } void strncasecmp_null_0() { @@ -1094,55 +997,47 @@ void strncasecmp_diff_length_0() { char *x = "abcde"; char *y = "aBd"; - if (strncasecmp(x, y, 5) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}} } void strncasecmp_diff_length_1() { char *x = "abc"; char *y = "aBdef"; - if (strncasecmp(x, y, 5) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}} } void strncasecmp_diff_length_2() { char *x = "aBcDe"; char *y = "abc"; - if (strncasecmp(x, y, 5) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 5) == 1); // expected-warning{{TRUE}} } void strncasecmp_diff_length_3() { char *x = "aBc"; char *y = "abcde"; - if (strncasecmp(x, y, 5) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}} } void strncasecmp_diff_length_4() { char *x = "abcde"; char *y = "aBc"; - if (strncasecmp(x, y, 3) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}} } void strncasecmp_diff_length_5() { char *x = "abcde"; char *y = "aBd"; - if (strncasecmp(x, y, 3) != -1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}} } void strncasecmp_diff_length_6() { char *x = "aBDe"; char *y = "abc"; - if (strncasecmp(x, y, 3) != 1) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}} } void strncasecmp_embedded_null () { - if (strncasecmp("ab\0zz", "ab\0yy", 4) != 0) - (void)*(char*)0; // no-warning + clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}} } //===----------------------------------------------------------------------=== @@ -1169,10 +1064,10 @@ if (strlen(x) != value) return; // Test relational operators. - if (strlen(x) < 2) { (void)*(char*)0; } // no-warning - if (2 > strlen(x)) { (void)*(char*)0; } // no-warning + clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} + clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} // Test equality operators. - if (strlen(x) == 1) { (void)*(char*)0; } // no-warning - if (1 == strlen(x)) { (void)*(char*)0; } // no-warning + clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} + clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} } From jediknil at belkadan.com Wed May 16 11:01:14 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 16 May 2012 16:01:14 -0000 Subject: [cfe-commits] r156921 - in /cfe/trunk/test/Analysis: outofbound-notwork.c reference.cpp Message-ID: <20120516160114.962132A6C067@llvm.org> Author: jrose Date: Wed May 16 11:01:14 2012 New Revision: 156921 URL: http://llvm.org/viewvc/llvm-project?rev=156921&view=rev Log: [analyzer] Fix RUN lines for old XFAIL tests, one of which actually works. Modified: cfe/trunk/test/Analysis/outofbound-notwork.c cfe/trunk/test/Analysis/reference.cpp Modified: cfe/trunk/test/Analysis/outofbound-notwork.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/outofbound-notwork.c?rev=156921&r1=156920&r2=156921&view=diff ============================================================================== --- cfe/trunk/test/Analysis/outofbound-notwork.c (original) +++ cfe/trunk/test/Analysis/outofbound-notwork.c Wed May 16 11:01:14 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-checker=core,experimental.unix,experimental.security.ArrayBound -analyzer-store=region -verify %s +// RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-checker=core,experimental.security.ArrayBound -analyzer-store=region -verify %s // XFAIL: * // Once we better handle modeling of sizes of VLAs, we can pull this back Modified: cfe/trunk/test/Analysis/reference.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/reference.cpp?rev=156921&r1=156920&r2=156921&view=diff ============================================================================== --- cfe/trunk/test/Analysis/reference.cpp (original) +++ cfe/trunk/test/Analysis/reference.cpp Wed May 16 11:01:14 2012 @@ -1,11 +1,10 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference %s -// XFAIL typedef typeof(sizeof(int)) size_t; void malloc (size_t); void f1() { - int const &i = 3; // <--- **FIXME** This is currently not being modeled correctly. + int const &i = 3; int b = i; int *p = 0; From jediknil at belkadan.com Wed May 16 11:01:07 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 16 May 2012 16:01:07 -0000 Subject: [cfe-commits] r156919 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/CMakeLists.txt lib/StaticAnalyzer/Checkers/Checkers.td lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp test/Analysis/global-region-invalidation.c Message-ID: <20120516160107.6C9E82A6C065@llvm.org> Author: jrose Date: Wed May 16 11:01:07 2012 New Revision: 156919 URL: http://llvm.org/viewvc/llvm-project?rev=156919&view=rev Log: [analyzer] Introduce clang_analyzer_eval for regression test constraint checks. The new debug.ExprInspection checker looks for calls to clang_analyzer_eval, and emits a warning of TRUE, FALSE, or UNKNOWN (or UNDEFINED) based on the constrained value of its (boolean) argument. It does not modify the analysis state though the conditions tested can result in branches (e.g. through the use of short-circuit operators). Added: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/test/Analysis/global-region-invalidation.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=156919&r1=156918&r2=156919&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Wed May 16 11:01:07 2012 @@ -31,6 +31,7 @@ DebugCheckers.cpp DereferenceChecker.cpp DivZeroChecker.cpp + ExprInspectionChecker.cpp FixedAddressChecker.cpp GenericTaintChecker.cpp IdempotentOperationChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=156919&r1=156918&r2=156919&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Wed May 16 11:01:07 2012 @@ -483,5 +483,9 @@ HelpText<"Mark tainted symbols as such.">, DescFile<"TaintTesterChecker.cpp">; +def ExprInspectionChecker : Checker<"ExprInspection">, + HelpText<"Check the analyzer's understanding of expressions">, + DescFile<"ExprInspectionChecker.cpp">; + } // end "debug" Added: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp?rev=156919&view=auto ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp (added) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp Wed May 16 11:01:07 2012 @@ -0,0 +1,85 @@ +//==- ExprInspectionChecker.cpp - Used for regression tests ------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" + +using namespace clang; +using namespace ento; + +namespace { +class ExprInspectionChecker : public Checker< eval::Call > { + mutable OwningPtr BT; +public: + bool evalCall(const CallExpr *CE, CheckerContext &C) const; +}; +} + +bool ExprInspectionChecker::evalCall(const CallExpr *CE, + CheckerContext &C) const { + // These checks should have no effect on the surrounding environment + // (globals should not be evaluated, etc), hence the use of evalCall. + ExplodedNode *N = C.getPredecessor(); + const LocationContext *LC = N->getLocationContext(); + + if (!C.getCalleeName(CE).equals("clang_analyzer_eval")) + return false; + + // A specific instantiation of an inlined function may have more constrained + // values than can generally be assumed. Skip the check. + if (LC->getParent() != 0) + return true; + + const char *Msg = 0; + + if (CE->getNumArgs() == 0) + Msg = "Missing assertion argument"; + else { + ProgramStateRef State = N->getState(); + const Expr *Assertion = CE->getArg(0); + SVal AssertionVal = State->getSVal(Assertion, LC); + + if (AssertionVal.isUndef()) + Msg = "UNDEFINED"; + else { + ProgramStateRef StTrue, StFalse; + llvm::tie(StTrue, StFalse) = + State->assume(cast(AssertionVal)); + + if (StTrue) { + if (StFalse) + Msg = "UNKNOWN"; + else + Msg = "TRUE"; + } else { + if (StFalse) + Msg = "FALSE"; + else + llvm_unreachable("Invalid constraint; neither true or false."); + } + } + } + + assert(Msg); + + if (!BT) + BT.reset(new BugType("Checking analyzer assumptions", "debug")); + + BugReport *R = new BugReport(*BT, Msg, N); + C.EmitReport(R); + + return true; +} + +void ento::registerExprInspectionChecker(CheckerManager &Mgr) { + Mgr.registerChecker(); +} + Modified: cfe/trunk/test/Analysis/global-region-invalidation.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/global-region-invalidation.c?rev=156919&r1=156918&r2=156919&view=diff ============================================================================== --- cfe/trunk/test/Analysis/global-region-invalidation.c (original) +++ cfe/trunk/test/Analysis/global-region-invalidation.c Wed May 16 11:01:07 2012 @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -disable-free -analyzer-eagerly-assume -analyzer-checker=core,deadcode,experimental.security.taint,debug.TaintTest -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -disable-free -analyzer-eagerly-assume -analyzer-checker=core,deadcode,experimental.security.taint,debug.TaintTest,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); // Note, we do need to include headers here, since the analyzer checks if the function declaration is located in a system header. #include "system-header-simulator.h" @@ -73,3 +75,12 @@ } return 0; } + +void testAnalyzerEvalIsPure() { + extern int someGlobal; + if (someGlobal == 0) { + clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}} + } +} + From dgregor at apple.com Wed May 16 11:11:17 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 16:11:17 -0000 Subject: [cfe-commits] r156922 - /cfe/trunk/lib/Sema/SemaStmt.cpp Message-ID: <20120516161117.ABFE92A6C065@llvm.org> Author: dgregor Date: Wed May 16 11:11:17 2012 New Revision: 156922 URL: http://llvm.org/viewvc/llvm-project?rev=156922&view=rev Log: Use a llvm::SmallString rather than std::string for duplicate-case errors Modified: cfe/trunk/lib/Sema/SemaStmt.cpp Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=156922&r1=156921&r2=156922&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed May 16 11:11:17 2012 @@ -30,6 +30,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" using namespace clang; using namespace sema; @@ -778,17 +779,18 @@ if (DeclRefExpr *DeclRef = dyn_cast(CurrCase)) { CurrString = DeclRef->getDecl()->getName(); } - std::string CaseValStr = CaseVals[i-1].first.toString(10); + llvm::SmallString<16> CaseValStr; + CaseVals[i-1].first.toString(CaseValStr); if (PrevString == CurrString) Diag(CaseVals[i].second->getLHS()->getLocStart(), diag::err_duplicate_case) << - (PrevString.empty() ? CaseValStr : PrevString.str()); + (PrevString.empty() ? CaseValStr.str() : PrevString); else Diag(CaseVals[i].second->getLHS()->getLocStart(), diag::err_duplicate_case_differing_expr) << - (PrevString.empty() ? CaseValStr : PrevString.str()) << - (CurrString.empty() ? CaseValStr : CurrString.str()) << + (PrevString.empty() ? CaseValStr.str() : PrevString) << + (CurrString.empty() ? CaseValStr.str() : CurrString) << CaseValStr; Diag(CaseVals[i-1].second->getLHS()->getLocStart(), From dgregor at apple.com Wed May 16 11:13:51 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 09:13:51 -0700 Subject: [cfe-commits] r156904 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaStmt.cpp test/Sema/switch.c In-Reply-To: <77679894-69F4-44E3-95D5-4178F03E6651@belkadan.com> References: <20120516053258.9C4032A6C065@llvm.org> <77679894-69F4-44E3-95D5-4178F03E6651@belkadan.com> Message-ID: <0435844F-8FEA-4A9F-8601-4BD7D8F9866E@apple.com> On May 15, 2012, at 10:40 PM, Jordy Rose wrote: > > On May 16, 2012, at 1:32, Douglas Gregor wrote: > >> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=156904&r1=156903&r2=156904&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed May 16 00:32:58 2012 >> @@ -768,8 +768,29 @@ >> >> if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) { >> // If we have a duplicate, report it. >> - Diag(CaseVals[i].second->getLHS()->getLocStart(), >> - diag::err_duplicate_case) << CaseVals[i].first.toString(10); >> + // First, determine if either case value has a name >> + StringRef PrevString, CurrString; >> + Expr *PrevCase = CaseVals[i-1].second->getLHS()->IgnoreParenCasts(); >> + Expr *CurrCase = CaseVals[i].second->getLHS()->IgnoreParenCasts(); >> + if (DeclRefExpr *DeclRef = dyn_cast(PrevCase)) { >> + PrevString = DeclRef->getDecl()->getName(); >> + } >> + if (DeclRefExpr *DeclRef = dyn_cast(CurrCase)) { >> + CurrString = DeclRef->getDecl()->getName(); >> + } > >> + std::string CaseValStr = CaseVals[i-1].first.toString(10); > > Just saw this earlier today. APSInt has a toString method that takes a SmallString to print to (and defaults to base 10). > > SmallString<16> CaseValStr; > CaseVals[i-1].first.toString(CaseValStr); Good call, fixed in r156922! - Doug From matthewbg at google.com Wed May 16 11:30:43 2012 From: matthewbg at google.com (Matt Beaumont-Gay) Date: Wed, 16 May 2012 09:30:43 -0700 Subject: [cfe-commits] r156910 - /cfe/trunk/docs/ThreadSanitizer.html In-Reply-To: <20120516081436.512AE2A6C065@llvm.org> References: <20120516081436.512AE2A6C065@llvm.org> Message-ID: Some tiny spelling/grammar nits: > +

      Supported Platforms

      > +ThreadSanitizer is supported on Linux x86_64 (tested on Ubuntu 10.04).
      > +Support for MacOS 10.7 (64-bit only) is planed for late 2012.
      > +Support for 32-bit platforms is problematic and not yet planed. s/planed/planned/ > +
    • ThreadSanitizer uses more real memory than a native run. > +At the default settings the memory overhead is 9x plus 9Mb per each thread. > +Settings with 5x and 3x overhead (but less accurate analysis) are also available. > +
    • ThreadSanitizer maps (but not reserves) a lot of virtual address space. "(but does not reserve)" From dgregor at apple.com Wed May 16 11:31:59 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 16:31:59 -0000 Subject: [cfe-commits] r156923 - in /cfe/trunk: lib/Serialization/ASTReaderDecl.cpp test/Modules/Inputs/import-decl.h test/Modules/Inputs/module.map test/Modules/import-decl.cpp Message-ID: <20120516163159.781862A6C065@llvm.org> Author: dgregor Date: Wed May 16 11:31:58 2012 New Revision: 156923 URL: http://llvm.org/viewvc/llvm-project?rev=156923&view=rev Log: Fix ASTReader handling of ImportDecls, from Meador Inge! Added: cfe/trunk/test/Modules/Inputs/import-decl.h (with props) cfe/trunk/test/Modules/import-decl.cpp (with props) Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/test/Modules/Inputs/module.map Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=156923&r1=156922&r2=156923&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed May 16 11:31:58 2012 @@ -1249,7 +1249,6 @@ SourceLocation *StoredLocs = reinterpret_cast(D + 1); for (unsigned I = 0, N = Record.back(); I != N; ++I) StoredLocs[I] = ReadSourceLocation(Record, Idx); - ++Idx; } void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { Added: cfe/trunk/test/Modules/Inputs/import-decl.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/import-decl.h?rev=156923&view=auto ============================================================================== --- cfe/trunk/test/Modules/Inputs/import-decl.h (added) +++ cfe/trunk/test/Modules/Inputs/import-decl.h Wed May 16 11:31:58 2012 @@ -0,0 +1 @@ +struct T {}; Propchange: cfe/trunk/test/Modules/Inputs/import-decl.h ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/test/Modules/Inputs/import-decl.h ------------------------------------------------------------------------------ svn:keywords = Id Propchange: cfe/trunk/test/Modules/Inputs/import-decl.h ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: cfe/trunk/test/Modules/Inputs/module.map URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=156923&r1=156922&r2=156923&view=diff ============================================================================== --- cfe/trunk/test/Modules/Inputs/module.map (original) +++ cfe/trunk/test/Modules/Inputs/module.map Wed May 16 11:31:58 2012 @@ -84,3 +84,6 @@ module MethodPoolB { header "MethodPoolB.h" } +module import_decl { + header "import-decl.h" +} Added: cfe/trunk/test/Modules/import-decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/import-decl.cpp?rev=156923&view=auto ============================================================================== --- cfe/trunk/test/Modules/import-decl.cpp (added) +++ cfe/trunk/test/Modules/import-decl.cpp Wed May 16 11:31:58 2012 @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: %clang -fmodule-cache-path %t -fmodules -x objective-c -I %S/Inputs -emit-ast -o %t.ast %s +// RUN: %clang -cc1 -ast-print -x ast - < %t.ast | FileCheck %s + + at __experimental_modules_import import_decl; +// CHECK: struct T + +int main() { + return 0; +} Propchange: cfe/trunk/test/Modules/import-decl.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/test/Modules/import-decl.cpp ------------------------------------------------------------------------------ svn:keywords = Id Propchange: cfe/trunk/test/Modules/import-decl.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain From dgregor at apple.com Wed May 16 11:34:31 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 09:34:31 -0700 Subject: [cfe-commits] [PATCH] Fix ASTReader handling of ImportDecls In-Reply-To: References: Message-ID: <98E5C374-9E3C-4810-9F89-FAE325F58E71@apple.com> On May 15, 2012, at 3:55 PM, Meador Inge wrote: > Hi All, > > I came across this bug while hacking on another C FE issue. 'void > ASTDeclReader::VisitImportDecl' bumps the current index one too many. > OK? > > P.S. If it is OK, then can someone commit it for me. I don't have > write access. I moved the new test over to test/Modules and committed as r156923. Thanks! - Doug From dgregor at apple.com Wed May 16 11:50:20 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 16:50:20 -0000 Subject: [cfe-commits] r156925 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/Sema/SemaExpr.cpp test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Message-ID: <20120516165020.D2CD22A6C065@llvm.org> Author: dgregor Date: Wed May 16 11:50:20 2012 New Revision: 156925 URL: http://llvm.org/viewvc/llvm-project?rev=156925&view=rev Log: Fix code generation of variables reference expressions when mixing blocks and lambdas, based heavily on a patch from Meador Inge. Fixes PR12746 / . Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=156925&r1=156924&r2=156925&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Wed May 16 11:50:20 2012 @@ -698,7 +698,7 @@ // Compute the address of the thing we're going to move into the // block literal. llvm::Value *src; - if (ci->isNested()) { + if (BlockInfo && ci->isNested()) { // We need to use the capture from the enclosing block. const CGBlockInfo::Capture &enclosingCapture = BlockInfo->getCapture(variable); Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=156925&r1=156924&r2=156925&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed May 16 11:50:20 2012 @@ -10069,7 +10069,7 @@ // C++ [expr.prim.labda]p12: // An entity captured by a lambda-expression is odr-used (3.2) in // the scope containing the lambda-expression. - Expr *Ref = new (S.Context) DeclRefExpr(Var, false, DeclRefType, + Expr *Ref = new (S.Context) DeclRefExpr(Var, true, DeclRefType, VK_LValue, Loc); Var->setReferenced(true); Var->setUsed(true); Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm?rev=156925&r1=156924&r2=156925&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Wed May 16 11:50:20 2012 @@ -86,3 +86,25 @@ int &ir = accept_lambda_conv([](int x) { return x + 1; }); } } + +namespace PR12746 { + bool f1(int *x) { + bool (^outer)() = ^ { + auto inner = [&]() -> bool { + return x == 0; + }; + return inner(); + }; + return outer(); + } + + bool f2(int *x) { + auto outer = [&]() -> bool { + bool (^inner)() = ^ { + return x == 0; + }; + return inner(); + }; + return outer(); + } +} From dgregor at apple.com Wed May 16 12:01:33 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 17:01:33 -0000 Subject: [cfe-commits] r156926 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Message-ID: <20120516170133.B59A12A6C065@llvm.org> Author: dgregor Date: Wed May 16 12:01:33 2012 New Revision: 156926 URL: http://llvm.org/viewvc/llvm-project?rev=156926&view=rev Log: Clean up r156925, so that we only mark the capturing DeclRefExpr of a lambda as referring to a local in an enclosing scope if we're in the enclosing scope of the lambda (not it's function call operator). Also, turn the test into an IR generation test, since that's where the crashes occurred. Really fixes PR12746 / . Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm Modified: cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=156926&r1=156925&r2=156926&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed May 16 12:01:33 2012 @@ -10040,7 +10040,8 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, VarDecl *Var, QualType FieldType, QualType DeclRefType, - SourceLocation Loc) { + SourceLocation Loc, + bool RefersToEnclosingLocal) { CXXRecordDecl *Lambda = LSI->Lambda; // Build the non-static data member. @@ -10069,8 +10070,8 @@ // C++ [expr.prim.labda]p12: // An entity captured by a lambda-expression is odr-used (3.2) in // the scope containing the lambda-expression. - Expr *Ref = new (S.Context) DeclRefExpr(Var, true, DeclRefType, - VK_LValue, Loc); + Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal, + DeclRefType, VK_LValue, Loc); Var->setReferenced(true); Var->setUsed(true); @@ -10413,7 +10414,8 @@ Expr *CopyExpr = 0; if (BuildAndDiagnose) { ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType, - DeclRefType, Loc); + DeclRefType, Loc, + I == N-1); if (!Result.isInvalid()) CopyExpr = Result.take(); } Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm?rev=156926&view=auto ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm (added) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm Wed May 16 12:01:33 2012 @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -fblocks -emit-llvm -o - -triple x86_64-apple-darwin11.3 %s | FileCheck %s + +namespace PR12746 { + // CHECK: define zeroext i1 @_ZN7PR127462f1EPi + bool f1(int *x) { + // CHECK: store i8* bitcast (i1 (i8*)* @__f1_block_invoke_0 to i8*) + bool (^outer)() = ^ { + auto inner = [&]() -> bool { + return x == 0; + }; + return inner(); + }; + return outer(); + } + + // CHECK: define internal zeroext i1 @__f1_block_invoke_0 + // CHECK: call zeroext i1 @"_ZNK7PR127462f119__f1_block_invoke_03$_0clEv" + + bool f2(int *x) { + auto outer = [&]() -> bool { + bool (^inner)() = ^ { + return x == 0; + }; + return inner(); + }; + return outer(); + } +} + Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm?rev=156926&r1=156925&r2=156926&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Wed May 16 12:01:33 2012 @@ -86,25 +86,3 @@ int &ir = accept_lambda_conv([](int x) { return x + 1; }); } } - -namespace PR12746 { - bool f1(int *x) { - bool (^outer)() = ^ { - auto inner = [&]() -> bool { - return x == 0; - }; - return inner(); - }; - return outer(); - } - - bool f2(int *x) { - auto outer = [&]() -> bool { - bool (^inner)() = ^ { - return x == 0; - }; - return inner(); - }; - return outer(); - } -} From dgregor at apple.com Wed May 16 12:05:51 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 10:05:51 -0700 Subject: [cfe-commits] [PATCH] PR 12746: Code generation of variables reference expressions when mixing blocks and lambdas In-Reply-To: References: Message-ID: On May 8, 2012, at 6:18 PM, Meador Inge wrote: > Hi All, > > In PR 12746 a failing assertion was reported when mixing blocks and lambdas. > The original reproduction case looked something like: > > void foo(int *x) > { > ^() { > [&]() { > return x == 0; > }(); > }(); > } > > The following assert in 'clang::CodeGenFunction::EmitDeclRefLValue' was failing > because the variable declaration referenced in 'E' was not in the 'LocalDeclMap' > and was not marked as referring to an enclosing local: > > assert(isa(CurCodeDecl) && E->refersToEnclosingLocal()); > > This problem has been fixed by ensuring that the 'DeclRefExpr' gets marked as > referring to an enclosing local as it should be. > > While investigating this issue I noticed that the reverse nesting fails too, > but for a different reason: > > void foo(int *x) > { > [&]() { > ^() { > return x == 0; > }(); > }(); > } > > This time 'clang::CodeGen::CodeGenFunction::EmitBlockLiteral' goes to lookup > the capture information for the nested parameter 'x', but crashes because it > is actually nested in a lambda and the 'BlockInfo' is NULL. This was fixed by > adding a check to ensure 'BlockInfo' is not NULL. > > OK? I simplified the patch a bit and committed as r156925/156926. Essentially, we can compute whether the DeclRefExpr refers to an enclosing local directly in tryCaptureVariable, so it doesn't need to be passed down. Also, I moved the new test cases into the appropriate place (test/CXX/expr/expr.prim/expr.prim.lambda) and turned them into tests of IR generation, since the normal "-verify" only does semantic analysis. Thank you! - Doug From geek4civic at gmail.com Wed May 16 12:37:57 2012 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 16 May 2012 17:37:57 -0000 Subject: [cfe-commits] r156929 - /cfe/trunk/test/Tooling/clang-check-pwd.cpp Message-ID: <20120516173757.159F82A6C065@llvm.org> Author: chapuni Date: Wed May 16 12:37:56 2012 New Revision: 156929 URL: http://llvm.org/viewvc/llvm-project?rev=156929&view=rev Log: clang/test/Tooling/clang-check-pwd.cpp: Add "REQUIRES: shell". This passes on MSYS bash and Cygwin. Modified: cfe/trunk/test/Tooling/clang-check-pwd.cpp Modified: cfe/trunk/test/Tooling/clang-check-pwd.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-pwd.cpp?rev=156929&r1=156928&r2=156929&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check-pwd.cpp (original) +++ cfe/trunk/test/Tooling/clang-check-pwd.cpp Wed May 16 12:37:56 2012 @@ -8,6 +8,4 @@ // CHECK: C++ requires invalid; -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. -// FIXME: clang-check doesn't like gcc driver on cygming. -// XFAIL: cygwin,mingw32,win32 +// REQUIRES: shell From geek4civic at gmail.com Wed May 16 12:38:04 2012 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 16 May 2012 17:38:04 -0000 Subject: [cfe-commits] r156930 - in /cfe/trunk/test/Tooling: clang-check-args.cpp clang-check-builtin-headers.cpp clang-check-chdir.cpp clang-check.cpp multi-jobs.cpp Message-ID: <20120516173804.C0DE92A6C065@llvm.org> Author: chapuni Date: Wed May 16 12:38:04 2012 New Revision: 156930 URL: http://llvm.org/viewvc/llvm-project?rev=156930&view=rev Log: clang/test/Tooling: Remove XFAIL in 5 tests to unveil the real failure. FYI, they can pass on Cygwin w/o any tweaks. Modified: cfe/trunk/test/Tooling/clang-check-args.cpp cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp cfe/trunk/test/Tooling/clang-check-chdir.cpp cfe/trunk/test/Tooling/clang-check.cpp cfe/trunk/test/Tooling/multi-jobs.cpp Modified: cfe/trunk/test/Tooling/clang-check-args.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-args.cpp?rev=156930&r1=156929&r2=156930&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check-args.cpp (original) +++ cfe/trunk/test/Tooling/clang-check-args.cpp Wed May 16 12:38:04 2012 @@ -2,7 +2,3 @@ // CHECK: C++ requires invalid; - -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. -// FIXME: clang-check doesn't like gcc driver on cygming. -// XFAIL: cygwin,mingw32,win32 Modified: cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp?rev=156930&r1=156929&r2=156930&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp (original) +++ cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp Wed May 16 12:38:04 2012 @@ -10,7 +10,3 @@ // CHECK: C++ requires invalid; - -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. -// FIXME: clang-check doesn't like gcc driver on cygming. -// XFAIL: cygwin,mingw32,win32 Modified: cfe/trunk/test/Tooling/clang-check-chdir.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-chdir.cpp?rev=156930&r1=156929&r2=156930&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check-chdir.cpp (original) +++ cfe/trunk/test/Tooling/clang-check-chdir.cpp Wed May 16 12:38:04 2012 @@ -12,7 +12,3 @@ // CHECK: C++ requires invalid; - -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. -// FIXME: clang-check doesn't like gcc driver on cygming. -// XFAIL: cygwin,mingw32,win32 Modified: cfe/trunk/test/Tooling/clang-check.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check.cpp?rev=156930&r1=156929&r2=156930&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check.cpp (original) +++ cfe/trunk/test/Tooling/clang-check.cpp Wed May 16 12:38:04 2012 @@ -7,7 +7,3 @@ // CHECK: C++ requires invalid; - -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. -// FIXME: clang-check doesn't like gcc driver on cygming. -// XFAIL: cygwin,mingw32,win32 Modified: cfe/trunk/test/Tooling/multi-jobs.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/multi-jobs.cpp?rev=156930&r1=156929&r2=156930&view=diff ============================================================================== --- cfe/trunk/test/Tooling/multi-jobs.cpp (original) +++ cfe/trunk/test/Tooling/multi-jobs.cpp Wed May 16 12:38:04 2012 @@ -2,7 +2,3 @@ // CHECK: C++ requires invalid; - -// FIXME: clang-check doesn't like gcc driver on cygming. -// XFAIL: cygwin,mingw32,win32 - From dgregor at apple.com Wed May 16 13:25:43 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 11:25:43 -0700 Subject: [cfe-commits] [Patch] -Wextra-semi for semi-colon warnings with fixit for removal In-Reply-To: References: Message-ID: On May 15, 2012, at 6:43 PM, Richard Trieu wrote: > This patch will group the extra semi-colon warnings together under -Wextra-semi. A warning for the optional semi-colon after a function definition has also been added. A fixit has been added for the removal of the semi-colons. Also, contiguous semi-colons on a line will only produce one warning. Previously, each semi-colon got its own warning. _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits LGTM! - Doug From silvas at purdue.edu Wed May 16 13:40:06 2012 From: silvas at purdue.edu (Sean Silva) Date: Wed, 16 May 2012 12:40:06 -0600 Subject: [cfe-commits] [PATCH] ClangPlugin tutorial In-Reply-To: References: Message-ID: I really like this. For explaining the invocation, maybe it would be helpful to have a script like this one: https://github.com/chisophugis/clang_plugin_example/blob/82bb85397b16aa585a27ce3474bde496fbc6f50b/invocation_builder.py Basically, that script does the leg work of passing all the args to Clang and prefixing everything properly. Maybe that script could be adapted to actually exec clang with the proper command line. Usage would be like: ./clang_plugin.py ./MyPlugin.so my-plugin -- Does that sound like a good idea? --Sean Silva On Mon, May 14, 2012 at 9:16 AM, Manuel Klimek wrote: > Find a proposal for a short ClangPlugin tutorial attached. > > Cheers, > /Manuel > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120516/f10f2585/attachment.html From dgregor at apple.com Wed May 16 13:42:45 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 11:42:45 -0700 Subject: [cfe-commits] [Patch] Add a warning to catch enums with all elements having the same value In-Reply-To: References: Message-ID: <2C318FDC-958E-4BE7-80B1-6E7A12D66A36@apple.com> On May 15, 2012, at 4:10 PM, Richard Trieu wrote: > Add -Wunique-enum which will warn on enums with at least 2 elements such that all elements are the same value. This will catch enums such as: > > enum A { > FIRST = 1, > SECOND = 1 > }; Why do we need this warning? Personally, I can't recall having seen this be the source of any bugs, and it's scope is so narrow that it doesn't seem worth adding. As for the actual patch? +def warn_identical_enum_values : Warning< + "all elements of %select{anonymous enum|%1}0 have value %2">, + InGroup>, DefaultIgnore; + Default-ignore warnings are always a red flag. If this warning is important, it should be on by default. If it's not important, we shouldn't add it. + // Keep track of whther all the elements have the same value. + bool AllElementsEqual = true; + llvm::APSInt LastVal; Typo "whther". + // Keep track of whether every enum element is the same value. + if (AllElementsEqual && i > 0) { + if (InitVal.getBitWidth() > LastVal.getBitWidth()) + AllElementsEqual = InitVal == LastVal.extend(InitVal.getBitWidth()); + else if (InitVal.getBitWidth() < LastVal.getBitWidth()) + AllElementsEqual = InitVal.extend(LastVal.getBitWidth()) == LastVal; + else + AllElementsEqual = InitVal == LastVal; + } + LastVal = InitVal; + If you did this in the loop below, where we adjust the initializer values to all have the same size/# of bits, it would be easier. - Doug From klimek at google.com Wed May 16 13:46:32 2012 From: klimek at google.com (Manuel Klimek) Date: Wed, 16 May 2012 20:46:32 +0200 Subject: [cfe-commits] [PATCH] ClangPlugin tutorial In-Reply-To: References: Message-ID: On Wed, May 16, 2012 at 8:40 PM, Sean Silva wrote: > I really like this. For explaining the invocation, maybe it would be helpful > to have a script like this one: > https://github.com/chisophugis/clang_plugin_example/blob/82bb85397b16aa585a27ce3474bde496fbc6f50b/invocation_builder.py > > Basically, that script does the leg work of passing all the args to Clang > and prefixing everything properly. Maybe that script could be adapted to > actually exec clang with the proper command line. > > Usage would be like: > > ./clang_plugin.py ./MyPlugin.so my-plugin -- args> > > Does that sound like a good idea? If that script gets checked in, I think it'd be a good idea to mention it - I still think that explaining how plugins work on the lowest level provides some benefit for people who just want to do a low-level build integration... Cheers, /Manuel > > --Sean Silva > > On Mon, May 14, 2012 at 9:16 AM, Manuel Klimek wrote: >> >> Find a proposal for a short ClangPlugin tutorial attached. >> >> Cheers, >> /Manuel >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> > From ganna at apple.com Wed May 16 13:46:25 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 16 May 2012 18:46:25 -0000 Subject: [cfe-commits] r156932 - /cfe/trunk/test/Analysis/string.c Message-ID: <20120516184625.828FA2A6C065@llvm.org> Author: zaks Date: Wed May 16 13:46:25 2012 New Revision: 156932 URL: http://llvm.org/viewvc/llvm-project?rev=156932&view=rev Log: [analyzer] Revert a regression committed in r156920. This breaks the build with -triple i386-apple-darwin9. Modified: cfe/trunk/test/Analysis/string.c Modified: cfe/trunk/test/Analysis/string.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156932&r1=156931&r2=156932&view=diff ============================================================================== --- cfe/trunk/test/Analysis/string.c (original) +++ cfe/trunk/test/Analysis/string.c Wed May 16 13:46:25 2012 @@ -1062,12 +1062,11 @@ // Constrain the length of x. if (strlen(x) != value) return; - // Test relational operators. - clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} - clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} + if (strlen(x) < 2) { (void)*(char*)0; } // no-warning + if (2 > strlen(x)) { (void)*(char*)0; } // no-warning // Test equality operators. - clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} - clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} + if (strlen(x) == 1) { (void)*(char*)0; } // no-warning + if (1 == strlen(x)) { (void)*(char*)0; } // no-warning } From dgregor at apple.com Wed May 16 13:51:29 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 11:51:29 -0700 Subject: [cfe-commits] Handle missing 'typename' in function template definitions In-Reply-To: References: Message-ID: On May 15, 2012, at 6:12 PM, Richard Smith wrote: > Hi, > > The attached patch allows Clang to recover better from a missing 'typename' keyword in a function template definition: > > :1:29: error: missing 'typename' prior to dependent type name 'T::type' > template void f(T::type) {} > ^~~~~~~ > typename > > With this patch, we carry on disambiguating past such a situation. If we can't disambiguate the declaration in some other way, the absence of 'typename' is used to infer that we have a variable declaration. I've also extended the disambiguation code to inspect the token immediately after the parameter-declaration-clause to disambiguate (in the above case, the { token is used to disambiguate, and more generally we will also look for an exception-specification, ref-qualifier, cv-qualifier, etc., which cannot appear after a parenthesized initializer in a variable declaration). > > Does this seem like a reasonable approach? I like this approach. Just one trivial comment: + else if (NextToken().is(tok::amp) || NextToken().is(tok::ampamp) || + NextToken().is(tok::kw_const) || + NextToken().is(tok::kw_volatile) || + NextToken().is(tok::kw_throw) || + NextToken().is(tok::kw_noexcept) || + NextToken().is(tok::l_square) || + isCXX0XVirtSpecifier(NextToken()) || + NextToken().is(tok::l_brace) || NextToken().is(tok::kw_try) || + NextToken().is(tok::equal)) Please cache NextToken() here. - Doug -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120516/8c2165d7/attachment.html From rtrieu at google.com Wed May 16 14:05:00 2012 From: rtrieu at google.com (Richard Trieu) Date: Wed, 16 May 2012 19:05:00 -0000 Subject: [cfe-commits] r156934 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseObjc.cpp lib/Parse/Parser.cpp test/Misc/warning-flags.c test/Parser/cxx-class.cpp test/Parser/cxx-extra-semi.cpp Message-ID: <20120516190500.3A5452A6C065@llvm.org> Author: rtrieu Date: Wed May 16 14:04:59 2012 New Revision: 156934 URL: http://llvm.org/viewvc/llvm-project?rev=156934&view=rev Log: Move the warnings for extra semi-colons under -Wextra-semi. Also, added a warning for an extra semi-colon after function definitions. Added logic so that a block of semi-colons on a line will only get one warning instead of a warning for each semi-colon. Added: cfe/trunk/test/Parser/cxx-extra-semi.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Parse/ParseObjc.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/test/Misc/warning-flags.c cfe/trunk/test/Parser/cxx-class.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed May 16 14:04:59 2012 @@ -21,15 +21,16 @@ let CategoryName = "Parse Issue" in { def ext_empty_source_file : Extension<"ISO C forbids an empty source file">; -def ext_top_level_semi : Extension< - "extra ';' outside of a function">; def warn_cxx98_compat_top_level_semi : Warning< "extra ';' outside of a function is incompatible with C++98">, InGroup, DefaultIgnore; -def ext_extra_struct_semi : Extension< - "extra ';' inside a %0">; -def ext_extra_ivar_semi : Extension< - "extra ';' inside instance variable list">; +def ext_extra_semi : Extension< + "extra ';' %select{" + "outside of a function|" + "inside a %1|" + "inside instance variable list|" + "after function definition}0">, + InGroup>; def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">; def ext_plain_complex : ExtWarn< Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed May 16 14:04:59 2012 @@ -654,6 +654,17 @@ /// to the semicolon, consumes that extra token. bool ExpectAndConsumeSemi(unsigned DiagID); + /// \brief The kind of extra semi diagnostic to emit. + enum ExtraSemiKind { + OutsideFunction = 0, + InsideStruct = 1, + InstanceVariableList = 2, + AfterDefinition = 3 + }; + + /// \brief Consume any extra semi-colons until the end of the line. + void ConsumeExtraSemi(ExtraSemiKind Kind, const char* DiagMsg = ""); + //===--------------------------------------------------------------------===// // Scope manipulation Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed May 16 14:04:59 2012 @@ -2701,10 +2701,8 @@ // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { - Diag(Tok, diag::ext_extra_struct_semi) - << DeclSpec::getSpecifierName((DeclSpec::TST)TagType) - << FixItHint::CreateRemoval(Tok.getLocation()); - ConsumeToken(); + ConsumeExtraSemi(InsideStruct, + DeclSpec::getSpecifierName((DeclSpec::TST)TagType)); continue; } Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed May 16 14:04:59 2012 @@ -1929,9 +1929,8 @@ LateParsedAttrs.clear(); // Consume the ';' - it's optional unless we have a delete or default - if (Tok.is(tok::semi)) { - ConsumeToken(); - } + if (Tok.is(tok::semi)) + ConsumeExtraSemi(AfterDefinition); return; } @@ -2280,10 +2279,8 @@ // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { - Diag(Tok, diag::ext_extra_struct_semi) - << DeclSpec::getSpecifierName((DeclSpec::TST)TagType) - << FixItHint::CreateRemoval(Tok.getLocation()); - ConsumeToken(); + ConsumeExtraSemi(InsideStruct, + DeclSpec::getSpecifierName((DeclSpec::TST)TagType)); continue; } @@ -3007,10 +3004,8 @@ // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { - Diag(Tok, diag::ext_extra_struct_semi) - << DeclSpec::getSpecifierName((DeclSpec::TST)TagType) - << FixItHint::CreateRemoval(Tok.getLocation()); - ConsumeToken(); + ConsumeExtraSemi(InsideStruct, + DeclSpec::getSpecifierName((DeclSpec::TST)TagType)); continue; } Modified: cfe/trunk/lib/Parse/ParseObjc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseObjc.cpp (original) +++ cfe/trunk/lib/Parse/ParseObjc.cpp Wed May 16 14:04:59 2012 @@ -1259,9 +1259,7 @@ // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { - Diag(Tok, diag::ext_extra_ivar_semi) - << FixItHint::CreateRemoval(Tok.getLocation()); - ConsumeToken(); + ConsumeExtraSemi(InstanceVariableList); continue; } Modified: cfe/trunk/lib/Parse/Parser.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/lib/Parse/Parser.cpp (original) +++ cfe/trunk/lib/Parse/Parser.cpp Wed May 16 14:04:59 2012 @@ -202,6 +202,33 @@ return ExpectAndConsume(tok::semi, DiagID); } +void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, const char* DiagMsg) { + if (!Tok.is(tok::semi)) return; + + // AfterDefinition should only warn when placed on the same line as the + // definition. Otherwise, defer to another semi warning. + if (Kind == AfterDefinition && Tok.isAtStartOfLine()) return; + + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc = Tok.getLocation(); + ConsumeToken(); + + while ((Tok.is(tok::semi) && !Tok.isAtStartOfLine())) { + EndLoc = Tok.getLocation(); + ConsumeToken(); + } + + if (Kind == OutsideFunction && getLangOpts().CPlusPlus0x) { + Diag(StartLoc, diag::warn_cxx98_compat_top_level_semi) + << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); + return; + } + + Diag(StartLoc, diag::ext_extra_semi) + << Kind << DiagMsg << FixItHint::CreateRemoval(SourceRange(StartLoc, + EndLoc)); +} + //===----------------------------------------------------------------------===// // Error recovery. //===----------------------------------------------------------------------===// @@ -582,11 +609,7 @@ HandlePragmaPack(); return DeclGroupPtrTy(); case tok::semi: - Diag(Tok, getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_top_level_semi : diag::ext_top_level_semi) - << FixItHint::CreateRemoval(Tok.getLocation()); - - ConsumeToken(); + ConsumeExtraSemi(OutsideFunction); // TODO: Invoke action for top-level semicolon. return DeclGroupPtrTy(); case tok::r_brace: Modified: cfe/trunk/test/Misc/warning-flags.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/warning-flags.c?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/test/Misc/warning-flags.c (original) +++ cfe/trunk/test/Misc/warning-flags.c Wed May 16 14:04:59 2012 @@ -17,7 +17,7 @@ The list of warnings below should NEVER grow. It should gradually shrink to 0. -CHECK: Warnings without flags (245): +CHECK: Warnings without flags (242): CHECK-NEXT: ext_anonymous_struct_union_qualified CHECK-NEXT: ext_binary_literal CHECK-NEXT: ext_cast_fn_obj @@ -33,8 +33,6 @@ CHECK-NEXT: ext_expected_semi_decl_list CHECK-NEXT: ext_explicit_instantiation_without_qualified_id CHECK-NEXT: ext_explicit_specialization_storage_class -CHECK-NEXT: ext_extra_ivar_semi -CHECK-NEXT: ext_extra_struct_semi CHECK-NEXT: ext_forward_ref_enum CHECK-NEXT: ext_freestanding_complex CHECK-NEXT: ext_hexconstant_invalid @@ -65,7 +63,6 @@ CHECK-NEXT: ext_subscript_non_lvalue CHECK-NEXT: ext_template_arg_extra_parens CHECK-NEXT: ext_thread_before -CHECK-NEXT: ext_top_level_semi CHECK-NEXT: ext_typecheck_addrof_void CHECK-NEXT: ext_typecheck_cast_nonscalar CHECK-NEXT: ext_typecheck_cast_to_union Modified: cfe/trunk/test/Parser/cxx-class.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-class.cpp?rev=156934&r1=156933&r2=156934&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx-class.cpp (original) +++ cfe/trunk/test/Parser/cxx-class.cpp Wed May 16 14:04:59 2012 @@ -14,9 +14,9 @@ public: void m() { int l = 2; - }; + }; // expected-warning{{extra ';' after function definition}} - template void mt(T) { }; + template void mt(T) { } ; // expected-warning{{extra ';' inside a class}} virtual int vf() const volatile = 0; Added: cfe/trunk/test/Parser/cxx-extra-semi.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-extra-semi.cpp?rev=156934&view=auto ============================================================================== --- cfe/trunk/test/Parser/cxx-extra-semi.cpp (added) +++ cfe/trunk/test/Parser/cxx-extra-semi.cpp Wed May 16 14:04:59 2012 @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -Wextra-semi -verify %s +// RUN: cp %s %t +// RUN: %clang_cc1 -x c++ -Wextra-semi -fixit %t +// RUN: %clang_cc1 -x c++ -Wextra-semi -Werror %t + +class A { + void A1(); + void A2() { }; // expected-warning{{extra ';' after function definition}} + ; // expected-warning{{extra ';' inside a class}} + void A3() { }; ;; // expected-warning{{extra ';' after function definition}} + ;;;;;;; // expected-warning{{extra ';' inside a class}} + ; // expected-warning{{extra ';' inside a class}} + ; ;; ; ;;; // expected-warning{{extra ';' inside a class}} + ; ; ; ; ;; // expected-warning{{extra ';' inside a class}} + void A4(); +}; + +union B { + int a1; + int a2;; // expected-warning{{extra ';' inside a union}} +}; + +; // expected-warning{{extra ';' outside of a function}} +; ;;// expected-warning{{extra ';' outside of a function}} + From rtrieu at google.com Wed May 16 14:06:45 2012 From: rtrieu at google.com (Richard Trieu) Date: Wed, 16 May 2012 12:06:45 -0700 Subject: [cfe-commits] [Patch] -Wextra-semi for semi-colon warnings with fixit for removal In-Reply-To: References: Message-ID: On Wed, May 16, 2012 at 11:25 AM, Douglas Gregor wrote: > > On May 15, 2012, at 6:43 PM, Richard Trieu wrote: > > > This patch will group the extra semi-colon warnings together under > -Wextra-semi. A warning for the optional semi-colon after a function > definition has also been added. A fixit has been added for the removal of > the semi-colons. Also, contiguous semi-colons on a line will only produce > one warning. Previously, each semi-colon got its own warning. > _______________________________________________ > > cfe-commits mailing list > > cfe-commits at cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > LGTM! > > - Doug > Committed at r156934. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120516/74a9d4de/attachment-0001.html From akyrtzi at gmail.com Wed May 16 14:22:47 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Wed, 16 May 2012 19:22:47 -0000 Subject: [cfe-commits] r156936 - in /cfe/trunk: include/clang/AST/RecursiveASTVisitor.h tools/libclang/RecursiveASTVisitor.h Message-ID: <20120516192247.B7FA62A6C065@llvm.org> Author: akirtzidis Date: Wed May 16 14:22:47 2012 New Revision: 156936 URL: http://llvm.org/viewvc/llvm-project?rev=156936&view=rev Log: [libclang] Properly handle @encode() in RecursiveASTVisitor and traverse its type source info. Fixes indexing references inside @encode(). Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/tools/libclang/RecursiveASTVisitor.h Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=156936&r1=156935&r2=156936&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed May 16 14:22:47 2012 @@ -1241,8 +1241,7 @@ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - TypeSourceInfo *TInfo = D->getSignatureAsWritten(); - if (TInfo) + if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); // This return statement makes sure the traversal of nodes in @@ -2130,7 +2129,10 @@ DEF_TRAVERSE_STMT(GNUNullExpr, { }) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { }) DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { }) -DEF_TRAVERSE_STMT(ObjCEncodeExpr, { }) +DEF_TRAVERSE_STMT(ObjCEncodeExpr, { + if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); +}) DEF_TRAVERSE_STMT(ObjCIsaExpr, { }) DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { }) DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) Modified: cfe/trunk/tools/libclang/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/RecursiveASTVisitor.h?rev=156936&r1=156935&r2=156936&view=diff ============================================================================== --- cfe/trunk/tools/libclang/RecursiveASTVisitor.h (original) +++ cfe/trunk/tools/libclang/RecursiveASTVisitor.h Wed May 16 14:22:47 2012 @@ -1188,7 +1188,8 @@ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc())); + if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); // This return statement makes sure the traversal of nodes in // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) @@ -2079,7 +2080,10 @@ DEF_TRAVERSE_STMT(GNUNullExpr, { }) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { }) DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { }) -DEF_TRAVERSE_STMT(ObjCEncodeExpr, { }) +DEF_TRAVERSE_STMT(ObjCEncodeExpr, { + if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); +}) DEF_TRAVERSE_STMT(ObjCIsaExpr, { }) DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { }) DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) From mcrosier at apple.com Wed May 16 14:28:02 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 16 May 2012 19:28:02 -0000 Subject: [cfe-commits] r156937 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td lib/Frontend/Warnings.cpp test/Driver/warning-options.cpp Message-ID: <20120516192802.A6C2F2A6C065@llvm.org> Author: mcrosier Date: Wed May 16 14:28:02 2012 New Revision: 156937 URL: http://llvm.org/viewvc/llvm-project?rev=156937&view=rev Log: Warn about -Wno-foo where foo is an unknown warning option. This is helpful for subtle misspellings such as -Wno-unused-command-line-arguments instead of -Wno-unused-command-line-argument. Also fix the diagnostic messages to properly handle -Wno- options. Previously, the positive version was always emitted (i.e., -Wfoo was emitted for -Wno-foo). rdar://11461500 Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td cfe/trunk/lib/Frontend/Warnings.cpp cfe/trunk/test/Driver/warning-options.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=156937&r1=156936&r2=156937&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Wed May 16 14:28:02 2012 @@ -94,13 +94,13 @@ InGroup >; def warn_unknown_negative_warning_option : Warning< "unknown warning option '%0'?">, - InGroup >, DefaultIgnore; + InGroup >; def warn_unknown_warning_option_suggest : Warning< "unknown warning option '%0'; did you mean '%1'?">, InGroup >; def warn_unknown_negative_warning_option_suggest : Warning< "unknown warning option '%0'; did you mean '%1'?">, - InGroup >, DefaultIgnore; + InGroup >; def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, InGroup >; Modified: cfe/trunk/lib/Frontend/Warnings.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Warnings.cpp?rev=156937&r1=156936&r2=156937&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/Warnings.cpp (original) +++ cfe/trunk/lib/Frontend/Warnings.cpp Wed May 16 14:28:02 2012 @@ -83,6 +83,7 @@ bool SetDiagnostic = (Report == 0); for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) { StringRef Opt = Opts.Warnings[i]; + StringRef OrigOpt = Opts.Warnings[i]; // Treat -Wformat=0 as an alias for -Wno-format. if (Opt == "format=0") @@ -130,7 +131,7 @@ if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) { if (Report) Diags.Report(diag::warn_unknown_warning_specifier) - << "-Werror" << ("-W" + Opt.str()); + << "-Werror" << ("-W" + OrigOpt.str()); continue; } Specifier = Opt.substr(6); @@ -158,7 +159,7 @@ if ((Opt[12] != '=' && Opt[12] != '-') || Opt.size() == 13) { if (Report) Diags.Report(diag::warn_unknown_warning_specifier) - << "-Wfatal-errors" << ("-W" + Opt.str()); + << "-Wfatal-errors" << ("-W" + OrigOpt.str()); continue; } Specifier = Opt.substr(13); @@ -182,7 +183,7 @@ if (Report) { if (DiagIDs->getDiagnosticsInGroup(Opt, _Diags)) - EmitUnknownDiagWarning(Diags, "-W", Opt, isPositive); + EmitUnknownDiagWarning(Diags, "-W", OrigOpt, isPositive); } else { Diags.setDiagnosticGroupMapping(Opt, Mapping); } Modified: cfe/trunk/test/Driver/warning-options.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/warning-options.cpp?rev=156937&r1=156936&r2=156937&view=diff ============================================================================== --- cfe/trunk/test/Driver/warning-options.cpp (original) +++ cfe/trunk/test/Driver/warning-options.cpp Wed May 16 14:28:02 2012 @@ -2,3 +2,9 @@ // LARGE_VALUE_COPY_DEFAULT: -Wlarge-by-value-copy=64 // RUN: %clang -### -Wlarge-by-value-copy=128 %s 2>&1 | FileCheck -check-prefix=LARGE_VALUE_COPY_JOINED %s // LARGE_VALUE_COPY_JOINED: -Wlarge-by-value-copy=128 + +// RUN: %clang -c -Wmonkey -Wno-monkey -Wno-unused-command-line-arguments \ +// RUN: -Wno-unused-command-line-argument %s 2>&1 | FileCheck %s +// CHECK: unknown warning option '-Wmonkey' +// CHECK: unknown warning option '-Wno-monkey' +// CHECK: unknown warning option '-Wno-unused-command-line-arguments' From mcrosier at apple.com Wed May 16 14:42:04 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 16 May 2012 19:42:04 -0000 Subject: [cfe-commits] r156938 - in /cfe/trunk: lib/Frontend/Warnings.cpp test/Driver/warning-options.cpp Message-ID: <20120516194204.2BFA42A6C065@llvm.org> Author: mcrosier Date: Wed May 16 14:42:03 2012 New Revision: 156938 URL: http://llvm.org/viewvc/llvm-project?rev=156938&view=rev Log: Tweek r156937 a bit so that the suggestions are correct. Modified: cfe/trunk/lib/Frontend/Warnings.cpp cfe/trunk/test/Driver/warning-options.cpp Modified: cfe/trunk/lib/Frontend/Warnings.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Warnings.cpp?rev=156938&r1=156937&r2=156938&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/Warnings.cpp (original) +++ cfe/trunk/lib/Frontend/Warnings.cpp Wed May 16 14:42:03 2012 @@ -183,7 +183,8 @@ if (Report) { if (DiagIDs->getDiagnosticsInGroup(Opt, _Diags)) - EmitUnknownDiagWarning(Diags, "-W", OrigOpt, isPositive); + EmitUnknownDiagWarning(Diags, isPositive ? "-W" : "-Wno-", Opt, + isPositive); } else { Diags.setDiagnosticGroupMapping(Opt, Mapping); } Modified: cfe/trunk/test/Driver/warning-options.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/warning-options.cpp?rev=156938&r1=156937&r2=156938&view=diff ============================================================================== --- cfe/trunk/test/Driver/warning-options.cpp (original) +++ cfe/trunk/test/Driver/warning-options.cpp Wed May 16 14:42:03 2012 @@ -7,4 +7,4 @@ // RUN: -Wno-unused-command-line-argument %s 2>&1 | FileCheck %s // CHECK: unknown warning option '-Wmonkey' // CHECK: unknown warning option '-Wno-monkey' -// CHECK: unknown warning option '-Wno-unused-command-line-arguments' +// CHECK: unknown warning option '-Wno-unused-command-line-arguments'; did you mean '-Wno-unused-command-line-argument'? From dgregor at apple.com Wed May 16 14:55:51 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 12:55:51 -0700 Subject: [cfe-commits] r156937 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td lib/Frontend/Warnings.cpp test/Driver/warning-options.cpp In-Reply-To: <20120516192802.A6C2F2A6C065@llvm.org> References: <20120516192802.A6C2F2A6C065@llvm.org> Message-ID: On May 16, 2012, at 12:28 PM, Chad Rosier wrote: > Author: mcrosier > Date: Wed May 16 14:28:02 2012 > New Revision: 156937 > > URL: http://llvm.org/viewvc/llvm-project?rev=156937&view=rev > Log: > Warn about -Wno-foo where foo is an unknown warning option. This is helpful > for subtle misspellings such as -Wno-unused-command-line-arguments instead of > -Wno-unused-command-line-argument. Maybe we should do typo correction here? - Doug From mcrosier at apple.com Wed May 16 14:59:37 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 16 May 2012 12:59:37 -0700 Subject: [cfe-commits] r156937 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td lib/Frontend/Warnings.cpp test/Driver/warning-options.cpp In-Reply-To: References: <20120516192802.A6C2F2A6C065@llvm.org> Message-ID: On May 16, 2012, at 12:55 PM, Douglas Gregor wrote: > > On May 16, 2012, at 12:28 PM, Chad Rosier wrote: > >> Author: mcrosier >> Date: Wed May 16 14:28:02 2012 >> New Revision: 156937 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=156937&view=rev >> Log: >> Warn about -Wno-foo where foo is an unknown warning option. This is helpful >> for subtle misspellings such as -Wno-unused-command-line-arguments instead of >> -Wno-unused-command-line-argument. > > Maybe we should do typo correction here? We do in fact do this, but the typo correction is only emitted by the diagnostics engine if it is a warning. Chad > > - Doug > From dgregor at apple.com Wed May 16 15:04:05 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 20:04:05 -0000 Subject: [cfe-commits] r156940 - in /cfe/trunk: include/clang/Basic/TokenKinds.def test/Parser/MicrosoftExtensions.c Message-ID: <20120516200405.9A6352A6C065@llvm.org> Author: dgregor Date: Wed May 16 15:04:05 2012 New Revision: 156940 URL: http://llvm.org/viewvc/llvm-project?rev=156940&view=rev Log: Add _alignof and __builtin_alignof as aliases for __alignof in Microsoft mode, from Will Wilson! Modified: cfe/trunk/include/clang/Basic/TokenKinds.def cfe/trunk/test/Parser/MicrosoftExtensions.c Modified: cfe/trunk/include/clang/Basic/TokenKinds.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=156940&r1=156939&r2=156940&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) +++ cfe/trunk/include/clang/Basic/TokenKinds.def Wed May 16 15:04:05 2012 @@ -486,28 +486,30 @@ ALIAS("__volatile__" , volatile , KEYALL) // Microsoft extensions which should be disabled in strict conformance mode -KEYWORD(__ptr64 , KEYMS) -KEYWORD(__ptr32 , KEYMS) -KEYWORD(__w64 , KEYMS) -KEYWORD(__uuidof , KEYMS | KEYBORLAND) -KEYWORD(__try , KEYMS | KEYBORLAND) -KEYWORD(__finally , KEYMS | KEYBORLAND) -KEYWORD(__leave , KEYMS | KEYBORLAND) -KEYWORD(__int64 , KEYMS) -KEYWORD(__if_exists , KEYMS) -KEYWORD(__if_not_exists , KEYMS) -ALIAS("__int8" , char , KEYMS) -ALIAS("__int16" , short , KEYMS) -ALIAS("__int32" , int , KEYMS) -ALIAS("_asm" , asm , KEYMS) -ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) -ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) -ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND) -ALIAS("_thiscall" , __thiscall , KEYMS) -ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) -ALIAS("_inline" , inline , KEYMS) -ALIAS("_declspec" , __declspec , KEYMS) -ALIAS("__interface" , struct , KEYMS) +KEYWORD(__ptr64 , KEYMS) +KEYWORD(__ptr32 , KEYMS) +KEYWORD(__w64 , KEYMS) +KEYWORD(__uuidof , KEYMS | KEYBORLAND) +KEYWORD(__try , KEYMS | KEYBORLAND) +KEYWORD(__finally , KEYMS | KEYBORLAND) +KEYWORD(__leave , KEYMS | KEYBORLAND) +KEYWORD(__int64 , KEYMS) +KEYWORD(__if_exists , KEYMS) +KEYWORD(__if_not_exists , KEYMS) +ALIAS("__int8" , char , KEYMS) +ALIAS("__int16" , short , KEYMS) +ALIAS("__int32" , int , KEYMS) +ALIAS("_asm" , asm , KEYMS) +ALIAS("_alignof" , __alignof , KEYMS) +ALIAS("__builtin_alignof", __alignof , KEYMS) +ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) +ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) +ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND) +ALIAS("_thiscall" , __thiscall , KEYMS) +ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) +ALIAS("_inline" , inline , KEYMS) +ALIAS("_declspec" , __declspec , KEYMS) +ALIAS("__interface" , struct , KEYMS) // Borland Extensions which should be disabled in strict conformance mode. ALIAS("_pascal" , __pascal , KEYBORLAND) Modified: cfe/trunk/test/Parser/MicrosoftExtensions.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.c?rev=156940&r1=156939&r2=156940&view=diff ============================================================================== --- cfe/trunk/test/Parser/MicrosoftExtensions.c (original) +++ cfe/trunk/test/Parser/MicrosoftExtensions.c Wed May 16 15:04:05 2012 @@ -29,6 +29,11 @@ } _inline int foo99() { return 99; } +void test_ms_alignof_alias() { + unsigned int s = _alignof(int); + s = __builtin_alignof(int); +} + void *_alloca(int); void foo() { From dgregor at apple.com Wed May 16 15:05:06 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 13:05:06 -0700 Subject: [cfe-commits] [PATCH] Microsoft extension: "_alignof" alias for "__alignof" In-Reply-To: References: Message-ID: On May 7, 2012, at 10:17 AM, Will Wilson wrote: >>>> Looks fine as far as I can tell. Should we support __builtin_alignof in >>>> ms >>>> mode as well? >>> >>> Do you mean as an additional keyword alias of __alignof? >> >> >> Yes. > > Okay, I've updated the patch with the test-case to add support for > "__builtin_alignof". All tests pass locally. > > According to http://www.geoffchappell.com/studies/msvc/cl/c1xx/warnings/c4932.htm > there is a single-underscore version "_builtin_alignof" that's allowed > in MSVC if /Ze is specified. That said, in VS2010 intellisense doesn't > even seem to recognise this version, so I've only added the double > underscore version for now as it seems even MS are reticent about > supporting the more exotic form. > > This should also solve: http://llvm.org/bugs/show_bug.cgi?id=12648 Committed as r156940, thanks! - Doug From jediknil at belkadan.com Wed May 16 15:29:44 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 16 May 2012 20:29:44 -0000 Subject: [cfe-commits] r156941 - in /cfe/trunk/test/Analysis: additive-folding.cpp comparison-implicit-casts.cpp string.c Message-ID: <20120516202944.544292A6C065@llvm.org> Author: jrose Date: Wed May 16 15:29:44 2012 New Revision: 156941 URL: http://llvm.org/viewvc/llvm-project?rev=156941&view=rev Log: [analyzer] Fix test for PR12206, which was failing on i386. Added: cfe/trunk/test/Analysis/comparison-implicit-casts.cpp Modified: cfe/trunk/test/Analysis/additive-folding.cpp cfe/trunk/test/Analysis/string.c Modified: cfe/trunk/test/Analysis/additive-folding.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/additive-folding.cpp?rev=156941&r1=156940&r2=156941&view=diff ============================================================================== --- cfe/trunk/test/Analysis/additive-folding.cpp (original) +++ cfe/trunk/test/Analysis/additive-folding.cpp Wed May 16 15:29:44 2012 @@ -186,64 +186,6 @@ } -// PR12206/12510 - When SimpleSValBuilder figures out that a symbol is fully -// constrained, it should cast the value to the result type in a binary -// operation...unless the binary operation is a comparison, in which case the -// two arguments should be the same type, but won't match the result type. -// -// This is easier to trigger in C++ mode, where the comparison result type is -// 'bool' and is thus differently sized from int on pretty much every system. -// -// This is not directly related to additive folding, but we use SValBuilder's -// additive folding to tickle the bug. ExprEngine will simplify fully-constrained -// symbols, so SValBuilder will only see them if they are (a) part of an evaluated -// SymExpr (e.g. with additive folding) or (b) generated by a checker (e.g. -// unix.cstring's strlen() modelling). -void PR12206(int x) { - // Build a SymIntExpr, dependent on x. - int local = x - 1; - - // Constrain the value of x. - int value = 1 + (1 << (8 * sizeof(1 == 1))); // not representable by bool - if (x != value) return; - - // Constant-folding will turn (local+1) back into the symbol for x. - // The point of this dance is to make SValBuilder be responsible for - // turning the symbol into a ConcreteInt, rather than ExprEngine. - - // Test relational operators. - clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}} - clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}} - - // Test equality operators. - clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}} - clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}} -} - -void PR12206_truncation(signed char x) { - // Build a SymIntExpr, dependent on x. - signed char local = x - 1; - - // Constrain the value of x. - if (x != 1) return; - - // Constant-folding will turn (local+1) back into the symbol for x. - // The point of this dance is to make SValBuilder be responsible for - // turning the symbol into a ConcreteInt, rather than ExprEngine. - - // Construct a value that cannot be represented by 'char', - // but that has the same lower bits as x. - signed int value = 1 + (1 << 8); - - // Test relational operators. - clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}} - clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}} - - // Test equality operators. - clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}} - clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}} -} - void multiplicativeSanityTest(int x) { // At one point we were ignoring the *4 completely -- the constraint manager // would see x < 8 and then declare the assertion to be known false. Added: cfe/trunk/test/Analysis/comparison-implicit-casts.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/comparison-implicit-casts.cpp?rev=156941&view=auto ============================================================================== --- cfe/trunk/test/Analysis/comparison-implicit-casts.cpp (added) +++ cfe/trunk/test/Analysis/comparison-implicit-casts.cpp Wed May 16 15:29:44 2012 @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=basic -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -verify %s + +// This file runs in C++ mode so that the comparison type is 'bool', not 'int'. +void clang_analyzer_eval(int); +typedef typeof(sizeof(int)) size_t; + +// PR12206/12510 - When SimpleSValBuilder figures out that a symbol is fully +// constrained, it should cast the value to the result type in a binary +// operation...unless the binary operation is a comparison, in which case the +// two arguments should be the same type, but won't match the result type. +// +// This is not directly related to additive folding, but we use SValBuilder's +// additive folding to tickle the bug. ExprEngine will simplify fully-constrained +// symbols, so SValBuilder will only see them if they are (a) part of an evaluated +// SymExpr (e.g. with additive folding) or (b) generated by a checker (e.g. +// unix.cstring's strlen() modelling). +void PR12206(int x) { + size_t comparisonSize = sizeof(1 == 1); + + // Sanity check. This test is useless if size_t isn't bigger than bool. + clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}} + + // Build a SymIntExpr, dependent on x. + int local = x - 1; + + // Create a value that requires more bits to store than a comparison result. + int value = 1; + value <<= 8 * comparisonSize; + value += 1; + + // Constrain the value of x. + if (x != value) return; + + // Constant-folding will turn (local+1) back into the symbol for x. + // The point of this dance is to make SValBuilder be responsible for + // turning the symbol into a ConcreteInt, rather than ExprEngine. + + // Test relational operators. + clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}} + clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}} + + // Test equality operators. + clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}} + clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}} +} + +void PR12206_truncation(signed char x) { + // Build a SymIntExpr, dependent on x. + signed char local = x - 1; + + // Constrain the value of x. + if (x != 1) return; + + // Constant-folding will turn (local+1) back into the symbol for x. + // The point of this dance is to make SValBuilder be responsible for + // turning the symbol into a ConcreteInt, rather than ExprEngine. + + // Construct a value that cannot be represented by 'char', + // but that has the same lower bits as x. + signed int value = 1 + (1 << 8); + + // Test relational operators. + clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}} + clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}} + + // Test equality operators. + clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}} + clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}} +} + +// This test is insurance in case we significantly change how SymExprs are +// evaluated. +size_t strlen(const char *s); +void PR12206_strlen(const char *x) { + size_t comparisonSize = sizeof(1 == 1); + + // Sanity check. This test is useless if size_t isn't bigger than bool. + clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}} + + // Create a value that requires more bits to store than a comparison result. + size_t value = 1UL; + value <<= 8 * comparisonSize; + value += 1; + + // Constrain the length of x. + if (strlen(x) != value) return; + + // Test relational operators. + clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} + clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} + + // Test equality operators. + clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} + clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} +} Modified: cfe/trunk/test/Analysis/string.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156941&r1=156940&r2=156941&view=diff ============================================================================== --- cfe/trunk/test/Analysis/string.c (original) +++ cfe/trunk/test/Analysis/string.c Wed May 16 15:29:44 2012 @@ -1039,34 +1039,3 @@ void strncasecmp_embedded_null () { clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}} } - -//===----------------------------------------------------------------------=== -// Miscellaneous extras. -//===----------------------------------------------------------------------=== - -// See additive-folding.cpp for a description of this bug. -// This test is insurance in case we significantly change how SymExprs are -// evaluated. It isn't as good as additive-folding.cpp's version -// because it will only actually be a test on systems where -// sizeof(1 == 1) < sizeof(size_t). -// We could add a triple if it becomes necessary. -void PR12206(const char *x) { - // This test is only useful under these conditions. - size_t comparisonSize = sizeof(1 == 1); - if (sizeof(size_t) <= comparisonSize) return; - - // Create a value that requires more bits to store than a comparison result. - size_t value = 1UL; - value <<= 8 * comparisonSize; - value += 1; - - // Constrain the length of x. - if (strlen(x) != value) return; - // Test relational operators. - if (strlen(x) < 2) { (void)*(char*)0; } // no-warning - if (2 > strlen(x)) { (void)*(char*)0; } // no-warning - - // Test equality operators. - if (strlen(x) == 1) { (void)*(char*)0; } // no-warning - if (1 == strlen(x)) { (void)*(char*)0; } // no-warning -} From klimek at google.com Wed May 16 15:32:46 2012 From: klimek at google.com (Manuel Klimek) Date: Wed, 16 May 2012 22:32:46 +0200 Subject: [cfe-commits] [PATCH] Pulls diagnostics for temp file handling into the common diagnostic kinds Message-ID: As suggested on irc: Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td (revision 156808) +++ include/clang/Basic/DiagnosticDriverKinds.td (working copy) @@ -33,8 +33,6 @@ "unsupported use of internal gcc -Z option '%0'">; def err_drv_output_argument_with_multiple_files : Error< "cannot specify -o when generating multiple output files">; -def err_drv_unable_to_make_temp : Error< - "unable to make temporary file: %0">; def err_drv_unable_to_remove_file : Error< "unable to remove file: %0">; def err_drv_command_failure : Error< Index: include/clang/Basic/DiagnosticFrontendKinds.td =================================================================== --- include/clang/Basic/DiagnosticFrontendKinds.td (revision 156808) +++ include/clang/Basic/DiagnosticFrontendKinds.td (working copy) @@ -48,8 +48,6 @@ "unable to interface with target machine">; def err_fe_unable_to_open_output : Error< "unable to open output file '%0': '%1'">; -def err_fe_unable_to_rename_temp : Error< - "unable to rename temporary '%0' to output file '%1': '%2'">; def err_fe_unable_to_open_logfile : Error< "unable to open logfile file '%0': '%1'">; def err_fe_pth_file_has_no_source_header : Error< Index: include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- include/clang/Basic/DiagnosticCommonKinds.td (revision 156808) +++ include/clang/Basic/DiagnosticCommonKinds.td (working copy) @@ -108,4 +108,8 @@ "file '%0' modified since it was first processed">, DefaultFatal; def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but " "encoding is not supported">, DefaultFatal; +def err_unable_to_rename_temp : Error< + "unable to rename temporary '%0' to output file '%1': '%2'">; +def err_unable_to_make_temp : Error< + "unable to make temporary file: %0">; } Index: lib/Frontend/CompilerInstance.cpp =================================================================== --- lib/Frontend/CompilerInstance.cpp (revision 156808) +++ lib/Frontend/CompilerInstance.cpp (working copy) @@ -456,7 +456,7 @@ FileMgr->FixupRelativePath(NewOutFile); if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, NewOutFile.str())) { - getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) + getDiagnostics().Report(diag::err_unable_to_rename_temp) << it->TempFilename << it->Filename << ec.message(); bool existed; Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp (revision 156808) +++ lib/Driver/Driver.cpp (working copy) @@ -1635,7 +1635,7 @@ llvm::sys::Path P(TmpDir); P.appendComponent(Prefix); if (P.makeUnique(false, &Error)) { - Diag(clang::diag::err_drv_unable_to_make_temp) << Error; + Diag(clang::diag::err_unable_to_make_temp) << Error; return ""; } -------------- next part -------------- A non-text attachment was scrubbed... Name: diags.patch Type: application/octet-stream Size: 3076 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120516/d321c43f/attachment.obj From jediknil at belkadan.com Wed May 16 15:37:19 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 16 May 2012 16:37:19 -0400 Subject: [cfe-commits] r156932 - /cfe/trunk/test/Analysis/string.c In-Reply-To: <20120516184625.828FA2A6C065@llvm.org> References: <20120516184625.828FA2A6C065@llvm.org> Message-ID: <81D85465-0A96-4970-87EA-FD547771810F@belkadan.com> I should have known when I wrote the comment about requiring sizeof(size_t) > sizeof(1 == 1) that this was going to come back to haunt me. This worked before because we could early-exit and /avoid/ triggering warnings, but clang_analyzer_eval with -verify is a little stronger... Moved the test to a C++ file in r156941. If any platform has sizeof(size_t) == sizeof(bool), we're in trouble, but I don't think we support any of those. :-) Thanks for handling this, Anna. Jordy On May 16, 2012, at 14:46, Anna Zaks wrote: > Author: zaks > Date: Wed May 16 13:46:25 2012 > New Revision: 156932 > > URL: http://llvm.org/viewvc/llvm-project?rev=156932&view=rev > Log: > [analyzer] Revert a regression committed in r156920. > > This breaks the build with -triple i386-apple-darwin9. > > Modified: > cfe/trunk/test/Analysis/string.c > > Modified: cfe/trunk/test/Analysis/string.c > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156932&r1=156931&r2=156932&view=diff > ============================================================================== > --- cfe/trunk/test/Analysis/string.c (original) > +++ cfe/trunk/test/Analysis/string.c Wed May 16 13:46:25 2012 > @@ -1062,12 +1062,11 @@ > > // Constrain the length of x. > if (strlen(x) != value) return; > - > // Test relational operators. > - clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} > - clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} > + if (strlen(x) < 2) { (void)*(char*)0; } // no-warning > + if (2 > strlen(x)) { (void)*(char*)0; } // no-warning > > // Test equality operators. > - clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} > - clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} > + if (strlen(x) == 1) { (void)*(char*)0; } // no-warning > + if (1 == strlen(x)) { (void)*(char*)0; } // no-warning > } > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From mcrosier at apple.com Wed May 16 15:40:10 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 16 May 2012 20:40:10 -0000 Subject: [cfe-commits] r156942 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Driver/Options.td lib/Driver/Tools.cpp test/Driver/flags.c Message-ID: <20120516204010.21C9C2A6C065@llvm.org> Author: mcrosier Date: Wed May 16 15:40:09 2012 New Revision: 156942 URL: http://llvm.org/viewvc/llvm-project?rev=156942&view=rev Log: [driver] Allow the driver to directly accept the -no-implicit-float option, so that the generation of implicit floating point instructions can be disable for ARM. rdar://11409142 Modified: cfe/trunk/include/clang/Driver/CC1Options.td cfe/trunk/include/clang/Driver/Options.td cfe/trunk/lib/Driver/Tools.cpp cfe/trunk/test/Driver/flags.c Modified: cfe/trunk/include/clang/Driver/CC1Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=156942&r1=156941&r2=156942&view=diff ============================================================================== --- cfe/trunk/include/clang/Driver/CC1Options.td (original) +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed May 16 15:40:09 2012 @@ -146,8 +146,6 @@ HelpText<"The string to embed in the Dwarf debug flags record.">; def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; -def no_implicit_float : Flag<"-no-implicit-float">, - HelpText<"Don't generate implicit floating point instructions (x86-only)">; def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; def femit_coverage_notes : Flag<"-femit-coverage-notes">, Modified: cfe/trunk/include/clang/Driver/Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=156942&r1=156941&r2=156942&view=diff ============================================================================== --- cfe/trunk/include/clang/Driver/Options.td (original) +++ cfe/trunk/include/clang/Driver/Options.td Wed May 16 15:40:09 2012 @@ -800,6 +800,8 @@ def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group; def msoft_float : Flag<"-msoft-float">, Group, Flags<[CC1Option]>, HelpText<"Use software floating point">; +def no_implicit_float : Flag<"-no-implicit-float">, Flags<[CC1Option]>, + HelpText<"Don't generate implicit floating point instructions">; def msse2 : Flag<"-msse2">, Group; def msse3 : Flag<"-msse3">, Group; def msse4a : Flag<"-msse4a">, Group; Modified: cfe/trunk/lib/Driver/Tools.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=156942&r1=156941&r2=156942&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Tools.cpp (original) +++ cfe/trunk/lib/Driver/Tools.cpp Wed May 16 15:40:09 2012 @@ -755,6 +755,9 @@ if (A->getOption().matches(options::OPT_mno_global_merge)) CmdArgs.push_back("-mno-global-merge"); } + + if (Args.hasArg(options::OPT_no_implicit_float)) + CmdArgs.push_back("-no-implicit-float"); } // Get default architecture. Modified: cfe/trunk/test/Driver/flags.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/flags.c?rev=156942&r1=156941&r2=156942&view=diff ============================================================================== --- cfe/trunk/test/Driver/flags.c (original) +++ cfe/trunk/test/Driver/flags.c Wed May 16 15:40:09 2012 @@ -7,3 +7,5 @@ // RUN: %clang -target i386-apple-darwin9 -### -S -mno-soft-float %s -msoft-float 2> %t.log // RUN: grep '"-no-implicit-float"' %t.log +// RUN: %clang -target armv7-apple-darwin10 -### -S -no-implicit-float %s 2> %t.log +// RUN: grep '"-no-implicit-float"' %t.log | count 1 From dgregor at apple.com Wed May 16 15:41:40 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 16 May 2012 13:41:40 -0700 Subject: [cfe-commits] [PATCH] Pulls diagnostics for temp file handling into the common diagnostic kinds In-Reply-To: References: Message-ID: <9DD4FC31-CB7C-4ABE-A2E0-D1D76CB07537@apple.com> LGTM On May 16, 2012, at 1:32 PM, Manuel Klimek wrote: > As suggested on irc: > > Index: include/clang/Basic/DiagnosticDriverKinds.td > =================================================================== > --- include/clang/Basic/DiagnosticDriverKinds.td (revision 156808) > +++ include/clang/Basic/DiagnosticDriverKinds.td (working copy) > @@ -33,8 +33,6 @@ > "unsupported use of internal gcc -Z option '%0'">; > def err_drv_output_argument_with_multiple_files : Error< > "cannot specify -o when generating multiple output files">; > -def err_drv_unable_to_make_temp : Error< > - "unable to make temporary file: %0">; > def err_drv_unable_to_remove_file : Error< > "unable to remove file: %0">; > def err_drv_command_failure : Error< > Index: include/clang/Basic/DiagnosticFrontendKinds.td > =================================================================== > --- include/clang/Basic/DiagnosticFrontendKinds.td (revision 156808) > +++ include/clang/Basic/DiagnosticFrontendKinds.td (working copy) > @@ -48,8 +48,6 @@ > "unable to interface with target machine">; > def err_fe_unable_to_open_output : Error< > "unable to open output file '%0': '%1'">; > -def err_fe_unable_to_rename_temp : Error< > - "unable to rename temporary '%0' to output file '%1': '%2'">; > def err_fe_unable_to_open_logfile : Error< > "unable to open logfile file '%0': '%1'">; > def err_fe_pth_file_has_no_source_header : Error< > Index: include/clang/Basic/DiagnosticCommonKinds.td > =================================================================== > --- include/clang/Basic/DiagnosticCommonKinds.td (revision 156808) > +++ include/clang/Basic/DiagnosticCommonKinds.td (working copy) > @@ -108,4 +108,8 @@ > "file '%0' modified since it was first processed">, DefaultFatal; > def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but " > "encoding is not supported">, DefaultFatal; > +def err_unable_to_rename_temp : Error< > + "unable to rename temporary '%0' to output file '%1': '%2'">; > +def err_unable_to_make_temp : Error< > + "unable to make temporary file: %0">; > } > Index: lib/Frontend/CompilerInstance.cpp > =================================================================== > --- lib/Frontend/CompilerInstance.cpp (revision 156808) > +++ lib/Frontend/CompilerInstance.cpp (working copy) > @@ -456,7 +456,7 @@ > FileMgr->FixupRelativePath(NewOutFile); > if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, > NewOutFile.str())) { > - getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) > + getDiagnostics().Report(diag::err_unable_to_rename_temp) > << it->TempFilename << it->Filename << ec.message(); > > bool existed; > Index: lib/Driver/Driver.cpp > =================================================================== > --- lib/Driver/Driver.cpp (revision 156808) > +++ lib/Driver/Driver.cpp (working copy) > @@ -1635,7 +1635,7 @@ > llvm::sys::Path P(TmpDir); > P.appendComponent(Prefix); > if (P.makeUnique(false, &Error)) { > - Diag(clang::diag::err_drv_unable_to_make_temp) << Error; > + Diag(clang::diag::err_unable_to_make_temp) << Error; > return ""; > } > From klimek at google.com Wed May 16 15:55:59 2012 From: klimek at google.com (Manuel Klimek) Date: Wed, 16 May 2012 20:55:59 -0000 Subject: [cfe-commits] r156947 - in /cfe/trunk: include/clang/Basic/DiagnosticCommonKinds.td include/clang/Basic/DiagnosticDriverKinds.td include/clang/Basic/DiagnosticFrontendKinds.td lib/Driver/Driver.cpp lib/Frontend/CompilerInstance.cpp Message-ID: <20120516205559.4E2AB2A6C065@llvm.org> Author: klimek Date: Wed May 16 15:55:58 2012 New Revision: 156947 URL: http://llvm.org/viewvc/llvm-project?rev=156947&view=rev Log: Pulls diagnostics for temp file handling into the common diagnostic kinds. Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td cfe/trunk/lib/Driver/Driver.cpp cfe/trunk/lib/Frontend/CompilerInstance.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=156947&r1=156946&r2=156947&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Wed May 16 15:55:58 2012 @@ -108,4 +108,8 @@ "file '%0' modified since it was first processed">, DefaultFatal; def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but " "encoding is not supported">, DefaultFatal; +def err_unable_to_rename_temp : Error< + "unable to rename temporary '%0' to output file '%1': '%2'">; +def err_unable_to_make_temp : Error< + "unable to make temporary file: %0">; } Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=156947&r1=156946&r2=156947&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Wed May 16 15:55:58 2012 @@ -33,8 +33,6 @@ "unsupported use of internal gcc -Z option '%0'">; def err_drv_output_argument_with_multiple_files : Error< "cannot specify -o when generating multiple output files">; -def err_drv_unable_to_make_temp : Error< - "unable to make temporary file: %0">; def err_drv_unable_to_remove_file : Error< "unable to remove file: %0">; def err_drv_command_failure : Error< Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=156947&r1=156946&r2=156947&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Wed May 16 15:55:58 2012 @@ -48,8 +48,6 @@ "unable to interface with target machine">; def err_fe_unable_to_open_output : Error< "unable to open output file '%0': '%1'">; -def err_fe_unable_to_rename_temp : Error< - "unable to rename temporary '%0' to output file '%1': '%2'">; def err_fe_unable_to_open_logfile : Error< "unable to open logfile file '%0': '%1'">; def err_fe_pth_file_has_no_source_header : Error< Modified: cfe/trunk/lib/Driver/Driver.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=156947&r1=156946&r2=156947&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Driver.cpp (original) +++ cfe/trunk/lib/Driver/Driver.cpp Wed May 16 15:55:58 2012 @@ -1635,7 +1635,7 @@ llvm::sys::Path P(TmpDir); P.appendComponent(Prefix); if (P.makeUnique(false, &Error)) { - Diag(clang::diag::err_drv_unable_to_make_temp) << Error; + Diag(clang::diag::err_unable_to_make_temp) << Error; return ""; } Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=156947&r1=156946&r2=156947&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original) +++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Wed May 16 15:55:58 2012 @@ -456,7 +456,7 @@ FileMgr->FixupRelativePath(NewOutFile); if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, NewOutFile.str())) { - getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) + getDiagnostics().Report(diag::err_unable_to_rename_temp) << it->TempFilename << it->Filename << ec.message(); bool existed; From ganna at apple.com Wed May 16 15:59:17 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 16 May 2012 13:59:17 -0700 Subject: [cfe-commits] r156932 - /cfe/trunk/test/Analysis/string.c In-Reply-To: <81D85465-0A96-4970-87EA-FD547771810F@belkadan.com> References: <20120516184625.828FA2A6C065@llvm.org> <81D85465-0A96-4970-87EA-FD547771810F@belkadan.com> Message-ID: <363110EC-53D0-4809-9BAA-81BFA4927A86@apple.com> How about putting it in a separate file and test on only one target (add -triple x86_64 to the command line)? Anna. On May 16, 2012, at 1:37 PM, Jordy Rose wrote: > I should have known when I wrote the comment about requiring sizeof(size_t) > sizeof(1 == 1) that this was going to come back to haunt me. This worked before because we could early-exit and /avoid/ triggering warnings, but clang_analyzer_eval with -verify is a little stronger... > > Moved the test to a C++ file in r156941. If any platform has sizeof(size_t) == sizeof(bool), we're in trouble, but I don't think we support any of those. :-) > > Thanks for handling this, Anna. > > Jordy > > > On May 16, 2012, at 14:46, Anna Zaks wrote: > >> Author: zaks >> Date: Wed May 16 13:46:25 2012 >> New Revision: 156932 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=156932&view=rev >> Log: >> [analyzer] Revert a regression committed in r156920. >> >> This breaks the build with -triple i386-apple-darwin9. >> >> Modified: >> cfe/trunk/test/Analysis/string.c >> >> Modified: cfe/trunk/test/Analysis/string.c >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156932&r1=156931&r2=156932&view=diff >> ============================================================================== >> --- cfe/trunk/test/Analysis/string.c (original) >> +++ cfe/trunk/test/Analysis/string.c Wed May 16 13:46:25 2012 >> @@ -1062,12 +1062,11 @@ >> >> // Constrain the length of x. >> if (strlen(x) != value) return; >> - >> // Test relational operators. >> - clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} >> - clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} >> + if (strlen(x) < 2) { (void)*(char*)0; } // no-warning >> + if (2 > strlen(x)) { (void)*(char*)0; } // no-warning >> >> // Test equality operators. >> - clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} >> - clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} >> + if (strlen(x) == 1) { (void)*(char*)0; } // no-warning >> + if (1 == strlen(x)) { (void)*(char*)0; } // no-warning >> } >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > From eli.friedman at gmail.com Wed May 16 16:08:36 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 16 May 2012 14:08:36 -0700 Subject: [cfe-commits] r156942 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Driver/Options.td lib/Driver/Tools.cpp test/Driver/flags.c In-Reply-To: <20120516204010.21C9C2A6C065@llvm.org> References: <20120516204010.21C9C2A6C065@llvm.org> Message-ID: On Wed, May 16, 2012 at 1:40 PM, Chad Rosier wrote: > Author: mcrosier > Date: Wed May 16 15:40:09 2012 > New Revision: 156942 > > URL: http://llvm.org/viewvc/llvm-project?rev=156942&view=rev > Log: > [driver] Allow the driver to directly accept the -no-implicit-float option, so that the > generation of implicit floating point instructions can be disable for ARM. > rdar://11409142 > > Modified: > ? ?cfe/trunk/include/clang/Driver/CC1Options.td > ? ?cfe/trunk/include/clang/Driver/Options.td > ? ?cfe/trunk/lib/Driver/Tools.cpp > ? ?cfe/trunk/test/Driver/flags.c > > Modified: cfe/trunk/include/clang/Driver/CC1Options.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=156942&r1=156941&r2=156942&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Driver/CC1Options.td (original) > +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed May 16 15:40:09 2012 > @@ -146,8 +146,6 @@ > ? HelpText<"The string to embed in the Dwarf debug flags record.">; > ?def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, > ? HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; > -def no_implicit_float : Flag<"-no-implicit-float">, > - ?HelpText<"Don't generate implicit floating point instructions (x86-only)">; > ?def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, > ? HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; > ?def femit_coverage_notes : Flag<"-femit-coverage-notes">, > > Modified: cfe/trunk/include/clang/Driver/Options.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=156942&r1=156941&r2=156942&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Driver/Options.td (original) > +++ cfe/trunk/include/clang/Driver/Options.td Wed May 16 15:40:09 2012 > @@ -800,6 +800,8 @@ > ?def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group; > ?def msoft_float : Flag<"-msoft-float">, Group, Flags<[CC1Option]>, > ? HelpText<"Use software floating point">; > +def no_implicit_float : Flag<"-no-implicit-float">, Flags<[CC1Option]>, > + ?HelpText<"Don't generate implicit floating point instructions">; Please name the driver option -mno-implicit-float. -Eli From jediknil at belkadan.com Wed May 16 16:12:05 2012 From: jediknil at belkadan.com (Jordan Rose) Date: Wed, 16 May 2012 17:12:05 -0400 Subject: [cfe-commits] r156932 - /cfe/trunk/test/Analysis/string.c In-Reply-To: <363110EC-53D0-4809-9BAA-81BFA4927A86@apple.com> References: <20120516184625.828FA2A6C065@llvm.org> <81D85465-0A96-4970-87EA-FD547771810F@belkadan.com> <363110EC-53D0-4809-9BAA-81BFA4927A86@apple.com> Message-ID: <00D02242-CBBD-4ADB-B81E-E930A4B6DD3A@belkadan.com> I did put it in a separate file (comparison-implicit-casts.cpp). I considered adding the target triple but decided that once we were dealing with bool comparisons instead of int, it shouldn't be a problem. The test should be successful on /any/ platform now. I did just check the standard, though, and sizeof(bool) is not guaranteed to be 1. I'll have that test run under i386 and x86_64. Jordy On May 16, 2012, at 16:59, Anna Zaks wrote: > How about putting it in a separate file and test on only one target (add -triple x86_64 to the command line)? > > Anna. > On May 16, 2012, at 1:37 PM, Jordy Rose wrote: > >> I should have known when I wrote the comment about requiring sizeof(size_t) > sizeof(1 == 1) that this was going to come back to haunt me. This worked before because we could early-exit and /avoid/ triggering warnings, but clang_analyzer_eval with -verify is a little stronger... >> >> Moved the test to a C++ file in r156941. If any platform has sizeof(size_t) == sizeof(bool), we're in trouble, but I don't think we support any of those. :-) >> >> Thanks for handling this, Anna. >> >> Jordy >> >> >> On May 16, 2012, at 14:46, Anna Zaks wrote: >> >>> Author: zaks >>> Date: Wed May 16 13:46:25 2012 >>> New Revision: 156932 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=156932&view=rev >>> Log: >>> [analyzer] Revert a regression committed in r156920. >>> >>> This breaks the build with -triple i386-apple-darwin9. >>> >>> Modified: >>> cfe/trunk/test/Analysis/string.c >>> >>> Modified: cfe/trunk/test/Analysis/string.c >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156932&r1=156931&r2=156932&view=diff >>> ============================================================================== >>> --- cfe/trunk/test/Analysis/string.c (original) >>> +++ cfe/trunk/test/Analysis/string.c Wed May 16 13:46:25 2012 >>> @@ -1062,12 +1062,11 @@ >>> >>> // Constrain the length of x. >>> if (strlen(x) != value) return; >>> - >>> // Test relational operators. >>> - clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} >>> - clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} >>> + if (strlen(x) < 2) { (void)*(char*)0; } // no-warning >>> + if (2 > strlen(x)) { (void)*(char*)0; } // no-warning >>> >>> // Test equality operators. >>> - clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} >>> - clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} >>> + if (strlen(x) == 1) { (void)*(char*)0; } // no-warning >>> + if (1 == strlen(x)) { (void)*(char*)0; } // no-warning >>> } >>> >>> >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> > From mcrosier at apple.com Wed May 16 16:12:57 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 16 May 2012 14:12:57 -0700 Subject: [cfe-commits] r156942 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Driver/Options.td lib/Driver/Tools.cpp test/Driver/flags.c In-Reply-To: References: <20120516204010.21C9C2A6C065@llvm.org> Message-ID: <20F2788F-A952-430C-8207-59A0107F4672@apple.com> On May 16, 2012, at 2:08 PM, Eli Friedman wrote: > On Wed, May 16, 2012 at 1:40 PM, Chad Rosier wrote: >> Author: mcrosier >> Date: Wed May 16 15:40:09 2012 >> New Revision: 156942 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=156942&view=rev >> Log: >> [driver] Allow the driver to directly accept the -no-implicit-float option, so that the >> generation of implicit floating point instructions can be disable for ARM. >> rdar://11409142 >> >> Modified: >> cfe/trunk/include/clang/Driver/CC1Options.td >> cfe/trunk/include/clang/Driver/Options.td >> cfe/trunk/lib/Driver/Tools.cpp >> cfe/trunk/test/Driver/flags.c >> >> Modified: cfe/trunk/include/clang/Driver/CC1Options.td >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=156942&r1=156941&r2=156942&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/Driver/CC1Options.td (original) >> +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed May 16 15:40:09 2012 >> @@ -146,8 +146,6 @@ >> HelpText<"The string to embed in the Dwarf debug flags record.">; >> def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, >> HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; >> -def no_implicit_float : Flag<"-no-implicit-float">, >> - HelpText<"Don't generate implicit floating point instructions (x86-only)">; >> def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, >> HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; >> def femit_coverage_notes : Flag<"-femit-coverage-notes">, >> >> Modified: cfe/trunk/include/clang/Driver/Options.td >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=156942&r1=156941&r2=156942&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/Driver/Options.td (original) >> +++ cfe/trunk/include/clang/Driver/Options.td Wed May 16 15:40:09 2012 >> @@ -800,6 +800,8 @@ >> def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group; >> def msoft_float : Flag<"-msoft-float">, Group, Flags<[CC1Option]>, >> HelpText<"Use software floating point">; >> +def no_implicit_float : Flag<"-no-implicit-float">, Flags<[CC1Option]>, >> + HelpText<"Don't generate implicit floating point instructions">; > > Please name the driver option -mno-implicit-float. Sure that makes sense. To be more explicit, you would like the driver option to be -mno-implicit-float and the cc1 option to remain -no-implicit-float, right? Chad > > -Eli From jediknil at belkadan.com Wed May 16 16:13:36 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 16 May 2012 21:13:36 -0000 Subject: [cfe-commits] r156949 - /cfe/trunk/test/Analysis/comparison-implicit-casts.cpp Message-ID: <20120516211336.7C3FC2A6C065@llvm.org> Author: jrose Date: Wed May 16 16:13:36 2012 New Revision: 156949 URL: http://llvm.org/viewvc/llvm-project?rev=156949&view=rev Log: Add triples for test. Modified: cfe/trunk/test/Analysis/comparison-implicit-casts.cpp Modified: cfe/trunk/test/Analysis/comparison-implicit-casts.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/comparison-implicit-casts.cpp?rev=156949&r1=156948&r2=156949&view=diff ============================================================================== --- cfe/trunk/test/Analysis/comparison-implicit-casts.cpp (original) +++ cfe/trunk/test/Analysis/comparison-implicit-casts.cpp Wed May 16 16:13:36 2012 @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=basic -verify %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=basic -triple i386-apple-darwin9 -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=basic -triple x86_64-apple-darwin9 -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple i386-apple-darwin9 -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple x86_64-apple-darwin9 -verify %s // This file runs in C++ mode so that the comparison type is 'bool', not 'int'. void clang_analyzer_eval(int); From klimek at google.com Wed May 16 16:16:50 2012 From: klimek at google.com (Manuel Klimek) Date: Wed, 16 May 2012 23:16:50 +0200 Subject: [cfe-commits] [PATCH] Add OverwriteChangedFiles to the Rewriter In-Reply-To: References: Message-ID: On Tue, May 15, 2012 at 8:39 PM, Douglas Gregor wrote: > > On May 11, 2012, at 4:33 AM, Manuel Klimek wrote: > >> On Tue, May 8, 2012 at 11:49 AM, Manuel Klimek wrote: >>> On Thu, May 3, 2012 at 6:40 PM, Manuel Klimek wrote: >>>> as requested by Doug in the clangRefactoring review... in addition, >>>> this patch adds a unit test for the Rewriter (into Tooling/ so we >>>> don't link yet another unit test), and pulls out a RewriterTestContext >>>> which I need for clangRefactoring when it's checked in - but it's also >>>> really nice to unit test Rewriter functionality... >> >> Inlining the patch in the hope that that speeds up review :) >> >> First, the changed code: >> >> Index: include/clang/Rewrite/Rewriter.h >> =================================================================== >> --- include/clang/Rewrite/Rewriter.h ? ?(revision 156059) >> +++ include/clang/Rewrite/Rewriter.h ? ?(working copy) >> @@ -279,6 +279,13 @@ >> ? buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } >> ? buffer_iterator buffer_end() { return RewriteBuffers.end(); } >> >> + ?/// SaveFiles - Save all changed files to disk. >> + ?/// >> + ?/// Returns whether all changes were saves successfully. >> + ?/// Outputs diagnostics via the source manager's diagnostic engine >> + ?/// in case of an error. >> + ?bool OverwriteChangedFiles(); >> + > > I think that's spelled: > > ?bool overwriteChangedFiles(); > > Also, we usually use a return of "true" to indicate that there was an error. > > >> private: >> ? unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; >> }; >> Index: lib/Rewrite/Rewriter.cpp >> =================================================================== >> --- lib/Rewrite/Rewriter.cpp ? ?(revision 156059) >> +++ lib/Rewrite/Rewriter.cpp ? ?(working copy) >> @@ -15,8 +15,10 @@ >> #include "clang/Rewrite/Rewriter.h" >> #include "clang/AST/Stmt.h" >> #include "clang/AST/Decl.h" >> +#include "clang/Basic/FileManager.h" >> +#include "clang/Basic/SourceManager.h" >> #include "clang/Lex/Lexer.h" >> -#include "clang/Basic/SourceManager.h" >> +#include "clang/Frontend/FrontendDiagnostic.h" >> #include "llvm/ADT/SmallString.h" >> using namespace clang; >> >> @@ -412,3 +414,23 @@ >> >> ? return false; >> } >> + >> +bool Rewriter::OverwriteChangedFiles() { >> + ?bool AllWritten = true; >> + ?for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { >> + ? ?const FileEntry *Entry = >> + ? ? ? ?getSourceMgr().getFileEntryForID(I->first); >> + ? ?std::string ErrorInfo; >> + ? ?llvm::raw_fd_ostream FileStream( >> + ? ? ? ?Entry->getName(), ErrorInfo, llvm::raw_fd_ostream::F_Binary); >> + ? ?if (!ErrorInfo.empty()) { >> + ? ? ?getSourceMgr().getDiagnostics().Report(clang::diag::err_fe_unable_to_open_output) >> + ? ? ? ?<< Entry->getName() << ErrorInfo; >> + ? ? ?AllWritten = false; >> + ? ? ?continue; >> + ? ?} >> + ? ?I->second.write(FileStream); >> + ? ?FileStream.flush(); >> + ?} >> + ?return AllWritten; >> +} > > It would be better to write the data to a temporary file and then rename it, like we do with other outputs. All done. PTAL. Thanks! /Manuel Index: include/clang/Rewrite/Rewriter.h =================================================================== --- include/clang/Rewrite/Rewriter.h (revision 156947) +++ include/clang/Rewrite/Rewriter.h (working copy) @@ -279,6 +279,13 @@ buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } buffer_iterator buffer_end() { return RewriteBuffers.end(); } + /// SaveFiles - Save all changed files to disk. + /// + /// Returns whether not all changes were saved successfully. + /// Outputs diagnostics via the source manager's diagnostic engine + /// in case of an error. + bool overwriteChangedFiles(); + private: unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; }; Index: lib/Rewrite/Rewriter.cpp =================================================================== --- lib/Rewrite/Rewriter.cpp (revision 156947) +++ lib/Rewrite/Rewriter.cpp (working copy) @@ -15,9 +15,12 @@ #include "clang/Rewrite/Rewriter.h" #include "clang/AST/Stmt.h" #include "clang/AST/Decl.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" -#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" using namespace clang; raw_ostream &RewriteBuffer::write(raw_ostream &os) const { @@ -412,3 +415,68 @@ return false; } + +// A wrapper for a file stream that atomically overwrites the target. +// +// Creates a file output stream for a temporary file in the constructor, +// which is later accessible via getStream() if ok() return true. +// Flushes the stream and moves the temporary file to the target location +// in the destructor. +class AtomicallyMovedFile { +public: + AtomicallyMovedFile(DiagnosticsEngine &Diagnostics, StringRef Filename, + bool &AllWritten) + : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) { + TempFilename = Filename; + TempFilename += "-%%%%%%%%"; + int FD; + if (llvm::sys::fs::unique_file(TempFilename.str(), FD, TempFilename, + /*makeAbsolute=*/true, 0664)) { + AllWritten = false; + Diagnostics.Report(clang::diag::err_unable_to_make_temp) + << TempFilename; + } else { + FileStream.reset(new llvm::raw_fd_ostream(FD, /*shouldClose=*/true)); + } + } + + ~AtomicallyMovedFile() { + if (!ok()) return; + + FileStream->flush(); + if (llvm::error_code ec = + llvm::sys::fs::rename(TempFilename.str(), Filename)) { + AllWritten = false; + Diagnostics.Report(clang::diag::err_unable_to_rename_temp) + << TempFilename << Filename << ec.message(); + bool existed; + // If the remove fails, there's not a lot we can do - this is already an + // error. + llvm::sys::fs::remove(TempFilename.str(), existed); + } + } + + bool ok() { return FileStream; } + llvm::raw_ostream &getStream() { return *FileStream; } + +private: + DiagnosticsEngine &Diagnostics; + StringRef Filename; + SmallString<128> TempFilename; + OwningPtr FileStream; + bool &AllWritten; +}; + +bool Rewriter::overwriteChangedFiles() { + bool AllWritten = true; + for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { + const FileEntry *Entry = + getSourceMgr().getFileEntryForID(I->first); + AtomicallyMovedFile File(getSourceMgr().getDiagnostics(), Entry->getName(), + AllWritten); + if (File.ok()) { + I->second.write(File.getStream()); + } + } + return !AllWritten; +} From eli.friedman at gmail.com Wed May 16 16:18:10 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 16 May 2012 14:18:10 -0700 Subject: [cfe-commits] r156942 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Driver/Options.td lib/Driver/Tools.cpp test/Driver/flags.c In-Reply-To: <20F2788F-A952-430C-8207-59A0107F4672@apple.com> References: <20120516204010.21C9C2A6C065@llvm.org> <20F2788F-A952-430C-8207-59A0107F4672@apple.com> Message-ID: On Wed, May 16, 2012 at 2:12 PM, Chad Rosier wrote: > > On May 16, 2012, at 2:08 PM, Eli Friedman wrote: > >> On Wed, May 16, 2012 at 1:40 PM, Chad Rosier wrote: >>> Author: mcrosier >>> Date: Wed May 16 15:40:09 2012 >>> New Revision: 156942 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=156942&view=rev >>> Log: >>> [driver] Allow the driver to directly accept the -no-implicit-float option, so that the >>> generation of implicit floating point instructions can be disable for ARM. >>> rdar://11409142 >>> >>> Modified: >>> ? ?cfe/trunk/include/clang/Driver/CC1Options.td >>> ? ?cfe/trunk/include/clang/Driver/Options.td >>> ? ?cfe/trunk/lib/Driver/Tools.cpp >>> ? ?cfe/trunk/test/Driver/flags.c >>> >>> Modified: cfe/trunk/include/clang/Driver/CC1Options.td >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=156942&r1=156941&r2=156942&view=diff >>> ============================================================================== >>> --- cfe/trunk/include/clang/Driver/CC1Options.td (original) >>> +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed May 16 15:40:09 2012 >>> @@ -146,8 +146,6 @@ >>> ? HelpText<"The string to embed in the Dwarf debug flags record.">; >>> ?def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, >>> ? HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; >>> -def no_implicit_float : Flag<"-no-implicit-float">, >>> - ?HelpText<"Don't generate implicit floating point instructions (x86-only)">; >>> ?def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, >>> ? HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; >>> ?def femit_coverage_notes : Flag<"-femit-coverage-notes">, >>> >>> Modified: cfe/trunk/include/clang/Driver/Options.td >>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=156942&r1=156941&r2=156942&view=diff >>> ============================================================================== >>> --- cfe/trunk/include/clang/Driver/Options.td (original) >>> +++ cfe/trunk/include/clang/Driver/Options.td Wed May 16 15:40:09 2012 >>> @@ -800,6 +800,8 @@ >>> ?def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group; >>> ?def msoft_float : Flag<"-msoft-float">, Group, Flags<[CC1Option]>, >>> ? HelpText<"Use software floating point">; >>> +def no_implicit_float : Flag<"-no-implicit-float">, Flags<[CC1Option]>, >>> + ?HelpText<"Don't generate implicit floating point instructions">; >> >> Please name the driver option -mno-implicit-float. > > Sure that makes sense. ?To be more explicit, you would like the driver option to be -mno-implicit-float and the cc1 option to remain -no-implicit-float, right? I don't really care what the -cc1 option is... -Eli From mcrosier at apple.com Wed May 16 16:19:55 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 16 May 2012 21:19:55 -0000 Subject: [cfe-commits] r156950 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Driver/Options.td lib/Driver/Tools.cpp test/Driver/flags.c Message-ID: <20120516211955.512892A6C065@llvm.org> Author: mcrosier Date: Wed May 16 16:19:55 2012 New Revision: 156950 URL: http://llvm.org/viewvc/llvm-project?rev=156950&view=rev Log: Rename the driver option to -mno-implicit-float, per Eli's suggestion. Modified: cfe/trunk/include/clang/Driver/CC1Options.td cfe/trunk/include/clang/Driver/Options.td cfe/trunk/lib/Driver/Tools.cpp cfe/trunk/test/Driver/flags.c Modified: cfe/trunk/include/clang/Driver/CC1Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=156950&r1=156949&r2=156950&view=diff ============================================================================== --- cfe/trunk/include/clang/Driver/CC1Options.td (original) +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed May 16 16:19:55 2012 @@ -146,6 +146,8 @@ HelpText<"The string to embed in the Dwarf debug flags record.">; def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; +def no_implicit_float : Flag<"-no-implicit-float">, + HelpText<"Don't generate implicit floating point instructions">; def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; def femit_coverage_notes : Flag<"-femit-coverage-notes">, Modified: cfe/trunk/include/clang/Driver/Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=156950&r1=156949&r2=156950&view=diff ============================================================================== --- cfe/trunk/include/clang/Driver/Options.td (original) +++ cfe/trunk/include/clang/Driver/Options.td Wed May 16 16:19:55 2012 @@ -800,7 +800,7 @@ def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group; def msoft_float : Flag<"-msoft-float">, Group, Flags<[CC1Option]>, HelpText<"Use software floating point">; -def no_implicit_float : Flag<"-no-implicit-float">, Flags<[CC1Option]>, +def mno_implicit_float : Flag<"-mno-implicit-float">, HelpText<"Don't generate implicit floating point instructions">; def msse2 : Flag<"-msse2">, Group; def msse3 : Flag<"-msse3">, Group; Modified: cfe/trunk/lib/Driver/Tools.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=156950&r1=156949&r2=156950&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Tools.cpp (original) +++ cfe/trunk/lib/Driver/Tools.cpp Wed May 16 16:19:55 2012 @@ -756,7 +756,7 @@ CmdArgs.push_back("-mno-global-merge"); } - if (Args.hasArg(options::OPT_no_implicit_float)) + if (Args.hasArg(options::OPT_mno_implicit_float)) CmdArgs.push_back("-no-implicit-float"); } Modified: cfe/trunk/test/Driver/flags.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/flags.c?rev=156950&r1=156949&r2=156950&view=diff ============================================================================== --- cfe/trunk/test/Driver/flags.c (original) +++ cfe/trunk/test/Driver/flags.c Wed May 16 16:19:55 2012 @@ -7,5 +7,5 @@ // RUN: %clang -target i386-apple-darwin9 -### -S -mno-soft-float %s -msoft-float 2> %t.log // RUN: grep '"-no-implicit-float"' %t.log -// RUN: %clang -target armv7-apple-darwin10 -### -S -no-implicit-float %s 2> %t.log +// RUN: %clang -target armv7-apple-darwin10 -### -S -mno-implicit-float %s 2> %t.log // RUN: grep '"-no-implicit-float"' %t.log | count 1 From mcrosier at apple.com Wed May 16 16:21:21 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 16 May 2012 14:21:21 -0700 Subject: [cfe-commits] r156942 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Driver/Options.td lib/Driver/Tools.cpp test/Driver/flags.c In-Reply-To: References: <20120516204010.21C9C2A6C065@llvm.org> <20F2788F-A952-430C-8207-59A0107F4672@apple.com> Message-ID: <0C643DBD-A768-45BE-BD34-4CB3D045D1CC@apple.com> On May 16, 2012, at 2:18 PM, Eli Friedman wrote: > On Wed, May 16, 2012 at 2:12 PM, Chad Rosier wrote: >> >> On May 16, 2012, at 2:08 PM, Eli Friedman wrote: >> >>> On Wed, May 16, 2012 at 1:40 PM, Chad Rosier wrote: >>>> Author: mcrosier >>>> Date: Wed May 16 15:40:09 2012 >>>> New Revision: 156942 >>>> >>>> URL: http://llvm.org/viewvc/llvm-project?rev=156942&view=rev >>>> Log: >>>> [driver] Allow the driver to directly accept the -no-implicit-float option, so that the >>>> generation of implicit floating point instructions can be disable for ARM. >>>> rdar://11409142 >>>> >>>> Modified: >>>> cfe/trunk/include/clang/Driver/CC1Options.td >>>> cfe/trunk/include/clang/Driver/Options.td >>>> cfe/trunk/lib/Driver/Tools.cpp >>>> cfe/trunk/test/Driver/flags.c >>>> >>>> Modified: cfe/trunk/include/clang/Driver/CC1Options.td >>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=156942&r1=156941&r2=156942&view=diff >>>> ============================================================================== >>>> --- cfe/trunk/include/clang/Driver/CC1Options.td (original) >>>> +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed May 16 15:40:09 2012 >>>> @@ -146,8 +146,6 @@ >>>> HelpText<"The string to embed in the Dwarf debug flags record.">; >>>> def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, >>>> HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; >>>> -def no_implicit_float : Flag<"-no-implicit-float">, >>>> - HelpText<"Don't generate implicit floating point instructions (x86-only)">; >>>> def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, >>>> HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; >>>> def femit_coverage_notes : Flag<"-femit-coverage-notes">, >>>> >>>> Modified: cfe/trunk/include/clang/Driver/Options.td >>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=156942&r1=156941&r2=156942&view=diff >>>> ============================================================================== >>>> --- cfe/trunk/include/clang/Driver/Options.td (original) >>>> +++ cfe/trunk/include/clang/Driver/Options.td Wed May 16 15:40:09 2012 >>>> @@ -800,6 +800,8 @@ >>>> def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group; >>>> def msoft_float : Flag<"-msoft-float">, Group, Flags<[CC1Option]>, >>>> HelpText<"Use software floating point">; >>>> +def no_implicit_float : Flag<"-no-implicit-float">, Flags<[CC1Option]>, >>>> + HelpText<"Don't generate implicit floating point instructions">; >>> >>> Please name the driver option -mno-implicit-float. >> >> Sure that makes sense. To be more explicit, you would like the driver option to be -mno-implicit-float and the cc1 option to remain -no-implicit-float, right? > > I don't really care what the -cc1 option is? Fixed in r156950. Chad > -Eli From will at indefiant.com Wed May 16 16:31:51 2012 From: will at indefiant.com (Will Wilson) Date: Wed, 16 May 2012 23:31:51 +0200 Subject: [cfe-commits] [PATCH] Add support to VS debugger for previewing SmallString<> In-Reply-To: References: <68D25C0E-4310-48E3-9F5F-F73B79CE66B2@belkadan.com> Message-ID: On 3 May 2012 19:40, Will Wilson wrote: >>>>> For Visual Studio users: Here's little patch to the >>>>> clangVisualizers.txt that allows the contents of a SmallString to be >>>>> seen in string form, rather than (somewhat less usefully) as a >>>>> SmallVector. >>>> >>>> I assume this wouldn't work for SmallStrings that include embedded >>>> '\0' characters? Though I suppose we don't do any better for StringRef >>>> either, so perhaps that's not a priority. >>> >>> Unfortunately not, I can't find any support for anything other than >>> basic zero-terminated strings in the syntax. >> >> I don't know anything about VS, really, but SmallStrings are not usually null-terminated. Have you tested this when there is definitely something after the string? > > Yes, in such cases you see whatever follows the string data. Therefore > (as with StringRef) you need to be careful interpreting the string > data in the debugger preview. That said, I'd far rather have the > utility of seeing it displayed as a string with garbage at the end > than have to interpret it as an array of characters. And either way, > you may still view it as an array by expanding the string node to show > the underlying view of the SmallVector<> which also lets you see the > true extent of it. > > So it's definitely imperfect, but better than nothing :) Any thoughts on getting this committed? It's pretty minor but helpful. Incidentally, I could look at writing a custom debug plugin in the future to deal better with StringRef and it's relatives in VS. - Will. From will at indefiant.com Wed May 16 16:36:33 2012 From: will at indefiant.com (Will Wilson) Date: Wed, 16 May 2012 23:36:33 +0200 Subject: [cfe-commits] [PATCH] Allow typedef with unnecessary "typename" when ms-extensions are enabled. In-Reply-To: References: Message-ID: On 15 May 2012 00:48, Richard Smith wrote: > On Sat, May 12, 2012 at 7:18 AM, Will Wilson wrote: >> >> > This is still only producing a warning if 'typename' is followed by >> > something which isn't a type name in MS mode. We should reject this: >> > >> > int n; int k = typename n; >> >> Thanks for the review. I've updated the patch to only issue the >> warning if an annotated typename was parsed, otherwise it defaults to >> the error case. I've also updated the MS test cases. See what you >> think... > > > Thanks, I've committed this as r156786. I tweaked it slightly to only return > 'false' if we managed to produce a (type) annotation. Thanks! I've also closed http://llvm.org/bugs/show_bug.cgi?id=12715 as fixed. Cheers, Will. From ganna at apple.com Wed May 16 16:47:47 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 16 May 2012 14:47:47 -0700 Subject: [cfe-commits] r156930 - in /cfe/trunk/test/Tooling: clang-check-args.cpp clang-check-builtin-headers.cpp clang-check-chdir.cpp clang-check.cpp multi-jobs.cpp In-Reply-To: <20120516173804.C0DE92A6C065@llvm.org> References: <20120516173804.C0DE92A6C065@llvm.org> Message-ID: <8956E5B7-3B36-4FAC-876C-220795D51083@apple.com> These are failing on one of our internal bots called i386-xp-msvc9. Let me know if you need more info. Anna. On May 16, 2012, at 10:38 AM, NAKAMURA Takumi wrote: > Author: chapuni > Date: Wed May 16 12:38:04 2012 > New Revision: 156930 > > URL: http://llvm.org/viewvc/llvm-project?rev=156930&view=rev > Log: > clang/test/Tooling: Remove XFAIL in 5 tests to unveil the real failure. > > FYI, they can pass on Cygwin w/o any tweaks. > > Modified: > cfe/trunk/test/Tooling/clang-check-args.cpp > cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp > cfe/trunk/test/Tooling/clang-check-chdir.cpp > cfe/trunk/test/Tooling/clang-check.cpp > cfe/trunk/test/Tooling/multi-jobs.cpp > > Modified: cfe/trunk/test/Tooling/clang-check-args.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-args.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check-args.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check-args.cpp Wed May 16 12:38:04 2012 > @@ -2,7 +2,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp Wed May 16 12:38:04 2012 > @@ -10,7 +10,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/clang-check-chdir.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-chdir.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check-chdir.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check-chdir.cpp Wed May 16 12:38:04 2012 > @@ -12,7 +12,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/clang-check.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check.cpp Wed May 16 12:38:04 2012 > @@ -7,7 +7,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/multi-jobs.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/multi-jobs.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/multi-jobs.cpp (original) > +++ cfe/trunk/test/Tooling/multi-jobs.cpp Wed May 16 12:38:04 2012 > @@ -2,7 +2,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > - > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/cfe-commits/attachments/20120516/1d8233a8/attachment.html From echristo at apple.com Wed May 16 17:02:36 2012 From: echristo at apple.com (Eric Christopher) Date: Wed, 16 May 2012 22:02:36 -0000 Subject: [cfe-commits] r156953 - /cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Message-ID: <20120516220236.60EDE2A6C065@llvm.org> Author: echristo Date: Wed May 16 17:02:36 2012 New Revision: 156953 URL: http://llvm.org/viewvc/llvm-project?rev=156953&view=rev Log: Remove unnecessary temporary. Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=156953&r1=156952&r2=156953&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Wed May 16 17:02:36 2012 @@ -688,9 +688,7 @@ } llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys); - - llvm::DIType DbgTy = DBuilder.createSubroutineType(Unit, EltTypeArray); - return DbgTy; + return DBuilder.createSubroutineType(Unit, EltTypeArray); } From ahatanaka at mips.com Wed May 16 17:06:47 2012 From: ahatanaka at mips.com (Akira Hatanaka) Date: Wed, 16 May 2012 22:06:47 -0000 Subject: [cfe-commits] r156954 - /cfe/trunk/test/CodeGen/2008-01-25-ByValReadNone.c Message-ID: <20120516220647.77A0D2A6C065@llvm.org> Author: ahatanak Date: Wed May 16 17:06:47 2012 New Revision: 156954 URL: http://llvm.org/viewvc/llvm-project?rev=156954&view=rev Log: XFAIL this test on MIPS. Since r156650, clang has stopped emitting byval arguments for MIPS targets. Modified: cfe/trunk/test/CodeGen/2008-01-25-ByValReadNone.c Modified: cfe/trunk/test/CodeGen/2008-01-25-ByValReadNone.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/2008-01-25-ByValReadNone.c?rev=156954&r1=156953&r2=156954&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/2008-01-25-ByValReadNone.c (original) +++ cfe/trunk/test/CodeGen/2008-01-25-ByValReadNone.c Wed May 16 17:06:47 2012 @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -emit-llvm -o - %s | not grep readonly // RUN: %clang_cc1 -emit-llvm -o - %s | not grep readnone -// XFAIL: arm +// XFAIL: arm,mips // The struct being passed byval means that we cannot mark the // function readnone. Readnone would allow stores to the arg to From geek4civic at gmail.com Wed May 16 17:14:15 2012 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 16 May 2012 22:14:15 -0000 Subject: [cfe-commits] r156957 - in /cfe/trunk/test/Tooling: clang-check-args.cpp clang-check-builtin-headers.cpp clang-check-chdir.cpp clang-check.cpp multi-jobs.cpp Message-ID: <20120516221415.1A8BC2A6C065@llvm.org> Author: chapuni Date: Wed May 16 17:14:14 2012 New Revision: 156957 URL: http://llvm.org/viewvc/llvm-project?rev=156957&view=rev Log: clang/test/Tooling: Remark as XFAIL again in 5 tests for msvc hosts. FIXME: JSON doesn't like path separator '\', on Win32 hosts. Modified: cfe/trunk/test/Tooling/clang-check-args.cpp cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp cfe/trunk/test/Tooling/clang-check-chdir.cpp cfe/trunk/test/Tooling/clang-check.cpp cfe/trunk/test/Tooling/multi-jobs.cpp Modified: cfe/trunk/test/Tooling/clang-check-args.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-args.cpp?rev=156957&r1=156956&r2=156957&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check-args.cpp (original) +++ cfe/trunk/test/Tooling/clang-check-args.cpp Wed May 16 17:14:14 2012 @@ -2,3 +2,6 @@ // CHECK: C++ requires invalid; + +// FIXME: JSON doesn't like path separator '\', on Win32 hosts. +// XFAIL: win32 Modified: cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp?rev=156957&r1=156956&r2=156957&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp (original) +++ cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp Wed May 16 17:14:14 2012 @@ -10,3 +10,6 @@ // CHECK: C++ requires invalid; + +// FIXME: JSON doesn't like path separator '\', on Win32 hosts. +// XFAIL: win32 Modified: cfe/trunk/test/Tooling/clang-check-chdir.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-chdir.cpp?rev=156957&r1=156956&r2=156957&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check-chdir.cpp (original) +++ cfe/trunk/test/Tooling/clang-check-chdir.cpp Wed May 16 17:14:14 2012 @@ -12,3 +12,6 @@ // CHECK: C++ requires invalid; + +// FIXME: JSON doesn't like path separator '\', on Win32 hosts. +// XFAIL: win32 Modified: cfe/trunk/test/Tooling/clang-check.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check.cpp?rev=156957&r1=156956&r2=156957&view=diff ============================================================================== --- cfe/trunk/test/Tooling/clang-check.cpp (original) +++ cfe/trunk/test/Tooling/clang-check.cpp Wed May 16 17:14:14 2012 @@ -7,3 +7,6 @@ // CHECK: C++ requires invalid; + +// FIXME: JSON doesn't like path separator '\', on Win32 hosts. +// XFAIL: win32 Modified: cfe/trunk/test/Tooling/multi-jobs.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/multi-jobs.cpp?rev=156957&r1=156956&r2=156957&view=diff ============================================================================== --- cfe/trunk/test/Tooling/multi-jobs.cpp (original) +++ cfe/trunk/test/Tooling/multi-jobs.cpp Wed May 16 17:14:14 2012 @@ -2,3 +2,6 @@ // CHECK: C++ requires invalid; + +// FIXME: JSON doesn't like path separator '\', on Win32 hosts. +// XFAIL: win32 From geek4civic at gmail.com Wed May 16 17:18:51 2012 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Thu, 17 May 2012 07:18:51 +0900 Subject: [cfe-commits] r156930 - in /cfe/trunk/test/Tooling: clang-check-args.cpp clang-check-builtin-headers.cpp clang-check-chdir.cpp clang-check.cpp multi-jobs.cpp In-Reply-To: <8956E5B7-3B36-4FAC-876C-220795D51083@apple.com> References: <20120516173804.C0DE92A6C065@llvm.org> <8956E5B7-3B36-4FAC-876C-220795D51083@apple.com> Message-ID: Anna, sorry for inconvenience. Marking XFAIL again in r156957. I have private patches for them but they are still incomplete to commit them. ...Takumi 2012/5/17 Anna Zaks : > These are failing on one of our internal bots called?i386-xp-msvc9. > > Let me know if you need more info. > Anna. > On May 16, 2012, at 10:38 AM, NAKAMURA Takumi wrote: > > Author: chapuni > Date: Wed May 16 12:38:04 2012 > New Revision: 156930 > > URL: http://llvm.org/viewvc/llvm-project?rev=156930&view=rev > Log: > clang/test/Tooling: Remove XFAIL in 5 tests to unveil the real failure. > > FYI, they can pass on Cygwin w/o any tweaks. > > Modified: > ???cfe/trunk/test/Tooling/clang-check-args.cpp > ???cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp > ???cfe/trunk/test/Tooling/clang-check-chdir.cpp > ???cfe/trunk/test/Tooling/clang-check.cpp > ???cfe/trunk/test/Tooling/multi-jobs.cpp > > Modified: cfe/trunk/test/Tooling/clang-check-args.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-args.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check-args.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check-args.cpp Wed May 16 12:38:04 2012 > @@ -2,7 +2,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check-builtin-headers.cpp Wed May 16 > 12:38:04 2012 > @@ -10,7 +10,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/clang-check-chdir.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-chdir.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check-chdir.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check-chdir.cpp Wed May 16 12:38:04 2012 > @@ -12,7 +12,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/clang-check.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/clang-check.cpp (original) > +++ cfe/trunk/test/Tooling/clang-check.cpp Wed May 16 12:38:04 2012 > @@ -7,7 +7,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: JSON doesn't like path separator '\', on Win32 hosts. > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > > Modified: cfe/trunk/test/Tooling/multi-jobs.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/multi-jobs.cpp?rev=156930&r1=156929&r2=156930&view=diff > ============================================================================== > --- cfe/trunk/test/Tooling/multi-jobs.cpp (original) > +++ cfe/trunk/test/Tooling/multi-jobs.cpp Wed May 16 12:38:04 2012 > @@ -2,7 +2,3 @@ > > // CHECK: C++ requires > invalid; > - > -// FIXME: clang-check doesn't like gcc driver on cygming. > -// XFAIL: cygwin,mingw32,win32 > - > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > From dblaikie at gmail.com Wed May 16 17:28:47 2012 From: dblaikie at gmail.com (David Blaikie) Date: Wed, 16 May 2012 22:28:47 -0000 Subject: [cfe-commits] r156959 - /cfe/trunk/utils/clangVisualizers.txt Message-ID: <20120516222847.CE2472A6C065@llvm.org> Author: dblaikie Date: Wed May 16 17:28:47 2012 New Revision: 156959 URL: http://llvm.org/viewvc/llvm-project?rev=156959&view=rev Log: SmallString Visual Studio visualizer by Will Wilson. Modified: cfe/trunk/utils/clangVisualizers.txt Modified: cfe/trunk/utils/clangVisualizers.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/clangVisualizers.txt?rev=156959&r1=156958&r2=156959&view=diff ============================================================================== --- cfe/trunk/utils/clangVisualizers.txt (original) +++ cfe/trunk/utils/clangVisualizers.txt Wed May 16 17:28:47 2012 @@ -53,6 +53,11 @@ ) } +llvm::SmallString<*>{ + preview ([$e.BeginX,s]) + stringview ([$e.BeginX,sb]) +} + llvm::StringRef{ preview ([$e.Data,s]) stringview ([$e.Data,sb]) From dblaikie at gmail.com Wed May 16 17:31:10 2012 From: dblaikie at gmail.com (David Blaikie) Date: Wed, 16 May 2012 15:31:10 -0700 Subject: [cfe-commits] [PATCH] Add support to VS debugger for previewing SmallString<> In-Reply-To: References: <68D25C0E-4310-48E3-9F5F-F73B79CE66B2@belkadan.com> Message-ID: On Wed, May 16, 2012 at 2:31 PM, Will Wilson wrote: > On 3 May 2012 19:40, Will Wilson wrote: >>>>>> For Visual Studio users: Here's little patch to the >>>>>> clangVisualizers.txt that allows the contents of a SmallString to be >>>>>> seen in string form, rather than (somewhat less usefully) as a >>>>>> SmallVector. >>>>> >>>>> I assume this wouldn't work for SmallStrings that include embedded >>>>> '\0' characters? Though I suppose we don't do any better for StringRef >>>>> either, so perhaps that's not a priority. >>>> >>>> Unfortunately not, I can't find any support for anything other than >>>> basic zero-terminated strings in the syntax. >>> >>> I don't know anything about VS, really, but SmallStrings are not usually null-terminated. Have you tested this when there is definitely something after the string? >> >> Yes, in such cases you see whatever follows the string data. Therefore >> (as with StringRef) you need to be careful interpreting the string >> data in the debugger preview. That said, I'd far rather have the >> utility of seeing it displayed as a string with garbage at the end >> than have to interpret it as an array of characters. And either way, >> you may still view it as an array by expanding the string node to show >> the underlying view of the SmallVector<> which also lets you see the >> true extent of it. >> >> So it's definitely imperfect, but better than nothing :) > > Any thoughts on getting this committed? It's pretty minor but helpful. Sorry, just lost track of it. Committed as r156959. > Incidentally, I could look at writing a custom debug plugin in the > future to deal better with StringRef and it's relatives in VS. Sounds good - I don't personally use VS for development, but happy to throw these in. [maybe I mentioned this already & it was refuted, but: It'd be nice if they could use some common functionality (it's weird that visualizing a derived class can't use a base class's visualization behavior by default... but perhaps that makes sense, I'm not sure - if not by default, perhaps explicitly just by casting to the base)] From richard-llvm at metafoo.co.uk Wed May 16 18:40:18 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Wed, 16 May 2012 23:40:18 -0000 Subject: [cfe-commits] r156963 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseTentative.cpp test/CXX/except/except.spec/p5-pointers.cpp test/SemaCXX/unknown-type-name.cpp Message-ID: <20120516234018.25A382A6C065@llvm.org> Author: rsmith Date: Wed May 16 18:40:17 2012 New Revision: 156963 URL: http://llvm.org/viewvc/llvm-project?rev=156963&view=rev Log: Recover better from a missing 'typename' in a function template definition. Disambiguate past such a potential problem, and use the absence of 'typename' to break ties in favor of a parenthesized thingy being an initializer, if nothing else in the declaration disambiguates it as declaring a function. Modified: cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseTentative.cpp cfe/trunk/test/CXX/except/except.spec/p5-pointers.cpp cfe/trunk/test/SemaCXX/unknown-type-name.cpp Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=156963&r1=156962&r2=156963&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed May 16 18:40:17 2012 @@ -1753,7 +1753,8 @@ /// BracedCastResult. /// Doesn't consume tokens. TPResult - isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False()); + isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False(), + bool *HasMissingTypename = 0); // "Tentative parsing" functions, used for disambiguation. If a parsing error // is encountered they will return TPResult::Error(). @@ -1762,13 +1763,13 @@ // that more tentative parsing is necessary for disambiguation. // They all consume tokens, so backtracking should be used after calling them. - TPResult TryParseDeclarationSpecifier(); + TPResult TryParseDeclarationSpecifier(bool *HasMissingTypename = 0); TPResult TryParseSimpleDeclaration(bool AllowForRangeDecl); TPResult TryParseTypeofSpecifier(); TPResult TryParseProtocolQualifiers(); TPResult TryParseInitDeclaratorList(); TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true); - TPResult TryParseParameterDeclarationClause(); + TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = 0); TPResult TryParseFunctionDeclarator(); TPResult TryParseBracketDeclarator(); Modified: cfe/trunk/lib/Parse/ParseTentative.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=156963&r1=156962&r2=156963&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTentative.cpp (original) +++ cfe/trunk/lib/Parse/ParseTentative.cpp Wed May 16 18:40:17 2012 @@ -827,6 +827,10 @@ /// be either a decl-specifier or a function-style cast, and TPResult::Error() /// if a parsing error was found and reported. /// +/// If HasMissingTypename is provided, a name with a dependent scope specifier +/// will be treated as ambiguous if the 'typename' keyword is missing. If this +/// happens, *HasMissingTypename will be set to 'true'. +/// /// decl-specifier: /// storage-class-specifier /// type-specifier @@ -918,7 +922,8 @@ /// [GNU] restrict /// Parser::TPResult -Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult) { +Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, + bool *HasMissingTypename) { switch (Tok.getKind()) { case tok::identifier: // foo::bar // Check for need to substitute AltiVec __vector keyword @@ -936,7 +941,7 @@ return (!getLangOpts().ObjC1 && Next.is(tok::identifier)) ? TPResult::True() : TPResult::False(); } - return isCXXDeclarationSpecifier(BracedCastResult); + return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); case tok::coloncolon: { // ::foo::bar const Token &Next = NextToken(); @@ -950,7 +955,7 @@ // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) return TPResult::Error(); - return isCXXDeclarationSpecifier(BracedCastResult); + return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); // decl-specifier: // storage-class-specifier @@ -1052,12 +1057,20 @@ bool isIdentifier = Tok.is(tok::identifier); TPResult TPR = TPResult::False(); if (!isIdentifier) - TPR = isCXXDeclarationSpecifier(BracedCastResult); + TPR = isCXXDeclarationSpecifier(BracedCastResult, + HasMissingTypename); PA.Revert(); if (isIdentifier || TPR == TPResult::True() || TPR == TPResult::Error()) return TPResult::Error(); + + if (HasMissingTypename) { + // We can't tell whether this is a missing 'typename' or a valid + // expression. + *HasMissingTypename = true; + return TPResult::Ambiguous(); + } } } return TPResult::False(); @@ -1221,21 +1234,24 @@ return TPResult::Error(); } -Parser::TPResult Parser::TryParseDeclarationSpecifier() { - TPResult TPR = isCXXDeclarationSpecifier(); +Parser::TPResult +Parser::TryParseDeclarationSpecifier(bool *HasMissingTypename) { + TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), + HasMissingTypename); if (TPR != TPResult::Ambiguous()) return TPR; if (Tok.is(tok::kw_typeof)) TryParseTypeofSpecifier(); else { + if (Tok.is(tok::annot_cxxscope)) + ConsumeToken(); ConsumeToken(); if (getLangOpts().ObjC1 && Tok.is(tok::less)) TryParseProtocolQualifiers(); } - assert(Tok.is(tok::l_paren) && "Expected '('!"); return TPResult::Ambiguous(); } @@ -1263,9 +1279,28 @@ TentativeParsingAction PA(*this); ConsumeParen(); - TPResult TPR = TryParseParameterDeclarationClause(); - if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) - TPR = TPResult::False(); + bool InvalidAsDeclaration = false; + TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration); + if (TPR == TPResult::Ambiguous()) { + if (Tok.isNot(tok::r_paren)) + TPR = TPResult::False(); + else { + const Token &Next = NextToken(); + if (Next.is(tok::amp) || Next.is(tok::ampamp) || + Next.is(tok::kw_const) || Next.is(tok::kw_volatile) || + Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) || + Next.is(tok::l_square) || isCXX0XVirtSpecifier(Next) || + Next.is(tok::l_brace) || Next.is(tok::kw_try) || + Next.is(tok::equal)) + // The next token cannot appear after a constructor-style initializer, + // and can appear next in a function definition. This must be a function + // declarator. + TPR = TPResult::True(); + else if (InvalidAsDeclaration) + // Use the absence of 'typename' as a tie-breaker. + TPR = TPResult::False(); + } + } SourceLocation TPLoc = Tok.getLocation(); PA.Revert(); @@ -1303,7 +1338,8 @@ /// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt] /// attributes[opt] '=' assignment-expression /// -Parser::TPResult Parser::TryParseParameterDeclarationClause() { +Parser::TPResult +Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration) { if (Tok.is(tok::r_paren)) return TPResult::True(); @@ -1336,7 +1372,7 @@ // decl-specifier-seq // A parameter-declaration's initializer must be preceded by an '=', so // decl-specifier-seq '{' is not a parameter in C++11. - TPResult TPR = TryParseDeclarationSpecifier(); + TPResult TPR = TryParseDeclarationSpecifier(InvalidAsDeclaration); if (TPR != TPResult::Ambiguous()) return TPR; Modified: cfe/trunk/test/CXX/except/except.spec/p5-pointers.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p5-pointers.cpp?rev=156963&r1=156962&r2=156963&view=diff ============================================================================== --- cfe/trunk/test/CXX/except/except.spec/p5-pointers.cpp (original) +++ cfe/trunk/test/CXX/except/except.spec/p5-pointers.cpp Wed May 16 18:40:17 2012 @@ -65,9 +65,9 @@ void (*(*t7)())() throw(B1) = &s8; // valid void (*(*t8)())() throw(A) = &s8; // expected-error {{return types differ}} void (*(*t9)())() throw(D) = &s8; // expected-error {{return types differ}} - void (*t10)(void (*)() throw(B1)) = &s9; // valid expected-warning{{disambiguated}} - void (*t11)(void (*)() throw(A)) = &s9; // expected-error {{argument types differ}} expected-warning{{disambiguated}} - void (*t12)(void (*)() throw(D)) = &s9; // expected-error {{argument types differ}} expected-warning{{disambiguated}} + void (*t10)(void (*)() throw(B1)) = &s9; // valid + void (*t11)(void (*)() throw(A)) = &s9; // expected-error {{argument types differ}} + void (*t12)(void (*)() throw(D)) = &s9; // expected-error {{argument types differ}} } // Member function stuff Modified: cfe/trunk/test/SemaCXX/unknown-type-name.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unknown-type-name.cpp?rev=156963&r1=156962&r2=156963&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/unknown-type-name.cpp (original) +++ cfe/trunk/test/SemaCXX/unknown-type-name.cpp Wed May 16 18:40:17 2012 @@ -22,6 +22,11 @@ type f(); type g(); + + static int n; + static type m; + static int h(T::type, int); // expected-error{{missing 'typename'}} + static int h(T::type x, char); // expected-error{{missing 'typename'}} }; template @@ -31,11 +36,49 @@ A::type A::f() { return type(); } // expected-error{{missing 'typename'}} template +void f(T::type) { } // expected-error{{missing 'typename'}} + +template +void g(T::type x) { } // expected-error{{missing 'typename'}} + +template +void f(T::type, int) { } // expected-error{{missing 'typename'}} + +template +void f(T::type x, char) { } // expected-error{{missing 'typename'}} + +template void f(int, T::type) { } // expected-error{{missing 'typename'}} template +void f(char, T::type x) { } // expected-error{{missing 'typename'}} + +template void f(int, T::type, int) { } // expected-error{{missing 'typename'}} +template +void f(int, T::type x, char) { } // expected-error{{missing 'typename'}} + +template int A::n(T::value); // ok +template +A::type // expected-error{{missing 'typename'}} +A::m(T::value, 0); // ok + +template int A::h(T::type, int) {} // expected-error{{missing 'typename'}} +template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}} + +template int h(T::type, int); // expected-error{{missing 'typename'}} +template int h(T::type x, char); // expected-error{{missing 'typename'}} + +template int junk1(T::junk); // expected-error{{declared as a template}} +template int junk2(T::junk) throw(); // expected-error{{missing 'typename'}} +template int junk3(T::junk) = delete; // expected-error{{missing 'typename'}} expected-warning{{C++11}} +template int junk4(T::junk j); // expected-error{{missing 'typename'}} + +// FIXME: We can tell this was intended to be a function because it does not +// have a dependent nested name specifier. +template int i(T::type, int()); // expected-error{{variable 'i' declared as a template}} + // FIXME: We know which type specifier should have been specified here. Provide // a fix-it to add 'typename A::type' template From richard at metafoo.co.uk Wed May 16 18:41:28 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Wed, 16 May 2012 16:41:28 -0700 Subject: [cfe-commits] Handle missing 'typename' in function template definitions In-Reply-To: References: Message-ID: On Wed, May 16, 2012 at 11:51 AM, Douglas Gregor wrote: > > On May 15, 2012, at 6:12 PM, Richard Smith wrote: > > Hi, > > The attached patch allows Clang to recover better from a missing > 'typename' keyword in a function template definition: > > :1:29: error: missing 'typename' prior to dependent type name > 'T::type' > template void f(T::type) {} > ^~~~~~~ > typename > > With this patch, we carry on disambiguating past such a situation. If we > can't disambiguate the declaration in some other way, the absence of > 'typename' is used to infer that we have a variable declaration. I've also > extended the disambiguation code to inspect the token immediately after the > parameter-declaration-clause to disambiguate (in the above case, the {token is used to disambiguate, and more generally we will also look for an > exception-specification, ref-qualifier, cv-qualifier, etc., which cannot > appear after a parenthesized initializer in a variable declaration). > > Does this seem like a reasonable approach? > > > I like this approach. Just one trivial comment: > > + else if (NextToken().is(tok::amp) || NextToken().is(tok::ampamp) || > + NextToken().is(tok::kw_const) || > + NextToken().is(tok::kw_volatile) || > + NextToken().is(tok::kw_throw) || > + NextToken().is(tok::kw_noexcept) || > + NextToken().is(tok::l_square) || > + isCXX0XVirtSpecifier(NextToken()) || > + NextToken().is(tok::l_brace) || NextToken().is(tok::kw