From chandlerc at gmail.com Mon Feb 20 00:06:45 2012 From: chandlerc at gmail.com (Chandler Carruth) Date: Mon, 20 Feb 2012 00:06:45 -0800 Subject: [cfe-commits] [PATCH] Fixing include order for Windows In-Reply-To: References: Message-ID: On Sun, Feb 19, 2012 at 8:04 PM, Aaron Ballman wrote: > Here's what we've figured out so far. > > Several platform SDK header files include intrin.h from Visual Studio. > This file declares all of the intrinsics used by MSVC, including > chip-specific intrinsics (MMX, SSE, etc) as well as > platform-independent intrinsics (Interlocked***, etc). > > A full list of intrinsics is documented on MSDN at > and > > > We need to come up with our own intrin.h that supports Microsoft's so > that we can compile Win32 applications (and Microsoft's STL > implementation). Here is an initial cut at adding an MSVC compatible 'intrin.h' builtin header. I've left a FIXME to fill in the MS-specific intrinsics. This should at least provide a place to begin fleshing out the intrinsics. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: msvc_intrin_header.patch Type: text/x-patch Size: 3139 bytes Desc: not available URL: From chandlerc at gmail.com Mon Feb 20 00:07:20 2012 From: chandlerc at gmail.com (Chandler Carruth) Date: Mon, 20 Feb 2012 00:07:20 -0800 Subject: [cfe-commits] [PATCH] Fixing include order for Windows In-Reply-To: References: Message-ID: On Mon, Feb 20, 2012 at 12:06 AM, Chandler Carruth wrote: > On Sun, Feb 19, 2012 at 8:04 PM, Aaron Ballman wrote: > >> Here's what we've figured out so far. >> >> Several platform SDK header files include intrin.h from Visual Studio. >> This file declares all of the intrinsics used by MSVC, including >> chip-specific intrinsics (MMX, SSE, etc) as well as >> platform-independent intrinsics (Interlocked***, etc). >> >> A full list of intrinsics is documented on MSDN at >> and >> >> >> We need to come up with our own intrin.h that supports Microsoft's so >> that we can compile Win32 applications (and Microsoft's STL >> implementation). > > > Here is an initial cut at adding an MSVC compatible 'intrin.h' builtin > header. I've left a FIXME to fill in the MS-specific intrinsics. This > should at least provide a place to begin fleshing out the intrinsics. > Just to emphasize, this is completely untested. =] Just finished typing it up w/o all the weird include_next logic. -------------- next part -------------- An HTML attachment was scrubbed... URL: From rzg at apple.com Mon Feb 20 01:44:01 2012 From: rzg at apple.com (Ryan Govostes) Date: Mon, 20 Feb 2012 01:44:01 -0800 Subject: [cfe-commits] r150306 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp lib/StaticAnalyzer/Checkers/CMakeLists.txt lib/StaticAnalyzer/Checkers/Checkers.td test/Analysis/bool-assignment.cpp test/Analysis/bool-assignment2.c In-Reply-To: <3164C109-A5D2-434C-BEB6-76DBA6E7F967@belkadan.com> References: <20120211163209.A2DBE1BE003@llvm.org> <3164C109-A5D2-434C-BEB6-76DBA6E7F967@belkadan.com> Message-ID: On Feb 17, 2012, at 1:11 AM, Jordy Rose wrote: > Nice idea for a checker. The one thing I'm wondering is why you decided to use this less than / greater than approach...it might not matter here, but in general statements about equality and inequality are a bit easier for the analyzer to reason about than less than and greater than. It requires the same number of checks, too: Hi Jordy, Thanks. This is my first checker and the patch I submitted is the result of a few iterations with Ted. Indeed I originally wrote it using equality and inequality as you suggested, but Ted recommended the approach used now: > [...] I can say that you are definitely going into territory where the current solver isn't going to handle this well. It currently doesn't reason about arbitrary disjunctions. We currently accomplish that feat in the static analyzer by bifurcating states. So, we settled on (x <= 1) && (x >= 0) as you see in the patch. Best, Ryan -------------- next part -------------- An HTML attachment was scrubbed... URL: From sebastian.redl at getdesigned.at Mon Feb 20 01:46:28 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Mon, 20 Feb 2012 10:46:28 +0100 Subject: [cfe-commits] [PATCH] Fixing include order for Windows In-Reply-To: References: Message-ID: <4F421674.2020003@getdesigned.at> On 20.02.2012 09:06, Chandler Carruth wrote: > Here is an initial cut at adding an MSVC compatible 'intrin.h' builtin > header. I've left a FIXME to fill in the MS-specific intrinsics. This > should at least provide a place to begin fleshing out the intrinsics. > > +/* Unless we're compiling targeting MSVC platform, this header shouldn't even > + **exist*. If there is a system header with the same name, defer to that, > + * etherwise produce an error for the user. > + */ > +#ifndef _MSC_VER > +# if defined(__has_inclued_next)&& __has_inclued_next() > +# include_next > +# else > + s/inclued/include/ Sebastian -------------- next part -------------- An HTML attachment was scrubbed... URL: From rafael.espindola at gmail.com Mon Feb 20 04:24:13 2012 From: rafael.espindola at gmail.com (=?UTF-8?Q?Rafael_Esp=C3=ADndola?=) Date: Mon, 20 Feb 2012 07:24:13 -0500 Subject: [cfe-commits] [patch][pr12001] Avoid increasing visibility in some cases In-Reply-To: References: <4F41B060.9020500@gmail.com> <4F41B9E8.4020407@gmail.com> Message-ID: 2012/2/19 Nico Weber : > Thanks, Rafael! > > I verified that the components build of chromium/linux, and the > "normal" build of chromium/linux and mac continue to work. In > addition, the components build of chromium/mac starts to work with > this patch (with some changes on the chromium side). Hooray :-) What changes were needed on your side? > The patch looks similar what I was trying locally, so as far as I can > tell it looks good. (You have more testcases though :-) ). Yes, I started with your patch, but moved the logic to a new function. > Nico Cheers, Rafael From clattner at apple.com Mon Feb 20 04:58:01 2012 From: clattner at apple.com (Chris Lattner) Date: Mon, 20 Feb 2012 04:58:01 -0800 Subject: [cfe-commits] [patch] Don't mark libc++ functions as always_inline in debug mode. In-Reply-To: References: <134AE1F7-FF9C-4637-85E8-1EA7A9BCC0CE@apple.com> Message-ID: <3FE6C3D7-AFF4-42A8-9AD8-9A9ACCB59A7F@apple.com> Why are these functions marked always-inline in the first place? -Chris On Feb 19, 2012, at 7:24 PM, Jeffrey Yasskin wrote: > Really, even if libc++ is bug-free, it'll confuse users if debugging > it in -O0 mode produces strange line jumps. > > If NDEBUG is the wrong macro, would it make sense to provide a > LIBCXX_DEBUG flag to move the inlining decisions to clang? > > On Sun, Feb 19, 2012 at 6:57 PM, Howard Hinnant wrote: >> On Feb 19, 2012, at 9:30 PM, Jeffrey Yasskin wrote: >> >>> This patch may not be quite right, since the always_inline macros seem >>> to also have visibility effects, which this patch would block. I also >>> had to build with an explicit -UNDEBUG since cmake appears to add >>> -DNDEBUG regardless of whether the build mode requests it. >>> >>> Jeffrey >>> >> >> I can't commit this one. The presumption is that NDEBUG is up to the client to turn on and off for his own purposes, and that libc++ does not need to be debugged by him. I realize that libc++ has bugs. But the goal is for it to not have bugs, and when it does need to be debugged, a libc++ developer such as myself will do it. >> >> Howard >> > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From nobled at dreamwidth.org Mon Feb 20 06:00:23 2012 From: nobled at dreamwidth.org (Dylan Noblesmith) Date: Mon, 20 Feb 2012 14:00:23 -0000 Subject: [cfe-commits] r150958 - in /cfe/trunk: examples/clang-interpreter/ examples/wpa/ include/clang/AST/ include/clang/Basic/ include/clang/Frontend/ include/clang/Lex/ include/clang/StaticAnalyzer/Core/BugReporter/ include/clang/StaticAnalyzer/Core/PathSensitive/ lib/ARCMigrate/ lib/Basic/ lib/Frontend/ lib/Lex/ lib/StaticAnalyzer/Core/ tools/arcmt-test/ tools/driver/ tools/libclang/ unittests/Basic/ unittests/Lex/ Message-ID: <20120220140025.1F5A02A6C12F@llvm.org> Author: nobled Date: Mon Feb 20 08:00:23 2012 New Revision: 150958 URL: http://llvm.org/viewvc/llvm-project?rev=150958&view=rev Log: Basic: import IntrusiveRefCntPtr<> into clang namespace The class name is long enough without the llvm:: added. Also bring in RefCountedBase and RefCountedBaseVPTR. Modified: cfe/trunk/examples/clang-interpreter/main.cpp cfe/trunk/examples/wpa/clang-wpa.cpp cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/Basic/Diagnostic.h cfe/trunk/include/clang/Basic/DiagnosticIDs.h cfe/trunk/include/clang/Basic/FileManager.h cfe/trunk/include/clang/Basic/LLVM.h cfe/trunk/include/clang/Basic/LangOptions.h cfe/trunk/include/clang/Basic/SourceManager.h cfe/trunk/include/clang/Basic/TargetInfo.h cfe/trunk/include/clang/Frontend/ASTUnit.h cfe/trunk/include/clang/Frontend/CompilerInstance.h cfe/trunk/include/clang/Frontend/CompilerInvocation.h cfe/trunk/include/clang/Frontend/Utils.h cfe/trunk/include/clang/Lex/ModuleMap.h cfe/trunk/include/clang/Lex/Preprocessor.h cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h cfe/trunk/lib/ARCMigrate/ARCMT.cpp cfe/trunk/lib/Basic/Diagnostic.cpp cfe/trunk/lib/Frontend/ASTMerge.cpp cfe/trunk/lib/Frontend/ASTUnit.cpp cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp cfe/trunk/lib/Frontend/CompilerInstance.cpp cfe/trunk/lib/Frontend/CompilerInvocation.cpp cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp cfe/trunk/lib/Frontend/FrontendAction.cpp cfe/trunk/lib/Frontend/Warnings.cpp cfe/trunk/lib/Lex/ModuleMap.cpp cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp cfe/trunk/tools/arcmt-test/arcmt-test.cpp cfe/trunk/tools/driver/cc1_main.cpp cfe/trunk/tools/driver/cc1as_main.cpp cfe/trunk/tools/driver/driver.cpp cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp cfe/trunk/tools/libclang/Indexing.cpp cfe/trunk/tools/libclang/IndexingContext.h cfe/trunk/unittests/Basic/SourceManagerTest.cpp cfe/trunk/unittests/Lex/LexerTest.cpp Modified: cfe/trunk/examples/clang-interpreter/main.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/examples/clang-interpreter/main.cpp (original) +++ cfe/trunk/examples/clang-interpreter/main.cpp Mon Feb 20 08:00:23 2012 @@ -72,7 +72,7 @@ TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); DiagnosticsEngine Diags(DiagID, DiagClient); Driver TheDriver(Path.str(), llvm::sys::getDefaultTargetTriple(), "a.out", /*IsProduction=*/false, Diags); Modified: cfe/trunk/examples/wpa/clang-wpa.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/wpa/clang-wpa.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/examples/wpa/clang-wpa.cpp (original) +++ cfe/trunk/examples/wpa/clang-wpa.cpp Mon Feb 20 08:00:23 2012 @@ -90,7 +90,7 @@ return 0; DiagnosticOptions DiagOpts; - llvm::IntrusiveRefCntPtr Diags + IntrusiveRefCntPtr Diags = CompilerInstance::createDiagnostics(DiagOpts, argc, argv); for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { const std::string &InFile = InputFilenames[i]; Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Feb 20 08:00:23 2012 @@ -81,7 +81,7 @@ /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. -class ASTContext : public llvm::RefCountedBase { +class ASTContext : public RefCountedBase { ASTContext &this_() { return *this; } mutable std::vector Types; Modified: cfe/trunk/include/clang/Basic/Diagnostic.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Diagnostic.h (original) +++ cfe/trunk/include/clang/Basic/Diagnostic.h Mon Feb 20 08:00:23 2012 @@ -105,7 +105,7 @@ /// "report warnings as errors" and passes them off to the DiagnosticConsumer /// for reporting to the user. DiagnosticsEngine is tied to one translation unit /// and one SourceManager. -class DiagnosticsEngine : public llvm::RefCountedBase { +class DiagnosticsEngine : public RefCountedBase { public: /// Level - The level of the diagnostic, after it has been through mapping. enum Level { @@ -161,7 +161,7 @@ unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation // backtrace stack, 0 -> no limit. ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? - llvm::IntrusiveRefCntPtr Diags; + IntrusiveRefCntPtr Diags; DiagnosticConsumer *Client; bool OwnsDiagClient; SourceManager *SourceMgr; @@ -306,12 +306,12 @@ public: explicit DiagnosticsEngine( - const llvm::IntrusiveRefCntPtr &Diags, + const IntrusiveRefCntPtr &Diags, DiagnosticConsumer *client = 0, bool ShouldOwnClient = true); ~DiagnosticsEngine(); - const llvm::IntrusiveRefCntPtr &getDiagnosticIDs() const { + const IntrusiveRefCntPtr &getDiagnosticIDs() const { return Diags; } Modified: cfe/trunk/include/clang/Basic/DiagnosticIDs.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticIDs.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticIDs.h (original) +++ cfe/trunk/include/clang/Basic/DiagnosticIDs.h Mon Feb 20 08:00:23 2012 @@ -109,7 +109,7 @@ /// \brief Used for handling and querying diagnostic IDs. Can be used and shared /// by multiple Diagnostics for multiple translation units. -class DiagnosticIDs : public llvm::RefCountedBase { +class DiagnosticIDs : public RefCountedBase { public: /// Level - The level of the diagnostic, after it has been through mapping. enum Level { Modified: cfe/trunk/include/clang/Basic/FileManager.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/FileManager.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/FileManager.h (original) +++ cfe/trunk/include/clang/Basic/FileManager.h Mon Feb 20 08:00:23 2012 @@ -110,7 +110,7 @@ /// properties, such as uniquing files based on "inode", so that a file with two /// names (e.g. symlinked) will be treated as a single file. /// -class FileManager : public llvm::RefCountedBase { +class FileManager : public RefCountedBase { FileSystemOptions FileSystemOpts; class UniqueDirContainer; Modified: cfe/trunk/include/clang/Basic/LLVM.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LLVM.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/LLVM.h (original) +++ cfe/trunk/include/clang/Basic/LLVM.h Mon Feb 20 08:00:23 2012 @@ -29,6 +29,12 @@ template class SmallVector; template class SmallVectorImpl; + // Reference counting. + template class IntrusiveRefCntPtr; + template struct IntrusiveRefCntPtrInfo; + template class RefCountedBase; + class RefCountedBaseVPTR; + class raw_ostream; // TODO: DenseMap, ... } @@ -50,7 +56,13 @@ using llvm::SmallString; using llvm::SmallVector; using llvm::SmallVectorImpl; - + + // Reference counting. + using llvm::IntrusiveRefCntPtr; + using llvm::IntrusiveRefCntPtrInfo; + using llvm::RefCountedBase; + using llvm::RefCountedBaseVPTR; + using llvm::raw_ostream; } // end namespace clang. Modified: cfe/trunk/include/clang/Basic/LangOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/LangOptions.h (original) +++ cfe/trunk/include/clang/Basic/LangOptions.h Mon Feb 20 08:00:23 2012 @@ -15,6 +15,7 @@ #define LLVM_CLANG_LANGOPTIONS_H #include +#include "clang/Basic/LLVM.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -22,7 +23,7 @@ /// LangOptions - This class keeps track of the various options that can be /// enabled, which controls the dialect of C that is accepted. -class LangOptions : public llvm::RefCountedBase { +class LangOptions : public RefCountedBase { public: typedef clang::Visibility Visibility; Modified: cfe/trunk/include/clang/Basic/SourceManager.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/SourceManager.h (original) +++ cfe/trunk/include/clang/Basic/SourceManager.h Mon Feb 20 08:00:23 2012 @@ -483,7 +483,7 @@ /// the case of a macro expansion, for example, the spelling location indicates /// where the expanded token came from and the expansion location specifies /// where it was expanded. -class SourceManager : public llvm::RefCountedBase { +class SourceManager : public RefCountedBase { /// \brief DiagnosticsEngine object. DiagnosticsEngine &Diag; Modified: cfe/trunk/include/clang/Basic/TargetInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h (original) +++ cfe/trunk/include/clang/Basic/TargetInfo.h Mon Feb 20 08:00:23 2012 @@ -59,7 +59,7 @@ /// TargetInfo - This class exposes information about the current target. /// -class TargetInfo : public llvm::RefCountedBase { +class TargetInfo : public RefCountedBase { llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Frontend/ASTUnit.h (original) +++ cfe/trunk/include/clang/Frontend/ASTUnit.h Mon Feb 20 08:00:23 2012 @@ -61,7 +61,7 @@ /// \brief Allocator for a cached set of global code completions. class GlobalCodeCompletionAllocator : public CodeCompletionAllocator, - public llvm::RefCountedBase + public RefCountedBase { }; @@ -70,14 +70,14 @@ /// class ASTUnit : public ModuleLoader { private: - llvm::IntrusiveRefCntPtr LangOpts; - llvm::IntrusiveRefCntPtr Diagnostics; - llvm::IntrusiveRefCntPtr FileMgr; - llvm::IntrusiveRefCntPtr SourceMgr; - OwningPtr HeaderInfo; - llvm::IntrusiveRefCntPtr Target; - llvm::IntrusiveRefCntPtr PP; - llvm::IntrusiveRefCntPtr Ctx; + IntrusiveRefCntPtr LangOpts; + IntrusiveRefCntPtr Diagnostics; + IntrusiveRefCntPtr FileMgr; + IntrusiveRefCntPtr SourceMgr; + OwningPtr HeaderInfo; + IntrusiveRefCntPtr Target; + IntrusiveRefCntPtr PP; + IntrusiveRefCntPtr Ctx; ASTReader *Reader; FileSystemOptions FileSystemOpts; @@ -92,7 +92,7 @@ /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. - llvm::IntrusiveRefCntPtr Invocation; + IntrusiveRefCntPtr Invocation; /// \brief The set of target features. /// @@ -266,7 +266,7 @@ /// \brief The language options used when we load an AST file. LangOptions ASTFileLangOpts; - static void ConfigureDiags(llvm::IntrusiveRefCntPtr &Diags, + static void ConfigureDiags(IntrusiveRefCntPtr &Diags, const char **ArgBegin, const char **ArgEnd, ASTUnit &AST, bool CaptureDiagnostics); @@ -324,14 +324,14 @@ } /// \brief Retrieve the allocator used to cache global code completions. - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr getCachedCompletionAllocator() { return CachedCompletionAllocator; } /// \brief Retrieve the allocator used to cache global code completions. /// Creates the allocator if it doesn't already exist. - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr getCursorCompletionAllocator() { if (!CursorCompletionAllocator.getPtr()) { CursorCompletionAllocator = new GlobalCodeCompletionAllocator; @@ -341,11 +341,11 @@ private: /// \brief Allocator used to store cached code completions. - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr CachedCompletionAllocator; /// \brief Allocator used to store code completions for arbitrary cursors. - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr CursorCompletionAllocator; /// \brief The set of cached code-completion results. @@ -629,7 +629,7 @@ /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. static ASTUnit *create(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, bool CaptureDiagnostics = false); /// \brief Create a ASTUnit from an AST file. @@ -641,7 +641,7 @@ /// /// \returns - The initialized ASTUnit or null if the AST failed to load. static ASTUnit *LoadFromASTFile(const std::string &Filename, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, @@ -680,7 +680,7 @@ /// false means the caller is only interested in getting info through the /// provided \see Action. static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, ASTFrontendAction *Action = 0, ASTUnit *Unit = 0, bool Persistent = true, @@ -702,7 +702,7 @@ // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, bool PrecompilePreamble = false, @@ -726,7 +726,7 @@ // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCommandLine(const char **ArgBegin, const char **ArgEnd, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, StringRef ResourceFilesPath, bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original) +++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Mon Feb 20 08:00:23 2012 @@ -65,25 +65,25 @@ /// and a long form that takes explicit instances of any required objects. class CompilerInstance : public ModuleLoader { /// The options used in this compiler instance. - llvm::IntrusiveRefCntPtr Invocation; + IntrusiveRefCntPtr Invocation; /// The diagnostics engine instance. - llvm::IntrusiveRefCntPtr Diagnostics; + IntrusiveRefCntPtr Diagnostics; /// The target being compiled for. - llvm::IntrusiveRefCntPtr Target; + IntrusiveRefCntPtr Target; /// The file manager. - llvm::IntrusiveRefCntPtr FileMgr; + IntrusiveRefCntPtr FileMgr; /// The source manager. - llvm::IntrusiveRefCntPtr SourceMgr; + IntrusiveRefCntPtr SourceMgr; /// The preprocessor. - llvm::IntrusiveRefCntPtr PP; + IntrusiveRefCntPtr PP; /// The AST context. - llvm::IntrusiveRefCntPtr Context; + IntrusiveRefCntPtr Context; /// The AST consumer. OwningPtr Consumer; @@ -509,7 +509,7 @@ /// used by some diagnostics printers (for logging purposes only). /// /// \return The new object on success, or null on failure. - static llvm::IntrusiveRefCntPtr + static IntrusiveRefCntPtr createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, DiagnosticConsumer *Client = 0, Modified: cfe/trunk/include/clang/Frontend/CompilerInvocation.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInvocation.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Frontend/CompilerInvocation.h (original) +++ cfe/trunk/include/clang/Frontend/CompilerInvocation.h Mon Feb 20 08:00:23 2012 @@ -34,10 +34,10 @@ class CompilerInvocation; class DiagnosticsEngine; -class CompilerInvocationBase : public llvm::RefCountedBase { +class CompilerInvocationBase : public RefCountedBase { protected: /// Options controlling the language variant. - llvm::IntrusiveRefCntPtr LangOpts; + IntrusiveRefCntPtr LangOpts; public: CompilerInvocationBase(); Modified: cfe/trunk/include/clang/Frontend/Utils.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/Utils.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Frontend/Utils.h (original) +++ cfe/trunk/include/clang/Frontend/Utils.h Mon Feb 20 08:00:23 2012 @@ -100,8 +100,8 @@ /// argument vector. CompilerInvocation * createInvocationFromCommandLine(ArrayRef Args, - llvm::IntrusiveRefCntPtr Diags = - llvm::IntrusiveRefCntPtr()); + IntrusiveRefCntPtr Diags = + IntrusiveRefCntPtr()); } // end namespace clang Modified: cfe/trunk/include/clang/Lex/ModuleMap.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Lex/ModuleMap.h (original) +++ cfe/trunk/include/clang/Lex/ModuleMap.h Mon Feb 20 08:00:23 2012 @@ -37,7 +37,7 @@ class ModuleMap { SourceManager *SourceMgr; - llvm::IntrusiveRefCntPtr Diags; + IntrusiveRefCntPtr Diags; const LangOptions &LangOpts; const TargetInfo *Target; Modified: cfe/trunk/include/clang/Lex/Preprocessor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/Lex/Preprocessor.h (original) +++ cfe/trunk/include/clang/Lex/Preprocessor.h Mon Feb 20 08:00:23 2012 @@ -60,7 +60,7 @@ /// single source file, and don't know anything about preprocessor-level issues /// like the #include stack, token expansion, etc. /// -class Preprocessor : public llvm::RefCountedBase { +class Preprocessor : public RefCountedBase { DiagnosticsEngine *Diags; LangOptions &Features; const TargetInfo *Target; Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h Mon Feb 20 08:00:23 2012 @@ -260,7 +260,7 @@ // Path "pieces" for path-sensitive diagnostics. //===----------------------------------------------------------------------===// -class PathDiagnosticPiece : public llvm::RefCountedBaseVPTR { +class PathDiagnosticPiece : public RefCountedBaseVPTR { public: enum Kind { ControlFlow, Event, Macro, CallEnter, CallExit }; enum DisplayHint { Above, Below }; @@ -326,7 +326,7 @@ class PathPieces : - public std::deque > { + public std::deque > { public: ~PathPieces(); }; Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h Mon Feb 20 08:00:23 2012 @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_PROGRAMSTATE_FWD_H #define LLVM_CLANG_PROGRAMSTATE_FWD_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" namespace clang { @@ -34,7 +35,7 @@ namespace clang { namespace ento { - typedef llvm::IntrusiveRefCntPtr ProgramStateRef; + typedef IntrusiveRefCntPtr ProgramStateRef; } } Modified: cfe/trunk/lib/ARCMigrate/ARCMT.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ARCMT.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/ARCMigrate/ARCMT.cpp (original) +++ cfe/trunk/lib/ARCMigrate/ARCMT.cpp Mon Feb 20 08:00:23 2012 @@ -206,8 +206,8 @@ const DiagnosticOptions &diagOpts, Preprocessor &PP) { TextDiagnosticPrinter printer(llvm::errs(), diagOpts); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, &printer, /*ShouldOwnClient=*/false)); Diags->setSourceManager(&PP.getSourceManager()); @@ -244,8 +244,8 @@ CapturedDiagList capturedDiags; assert(DiagClient); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); // Filter of all diagnostics. @@ -349,8 +349,8 @@ if (err) return true; } - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); if (outputDir.empty()) { @@ -388,8 +388,8 @@ DiagnosticConsumer *DiagClient) { assert(!outputDir.empty()); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); FileRemapper remapper; @@ -491,8 +491,8 @@ StringRef outputDir) : OrigCI(CI), DiagClient(diagClient) { if (!outputDir.empty()) { - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true); } @@ -510,8 +510,8 @@ std::vector ARCMTMacroLocs; assert(DiagClient); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false)); // Filter of all diagnostics. Modified: cfe/trunk/lib/Basic/Diagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Basic/Diagnostic.cpp (original) +++ cfe/trunk/lib/Basic/Diagnostic.cpp Mon Feb 20 08:00:23 2012 @@ -34,7 +34,7 @@ DiagnosticsEngine::DiagnosticsEngine( - const llvm::IntrusiveRefCntPtr &diags, + const IntrusiveRefCntPtr &diags, DiagnosticConsumer *client, bool ShouldOwnClient) : Diags(diags), Client(client), OwnsDiagClient(ShouldOwnClient), SourceMgr(0) { Modified: cfe/trunk/lib/Frontend/ASTMerge.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTMerge.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/ASTMerge.cpp (original) +++ cfe/trunk/lib/Frontend/ASTMerge.cpp Mon Feb 20 08:00:23 2012 @@ -37,10 +37,10 @@ CI.getASTContext().getLangOptions()); CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &CI.getASTContext()); - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr DiagIDs(CI.getDiagnostics().getDiagnosticIDs()); for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr Diags(new DiagnosticsEngine(DiagIDs, CI.getDiagnostics().getClient(), /*ShouldOwnClient=*/false)); ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/ASTUnit.cpp (original) +++ cfe/trunk/lib/Frontend/ASTUnit.cpp Mon Feb 20 08:00:23 2012 @@ -493,7 +493,7 @@ ASTContext &Context; LangOptions &LangOpt; HeaderSearch &HSI; - llvm::IntrusiveRefCntPtr &Target; + IntrusiveRefCntPtr &Target; std::string &Predefines; unsigned &Counter; @@ -503,7 +503,7 @@ public: ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt, HeaderSearch &HSI, - llvm::IntrusiveRefCntPtr &Target, + IntrusiveRefCntPtr &Target, std::string &Predefines, unsigned &Counter) : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), Target(Target), @@ -630,7 +630,7 @@ } /// \brief Configure the diagnostics object for use with ASTUnit. -void ASTUnit::ConfigureDiags(llvm::IntrusiveRefCntPtr &Diags, +void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr &Diags, const char **ArgBegin, const char **ArgEnd, ASTUnit &AST, bool CaptureDiagnostics) { if (!Diags.getPtr()) { @@ -648,7 +648,7 @@ } ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls, RemappedFile *RemappedFiles, @@ -1031,7 +1031,7 @@ llvm::CrashRecoveryContextCleanupRegistrar CICleanup(Clang.get()); - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr CCInvocation(new CompilerInvocation(*Invocation)); Clang->setInvocation(CCInvocation.getPtr()); @@ -1308,7 +1308,7 @@ bool AllowRebuild, unsigned MaxLines) { - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr PreambleInvocation(new CompilerInvocation(PreambleInvocationIn)); FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts(); PreprocessorOptions &PreprocessorOpts @@ -1646,7 +1646,7 @@ } ASTUnit *ASTUnit::create(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, bool CaptureDiagnostics) { OwningPtr AST; AST.reset(new ASTUnit(false)); @@ -1661,7 +1661,7 @@ } ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, ASTFrontendAction *Action, ASTUnit *Unit, bool Persistent, @@ -1827,7 +1827,7 @@ } ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble, @@ -1858,7 +1858,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, const char **ArgEnd, - llvm::IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr Diags, StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics, @@ -1879,7 +1879,7 @@ SmallVector StoredDiagnostics; - llvm::IntrusiveRefCntPtr CI; + IntrusiveRefCntPtr CI; { @@ -2252,7 +2252,7 @@ CompletionTimer.setOutput("Code completion @ " + File + ":" + Twine(Line) + ":" + Twine(Column)); - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr CCInvocation(new CompilerInvocation(*Invocation)); FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts(); Modified: cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp (original) +++ cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp Mon Feb 20 08:00:23 2012 @@ -87,8 +87,8 @@ TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, DiagClient)); OwningPtr Clang(new CompilerInstance()); Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original) +++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Mon Feb 20 08:00:23 2012 @@ -175,15 +175,15 @@ &getCodeGenOpts()); } -llvm::IntrusiveRefCntPtr +IntrusiveRefCntPtr CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, DiagnosticConsumer *Client, bool ShouldOwnClient, bool ShouldCloneClient, const CodeGenOptions *CodeGenOpts) { - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags(new DiagnosticsEngine(DiagID)); // Create the diagnostic client for reporting errors or for @@ -734,7 +734,7 @@ = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); // Construct a compiler invocation for creating this module. - llvm::IntrusiveRefCntPtr Invocation + IntrusiveRefCntPtr Invocation (new CompilerInvocation(ImportingInstance.getInvocation())); PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original) +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Mon Feb 20 08:00:23 2012 @@ -38,7 +38,7 @@ : LangOpts(new LangOptions()) {} CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) - : llvm::RefCountedBase(), + : RefCountedBase(), LangOpts(new LangOptions(*X.getLangOpts())) {} //===----------------------------------------------------------------------===// Modified: cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp (original) +++ cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp Mon Feb 20 08:00:23 2012 @@ -30,7 +30,7 @@ /// argument vector. CompilerInvocation * clang::createInvocationFromCommandLine(ArrayRef ArgList, - llvm::IntrusiveRefCntPtr Diags) { + IntrusiveRefCntPtr Diags) { if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object // with the default options. Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/FrontendAction.cpp (original) +++ cfe/trunk/lib/Frontend/FrontendAction.cpp Mon Feb 20 08:00:23 2012 @@ -173,7 +173,7 @@ assert(hasASTFileSupport() && "This action does not have AST file support!"); - llvm::IntrusiveRefCntPtr Diags(&CI.getDiagnostics()); + IntrusiveRefCntPtr Diags(&CI.getDiagnostics()); std::string Error; ASTUnit *AST = ASTUnit::LoadFromASTFile(Input.File, Diags, CI.getFileSystemOpts()); Modified: cfe/trunk/lib/Frontend/Warnings.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Warnings.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/Warnings.cpp (original) +++ cfe/trunk/lib/Frontend/Warnings.cpp Mon Feb 20 08:00:23 2012 @@ -73,7 +73,7 @@ Diags.setExtensionHandlingBehavior(DiagnosticsEngine::Ext_Ignore); llvm::SmallVector _Diags; - const llvm::IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs = + const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs = Diags.getDiagnosticIDs(); // We parse the warning options twice. The first pass sets diagnostic state, // while the second pass reports warnings/errors. This has the effect that Modified: cfe/trunk/lib/Lex/ModuleMap.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/Lex/ModuleMap.cpp (original) +++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Feb 20 08:00:23 2012 @@ -73,8 +73,8 @@ const LangOptions &LangOpts, const TargetInfo *Target) : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0) { - llvm::IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs); - Diags = llvm::IntrusiveRefCntPtr( + IntrusiveRefCntPtr DiagIDs(new DiagnosticIDs); + Diags = IntrusiveRefCntPtr( new DiagnosticsEngine(DiagIDs)); Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); SourceMgr = new SourceManager(*Diags, FileMgr); Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Mon Feb 20 08:00:23 2012 @@ -1550,10 +1550,10 @@ /// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object /// and collapses PathDiagosticPieces that are expanded by macros. static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) { - typedef std::vector, SourceLocation> > + typedef std::vector, SourceLocation> > MacroStackTy; - typedef std::vector > + typedef std::vector > PiecesTy; MacroStackTy MacroStack; @@ -1585,7 +1585,7 @@ // We aren't in the same group. Are we descending into a new macro // or are part of an old one? - llvm::IntrusiveRefCntPtr MacroGroup; + IntrusiveRefCntPtr MacroGroup; SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? SM.getExpansionLoc(Loc) : Modified: cfe/trunk/tools/arcmt-test/arcmt-test.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/arcmt-test/arcmt-test.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/arcmt-test/arcmt-test.cpp (original) +++ cfe/trunk/tools/arcmt-test/arcmt-test.cpp Mon Feb 20 08:00:23 2012 @@ -107,8 +107,8 @@ ArrayRef Args) { DiagnosticConsumer *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr Diags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, DiagClient)); // Chain in -verify checker, if requested. VerifyDiagnosticConsumer *verifyDiag = 0; @@ -153,8 +153,8 @@ DiagnosticConsumer *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - llvm::IntrusiveRefCntPtr TopDiags( + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr TopDiags( new DiagnosticsEngine(DiagID, DiagClient)); CompilerInvocation origCI; Modified: cfe/trunk/tools/driver/cc1_main.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/cc1_main.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/driver/cc1_main.cpp (original) +++ cfe/trunk/tools/driver/cc1_main.cpp Mon Feb 20 08:00:23 2012 @@ -118,7 +118,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd, const char *Argv0, void *MainAddr) { OwningPtr Clang(new CompilerInstance()); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); // Run clang -cc1 test. if (ArgBegin != ArgEnd && StringRef(ArgBegin[0]) == "-cc1test") { Modified: cfe/trunk/tools/driver/cc1as_main.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/cc1as_main.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/driver/cc1as_main.cpp (original) +++ cfe/trunk/tools/driver/cc1as_main.cpp Mon Feb 20 08:00:23 2012 @@ -396,7 +396,7 @@ TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(errs(), DiagnosticOptions()); DiagClient->setPrefix("clang -cc1as"); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); DiagnosticsEngine Diags(DiagID, DiagClient); // Set an error handler, so that any LLVM backend diagnostics go through our Modified: cfe/trunk/tools/driver/driver.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/driver.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/driver/driver.cpp (original) +++ cfe/trunk/tools/driver/driver.cpp Mon Feb 20 08:00:23 2012 @@ -373,7 +373,7 @@ TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); DiagClient->setPrefix(llvm::sys::path::stem(Path.str())); - llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); DiagnosticsEngine Diags(DiagID, DiagClient); #ifdef CLANG_IS_PRODUCTION Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Mon Feb 20 08:00:23 2012 @@ -2429,7 +2429,7 @@ FileSystemOptions FileSystemOpts; FileSystemOpts.WorkingDir = CXXIdx->getWorkingDirectory(); - llvm::IntrusiveRefCntPtr Diags; + IntrusiveRefCntPtr Diags; ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts, CXXIdx->getOnlyLocalDecls(), 0, 0, true); @@ -2492,7 +2492,7 @@ // Configure the diagnostics. DiagnosticOptions DiagOpts; - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr Diags(CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args, command_line_args)); Modified: cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp (original) +++ cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp Mon Feb 20 08:00:23 2012 @@ -224,7 +224,7 @@ SmallVector Diagnostics; /// \brief Diag object - llvm::IntrusiveRefCntPtr Diag; + IntrusiveRefCntPtr Diag; /// \brief Language options used to adjust source locations. LangOptions LangOpts; @@ -232,10 +232,10 @@ FileSystemOptions FileSystemOpts; /// \brief File manager, used for diagnostics. - llvm::IntrusiveRefCntPtr FileMgr; + IntrusiveRefCntPtr FileMgr; /// \brief Source manager, used for diagnostics. - llvm::IntrusiveRefCntPtr SourceMgr; + IntrusiveRefCntPtr SourceMgr; /// \brief Temporary files that should be removed once we have finished /// with the code-completion results. @@ -246,7 +246,7 @@ SmallVector TemporaryBuffers; /// \brief Allocator used to store globally cached code-completion results. - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr CachedCompletionAllocator; /// \brief Allocator used to store code completion results. @@ -282,7 +282,7 @@ const FileSystemOptions& FileSystemOpts) : CXCodeCompleteResults(), Diag(new DiagnosticsEngine( - llvm::IntrusiveRefCntPtr(new DiagnosticIDs))), + IntrusiveRefCntPtr(new DiagnosticIDs))), FileSystemOpts(FileSystemOpts), FileMgr(new FileManager(FileSystemOpts)), SourceMgr(new SourceManager(*Diag, *FileMgr)), Modified: cfe/trunk/tools/libclang/Indexing.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Indexing.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/libclang/Indexing.cpp (original) +++ cfe/trunk/tools/libclang/Indexing.cpp Mon Feb 20 08:00:23 2012 @@ -279,7 +279,7 @@ // Configure the diagnostics. DiagnosticOptions DiagOpts; - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr Diags(CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args, command_line_args, CaptureDiag, @@ -309,7 +309,7 @@ if (source_filename) Args->push_back(source_filename); - llvm::IntrusiveRefCntPtr + IntrusiveRefCntPtr CInvok(createInvocationFromCommandLine(*Args, Diags)); if (!CInvok) Modified: cfe/trunk/tools/libclang/IndexingContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.h?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/tools/libclang/IndexingContext.h (original) +++ cfe/trunk/tools/libclang/IndexingContext.h Mon Feb 20 08:00:23 2012 @@ -30,7 +30,7 @@ struct EntityInfo : public CXIdxEntityInfo { const NamedDecl *Dcl; IndexingContext *IndexCtx; - llvm::IntrusiveRefCntPtr AttrList; + IntrusiveRefCntPtr AttrList; EntityInfo() { name = USR = 0; Modified: cfe/trunk/unittests/Basic/SourceManagerTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Basic/SourceManagerTest.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/unittests/Basic/SourceManagerTest.cpp (original) +++ cfe/trunk/unittests/Basic/SourceManagerTest.cpp Mon Feb 20 08:00:23 2012 @@ -40,12 +40,12 @@ FileSystemOptions FileMgrOpts; FileManager FileMgr; - llvm::IntrusiveRefCntPtr DiagID; + IntrusiveRefCntPtr DiagID; DiagnosticsEngine Diags; SourceManager SourceMgr; LangOptions LangOpts; TargetOptions TargetOpts; - llvm::IntrusiveRefCntPtr Target; + IntrusiveRefCntPtr Target; }; class VoidModuleLoader : public ModuleLoader { Modified: cfe/trunk/unittests/Lex/LexerTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Lex/LexerTest.cpp?rev=150958&r1=150957&r2=150958&view=diff ============================================================================== --- cfe/trunk/unittests/Lex/LexerTest.cpp (original) +++ cfe/trunk/unittests/Lex/LexerTest.cpp Mon Feb 20 08:00:23 2012 @@ -39,12 +39,12 @@ FileSystemOptions FileMgrOpts; FileManager FileMgr; - llvm::IntrusiveRefCntPtr DiagID; + IntrusiveRefCntPtr DiagID; DiagnosticsEngine Diags; SourceManager SourceMgr; LangOptions LangOpts; TargetOptions TargetOpts; - llvm::IntrusiveRefCntPtr Target; + IntrusiveRefCntPtr Target; }; class VoidModuleLoader : public ModuleLoader { From aaron at aaronballman.com Mon Feb 20 06:13:25 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 20 Feb 2012 14:13:25 -0000 Subject: [cfe-commits] r150960 - /cfe/trunk/lib/Driver/Driver.cpp Message-ID: <20120220141325.462622A6C12F@llvm.org> Author: aaronballman Date: Mon Feb 20 08:13:25 2012 New Revision: 150960 URL: http://llvm.org/viewvc/llvm-project?rev=150960&view=rev Log: Fixing the working-directory option so that it stores the proper directory. Modified: cfe/trunk/lib/Driver/Driver.cpp Modified: cfe/trunk/lib/Driver/Driver.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=150960&r1=150959&r2=150960&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Driver.cpp (original) +++ cfe/trunk/lib/Driver/Driver.cpp Mon Feb 20 08:13:25 2012 @@ -960,14 +960,16 @@ // Check that the file exists, if enabled. if (CheckInputsExist && memcmp(Value, "-", 2) != 0) { SmallString<64> Path(Value); - if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) - if (llvm::sys::path::is_absolute(Path.str())) { - Path = WorkDir->getValue(Args); - llvm::sys::path::append(Path, Value); + if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { + SmallString<64> Directory(WorkDir->getValue(Args)); + if (llvm::sys::path::is_absolute(Directory.str())) { + llvm::sys::path::append(Directory, Value); + Path.assign(Directory); } + } bool exists = false; - if (/*error_code ec =*/llvm::sys::fs::exists(Value, exists) || !exists) + if (llvm::sys::fs::exists(Path.c_str(), exists) || !exists) Diag(clang::diag::err_drv_no_such_file) << Path.str(); else Inputs.push_back(std::make_pair(Ty, A)); From hhinnant at apple.com Mon Feb 20 06:58:06 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Mon, 20 Feb 2012 09:58:06 -0500 Subject: [cfe-commits] [patch] Don't mark libc++ functions as always_inline in debug mode. In-Reply-To: <3FE6C3D7-AFF4-42A8-9AD8-9A9ACCB59A7F@apple.com> References: <134AE1F7-FF9C-4637-85E8-1EA7A9BCC0CE@apple.com> <3FE6C3D7-AFF4-42A8-9AD8-9A9ACCB59A7F@apple.com> Message-ID: <5172F1DC-227E-4C13-AC3B-73449D98B5B3@apple.com> This is more than just an optimization issue. Experience with libstdc++ has shown a persistent ABI stability problem over the years with functions getting silently uninlined in one release of libstdc++.dylib and inlined in the next. The best way to hold the ABI stable is to put inlining under my control, not the compielr's. For those clients wishing to change these settings, <__config> was designed to defer to the client's wishes from the command line: -D_LIBCPP_INLINE_VISIBILITY will be used in preference to whatever <__config> says (or if it doesn't, that's the bug to fix). Howard On Feb 20, 2012, at 7:58 AM, Chris Lattner wrote: > Why are these functions marked always-inline in the first place? > > -Chris > > On Feb 19, 2012, at 7:24 PM, Jeffrey Yasskin wrote: > >> Really, even if libc++ is bug-free, it'll confuse users if debugging >> it in -O0 mode produces strange line jumps. >> >> If NDEBUG is the wrong macro, would it make sense to provide a >> LIBCXX_DEBUG flag to move the inlining decisions to clang? >> >> On Sun, Feb 19, 2012 at 6:57 PM, Howard Hinnant wrote: >>> On Feb 19, 2012, at 9:30 PM, Jeffrey Yasskin wrote: >>> >>>> This patch may not be quite right, since the always_inline macros seem >>>> to also have visibility effects, which this patch would block. I also >>>> had to build with an explicit -UNDEBUG since cmake appears to add >>>> -DNDEBUG regardless of whether the build mode requests it. >>>> >>>> Jeffrey >>>> >>> >>> I can't commit this one. The presumption is that NDEBUG is up to the client to turn on and off for his own purposes, and that libc++ does not need to be debugged by him. I realize that libc++ has bugs. But the goal is for it to not have bugs, and when it does need to be debugged, a libc++ developer such as myself will do it. >>> >>> Howard >>> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From zarzycki at apple.com Mon Feb 20 08:04:10 2012 From: zarzycki at apple.com (Dave Zarzycki) Date: Mon, 20 Feb 2012 11:04:10 -0500 Subject: [cfe-commits] [patch] Don't mark libc++ functions as always_inline in debug mode. In-Reply-To: <5172F1DC-227E-4C13-AC3B-73449D98B5B3@apple.com> References: <134AE1F7-FF9C-4637-85E8-1EA7A9BCC0CE@apple.com> <3FE6C3D7-AFF4-42A8-9AD8-9A9ACCB59A7F@apple.com> <5172F1DC-227E-4C13-AC3B-73449D98B5B3@apple.com> Message-ID: Howard, Do we have libcxx FAQ somewhere? This question comes up from time to time and perhaps a FAQ entry would help. davez On Feb 20, 2012, at 9:58 AM, Howard Hinnant wrote: > This is more than just an optimization issue. Experience with libstdc++ has shown a persistent ABI stability problem over the years with functions getting silently uninlined in one release of libstdc++.dylib and inlined in the next. The best way to hold the ABI stable is to put inlining under my control, not the compielr's. > > For those clients wishing to change these settings, <__config> was designed to defer to the client's wishes from the command line: > > -D_LIBCPP_INLINE_VISIBILITY > > will be used in preference to whatever <__config> says (or if it doesn't, that's the bug to fix). > > Howard > > On Feb 20, 2012, at 7:58 AM, Chris Lattner wrote: > >> Why are these functions marked always-inline in the first place? >> >> -Chris >> >> On Feb 19, 2012, at 7:24 PM, Jeffrey Yasskin wrote: >> >>> Really, even if libc++ is bug-free, it'll confuse users if debugging >>> it in -O0 mode produces strange line jumps. >>> >>> If NDEBUG is the wrong macro, would it make sense to provide a >>> LIBCXX_DEBUG flag to move the inlining decisions to clang? >>> >>> On Sun, Feb 19, 2012 at 6:57 PM, Howard Hinnant wrote: >>>> On Feb 19, 2012, at 9:30 PM, Jeffrey Yasskin wrote: >>>> >>>>> This patch may not be quite right, since the always_inline macros seem >>>>> to also have visibility effects, which this patch would block. I also >>>>> had to build with an explicit -UNDEBUG since cmake appears to add >>>>> -DNDEBUG regardless of whether the build mode requests it. >>>>> >>>>> Jeffrey >>>>> >>>> >>>> I can't commit this one. The presumption is that NDEBUG is up to the client to turn on and off for his own purposes, and that libc++ does not need to be debugged by him. I realize that libc++ has bugs. But the goal is for it to not have bugs, and when it does need to be debugged, a libc++ developer such as myself will do it. >>>> >>>> Howard >>>> >>> >>> _______________________________________________ >>> 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 hhinnant at apple.com Mon Feb 20 08:05:09 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Mon, 20 Feb 2012 11:05:09 -0500 Subject: [cfe-commits] [patch] Don't mark libc++ functions as always_inline in debug mode. In-Reply-To: References: <134AE1F7-FF9C-4637-85E8-1EA7A9BCC0CE@apple.com> <3FE6C3D7-AFF4-42A8-9AD8-9A9ACCB59A7F@apple.com> <5172F1DC-227E-4C13-AC3B-73449D98B5B3@apple.com> Message-ID: <55A8E92D-3318-40E6-9095-48935C12BA1D@apple.com> I'll start one. Howard On Feb 20, 2012, at 11:04 AM, Dave Zarzycki wrote: > Howard, > > Do we have libcxx FAQ somewhere? This question comes up from time to time and perhaps a FAQ entry would help. > > davez > > > On Feb 20, 2012, at 9:58 AM, Howard Hinnant wrote: > >> This is more than just an optimization issue. Experience with libstdc++ has shown a persistent ABI stability problem over the years with functions getting silently uninlined in one release of libstdc++.dylib and inlined in the next. The best way to hold the ABI stable is to put inlining under my control, not the compielr's. >> >> For those clients wishing to change these settings, <__config> was designed to defer to the client's wishes from the command line: >> >> -D_LIBCPP_INLINE_VISIBILITY >> >> will be used in preference to whatever <__config> says (or if it doesn't, that's the bug to fix). >> >> Howard >> >> On Feb 20, 2012, at 7:58 AM, Chris Lattner wrote: >> >>> Why are these functions marked always-inline in the first place? >>> >>> -Chris >>> >>> On Feb 19, 2012, at 7:24 PM, Jeffrey Yasskin wrote: >>> >>>> Really, even if libc++ is bug-free, it'll confuse users if debugging >>>> it in -O0 mode produces strange line jumps. >>>> >>>> If NDEBUG is the wrong macro, would it make sense to provide a >>>> LIBCXX_DEBUG flag to move the inlining decisions to clang? >>>> >>>> On Sun, Feb 19, 2012 at 6:57 PM, Howard Hinnant wrote: >>>>> On Feb 19, 2012, at 9:30 PM, Jeffrey Yasskin wrote: >>>>> >>>>>> This patch may not be quite right, since the always_inline macros seem >>>>>> to also have visibility effects, which this patch would block. I also >>>>>> had to build with an explicit -UNDEBUG since cmake appears to add >>>>>> -DNDEBUG regardless of whether the build mode requests it. >>>>>> >>>>>> Jeffrey >>>>>> >>>>> >>>>> I can't commit this one. The presumption is that NDEBUG is up to the client to turn on and off for his own purposes, and that libc++ does not need to be debugged by him. I realize that libc++ has bugs. But the goal is for it to not have bugs, and when it does need to be debugged, a libc++ developer such as myself will do it. >>>>> >>>>> Howard >>>>> >>>> >>>> _______________________________________________ >>>> 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 jyasskin at gmail.com Mon Feb 20 08:07:24 2012 From: jyasskin at gmail.com (Jeffrey Yasskin) Date: Mon, 20 Feb 2012 08:07:24 -0800 Subject: [cfe-commits] [patch] Don't mark libc++ functions as always_inline in debug mode. In-Reply-To: <5172F1DC-227E-4C13-AC3B-73449D98B5B3@apple.com> References: <134AE1F7-FF9C-4637-85E8-1EA7A9BCC0CE@apple.com> <3FE6C3D7-AFF4-42A8-9AD8-9A9ACCB59A7F@apple.com> <5172F1DC-227E-4C13-AC3B-73449D98B5B3@apple.com> Message-ID: On Mon, Feb 20, 2012 at 6:58 AM, Howard Hinnant wrote: > This is more than just an optimization issue.  Experience with libstdc++ has shown a persistent ABI stability problem over the years with functions getting silently uninlined in one release of libstdc++.dylib and inlined in the next.  The best way to hold the ABI stable is to put inlining under my control, not the compielr's. > > For those clients wishing to change these settings, <__config> was designed to defer to the client's wishes from the command line: > > -D_LIBCPP_INLINE_VISIBILITY > > will be used in preference to whatever <__config> says (or if it doesn't, that's the bug to fix). Ah, ok. Then I think the right thing to do is to have cmake pass those flags to debug builds. I'll put together a patch along those lines instead. From dgregor at apple.com Mon Feb 20 08:12:14 2012 From: dgregor at apple.com (Douglas Gregor) Date: Mon, 20 Feb 2012 16:12:14 -0000 Subject: [cfe-commits] r150963 - in /cfe/trunk: lib/Serialization/ASTReaderStmt.cpp test/PCH/cxx-exprs.cpp Message-ID: <20120220161214.78F722A6C12F@llvm.org> Author: dgregor Date: Mon Feb 20 10:12:14 2012 New Revision: 150963 URL: http://llvm.org/viewvc/llvm-project?rev=150963&view=rev Log: Deserialize the direct-initialization range of a "new" expression properly. Previously, we deserialized it but failed to set the corresponding member in CXXNewExpr. Fixes . Added: cfe/trunk/test/PCH/cxx-exprs.cpp (with props) Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=150963&r1=150962&r2=150963&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Feb 20 10:12:14 2012 @@ -1174,14 +1174,9 @@ E->setOperatorNew(ReadDeclAs(Record, Idx)); E->setOperatorDelete(ReadDeclAs(Record, Idx)); E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx); - SourceRange TypeIdParens; - TypeIdParens.setBegin(ReadSourceLocation(Record, Idx)); - TypeIdParens.setEnd(ReadSourceLocation(Record, Idx)); - E->TypeIdParens = TypeIdParens; + E->TypeIdParens = ReadSourceRange(Record, Idx); E->StartLoc = ReadSourceLocation(Record, Idx); - SourceRange DirectInitRange; - DirectInitRange.setBegin(ReadSourceLocation(Record, Idx)); - DirectInitRange.setEnd(ReadSourceLocation(Record, Idx)); + E->DirectInitRange = ReadSourceRange(Record, Idx); E->AllocateArgsArray(Reader.getContext(), isArray, NumPlacementArgs, E->StoredInitializationStyle != 0); Added: cfe/trunk/test/PCH/cxx-exprs.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-exprs.cpp?rev=150963&view=auto ============================================================================== --- cfe/trunk/test/PCH/cxx-exprs.cpp (added) +++ cfe/trunk/test/PCH/cxx-exprs.cpp Mon Feb 20 10:12:14 2012 @@ -0,0 +1,27 @@ +// Test this without pch. +// RUN: %clang_cc1 -include %s -verify -std=c++11 %s + +// Test with pch. +// RUN: %clang_cc1 -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -include-pch %t -verify -std=c++11 %s + +#ifndef HEADER +#define HEADER + +template +class New { + New(const New&); + +public: + New *clone() { + return new New(*this); + } +}; + +#else + +New *clone_new(New *n) { + return n->clone(); +} + +#endif Propchange: cfe/trunk/test/PCH/cxx-exprs.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/test/PCH/cxx-exprs.cpp ------------------------------------------------------------------------------ svn:keywords = Id Propchange: cfe/trunk/test/PCH/cxx-exprs.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain From klimek at google.com Mon Feb 20 08:28:37 2012 From: klimek at google.com (Manuel Klimek) Date: Mon, 20 Feb 2012 08:28:37 -0800 Subject: [cfe-commits] [PATCH 2/5] [clang.py] Implement Type.__eq__ and Type.__ne__ In-Reply-To: References: Message-ID: Looks good. On Sat, Feb 18, 2012 at 8:26 PM, Gregory Szorc wrote: > I've made the implementation of Type.__eq__ more robust and added tests. > > > On Fri, Feb 17, 2012 at 1:37 AM, Manuel Klimek wrote: >> >> On Fri, Feb 17, 2012 at 8:56 AM, Gregory Szorc >> wrote: >> > The implementation could probably be a bit more robust (looking for >> > None, comparing types, etc). Do we care? >> >> Regarding looking for None: what happens if one calls t == None on a >> Type? Perhaps add a test? >> >> Cheers, >> /Manuel >> >> >> > --- >> >  bindings/python/clang/cindex.py           |   10 ++++++++++ >> >  bindings/python/tests/cindex/test_type.py |   17 +++++++++++++++++ >> >  2 files changed, 27 insertions(+), 0 deletions(-) >> > >> > _______________________________________________ >> > cfe-commits mailing list >> > cfe-commits at cs.uiuc.edu >> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> > > > From joerg at britannica.bec.de Mon Feb 20 08:39:50 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 17:39:50 +0100 Subject: [cfe-commits] [PATCH] [PR 12026] Restore target-prefix tool support Message-ID: <20120220163950.GA13346@britannica.bec.de> Hi all, this is the minimally intrusive fix for the target-prefixed toolchain support. This is a partial revert of r148839, fixed in r149083, reverted and re-broken in r149337. Given that's been 3 weeks now with a proper solution, I think it is time to restore the status quo. See also PR 12026. Joerg -------------- next part -------------- A non-text attachment was scrubbed... Name: Driver.cpp.diff Type: text/x-diff Size: 609 bytes Desc: not available URL: From hhinnant at apple.com Mon Feb 20 08:51:44 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Mon, 20 Feb 2012 16:51:44 -0000 Subject: [cfe-commits] [libcxx] r150964 - /libcxx/trunk/src/locale.cpp Message-ID: <20120220165144.51A702A6C12F@llvm.org> Author: hhinnant Date: Mon Feb 20 10:51:43 2012 New Revision: 150964 URL: http://llvm.org/viewvc/llvm-project?rev=150964&view=rev Log: Silence -Wmissing-field-initializers a little higher in the source. Modified: libcxx/trunk/src/locale.cpp Modified: libcxx/trunk/src/locale.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/locale.cpp?rev=150964&r1=150963&r2=150964&view=diff ============================================================================== --- libcxx/trunk/src/locale.cpp (original) +++ libcxx/trunk/src/locale.cpp Mon Feb 20 10:51:43 2012 @@ -4547,6 +4547,8 @@ freelocale(__loc_); } +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + template <> string __time_get_storage::__analyze(char fmt, const ctype& ct) @@ -4692,7 +4694,6 @@ } #pragma clang diagnostic ignored "-Wmissing-braces" -#pragma clang diagnostic ignored "-Wmissing-field-initializers" template <> wstring From bob.wilson at apple.com Mon Feb 20 08:56:13 2012 From: bob.wilson at apple.com (Bob Wilson) Date: Mon, 20 Feb 2012 16:56:13 -0000 Subject: [cfe-commits] [libcxx] r150965 - in /libcxx/trunk/include/support/win32: math_win32.h support.h Message-ID: <20120220165613.E801C2A6C12F@llvm.org> Author: bwilson Date: Mon Feb 20 10:56:13 2012 New Revision: 150965 URL: http://llvm.org/viewvc/llvm-project?rev=150965&view=rev Log: Add missing newlines at EOF. Modified: libcxx/trunk/include/support/win32/math_win32.h libcxx/trunk/include/support/win32/support.h Modified: libcxx/trunk/include/support/win32/math_win32.h URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/support/win32/math_win32.h?rev=150965&r1=150964&r2=150965&view=diff ============================================================================== --- libcxx/trunk/include/support/win32/math_win32.h (original) +++ libcxx/trunk/include/support/win32/math_win32.h Mon Feb 20 10:56:13 2012 @@ -110,4 +110,4 @@ #endif // _MSC_VER -#endif // _LIBCPP_SUPPORT_WIN32_MATH_WIN32_H \ No newline at end of file +#endif // _LIBCPP_SUPPORT_WIN32_MATH_WIN32_H Modified: libcxx/trunk/include/support/win32/support.h URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/support/win32/support.h?rev=150965&r1=150964&r2=150965&view=diff ============================================================================== --- libcxx/trunk/include/support/win32/support.h (original) +++ libcxx/trunk/include/support/win32/support.h Mon Feb 20 10:56:13 2012 @@ -112,4 +112,4 @@ #endif // !__clang__ #endif // _MSC_VER -#endif // _LIBCPP_SUPPORT_WIN32_SUPPORT_H \ No newline at end of file +#endif // _LIBCPP_SUPPORT_WIN32_SUPPORT_H From benny.kra at googlemail.com Mon Feb 20 09:06:20 2012 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Mon, 20 Feb 2012 18:06:20 +0100 Subject: [cfe-commits] [libcxx] r150964 - /libcxx/trunk/src/locale.cpp In-Reply-To: <20120220165144.51A702A6C12F@llvm.org> References: <20120220165144.51A702A6C12F@llvm.org> Message-ID: On 20.02.2012, at 17:51, Howard Hinnant wrote: > Author: hhinnant > Date: Mon Feb 20 10:51:43 2012 > New Revision: 150964 > > URL: http://llvm.org/viewvc/llvm-project?rev=150964&view=rev > Log: > Silence -Wmissing-field-initializers a little higher in the source. clang won't warn if it sees the more idiomatic tm t = {}; - Ben > > Modified: > libcxx/trunk/src/locale.cpp > > Modified: libcxx/trunk/src/locale.cpp > URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/locale.cpp?rev=150964&r1=150963&r2=150964&view=diff > ============================================================================== > --- libcxx/trunk/src/locale.cpp (original) > +++ libcxx/trunk/src/locale.cpp Mon Feb 20 10:51:43 2012 > @@ -4547,6 +4547,8 @@ > freelocale(__loc_); > } > > +#pragma clang diagnostic ignored "-Wmissing-field-initializers" > + > template <> > string > __time_get_storage::__analyze(char fmt, const ctype& ct) > @@ -4692,7 +4694,6 @@ > } > > #pragma clang diagnostic ignored "-Wmissing-braces" > -#pragma clang diagnostic ignored "-Wmissing-field-initializers" > > template <> > wstring > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From klimek at google.com Mon Feb 20 09:06:55 2012 From: klimek at google.com (Manuel Klimek) Date: Mon, 20 Feb 2012 09:06:55 -0800 Subject: [cfe-commits] [PATCH 3/5] [clang.py] Implement Type.arguments() In-Reply-To: <4F4145B7.20504@gmail.com> References: <4F40B783.2020709@grosser.es> <4F4145B7.20504@gmail.com> Message-ID: On Sun, Feb 19, 2012 at 10:55 AM, Gregory Szorc wrote: > On 2/19/2012 12:49 AM, Tobias Grosser wrote: >> On 02/19/2012 05:39 AM, Gregory Szorc wrote: >>> Does anyone else think that "arguments" may not be the best name? >>> Perhaps "argument_types" would be more suitable... >> >> Yes. I agree. Either name it argument_types, or return a class called >> 'argument' that than has a .type() function. Returning a class is >> probably overhead, as it would only have a single function. I would >> just name the iterator argument_types(). >> >> Also, I just realized you define the __iter__(self) method. Why is >> that needed? Diagnostic.ranges() gets away without using it? > > argument_types() it is. It seems __iter__ has a default implementation > somewhere (I guess in object). In the current patch, I changed the class > to derive from collections.Sequence. This is more appropriate than > deriving from object and the default implementation of __iter__ there > works as expected (it calls __getitem__ from 0..n until __getitem__ > throws IndexError). The one thing that strikes me as odd is that the method is on the "Type", but it looks like that's a design decision that was made earlier (just wandering what this will become in the future if *all* methods of all Type subclasses in the AST become accessible from that one class) Otherwise looks good. Cheers, /Manuel > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > From hhinnant at apple.com Mon Feb 20 09:13:20 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Mon, 20 Feb 2012 12:13:20 -0500 Subject: [cfe-commits] [libcxx] r150964 - /libcxx/trunk/src/locale.cpp In-Reply-To: References: <20120220165144.51A702A6C12F@llvm.org> Message-ID: <1D2153DD-D005-4C4E-B27F-B3E2DE766410@apple.com> On Feb 20, 2012, at 12:06 PM, Benjamin Kramer wrote: > > On 20.02.2012, at 17:51, Howard Hinnant wrote: > >> Author: hhinnant >> Date: Mon Feb 20 10:51:43 2012 >> New Revision: 150964 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=150964&view=rev >> Log: >> Silence -Wmissing-field-initializers a little higher in the source. > > clang won't warn if it sees the more idiomatic > > tm t = {}; I noticed that. I guess I'm just old fashioned. I agreed with Jeffrey Yasskin when he recently wrote: > I personally like the extra reminder that it's 0 the rest of the fields > will be initialized with. Howard From nobled at dreamwidth.org Mon Feb 20 09:36:36 2012 From: nobled at dreamwidth.org (nobled) Date: Mon, 20 Feb 2012 12:36:36 -0500 Subject: [cfe-commits] [patch] clang-wpa: adapt to API changes Message-ID: When clang-wpa was restored in r112014, it wasn't added back to the examples/ Makefile or CMakeLists.txt, so it was never actually built, and has been busted by API changes since August 2011. -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-examples-clang-wpa-adapt-to-API-changes.patch Type: text/x-patch Size: 3777 bytes Desc: not available URL: From gregory.szorc at gmail.com Mon Feb 20 09:44:49 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 17:44:49 -0000 Subject: [cfe-commits] r150969 - in /cfe/trunk/bindings/python: clang/cindex.py tests/cindex/test_type.py Message-ID: <20120220174449.BBA0B2A6C131@llvm.org> Author: gps Date: Mon Feb 20 11:44:49 2012 New Revision: 150969 URL: http://llvm.org/viewvc/llvm-project?rev=150969&view=rev Log: [clang.py] Implement Type.__eq__ and Type.__ne__ Modified: cfe/trunk/bindings/python/clang/cindex.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=150969&r1=150968&r2=150969&view=diff ============================================================================== --- cfe/trunk/bindings/python/clang/cindex.py (original) +++ cfe/trunk/bindings/python/clang/cindex.py Mon Feb 20 11:44:49 2012 @@ -1245,6 +1245,15 @@ """ return Type_get_array_size(self) + def __eq__(self, other): + if type(other) != type(self): + return False + + return Type_equal(self, other) + + def __ne__(self, other): + return not self.__eq__(other) + ## CIndex Objects ## # CIndex objects (derived from ClangObject) are essentially lightweight @@ -1936,6 +1945,10 @@ Type_get_array_size.argtype = [Type] Type_get_array_size.restype = c_longlong +Type_equal = lib.clang_equalTypes +Type_equal.argtypes = [Type, Type] +Type_equal.restype = bool + # Index Functions Index_create = lib.clang_createIndex Index_create.argtypes = [c_int, c_int] 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=150969&r1=150968&r2=150969&view=diff ============================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_type.py (original) +++ cfe/trunk/bindings/python/tests/cindex/test_type.py Mon Feb 20 11:44:49 2012 @@ -109,6 +109,31 @@ else: assert False, "Didn't find teststruct??" +def test_equal(): + """Ensure equivalence operators work on Type.""" + source = 'int a; int b; void *v;' + tu = get_tu(source) + + a, b, v = None, None, None + + for cursor in tu.cursor.get_children(): + if cursor.spelling == 'a': + a = cursor + elif cursor.spelling == 'b': + b = cursor + elif cursor.spelling == 'v': + v = cursor + + assert a is not None + assert b is not None + assert v is not None + + assert a.type == b.type + assert a.type != v.type + + assert a.type != None + assert a.type != 'foo' + def test_is_pod(): tu = get_tu('int i; void f();') i, f = None, None From gregory.szorc at gmail.com Mon Feb 20 09:45:30 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 17:45:30 -0000 Subject: [cfe-commits] r150970 - in /cfe/trunk/bindings/python: clang/cindex.py tests/cindex/test_type.py Message-ID: <20120220174531.0FABC2A6C131@llvm.org> Author: gps Date: Mon Feb 20 11:45:30 2012 New Revision: 150970 URL: http://llvm.org/viewvc/llvm-project?rev=150970&view=rev Log: [clang.py] Implement Type.argument_types() Modified: cfe/trunk/bindings/python/clang/cindex.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=150970&r1=150969&r2=150970&view=diff ============================================================================== --- cfe/trunk/bindings/python/clang/cindex.py (original) +++ cfe/trunk/bindings/python/clang/cindex.py Mon Feb 20 11:45:30 2012 @@ -63,6 +63,7 @@ # o implement additional SourceLocation, SourceRange, and File methods. from ctypes import * +import collections def get_cindex_library(): # FIXME: It's probably not the case that the library is actually found in @@ -1137,6 +1138,44 @@ """Return the kind of this type.""" return TypeKind.from_id(self._kind_id) + def argument_types(self): + """Retrieve a container for the non-variadic arguments for this type. + + The returned object is iterable and indexable. Each item in the + container is a Type instance. + """ + class ArgumentsIterator(collections.Sequence): + def __init__(self, parent): + self.parent = parent + self.length = None + + def __len__(self): + if self.length is None: + self.length = Type_get_num_arg_types(self.parent) + + return self.length + + def __getitem__(self, key): + # FIXME Support slice objects. + if not isinstance(key, int): + raise TypeError("Must supply a non-negative int.") + + if key < 0: + raise IndexError("Only non-negative indexes are accepted.") + + if key >= len(self): + raise IndexError("Index greater than container length: " + "%d > %d" % ( key, len(self) )) + + result = Type_get_arg_type(self.parent, key) + if result.kind == TypeKind.INVALID: + raise IndexError("Argument could not be retrieved.") + + return result + + assert self.kind == TypeKind.FUNCTIONPROTO + return ArgumentsIterator(self) + @property def element_type(self): """Retrieve the Type of elements within this Type. @@ -1927,7 +1966,16 @@ Type_get_result.restype = Type Type_get_result.errcheck = Type.from_result +Type_get_num_arg_types = lib.clang_getNumArgTypes +Type_get_num_arg_types.argtypes = [Type] +Type_get_num_arg_types.restype = c_uint + +Type_get_arg_type = lib.clang_getArgType +Type_get_arg_type.argtypes = [Type, c_uint] +Type_get_arg_type.restype = Type +Type_get_arg_type.errcheck = Type.from_result Type_get_element_type = lib.clang_getElementType + Type_get_element_type.argtypes = [Type] Type_get_element_type.restype = Type Type_get_element_type.errcheck = Type.from_result 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=150970&r1=150969&r2=150970&view=diff ============================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_type.py (original) +++ cfe/trunk/bindings/python/tests/cindex/test_type.py Mon Feb 20 11:45:30 2012 @@ -30,63 +30,63 @@ assert tu is not None return tu -def test_a_struct(): - tu = get_tu(kInput) - - for n in tu.cursor.get_children(): - if n.spelling == 'teststruct': - fields = list(n.get_children()) - - assert all(x.kind == CursorKind.FIELD_DECL for x in fields) - - assert fields[0].spelling == 'a' - assert not fields[0].type.is_const_qualified() - assert fields[0].type.kind == TypeKind.INT - assert fields[0].type.get_canonical().kind == TypeKind.INT - - assert fields[1].spelling == 'b' - assert not fields[1].type.is_const_qualified() - assert fields[1].type.kind == TypeKind.TYPEDEF - assert fields[1].type.get_canonical().kind == TypeKind.INT - assert fields[1].type.get_declaration().spelling == 'I' - - assert fields[2].spelling == 'c' - assert not fields[2].type.is_const_qualified() - assert fields[2].type.kind == TypeKind.LONG - assert fields[2].type.get_canonical().kind == TypeKind.LONG - - assert fields[3].spelling == 'd' - assert not fields[3].type.is_const_qualified() - assert fields[3].type.kind == TypeKind.ULONG - assert fields[3].type.get_canonical().kind == TypeKind.ULONG - - assert fields[4].spelling == 'e' - assert not fields[4].type.is_const_qualified() - assert fields[4].type.kind == TypeKind.LONG - assert fields[4].type.get_canonical().kind == TypeKind.LONG - - assert fields[5].spelling == 'f' - assert fields[5].type.is_const_qualified() - assert fields[5].type.kind == TypeKind.INT - assert fields[5].type.get_canonical().kind == TypeKind.INT - - assert fields[6].spelling == 'g' - assert not fields[6].type.is_const_qualified() - assert fields[6].type.kind == TypeKind.POINTER - assert fields[6].type.get_pointee().kind == TypeKind.INT - - assert fields[7].spelling == 'h' - assert not fields[7].type.is_const_qualified() - assert fields[7].type.kind == TypeKind.POINTER - assert fields[7].type.get_pointee().kind == TypeKind.POINTER - 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 get_cursor(tu, spelling): + for cursor in tu.cursor.get_children(): + if cursor.spelling == spelling: + return cursor - break + return None - else: - assert False, "Didn't find teststruct??" +def test_a_struct(): + tu = get_tu(kInput) + teststruct = get_cursor(tu, 'teststruct') + 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 fields[0].spelling == 'a' + assert not fields[0].type.is_const_qualified() + assert fields[0].type.kind == TypeKind.INT + assert fields[0].type.get_canonical().kind == TypeKind.INT + + assert fields[1].spelling == 'b' + assert not fields[1].type.is_const_qualified() + assert fields[1].type.kind == TypeKind.TYPEDEF + assert fields[1].type.get_canonical().kind == TypeKind.INT + assert fields[1].type.get_declaration().spelling == 'I' + + assert fields[2].spelling == 'c' + assert not fields[2].type.is_const_qualified() + assert fields[2].type.kind == TypeKind.LONG + assert fields[2].type.get_canonical().kind == TypeKind.LONG + + assert fields[3].spelling == 'd' + assert not fields[3].type.is_const_qualified() + assert fields[3].type.kind == TypeKind.ULONG + assert fields[3].type.get_canonical().kind == TypeKind.ULONG + + assert fields[4].spelling == 'e' + assert not fields[4].type.is_const_qualified() + assert fields[4].type.kind == TypeKind.LONG + assert fields[4].type.get_canonical().kind == TypeKind.LONG + + assert fields[5].spelling == 'f' + assert fields[5].type.is_const_qualified() + assert fields[5].type.kind == TypeKind.INT + assert fields[5].type.get_canonical().kind == TypeKind.INT + + assert fields[6].spelling == 'g' + assert not fields[6].type.is_const_qualified() + assert fields[6].type.kind == TypeKind.POINTER + assert fields[6].type.get_pointee().kind == TypeKind.INT + + assert fields[7].spelling == 'h' + assert not fields[7].type.is_const_qualified() + assert fields[7].type.kind == TypeKind.POINTER + assert fields[7].type.get_pointee().kind == TypeKind.POINTER + assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER + assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT constarrayInput=""" struct teststruct { @@ -96,33 +96,23 @@ def testConstantArray(): tu = get_tu(constarrayInput) - for n in tu.cursor.get_children(): - if n.spelling == 'teststruct': - fields = list(n.get_children()) - assert fields[0].spelling == 'A' - assert fields[0].type.kind == TypeKind.CONSTANTARRAY - assert fields[0].type.get_array_element_type() is not None - assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER - assert fields[0].type.get_array_size() == 2 - - break - else: - assert False, "Didn't find teststruct??" + teststruct = get_cursor(tu, 'teststruct') + assert teststruct is not None, "Didn't find teststruct??" + fields = list(teststruct.get_children()) + assert fields[0].spelling == 'A' + assert fields[0].type.kind == TypeKind.CONSTANTARRAY + assert fields[0].type.get_array_element_type() is not None + assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER + assert fields[0].type.get_array_size() == 2 def test_equal(): """Ensure equivalence operators work on Type.""" source = 'int a; int b; void *v;' tu = get_tu(source) - a, b, v = None, None, None - - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'a': - a = cursor - elif cursor.spelling == 'b': - b = cursor - elif cursor.spelling == 'v': - v = cursor + a = get_cursor(tu, 'a') + b = get_cursor(tu, 'b') + v = get_cursor(tu, 'v') assert a is not None assert b is not None @@ -134,15 +124,72 @@ assert a.type != None assert a.type != 'foo' +def test_function_argument_types(): + """Ensure that Type.argument_types() works as expected.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + assert f is not None + + args = f.type.argument_types() + assert args is not None + assert len(args) == 2 + + t0 = args[0] + assert t0 is not None + assert t0.kind == TypeKind.INT + + t1 = args[1] + assert t1 is not None + assert t1.kind == TypeKind.INT + + args2 = list(args) + assert len(args2) == 2 + assert t0 == args2[0] + assert t1 == args2[1] + + at raises(TypeError) +def test_argument_types_string_key(): + """Ensure that non-int keys raise a TypeError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + assert f is not None + + args = f.type.argument_types() + assert len(args) == 2 + + args['foo'] + + at raises(IndexError) +def test_argument_types_negative_index(): + """Ensure that negative indexes on argument_types Raises an IndexError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + args[-1] + + at raises(IndexError) +def test_argument_types_overflow_index(): + """Ensure that indexes beyond the length of Type.argument_types() raise.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + args[2] + + at raises(Exception) +def test_argument_types_invalid_type(): + """Ensure that obtaining argument_types on a Type without them raises.""" + tu = get_tu('int i;') + i = get_cursor(tu, 'i') + assert i is not None + + i.type.argument_types() + def test_is_pod(): tu = get_tu('int i; void f();') - i, f = None, None - - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - elif cursor.spelling == 'f': - f = cursor + i = get_cursor(tu, 'i') + f = get_cursor(tu, 'f') assert i is not None assert f is not None @@ -161,12 +208,8 @@ """ tu = get_tu(source) - foo, bar = None, None - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'foo': - foo = cursor - elif cursor.spelling == 'bar': - bar = cursor + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') assert foo is not None assert bar is not None @@ -177,12 +220,7 @@ def test_element_type(): tu = get_tu('int i[5];') - i = None - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - break - + i = get_cursor(tu, 'i') assert i is not None assert i.type.kind == TypeKind.CONSTANTARRAY @@ -192,24 +230,14 @@ def test_invalid_element_type(): """Ensure Type.element_type raises if type doesn't have elements.""" tu = get_tu('int i;') - - i = None - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - break - + i = get_cursor(tu, 'i') assert i is not None i.element_type def test_element_count(): tu = get_tu('int i[5]; int j;') - - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - elif cursor.spelling == 'j': - j = cursor + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') assert i is not None assert j is not None From aaron at aaronballman.com Mon Feb 20 10:02:11 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 20 Feb 2012 12:02:11 -0600 Subject: [cfe-commits] [PATCH] Supporting thiscall compatibility with MSVC In-Reply-To: References: Message-ID: Ping? On Sat, Feb 18, 2012 at 11:36 AM, Aaron Ballman wrote: > On Fri, Feb 17, 2012 at 7:30 PM, Eli Friedman wrote: >> On Fri, Feb 17, 2012 at 3:41 PM, Aaron Ballman wrote: >>> On Thu, Feb 16, 2012 at 10:42 PM, Eli Friedman wrote: >>>> On Thu, Feb 16, 2012 at 8:39 PM, Aaron Ballman wrote: >>>>> On Thu, Feb 16, 2012 at 9:50 PM, Eli Friedman wrote: >>>>>> On Thu, Feb 16, 2012 at 7:38 PM, Aaron Ballman wrote: >>>>>>> On Thu, Feb 16, 2012 at 8:52 PM, Eli Friedman wrote: >>>>>>>> On Thu, Feb 16, 2012 at 6:25 PM, Aaron Ballman wrote: >>>>>>>>> Here's the next attempt at the MSVC thiscall support patch, this time >>>>>>>>> with test cases and an improved tablegen declaration. >>>>>>>>> >>>>>>>>> This is the first time I've done a test case for clang or llvm >>>>>>>>> codegen, so please pay special attention to the test cases and let me >>>>>>>>> know if I'm off-base (and what I should do differently). >>>>>>>> >>>>>>>> You might want to make the LLVM testcase a bit stronger by using CHECK-NEXT. >>>>>>> >>>>>>> Does CHECK-NEXT basically chain the checks together to check several >>>>>>> lines as a group? >>>>>> >>>>>> Basically, yes. >>>>> >>>>> The problem is that the assembly is different between O levels.  So >>>>> -O0 does leal, leal, but -O1 does leal, movl. >>>>> >>>>> Is there a way for me to handle this in the test case, or should I >>>>> just be explicit about the O level and its behavior? >>>> >>>> We always run tests at the same -O level, so you shouldn't worry about >>>> that.  That said, if you think splitting your testcase into multiple >>>> functions would make it more stable, please do that. >>> >>> Here's another shot at the patch -- this time, I am using the proper >>> way to test for the Win32 ABI, and I've updated the X86 codegen test >>> case so that it's a bit more clear. >> >> Your test somehow disappeared form the clang patch. >> >> Please rename IsWin32FloatStructABI if you're going to use it this >> way.  I'm still not convinced it's necessary to behave differently >> when targeting MinGW, though. > > That was truly odd -- no idea how the test case got missed, but it's > back again.  I've also removed the check for the Win32 ABI as it > appears this is used by gcc (4.6 and up) for MS compat as well. > > ~Aaron From gregory.szorc at gmail.com Mon Feb 20 09:58:02 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 17:58:02 -0000 Subject: [cfe-commits] r150971 - /cfe/trunk/bindings/python/tests/cindex/test_type.py Message-ID: <20120220175802.C299C2A6C12F@llvm.org> Author: gps Date: Mon Feb 20 11:58:02 2012 New Revision: 150971 URL: http://llvm.org/viewvc/llvm-project?rev=150971&view=rev Log: [clang.py] Add tests for Type.is_volatile_qualified and Type.is_restrict_qualified Modified: cfe/trunk/bindings/python/tests/cindex/test_type.py 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=150971&r1=150970&r2=150971&view=diff ============================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_type.py (original) +++ cfe/trunk/bindings/python/tests/cindex/test_type.py Mon Feb 20 11:58:02 2012 @@ -1,3 +1,4 @@ +from clang.cindex import Cursor from clang.cindex import CursorKind from clang.cindex import Index from clang.cindex import TypeKind @@ -30,11 +31,23 @@ assert tu is not None return tu -def get_cursor(tu, spelling): - for cursor in tu.cursor.get_children(): +def get_cursor(source, spelling): + children = [] + if isinstance(source, Cursor): + children = source.get_children() + else: + # Assume TU + children = source.cursor.get_children() + + for cursor in children: if cursor.spelling == spelling: return cursor + # Recurse into children. + result = get_cursor(cursor, spelling) + if result is not None: + return result + return None def test_a_struct(): @@ -249,3 +262,33 @@ assert False except: assert True + +def test_is_volatile_qualified(): + """Ensure Type.is_volatile_qualified works.""" + + tu = get_tu('volatile int i = 4; int j = 2;') + + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + assert i is not None + assert j is not None + + assert isinstance(i.type.is_volatile_qualified(), bool) + assert i.type.is_volatile_qualified() + assert not j.type.is_volatile_qualified() + +def test_is_restrict_qualified(): + """Ensure Type.is_restrict_qualified works.""" + + tu = get_tu('struct s { void * restrict i; void * j };') + + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + assert i is not None + assert j is not None + + assert isinstance(i.type.is_restrict_qualified(), bool) + assert i.type.is_restrict_qualified() + assert not j.type.is_restrict_qualified() From gregory.szorc at gmail.com Mon Feb 20 09:58:40 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 17:58:40 -0000 Subject: [cfe-commits] r150972 - in /cfe/trunk/bindings/python: clang/cindex.py tests/cindex/test_type.py Message-ID: <20120220175840.EC1CB2A6C12F@llvm.org> Author: gps Date: Mon Feb 20 11:58:40 2012 New Revision: 150972 URL: http://llvm.org/viewvc/llvm-project?rev=150972&view=rev Log: [clang.py] Format and add documention for Type Modified: cfe/trunk/bindings/python/clang/cindex.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=150972&r1=150971&r2=150972&view=diff ============================================================================== --- cfe/trunk/bindings/python/clang/cindex.py (original) +++ cfe/trunk/bindings/python/clang/cindex.py Mon Feb 20 11:58:40 2012 @@ -1221,26 +1221,26 @@ return Type_get_canonical(self) def is_const_qualified(self): - """ - Determine whether a Type has the "const" qualifier set, - without looking through typedefs that may have added "const" + """Determine whether a Type has the "const" qualifier set. + + This does not look through typedefs that may have added "const" at a different level. """ return Type_is_const_qualified(self) def is_volatile_qualified(self): - """ - Determine whether a Type has the "volatile" qualifier set, - without looking through typedefs that may have added - "volatile" at a different level. + """Determine whether a Type has the "volatile" qualifier set. + + This does not look through typedefs that may have added "volatile" + at a different level. """ return Type_is_volatile_qualified(self) def is_restrict_qualified(self): - """ - Determine whether a Type has the "restrict" qualifier set, - without looking through typedefs that may have added - "restrict" at a different level. + """Determine whether a Type has the "restrict" qualifier set. + + This does not look through typedefs that may have added "restrict" at + a different level. """ return Type_is_restrict_qualified(self) 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=150972&r1=150971&r2=150972&view=diff ============================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_type.py (original) +++ cfe/trunk/bindings/python/tests/cindex/test_type.py Mon Feb 20 11:58:40 2012 @@ -200,6 +200,7 @@ i.type.argument_types() def test_is_pod(): + """Ensure Type.is_pod() works.""" tu = get_tu('int i; void f();') i = get_cursor(tu, 'i') f = get_cursor(tu, 'f') @@ -232,6 +233,7 @@ assert not bar.type.is_function_variadic() def test_element_type(): + """Ensure Type.element_type works.""" tu = get_tu('int i[5];') i = get_cursor(tu, 'i') assert i is not None @@ -248,6 +250,7 @@ i.element_type def test_element_count(): + """Ensure Type.element_count works.""" tu = get_tu('int i[5]; int j;') i = get_cursor(tu, 'i') j = get_cursor(tu, 'j') From echristo at apple.com Mon Feb 20 10:05:04 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 18:05:04 -0000 Subject: [cfe-commits] r150976 - /cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Message-ID: <20120220180504.454872A6C12F@llvm.org> Author: echristo Date: Mon Feb 20 12:05:04 2012 New Revision: 150976 URL: http://llvm.org/viewvc/llvm-project?rev=150976&view=rev Log: Make forward declarations for objective-c types use the new temporary forward declaration nodes. Fixes a problem building Chrome. 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=150976&r1=150975&r2=150976&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Feb 20 12:05:04 2012 @@ -336,21 +336,19 @@ case BuiltinType::Void: return llvm::DIType(); case BuiltinType::ObjCClass: - return DBuilder.createStructType(TheCU, "objc_class", - getOrCreateMainFile(), 0, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray()); + return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + "objc_class", getOrCreateMainFile(), + 0); case BuiltinType::ObjCId: { // typedef struct objc_class *Class; // typedef struct objc_object { // Class isa; // } *id; - llvm::DIType OCTy = - DBuilder.createStructType(TheCU, "objc_class", - getOrCreateMainFile(), 0, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray()); + llvm::DIType OCTy = + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + "objc_class", getOrCreateMainFile(), + 0); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size); @@ -368,10 +366,10 @@ 0, 0, 0, 0, Elements); } case BuiltinType::ObjCSel: { - return DBuilder.createStructType(TheCU, "objc_selector", - getOrCreateMainFile(), 0, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray()); + return + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + "objc_selector", getOrCreateMainFile(), + 0); } case BuiltinType::UChar: case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; @@ -1224,10 +1222,9 @@ ObjCInterfaceDecl *Def = ID->getDefinition(); if (!Def) { llvm::DIType FwdDecl = - DBuilder.createStructType(Unit, ID->getName(), - DefUnit, Line, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray(), RuntimeLang); + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + ID->getName(), DefUnit, Line, + RuntimeLang); return FwdDecl; } ID = Def; From echristo at apple.com Mon Feb 20 10:05:24 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 18:05:24 -0000 Subject: [cfe-commits] r150977 - in /cfe/trunk: lib/CodeGen/CGDebugInfo.cpp test/CodeGenCXX/debug-info-artificial-arg.cpp test/CodeGenCXX/debug-info-fwd-ref.cpp test/CodeGenObjC/debug-info-fwddecl.m Message-ID: <20120220180524.9C44D2A6C12F@llvm.org> Author: echristo Date: Mon Feb 20 12:05:24 2012 New Revision: 150977 URL: http://llvm.org/viewvc/llvm-project?rev=150977&view=rev Log: Remove the type retaining from the clang frontend. This is now handled by the caching and rauw. Also fix one cache that wasn't being added to highlighted by this patch. Update all testcases accordingly. This should fix the deall failure. Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp cfe/trunk/test/CodeGenCXX/debug-info-artificial-arg.cpp cfe/trunk/test/CodeGenCXX/debug-info-fwd-ref.cpp cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=150977&r1=150976&r2=150977&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Feb 20 12:05:24 2012 @@ -551,7 +551,9 @@ RecordDecl *RD = RTy->getDecl(); llvm::DIDescriptor FDContext = getContextDescriptor(cast(RD->getDeclContext())); - return createRecordFwdDecl(RD, FDContext); + llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext); + TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy; + return RetTy; } return getOrCreateType(PointeeTy, Unit); @@ -1118,7 +1120,6 @@ llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy, SourceLocation Loc) { llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc)); - DBuilder.retainType(T); return T; } @@ -1767,7 +1768,7 @@ // than C++ class type, but needs llvm metadata changes first. RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), - llvm::DIArray(), NULL, + llvm::DIArray(), llvm::DIType(), llvm::DIArray()); } else RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, @@ -2577,8 +2578,9 @@ RepTy = llvm::DIType(cast(it->second)); } - if (Ty.Verify() && RepTy.Verify()) + if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) { Ty.replaceAllUsesWith(RepTy); + } } DBuilder.finalize(); } Modified: cfe/trunk/test/CodeGenCXX/debug-info-artificial-arg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-artificial-arg.cpp?rev=150977&r1=150976&r2=150977&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/debug-info-artificial-arg.cpp (original) +++ cfe/trunk/test/CodeGenCXX/debug-info-artificial-arg.cpp Mon Feb 20 12:05:24 2012 @@ -23,7 +23,8 @@ } // FIXME: The numbers are truly awful. -// CHECK: !22 = metadata !{i32 786447, null, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !5} ; [ DW_TAG_pointer_type ] -// CHECK: metadata !5, metadata !"A", metadata !"A", metadata !"", metadata !6, i32 12, metadata !34, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !36} ; [ DW_TAG_subprogram ] -// CHECK: metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !35, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] -// CHECK: !35 = metadata !{null, metadata !30, metadata !13, metadata !22} +// CHECK: !18 = metadata !{i32 786447, i32 0, metadata !"", i32 0, i32 0, i64 64, i64 64, i64 0, i32 64, metadata !19} ; [ DW_TAG_pointer_type ] +// CHECK: !19 = metadata !{i32 786434, null, metadata !"A", metadata !6, i32 8, i64 128, i64 64, i32 0, i32 0, null, metadata !20, i32 0, metadata !19, null} ; [ DW_TAG_class_type ] +// CHECK: metadata !19, metadata !"A", metadata !"A", metadata !"", metadata !6, i32 12, metadata !45, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !47} ; [ DW_TAG_subprogram ] +// CHECK: metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !46, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] +// CHECK: !46 = metadata !{null, metadata !18, metadata !9, metadata !34} Modified: cfe/trunk/test/CodeGenCXX/debug-info-fwd-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-fwd-ref.cpp?rev=150977&r1=150976&r2=150977&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/debug-info-fwd-ref.cpp (original) +++ cfe/trunk/test/CodeGenCXX/debug-info-fwd-ref.cpp Mon Feb 20 12:05:24 2012 @@ -19,8 +19,8 @@ // Make sure we have two DW_TAG_class_types for baz and bar and no forward // references. // FIXME: These should be struct types to match the declaration. -// CHECK: metadata !{i32 {{.*}}, null, metadata !"bar", metadata !6, i32 8, i64 128, i64 64, i32 0, i32 0, null, metadata !7, i32 0, null, null} ; [ DW_TAG_class_type ] -// CHECK: metadata !{i32 {{.*}}, null, metadata !"baz", metadata !6, i32 3, i64 32, i64 32, i32 0, i32 0, null, metadata !10, i32 0, null, null} ; [ DW_TAG_class_type ] +// CHECK: metadata !{i32 {{.*}}, null, metadata !"bar", metadata !6, i32 8, i64 128, i64 64, i32 0, i32 0, null, metadata !20, i32 0, null, null} ; [ DW_TAG_class_type ] +// CHECK: metadata !{i32 {{.*}}, null, metadata !"baz", metadata !6, i32 3, i64 32, i64 32, i32 0, i32 0, null, metadata !23, i32 0, null, null} ; [ DW_TAG_class_type ] // CHECK-NOT: metadata !{i32 {{.*}}, null, metadata !"bar", metadata !6, i32 9, i64 0, i64 0, i32 0, i32 4, i32 0, null, i32 0, i32 0} ; [ DW_TAG_class_type ] // CHECK-NOT: metadata !{i32 {{.*}}, null, metadata !"baz", metadata !6, i32 3, i64 0, i64 0, i32 0, i32 4, null, null, i32 0, null, null} ; [ DW_TAG_class_type ] Modified: cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m?rev=150977&r1=150976&r2=150977&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m (original) +++ cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m Mon Feb 20 12:05:24 2012 @@ -2,4 +2,4 @@ @class ForwardObjcClass; ForwardObjcClass *ptr = 0; -// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, metadata !"ForwardObjcClass", metadata !{{.*}}, i32 2, i64 0, i64 0, i32 0, i32 4, null, null, i32 16, i32 0} ; [ DW_TAG_structure_type ] +// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !6, i32 2, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] From devlists at shadowlab.org Mon Feb 20 10:23:07 2012 From: devlists at shadowlab.org (Jean-Daniel Dupas) Date: Mon, 20 Feb 2012 19:23:07 +0100 Subject: [cfe-commits] [patch] -Wformat fixup for vprintf (and friends) In-Reply-To: References: <85F50322-F747-4463-8256-9D1A8C06310C@shadowlab.org> Message-ID: <3D271A4B-EF5F-4012-9E33-810DDF9758BD@shadowlab.org> ping. Le 16 févr. 2012 à 23:39, Jean-Daniel Dupas a écrit : > > Le 16 févr. 2012 à 19:17, Ted Kremenek a écrit : > >> On Feb 16, 2012, at 1:57 AM, Jean-Daniel Dupas wrote: >> >>> Hi, >>> >>> This patch implements a long standing FIXME. >>> When calling a non variadic format function(vprintf, vscanf, NSLogv, …), is the format argument references a parameter of the enclosing function, clang never warned. >>> With this change, clang will inhibit the warning only if the parameter is declared as a format string with a compatible type. >>> >>> >>> -- Jean-Daniel >>> >> >> Hi Jean-Daniel, >> >> I've noticed this patch contains seemingly unrelated changes, e.g.: >> >> >>> // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s >>> >>> +#include >>> + >>> extern "C" { >>> -extern int scanf(const char *restrict, ...); >>> -extern int printf(const char *restrict, ...); >>> +extern int scanf(const char *, ...); >>> +extern int printf(const char *, ...); >>> +extern int vprintf(const char *, va_list ap); >>> } >>> >> >> >> What is the motivation for removing the 'restrict' in these test cases? It seems completely unrelated, unnecessary, and actually incorrect since clang defaults to c99. > > My bad. > I noticed that the restrict keyword was not supported in C++ member declaration and was interpreted as the parameter name instead, so I removed it to avoid confusion, and I erroneously removed it from the C functions too. > > Is this new patch OK ? > > -- Jean-Daniel > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits -- Jean-Daniel -------------- next part -------------- A non-text attachment was scrubbed... Name: vprintf.patch Type: application/octet-stream Size: 8517 bytes Desc: not available URL: From hans at chromium.org Mon Feb 20 10:31:53 2012 From: hans at chromium.org (Hans Wennborg) Date: Mon, 20 Feb 2012 18:31:53 +0000 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) Message-ID: Hi all, Attached is a first stab at adding a warning for using non-standard things in format strings (like the 'q' length modifier or the 'S' conversion specifier). I'm a little bit confused about the status of some of these. For example, should 'C' and 'S' be considered GNU extensions, and therefore allowable when using -std=gnu99? Also, there might be a better approach to this, or better names for things, etc. so please take a look. This causes a bunch of new failures in the gcc.dg test-suite. For instance, in gcc.dg/format/c90-scanf-3.c it will warn about the 'a' length modifier. The test says "Formats using extensions to the standard should be rejected in strict pedantic mode." so I think my patch is doing the right thing, but maybe the expectations need to be tweaked a bit. Thanks, Hans -------------- next part -------------- A non-text attachment was scrubbed... Name: non-standard-format-strings.diff Type: application/octet-stream Size: 16958 bytes Desc: not available URL: From thakis at chromium.org Mon Feb 20 10:42:36 2012 From: thakis at chromium.org (Nico Weber) Date: Mon, 20 Feb 2012 10:42:36 -0800 Subject: [cfe-commits] [patch][pr12001] Avoid increasing visibility in some cases In-Reply-To: References: <4F41B060.9020500@gmail.com> <4F41B9E8.4020407@gmail.com> Message-ID: On Mon, Feb 20, 2012 at 4:24 AM, Rafael Espíndola wrote: > 2012/2/19 Nico Weber : >> Thanks, Rafael! >> >> I verified that the components build of chromium/linux, and the >> "normal" build of chromium/linux and mac continue to work. In >> addition, the components build of chromium/mac starts to work with >> this patch (with some changes on the chromium side). Hooray :-) > > What changes were needed on your side? Nothing interesting, mostly just adding visibility("default") attributes to a few functions, cleaning up library dependencies, etc (http://crbug.com/90078 and http://codereview.chromium.org/7484017/ mostly). > >> The patch looks similar what I was trying locally, so as far as I can >> tell it looks good. (You have more testcases though :-) ). > > Yes, I started with your patch, but moved the logic to a new function. > >> Nico > > Cheers, > Rafael From echristo at apple.com Mon Feb 20 11:04:45 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 11:04:45 -0800 Subject: [cfe-commits] [PATCH] Getting the driver to understand -working-directory In-Reply-To: References: Message-ID: On Feb 17, 2012, at 4:26 PM, Aaron Ballman wrote: > It turns out that cc1 understands the working-directory flag, but the > main driver does not. This patch corrects the logic. > > ~Aaron > _______________________________________________ I don't object, but is there a use of passing this in? Also, testcase? :) -eric From joerg at britannica.bec.de Mon Feb 20 11:04:32 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 20:04:32 +0100 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: Message-ID: <20120220190432.GA18744@britannica.bec.de> On Mon, Feb 20, 2012 at 06:31:53PM +0000, Hans Wennborg wrote: > I'm a little bit confused about the status of some of these. For > example, should 'C' and 'S' be considered GNU extensions, and > therefore allowable when using -std=gnu99? In my opinion: no. -std=gnu99 specifies C99 with GNU compiler extensions. It doesn't mean anything about the run time implementation. As such, all the non-standard flags should go into a -Wformat-extensions category and it should be enabled by default with -Wformat. Joerg From kremenek at apple.com Mon Feb 20 11:02:25 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 11:02:25 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: Message-ID: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> Hi Hans, Thanks so much for working on this, but I'm honestly *very* concerned about the practicality of issuing all these warnings. Real code makes assumptions on what format specifiers are available given the platform(s) they are targeting. Unconditionally warning about non-standard stuff seems like a recipe to irritate a huge number of users. Indeed, the format string checking now relaxes the strict interpretation of the standard in cases where it's basically always safe. This is the behavior users expect. I think it's also important to keep in mind the purpose of these warnings. The purpose of these warnings is to find problems, not annoy users. For me, the better approach would be two options: (1) Warn about non-standard format strings only when it is an issue for the target platform. This is hard to do, but this is basically what users will expect. (2) Provide an opt-in mechanism for such pedantic warnings. For example, activating these warnings under -pedantic, or simply requiring them to pass -Wformat-nonstandard. This will satisfy users who care about portability. I definitely think that -Wformat-nonstandard should not be on by default, and not activated by passing -Wformat. Concerning (2), there may just be an option question about warnings concerning non-portable code. That's a wide open topic, but checking for non-standard format specifiers is really just one drop in that bucket. It may be worth having a cohesive plan for just checking for non-portable stuff, and maybe grouping them under something like "-Wportable". Thoughts? Ted On Feb 20, 2012, at 10:31 AM, Hans Wennborg wrote: > Hi all, > > Attached is a first stab at adding a warning for using non-standard > things in format strings (like the 'q' length modifier or the 'S' > conversion specifier). > > I'm a little bit confused about the status of some of these. For > example, should 'C' and 'S' be considered GNU extensions, and > therefore allowable when using -std=gnu99? > > Also, there might be a better approach to this, or better names for > things, etc. so please take a look. > > This causes a bunch of new failures in the gcc.dg test-suite. For > instance, in gcc.dg/format/c90-scanf-3.c it will warn about the 'a' > length modifier. The test says "Formats using extensions to the > standard should be rejected in strict pedantic mode." so I think my > patch is doing the right thing, but maybe the expectations need to be > tweaked a bit. > > Thanks, > Hans > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From aaron at aaronballman.com Mon Feb 20 11:10:55 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 20 Feb 2012 13:10:55 -0600 Subject: [cfe-commits] [PATCH] Getting the driver to understand -working-directory In-Reply-To: References: Message-ID: On Mon, Feb 20, 2012 at 1:04 PM, Eric Christopher wrote: > > On Feb 17, 2012, at 4:26 PM, Aaron Ballman wrote: > >> It turns out that cc1 understands the working-directory flag, but the >> main driver does not.  This patch corrects the logic. >> >> ~Aaron >> _______________________________________________ > > I don't object, but is there a use of passing this in? Uncertain -- but it's a supported flag that didn't behave as expected when I ran into it. ;-) > Also, testcase? :) I'll add one this evening if I can think of a way to do it sensibly. Thanks! ~Aaron From chandlerc at google.com Mon Feb 20 11:13:33 2012 From: chandlerc at google.com (Chandler Carruth) Date: Mon, 20 Feb 2012 11:13:33 -0800 Subject: [cfe-commits] [PATCH] [PR 12026] Restore target-prefix tool support In-Reply-To: <20120220163950.GA13346@britannica.bec.de> References: <20120220163950.GA13346@britannica.bec.de> Message-ID: On Mon, Feb 20, 2012 at 8:39 AM, Joerg Sonnenberger wrote: > Hi all, > this is the minimally intrusive fix for the target-prefixed toolchain > support. This is a partial revert of r148839, fixed in r149083, reverted > and re-broken in r149337. Given that's been 3 weeks now with a proper > solution, I think it is time to restore the status quo. See also PR > 12026. > This is a hack though, and it's important to acknowledge that. We're now handling -target in two separate places. It would be better to sink this down to be grouped with the 'getToolChain()' call that is relevant, and add comments at the very least. Also, to introduce a hack like this, we definitely need good test cases so that we understand what is and isn't supposed to work. Relying on the happenstance of DefaultTargetTriple is what got us into the mess in the first place. -------------- next part -------------- An HTML attachment was scrubbed... URL: From echristo at apple.com Mon Feb 20 11:11:46 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 11:11:46 -0800 Subject: [cfe-commits] [PATCH] Getting the driver to understand -working-directory In-Reply-To: References: Message-ID: <1E506119-68BE-4AF7-8ECE-AC802108D81C@apple.com> On Feb 20, 2012, at 11:10 AM, Aaron Ballman wrote: > On Mon, Feb 20, 2012 at 1:04 PM, Eric Christopher wrote: >> >> On Feb 17, 2012, at 4:26 PM, Aaron Ballman wrote: >> >>> It turns out that cc1 understands the working-directory flag, but the >>> main driver does not. This patch corrects the logic. >>> >>> ~Aaron >>> _______________________________________________ >> >> I don't object, but is there a use of passing this in? > > Uncertain -- but it's a supported flag that didn't behave as expected > when I ran into it. ;-) > That's fair. Was just a "is anyone actually using it to worry about exposing it"? :) >> Also, testcase? :) > > I'll add one this evening if I can think of a way to do it sensibly. Sounds good to me. -eric From joerg at britannica.bec.de Mon Feb 20 11:22:21 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 20:22:21 +0100 Subject: [cfe-commits] [PATCH] [PR 12026] Restore target-prefix tool support In-Reply-To: References: <20120220163950.GA13346@britannica.bec.de> Message-ID: <20120220192221.GA19139@britannica.bec.de> On Mon, Feb 20, 2012 at 11:13:33AM -0800, Chandler Carruth wrote: > On Mon, Feb 20, 2012 at 8:39 AM, Joerg Sonnenberger > wrote: > > > Hi all, > > this is the minimally intrusive fix for the target-prefixed toolchain > > support. This is a partial revert of r148839, fixed in r149083, reverted > > and re-broken in r149337. Given that's been 3 weeks now with a proper > > solution, I think it is time to restore the status quo. See also PR > > 12026. > > > > This is a hack though, and it's important to acknowledge that. We're now > handling -target in two separate places. It would be better to sink this > down to be grouped with the 'getToolChain()' call that is relevant, and add > comments at the very least. Like I said, this is just the minimal version to get it back working. > Also, to introduce a hack like this, we definitely need good test cases so > that we understand what is and isn't supposed to work. Relying on the > happenstance of DefaultTargetTriple is what got us into the mess in the > first place. The test cases can be revived from r149083. Joerg From hans at chromium.org Mon Feb 20 11:25:40 2012 From: hans at chromium.org (Hans Wennborg) Date: Mon, 20 Feb 2012 19:25:40 +0000 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> Message-ID: On Mon, Feb 20, 2012 at 19:02, Ted Kremenek wrote: > Hi Hans, > > Thanks so much for working on this, but I'm honestly *very* concerned about the practicality of issuing all these warnings.  Real code makes assumptions on what format specifiers are available given the platform(s) they are targeting.  Unconditionally warning about non-standard stuff seems like a recipe to irritate a huge number of users.  Indeed, the format string checking now relaxes the strict interpretation of the standard in cases where it's basically always safe.  This is the behavior users expect.  I think it's also important to keep in mind the purpose of these warnings.  The purpose of these warnings is to find problems, not annoy users. > > For me, the better approach would be two options: > > (1) Warn about non-standard format strings only when it is an issue for the target platform.  This is hard to do, but this is basically what users will expect. > > (2) Provide an opt-in mechanism for such pedantic warnings.  For example, activating these warnings under -pedantic, or simply requiring them to pass -Wformat-nonstandard.  This will satisfy users who care about portability. > > I definitely think that -Wformat-nonstandard should not be on by default, and not activated by passing -Wformat. > > Concerning (2), there may just be an option question about warnings concerning non-portable code.  That's a wide open topic, but checking for non-standard format specifiers is really just one drop in that bucket.  It may be worth having a cohesive plan for just checking for non-portable stuff, and maybe grouping them under something like "-Wportable". > > Thoughts? Keeping -Wformat-nonstandard out of -Wformat and having it in -pedantic sounds perfectly fine to me. I expect that lines up with what gcc does too. Thanks, Hans From kremenek at apple.com Mon Feb 20 11:27:36 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 11:27:36 -0800 Subject: [cfe-commits] [patch] clang-wpa: adapt to API changes In-Reply-To: References: Message-ID: <77638448-51A6-41C2-9C38-190E7E89DD36@apple.com> Hi Dylan, I'm actually in favor of removing clang-wpa entirely. Ted On Feb 20, 2012, at 9:36 AM, nobled wrote: > When clang-wpa was restored in r112014, it wasn't added back to the > examples/ Makefile or CMakeLists.txt, so it was never actually built, > and has been busted by API changes since August 2011. > <0001-examples-clang-wpa-adapt-to-API-changes.patch>_______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From kremenek at apple.com Mon Feb 20 11:22:18 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 11:22:18 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <20120220190432.GA18744@britannica.bec.de> References: <20120220190432.GA18744@britannica.bec.de> Message-ID: On Feb 20, 2012, at 11:04 AM, Joerg Sonnenberger wrote: > On Mon, Feb 20, 2012 at 06:31:53PM +0000, Hans Wennborg wrote: >> I'm a little bit confused about the status of some of these. For >> example, should 'C' and 'S' be considered GNU extensions, and >> therefore allowable when using -std=gnu99? > > In my opinion: no. -std=gnu99 specifies C99 with GNU compiler > extensions. It doesn't mean anything about the run time implementation. > As such, all the non-standard flags should go into a -Wformat-extensions > category and it should be enabled by default with -Wformat. I would expect most users would be very unhappy to see these warnings even when compiling with -std=gnu99. I think it is reasonable to activate them (or a subset) for -std=c99, as that essentially ties in with the portability argument I said in my other email. We should aim to do the right thing for users. In my experience, most users are not going to want to see these pedantic warnings unless they add value. I agree that ultimately this comes down to what the runtime supports, but not knowing those details doesn't give us liberty to emit a bunch of new warnings just because we don't have enough information to make a good decision about whether to emit a warning or not. A reasonable heuristic is that if (a) adding a warning adds value for most users and (b) we can do that warning with a reasonable amount of noise then we should aggressively pursue turning that warning on the regular usage scenarios (e.g., passing -Wformat or -Wall). I'm not certain if either (a) or (b) are satisfied here, which is why I think this should be an opt-in warning until we know how to do this better. From joerg at britannica.bec.de Mon Feb 20 11:35:14 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 20:35:14 +0100 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> Message-ID: <20120220193514.GB19139@britannica.bec.de> On Mon, Feb 20, 2012 at 11:02:25AM -0800, Ted Kremenek wrote: > (1) Warn about non-standard format strings only when it is an issue > for the target platform. This is hard to do, but this is basically > what users will expect. IMO most of the format extensions are of questionable value (%m), outdated historic extensions (q modifier) or just plainly unportable (S modifier). Allowing them by default makes it a lot easier to slip them unintentionally in for no real value in case of the first two categories. The third category is even more painful since it can require extensive code changes. Worse, even a single target playform is not necessarily consistent. Consider 'a' handling for scanf. Many embeddeed systems use Linux with uClibc -- which doesn't implement it. How do you detect if the libc support it or not? Joerg From kremenek at apple.com Mon Feb 20 11:37:33 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 11:37:33 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> Message-ID: On Feb 20, 2012, at 11:25 AM, Hans Wennborg wrote: > Keeping -Wformat-nonstandard out of -Wformat and having it in > -pedantic sounds perfectly fine to me. I expect that lines up with > what gcc does too. Ok, I think that approach is worth experimenting with. I've looked at the patch, and other than the default configuration of the warnings, it looks okay to me. One nit on wording in the diagnostic: "non-standard" or "non-portable"? The former is more technically accurate, but the latter is the implication the user cares about. What do you think? -------------- next part -------------- An HTML attachment was scrubbed... URL: From clattner at apple.com Mon Feb 20 11:43:07 2012 From: clattner at apple.com (Chris Lattner) Date: Mon, 20 Feb 2012 11:43:07 -0800 Subject: [cfe-commits] [patch] clang-wpa: adapt to API changes In-Reply-To: <77638448-51A6-41C2-9C38-190E7E89DD36@apple.com> References: <77638448-51A6-41C2-9C38-190E7E89DD36@apple.com> Message-ID: <0E3042B0-05E6-40AB-9C5D-80FB121EF5D0@apple.com> Me too, any objections? -Chris On Feb 20, 2012, at 11:27 AM, Ted Kremenek wrote: > Hi Dylan, > > I'm actually in favor of removing clang-wpa entirely. > > Ted > > On Feb 20, 2012, at 9:36 AM, nobled wrote: > >> When clang-wpa was restored in r112014, it wasn't added back to the >> examples/ Makefile or CMakeLists.txt, so it was never actually built, >> and has been busted by API changes since August 2011. >> <0001-examples-clang-wpa-adapt-to-API-changes.patch>_______________________________________________ >> 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 dgregor at apple.com Mon Feb 20 11:44:40 2012 From: dgregor at apple.com (Douglas Gregor) Date: Mon, 20 Feb 2012 19:44:40 -0000 Subject: [cfe-commits] r150982 - in /cfe/trunk: include/clang/AST/ include/clang/Sema/ lib/AST/ lib/Parse/ lib/Sema/ lib/Serialization/ test/CodeGenCXX/ Message-ID: <20120220194440.D9D312A6C12F@llvm.org> Author: dgregor Date: Mon Feb 20 13:44:39 2012 New Revision: 150982 URL: http://llvm.org/viewvc/llvm-project?rev=150982&view=rev Log: Basic support for name mangling of C++11 lambda expressions. Because name mangling in the Itanium C++ ABI for lambda expressions is so dependent on context, we encode the number used to encode each lambda as part of the lambda closure type, and maintain this value within Sema. Note that there are a several pieces still missing: - We still get the linkage of lambda expressions wrong - We aren't properly numbering or mangling lambda expressions that occur in default function arguments or in data member initializers. - We aren't (de-)serializing the lambda numbering tables Added: cfe/trunk/include/clang/AST/LambdaMangleContext.h (with props) cfe/trunk/lib/AST/LambdaMangleContext.cpp (with props) cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (with props) Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/AST/CMakeLists.txt cfe/trunk/lib/AST/ExprCXX.cpp cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/lib/Parse/ParseExprCXX.cpp cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Feb 20 13:44:39 2012 @@ -21,6 +21,7 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/VersionTuple.h" #include "clang/AST/Decl.h" +#include "clang/AST/LambdaMangleContext.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateName.h" @@ -326,6 +327,10 @@ /// expression used to copy the lambda object. llvm::DenseMap LambdaBlockPointerInits; + /// \brief Mapping from each declaration context to its corresponding lambda + /// mangling context. + llvm::DenseMap LambdaMangleContexts; + friend class CXXConversionDecl; /// \brief Mapping that stores parameterIndex values for ParmVarDecls @@ -1765,6 +1770,8 @@ /// it is not used. bool DeclMustBeEmitted(const Decl *D); + /// \brief Retrieve the lambda mangling number for a lambda expression. + unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator); /// \brief Used by ParmVarDecl to store on the side the /// index of the parameter when it exceeds the size of the normal bitfield. Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Feb 20 13:44:39 2012 @@ -569,8 +569,12 @@ unsigned NumCaptures : 16; /// \brief The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 15; + unsigned NumExplicitCaptures : 16; + /// \brief The number used to indicate this lambda expression for name + /// mangling in the Itanium C++ ABI. + unsigned ManglingNumber; + /// \brief The "extra" data associated with the lambda, including /// captures, capture initializers, the body of the lambda, and the /// array-index variables for array captures. @@ -1442,6 +1446,17 @@ /// actually abstract. bool mayBeAbstract() const; + /// \brief If this is the closure type of a lambda expression, retrieve the + /// number to be used for name mangling in the Itanium C++ ABI. + /// + /// Zero indicates that this closure type has internal linkage, so the + /// mangling number does not matter, while a non-zero value indicates which + /// lambda expression this is in this particular context. + unsigned getLambdaManglingNumber() const { + assert(isLambda() && "Not a lambda closure type!"); + return getLambdaData().ManglingNumber; + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Feb 20 13:44:39 2012 @@ -1166,7 +1166,8 @@ ArrayRef CaptureInits, ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, - SourceLocation ClosingBrace); + SourceLocation ClosingBrace, + unsigned ManglingNumber); /// \brief Construct an empty lambda expression. LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) @@ -1204,7 +1205,8 @@ ArrayRef CaptureInits, ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, - SourceLocation ClosingBrace); + SourceLocation ClosingBrace, + unsigned ManglingNumber); /// \brief Construct a new lambda expression that will be deserialized from /// an external source. @@ -1296,7 +1298,7 @@ /// \brief Whether this lambda had its result type explicitly specified. bool hasExplicitResultType() const { return ExplicitResultType; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == LambdaExprClass; } Added: cfe/trunk/include/clang/AST/LambdaMangleContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/LambdaMangleContext.h?rev=150982&view=auto ============================================================================== --- cfe/trunk/include/clang/AST/LambdaMangleContext.h (added) +++ cfe/trunk/include/clang/AST/LambdaMangleContext.h Mon Feb 20 13:44:39 2012 @@ -0,0 +1,36 @@ +//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- 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 the LambdaMangleContext interface, which keeps track of +// the Itanium C++ ABI mangling numbers for lambda expressions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H +#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H + +#include "llvm/ADT/DenseMap.h" + +namespace clang { + +class CXXMethodDecl; +class FunctionProtoType; + +/// \brief Keeps track of the mangled names of lambda expressions within a +/// particular context. +class LambdaMangleContext { + llvm::DenseMap ManglingNumbers; + +public: + /// \brief Retrieve the mangling number of a new lambda expression with the + /// given call operator within this lambda context. + unsigned getManglingNumber(CXXMethodDecl *CallOperator); +}; + +} // end namespace clang +#endif Propchange: cfe/trunk/include/clang/AST/LambdaMangleContext.h ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/include/clang/AST/LambdaMangleContext.h ------------------------------------------------------------------------------ svn:keywords = Id Propchange: cfe/trunk/include/clang/AST/LambdaMangleContext.h ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon Feb 20 13:44:39 2012 @@ -3555,7 +3555,10 @@ /// ActOnLambdaExpr - This is called when the body of a lambda expression /// was successfully completed. ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, - Scope *CurScope, bool IsInstantiation = false); + Scope *CurScope, + llvm::Optional ManglingNumber + = llvm::Optional(), + bool IsInstantiation = false); /// \brief Define the "body" of the conversion from a lambda object to a /// function pointer. Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Feb 20 13:44:39 2012 @@ -6748,6 +6748,13 @@ + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); } +unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) { + CXXRecordDecl *Lambda = CallOperator->getParent(); + return LambdaMangleContexts[Lambda->getDeclContext()] + .getManglingNumber(CallOperator); +} + + void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; } Modified: cfe/trunk/lib/AST/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/AST/CMakeLists.txt (original) +++ cfe/trunk/lib/AST/CMakeLists.txt Mon Feb 20 13:44:39 2012 @@ -28,6 +28,7 @@ InheritViz.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp + LambdaMangleContext.cpp Mangle.cpp MicrosoftCXXABI.cpp MicrosoftMangle.cpp Modified: cfe/trunk/lib/AST/ExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprCXX.cpp (original) +++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Feb 20 13:44:39 2012 @@ -764,7 +764,8 @@ ArrayRef CaptureInits, ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, - SourceLocation ClosingBrace) + SourceLocation ClosingBrace, + unsigned ManglingNumber) : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->isDependentType(), /*ContainsUnexpandedParameterPack=*/false), @@ -785,6 +786,7 @@ ASTContext &Context = Class->getASTContext(); Data.NumCaptures = NumCaptures; Data.NumExplicitCaptures = 0; + Data.ManglingNumber = ManglingNumber; Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures); Capture *ToCapture = Data.Captures; for (unsigned I = 0, N = Captures.size(); I != N; ++I) { @@ -824,7 +826,8 @@ ArrayRef CaptureInits, ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, - SourceLocation ClosingBrace) { + SourceLocation ClosingBrace, + unsigned ManglingNumber) { // Determine the type of the expression (i.e., the type of the // function object we're creating). QualType T = Context.getTypeDeclType(Class); @@ -837,7 +840,7 @@ return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, - ClosingBrace); + ClosingBrace, ManglingNumber); } LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures, Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Feb 20 13:44:39 2012 @@ -122,6 +122,13 @@ } bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + // Lambda closure types with external linkage (indicated by a + // non-zero lambda mangling number) have their own numbering scheme, so + // they do not need a discriminator. + if (const CXXRecordDecl *RD = dyn_cast(ND)) + if (RD->isLambda() && RD->getLambdaManglingNumber() > 0) + return false; + unsigned &discriminator = Uniquifier[ND]; if (!discriminator) discriminator = ++Discriminator; @@ -1076,6 +1083,38 @@ break; } + // ::= + // + // ::= Ul E [ ] _ + // ::= + # Parameter types or 'v' for 'void'. + if (const CXXRecordDecl *Record = dyn_cast(TD)) { + if (Record->isLambda()) { + // FIXME: Figure out if we're in a function body, default argument, + // or initializer for a class member. + + Out << "Ul"; + DeclarationName Name + = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + const FunctionProtoType *Proto + = cast(*Record->lookup(Name).first)->getType()-> + getAs(); + mangleBareFunctionType(Proto, /*MangleReturnType=*/false); + Out << "E"; + + // The number is omitted for the first closure type with a given + // in a given context; it is n-2 for the nth closure type + // (in lexical order) with that same and context. + // + // The AST keeps track of the number for us. + if (unsigned Number = Record->getLambdaManglingNumber()) { + if (Number > 1) + mangleNumber(Number - 2); + } + Out << '_'; + break; + } + } + // Get a unique id for the anonymous struct. uint64_t AnonStructId = Context.getAnonymousStructId(TD); Added: cfe/trunk/lib/AST/LambdaMangleContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/LambdaMangleContext.cpp?rev=150982&view=auto ============================================================================== --- cfe/trunk/lib/AST/LambdaMangleContext.cpp (added) +++ cfe/trunk/lib/AST/LambdaMangleContext.cpp Mon Feb 20 13:44:39 2012 @@ -0,0 +1,30 @@ +//===--- LambdaMangleContext.cpp - Context for mangling lambdas -*- 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 the LambdaMangleContext class, which keeps track of +// the Itanium C++ ABI mangling numbers for lambda expressions. +// +//===----------------------------------------------------------------------===// +#include "clang/AST/LambdaMangleContext.h" +#include "clang/AST/DeclCXX.h" + +using namespace clang; + +unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl *CallOperator) { + const FunctionProtoType *Proto + = CallOperator->getType()->getAs(); + ASTContext &Context = CallOperator->getASTContext(); + + QualType Key = Context.getFunctionType(Context.VoidTy, + Proto->arg_type_begin(), + Proto->getNumArgs(), + FunctionProtoType::ExtProtoInfo()); + Key = Context.getCanonicalType(Key); + return ++ManglingNumbers[Key->castAs()]; +} Propchange: cfe/trunk/lib/AST/LambdaMangleContext.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/lib/AST/LambdaMangleContext.cpp ------------------------------------------------------------------------------ svn:keywords = Id Propchange: cfe/trunk/lib/AST/LambdaMangleContext.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Feb 20 13:44:39 2012 @@ -886,8 +886,7 @@ BodyScope.Exit(); if (!Stmt.isInvalid()) - return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), - getCurScope()); + return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), getCurScope()); Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); return ExprError(); Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 20 13:44:39 2012 @@ -483,7 +483,9 @@ } ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, - Scope *CurScope, bool IsInstantiation) { + Scope *CurScope, + llvm::Optional ManglingNumber, + bool IsInstantiation) { // Leave the expression-evaluation context. DiscardCleanupsInEvaluationContext(); PopExpressionEvaluationContext(); @@ -633,11 +635,19 @@ if (LambdaExprNeedsCleanups) ExprNeedsCleanups = true; + // If we don't already have a mangling number for this lambda expression, + // allocate one now. + if (!ManglingNumber) { + // FIXME: Default arguments, data member initializers are special. + ManglingNumber = Context.getLambdaManglingNumber(CallOperator); + } + LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, - ArrayIndexStarts, Body->getLocEnd()); + ArrayIndexStarts, Body->getLocEnd(), + *ManglingNumber); // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Feb 20 13:44:39 2012 @@ -7769,8 +7769,9 @@ return ExprError(); } + unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber(); return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), - /*CurScope=*/0, + /*CurScope=*/0, ManglingNumber, /*IsInstantiation=*/true); } Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Feb 20 13:44:39 2012 @@ -1105,6 +1105,7 @@ = static_cast(Data); Lambda.NumCaptures = Record[Idx++]; Lambda.NumExplicitCaptures = Record[Idx++]; + Lambda.ManglingNumber = Record[Idx++]; Lambda.Captures = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); Capture *ToCapture = Lambda.Captures; Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Feb 20 13:44:39 2012 @@ -4332,6 +4332,7 @@ CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData(); Record.push_back(Lambda.NumCaptures); Record.push_back(Lambda.NumExplicitCaptures); + Record.push_back(Lambda.ManglingNumber); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { LambdaExpr::Capture &Capture = Lambda.Captures[I]; AddSourceLocation(Capture.getLocation(), Record); Modified: cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp?rev=150982&r1=150981&r2=150982&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Mon Feb 20 13:44:39 2012 @@ -2,8 +2,8 @@ int a() { return []{ return 1; }(); } // CHECK: define i32 @_Z1av -// CHECK: call i32 @"_ZZ1avENK3$_0clEv" -// CHECK: define internal i32 @"_ZZ1avENK3$_0clEv" +// CHECK: call i32 @_ZZ1avENKUlvE_clEv +// CHECK: define internal i32 @_ZZ1avENKUlvE_clEv // CHECK: ret i32 1 int b(int x) { return [x]{return x;}(); } @@ -11,8 +11,8 @@ // CHECK: store i32 // CHECK: load i32* // CHECK: store i32 -// CHECK: call i32 @"_ZZ1biENK3$_1clEv" -// CHECK: define internal i32 @"_ZZ1biENK3$_1clEv" +// CHECK: call i32 @_ZZ1biENKUlvE_clEv +// CHECK: define internal i32 @_ZZ1biENKUlvE_clEv // CHECK: load i32* // CHECK: ret i32 @@ -20,8 +20,8 @@ // CHECK: define i32 @_Z1ci // CHECK: store i32 // CHECK: store i32* -// CHECK: call i32 @"_ZZ1ciENK3$_2clEv" -// CHECK: define internal i32 @"_ZZ1ciENK3$_2clEv" +// CHECK: call i32 @_ZZ1ciENKUlvE_clEv +// CHECK: define internal i32 @_ZZ1ciENKUlvE_clEv // CHECK: load i32** // CHECK: load i32* // CHECK: ret i32 @@ -33,8 +33,8 @@ // CHECK: call void @_ZN1DC1Ev // CHECK: icmp ult i64 %{{.*}}, 10 // CHECK: call void @_ZN1DC1ERKS_ -// CHECK: call i32 @"_ZZ1diENK3$_3clEv" -// CHECK: define internal i32 @"_ZZ1diENK3$_3clEv" +// CHECK: call i32 @_ZZ1diENKUlvE_clEv +// CHECK: define internal i32 @_ZZ1diENKUlvE_clEv // CHECK: load i32* // CHECK: load i32* // CHECK: ret i32 @@ -44,29 +44,29 @@ // CHECK: define i32 @_Z1e1ES_b // CHECK: call void @_ZN1EC1ERKS_ // CHECK: invoke void @_ZN1EC1ERKS_ -// CHECK: invoke i32 @"_ZZ1e1ES_bENK3$_4clEv" -// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev" -// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev" +// CHECK: invoke i32 @_ZZ1e1ES_bENKUlvE_clEv +// CHECK: call void @_ZZ1e1ES_bENUlvE_D1Ev +// CHECK: call void @_ZZ1e1ES_bENUlvE_D1Ev -// CHECK: define internal i32 @"_ZZ1e1ES_bENK3$_4clEv" +// CHECK: define internal i32 @_ZZ1e1ES_bENKUlvE_clEv // CHECK: trunc i8 // CHECK: load i32* // CHECK: ret i32 void f() { // CHECK: define void @_Z1fv() - // CHECK: {{call.*_5cvPFiiiEEv}} + // CHECK: {{call.*@_ZZ1fvENKUliiE_cvPFiiiEEv}} // CHECK-NEXT: store i32 (i32, i32)* // CHECK-NEXT: ret void int (*fp)(int, int) = [](int x, int y){ return x + y; }; } -// CHECK: define internal i32 @"_ZZ1fvEN3$_58__invokeEii" +// CHECK: define internal i32 @_ZZ1fvENUliiE_8__invokeEii // CHECK: store i32 // CHECK-NEXT: store i32 // CHECK-NEXT: load i32* // CHECK-NEXT: load i32* -// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_5clEii" +// CHECK-NEXT: call i32 @_ZZ1fvENKUliiE_clEii // CHECK-NEXT: ret i32 -// CHECK: define internal void @"_ZZ1e1ES_bEN3$_4D2Ev" +// CHECK: define internal void @_ZZ1e1ES_bENUlvE_D2Ev Added: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=150982&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (added) +++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Mon Feb 20 13:44:39 2012 @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s | FileCheck %s + +// CHECK: define linkonce_odr void @_Z11inline_funci +inline void inline_func(int n) { + // CHECK: call i32 @_ZZ11inline_funciENKUlvE_clEv + int i = []{ return 1; }(); + + // CHECK: call i32 @_ZZ11inline_funciENKUlvE0_clEv + int j = [=] { return n + i; }(); + + // CHECK: call double @_ZZ11inline_funciENKUlvE1_clEv + int k = [=] () -> double { return n + i; }(); + + // CHECK: call i32 @_ZZ11inline_funciENKUliE_clEi + int l = [=] (int x) -> int { return x + i; }(n); + + // CHECK: ret void +} + +void call_inline_func() { + inline_func(17); +} Propchange: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp ------------------------------------------------------------------------------ svn:keywords = Id Propchange: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp ------------------------------------------------------------------------------ svn:mime-type = text/plain From chandlerc at gmail.com Mon Feb 20 11:49:07 2012 From: chandlerc at gmail.com (Chandler Carruth) Date: Mon, 20 Feb 2012 11:49:07 -0800 Subject: [cfe-commits] PATCH: Remove lazy-parse support from llvm::Triple Message-ID: Hello LLVM folks (and Clang folks sense triple impacts the Clang driver greatly)! This patch removes the lazy-parsing from the Triple class. From what I could tell, no one deeply relied on this, and it seems unlikely that we want people to be creating enough triples to need them to parse lazily... The code gets significantly simpler with this change, and I'm looking at further changes that will make it more efficient and still cleaner. In passing, it fixes a bug in 'hasEnvironment' which would return the wrong answer if called before any other accessors on a triple. This category of bugs is one of the primary reasons I'm not a fan of deferred parsing here. All existing tests seem happy, and I can add a few more, as well as look for any cleanups I missed, but I wanted to get some feedback on the general direction. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: remove-lazy-parse.patch Type: text/x-patch Size: 9076 bytes Desc: not available URL: From kremenek at apple.com Mon Feb 20 11:48:41 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 11:48:41 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <20120220193514.GB19139@britannica.bec.de> References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> <20120220193514.GB19139@britannica.bec.de> Message-ID: <17495456-43B6-493F-AA82-584626D83CA2@apple.com> On Feb 20, 2012, at 11:35 AM, Joerg Sonnenberger wrote: > On Mon, Feb 20, 2012 at 11:02:25AM -0800, Ted Kremenek wrote: >> (1) Warn about non-standard format strings only when it is an issue >> for the target platform. This is hard to do, but this is basically >> what users will expect. > > IMO most of the format extensions are of questionable value (%m), > outdated historic extensions (q modifier) or just plainly unportable (S > modifier). I'm not questioning the motivation for these changes; I just don't think your argument is taking into account the implications of these warning changes on existing code. It's worth fighting the fight to change code when it has real value, but in my users get really testy about warnings that tells them something is wrong with their code when that isn't really the case. > Allowing them by default makes it a lot easier to slip them > unintentionally in for no real value in case of the first two > categories. The value is not pissing off users with useless warnings if they don't really apply to them. I'm not drawing a line in the sand here, but it's is important to keep in mind that there is a lot of code out there that has treated existing format string checking as "API" and will be dubious about us being more pedantic just for the sake of being pedantic. > The third category is even more painful since it can require > extensive code changes. Worse, even a single target playform is not > necessarily consistent. Yes, this is all a mess. > Consider 'a' handling for scanf. Many embeddeed > systems use Linux with uClibc -- which doesn't implement it. How do you > detect if the libc support it or not? I wish I had good answers to these questions. I don't, and that's my concern. What I do know is that I have reviewed bug reports from users who complained about Clang warning about format specifiers that were okay in their case (and their case wasn't that special), which is why some of these extensions got added to Clang in the first place. I'm all for catching bugs, but my concern is issuing too many warnings that people will get really pissed off, or worse, turn the warning off. If we are going to tighten the bolts on format string checking, I think we need a solution that either allows Clang to make accurate decisions, or provide a way for users to opt into stricter checking. Stricter checking that doesn't apply to most users that provides marginal value is not going to be popular. -------------- next part -------------- An HTML attachment was scrubbed... URL: From joerg at britannica.bec.de Mon Feb 20 11:51:03 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 20:51:03 +0100 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <20120220190432.GA18744@britannica.bec.de> Message-ID: <20120220195103.GA19546@britannica.bec.de> On Mon, Feb 20, 2012 at 11:22:18AM -0800, Ted Kremenek wrote: > On Feb 20, 2012, at 11:04 AM, Joerg Sonnenberger wrote: > > > On Mon, Feb 20, 2012 at 06:31:53PM +0000, Hans Wennborg wrote: > >> I'm a little bit confused about the status of some of these. For > >> example, should 'C' and 'S' be considered GNU extensions, and > >> therefore allowable when using -std=gnu99? > > > > In my opinion: no. -std=gnu99 specifies C99 with GNU compiler > > extensions. It doesn't mean anything about the run time implementation. > > As such, all the non-standard flags should go into a -Wformat-extensions > > category and it should be enabled by default with -Wformat. > > I would expect most users would be very unhappy to see these warnings > even when compiling with -std=gnu99. I think it is reasonable to > activate them (or a subset) for -std=c99, as that essentially ties in > with the portability argument I said in my other email. Language extensions and runtime extensions aren't strongly related, so I don't buy that. > We should aim to do the right thing for users. In my experience, most > users are not going to want to see these pedantic warnings unless they > add value. >From my experience, the same set of users doesn't understand how to use ctype(3) correctly and will complain about patches that makes the code standard compliant. As such, not warning in first place dramatically increases the maintainance code. > I agree that ultimately this comes down to what the runtime supports, > but not knowing those details doesn't give us liberty to emit a bunch > of new warnings just because we don't have enough information to make > a good decision about whether to emit a warning or not. The default behavior for -Wformat would be "check that the format string is standard compliant". I think that's a perfectively sane default and if someone wants to use non-standard format extensions, clang tells them how to get them. I don't think that the average piece of code written nowadays will only ever run on glibc-Linux / *BSD / Mac OSX or any other single platform. I do know that the GCC behavior of silently accepting them has created hidden bugs. There are some applications where more fine-grained controlled would be very helpful, e.g. "only allow C89 format modifiers", since there is still a certain demand for dealing with non-C99 environments (hello Microsoft?). Joerg From mcrosier at apple.com Mon Feb 20 11:51:44 2012 From: mcrosier at apple.com (Chad Rosier) Date: Mon, 20 Feb 2012 19:51:44 -0000 Subject: [cfe-commits] r150983 - /cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m Message-ID: <20120220195144.E56042A6C12F@llvm.org> Author: mcrosier Date: Mon Feb 20 13:51:44 2012 New Revision: 150983 URL: http://llvm.org/viewvc/llvm-project?rev=150983&view=rev Log: Make test case less sensitive to metadata numbering. Modified: cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m Modified: cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m?rev=150983&r1=150982&r2=150983&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m (original) +++ cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m Mon Feb 20 13:51:44 2012 @@ -2,4 +2,4 @@ @class ForwardObjcClass; ForwardObjcClass *ptr = 0; -// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !6, i32 2, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] +// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !{{.*}}, i32 2, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] From joerg at britannica.bec.de Mon Feb 20 11:56:52 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 20:56:52 +0100 Subject: [cfe-commits] [PATCH] [PR 12026] Restore target-prefix tool support In-Reply-To: <20120220192221.GA19139@britannica.bec.de> References: <20120220163950.GA13346@britannica.bec.de> <20120220192221.GA19139@britannica.bec.de> Message-ID: <20120220195652.GA19819@britannica.bec.de> On Mon, Feb 20, 2012 at 08:22:21PM +0100, Joerg Sonnenberger wrote: > The test cases can be revived from r149083. Attached is the last version of those. Joerg -------------- next part -------------- A non-text attachment was scrubbed... Name: prefixed-tools.tar.gz Type: application/octet-stream Size: 1095 bytes Desc: not available URL: From echristo at apple.com Mon Feb 20 12:04:20 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 12:04:20 -0800 Subject: [cfe-commits] r150983 - /cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m In-Reply-To: <20120220195144.E56042A6C12F@llvm.org> References: <20120220195144.E56042A6C12F@llvm.org> Message-ID: <56E32BCD-106D-43B5-A80E-272414F204A1@apple.com> Thanks! Sent from my iPhone On Feb 20, 2012, at 11:51 AM, Chad Rosier wrote: > Author: mcrosier > Date: Mon Feb 20 13:51:44 2012 > New Revision: 150983 > > URL: http://llvm.org/viewvc/llvm-project?rev=150983&view=rev > Log: > Make test case less sensitive to metadata numbering. > > Modified: > cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m > > Modified: cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m?rev=150983&r1=150982&r2=150983&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m (original) > +++ cfe/trunk/test/CodeGenObjC/debug-info-fwddecl.m Mon Feb 20 13:51:44 2012 > @@ -2,4 +2,4 @@ > @class ForwardObjcClass; > ForwardObjcClass *ptr = 0; > > -// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !6, i32 2, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] > +// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !{{.*}}, i32 2, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ] > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From kremenek at apple.com Mon Feb 20 12:05:41 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 12:05:41 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <20120220195103.GA19546@britannica.bec.de> References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> Message-ID: <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> On Feb 20, 2012, at 11:51 AM, Joerg Sonnenberger wrote: > The default behavior for -Wformat would be "check that the format string > is standard compliant". I think that's a perfectively sane default and > if someone wants to use non-standard format extensions, clang tells them > how to get them. There's "non-standard" and then there's completely unportable. Warnings like: + // Combining 'L' with an integer conversion specifier. + printf("%Li", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'i' is non-standard}} + printf("%Lo", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'o' is non-standard}} are likely going to just irritate people. What's the value in that? > I don't think that the average piece of code written > nowadays will only ever run on glibc-Linux / *BSD / Mac OSX or any other > single platform. I do know that the GCC behavior of silently accepting > them has created hidden bugs. I agree with you that permissive checking is allowing bugs to creep in. There's no disagreement here. I still think that (presently) having no good solution to handling non-portable format string specifiers doesn't mean we should just unconditionally warn about them. Consider '%S' and and '%C'. For OS X developers, it may be perfectly reasonable to use those, especially if they aren't using printf (there are other printf-like APIs on OS X). Should we just penalize those developers, who are intentionally writing non-portable code? I'll admit I'm a bit torn here, but I do know if we just started warning about these without any more intelligence on Clang's part to try and just warn when it makes sense the push back I'd receive from OS X developers would be significant. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dgregor at apple.com Mon Feb 20 12:05:29 2012 From: dgregor at apple.com (Douglas Gregor) Date: Mon, 20 Feb 2012 20:05:29 -0000 Subject: [cfe-commits] r150984 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/CodeGenCXX/lambda-expressions.cpp Message-ID: <20120220200529.6393D2A6C12F@llvm.org> Author: dgregor Date: Mon Feb 20 14:05:29 2012 New Revision: 150984 URL: http://llvm.org/viewvc/llvm-project?rev=150984&view=rev Log: When we resolve the type of an 'auto' variable, clear out the linkage of that variable; it will need to be recomputed with the resolved type. Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=150984&r1=150983&r2=150984&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Feb 20 14:05:29 2012 @@ -6101,7 +6101,8 @@ } VDecl->setTypeSourceInfo(DeducedType); VDecl->setType(DeducedType->getType()); - + VDecl->ClearLinkageCache(); + // In ARC, infer lifetime. if (getLangOptions().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) VDecl->setInvalidDecl(); Modified: cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp?rev=150984&r1=150983&r2=150984&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Mon Feb 20 14:05:29 2012 @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 | FileCheck %s +// CHECK: @var = internal global +auto var = [](int i) { return i+1; }; + int a() { return []{ return 1; }(); } // CHECK: define i32 @_Z1av // CHECK: call i32 @_ZZ1avENKUlvE_clEv From thakis at chromium.org Mon Feb 20 12:13:27 2012 From: thakis at chromium.org (Nico Weber) Date: Mon, 20 Feb 2012 12:13:27 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> Message-ID: On Mon, Feb 20, 2012 at 12:05 PM, Ted Kremenek wrote: > On Feb 20, 2012, at 11:51 AM, Joerg Sonnenberger > wrote: > > The default behavior for -Wformat would be "check that the format string > is standard compliant". I think that's a perfectively sane default and > if someone wants to use non-standard format extensions, clang tells them > how to get them. > > > There's "non-standard" and then there's completely unportable.  Warnings > like: > > +  // Combining 'L' with an integer conversion specifier. > +  printf("%Li", (long long)42); // expected-warning{{using the length > modifier 'L' with the conversion specifier 'i' is non-standard}} > +  printf("%Lo", (long long)42); // expected-warning{{using the length > modifier 'L' with the conversion specifier 'o' is non-standard}} > > are likely going to just irritate people.  What's the value in that? > > I don't think that the average piece of code written > nowadays will only ever run on glibc-Linux / *BSD / Mac OSX or any other > single platform. I do know that the GCC behavior of silently accepting > them has created hidden bugs. > > > I agree with you that permissive checking is allowing bugs to creep in. >  There's no disagreement here. > > I still think that (presently) having no good solution to handling > non-portable format string specifiers doesn't mean we should just > unconditionally warn about them.  Consider '%S' and and '%C'.  For OS X > developers, it may be perfectly reasonable to use those, especially if they > aren't using printf (there are other printf-like APIs on OS X).  Should we > just penalize those developers, who are intentionally writing non-portable > code?  I'll admit I'm a bit torn here, but I do know if we just started > warning about these without any more intelligence on Clang's part to try and > just warn when it makes sense the push back I'd receive from OS X developers > would be significant. The format checker knows if a string is an objc string literal – it already does something different for %S and %C in objc string literals (where these mean unichar) than in c string literals (where these mean wchar_t, which is usually utf32). So it's possible to have different defaults for C string literals and objc string literals. Nico From fjahanian at apple.com Mon Feb 20 12:09:20 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Mon, 20 Feb 2012 20:09:20 -0000 Subject: [cfe-commits] r150985 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/AST/ASTImporter.cpp lib/AST/DeclObjC.cpp lib/Rewrite/RewriteModernObjC.cpp lib/Sema/SemaDecl.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/Rewriter/rewrite-modern-class.mm test/Rewriter/rewrite-modern-ivars.mm test/Rewriter/rewrite-modern-protocol.mm Message-ID: <20120220200921.33F062A6C12F@llvm.org> Author: fjahanian Date: Mon Feb 20 14:09:20 2012 New Revision: 150985 URL: http://llvm.org/viewvc/llvm-project?rev=150985&view=rev Log: modern objc translator. Finish off first cut of the modern meta-data translation by commenting out private ivar declarations in user source. Also, added several tests. Added: cfe/trunk/test/Rewriter/rewrite-modern-class.mm cfe/trunk/test/Rewriter/rewrite-modern-ivars.mm cfe/trunk/test/Rewriter/rewrite-modern-protocol.mm Modified: cfe/trunk/include/clang/AST/DeclObjC.h cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/lib/AST/DeclObjC.cpp cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Modified: cfe/trunk/include/clang/AST/DeclObjC.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=150985&r1=150984&r2=150985&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclObjC.h (original) +++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Feb 20 14:09:20 2012 @@ -1283,12 +1283,19 @@ /// \brief The location of the category name in this declaration. SourceLocation CategoryNameLoc; + /// class extension may have private ivars. + SourceLocation IvarLBraceLoc; + SourceLocation IvarRBraceLoc; + ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, - IdentifierInfo *Id, ObjCInterfaceDecl *IDecl) + IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()) : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), ClassInterface(IDecl), NextClassCategory(0), HasSynthBitfield(false), - CategoryNameLoc(CategoryNameLoc) { + CategoryNameLoc(CategoryNameLoc), + IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { } public: @@ -1297,7 +1304,9 @@ SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id, - ObjCInterfaceDecl *IDecl); + ObjCInterfaceDecl *IDecl, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()); static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID); ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } @@ -1353,6 +1362,11 @@ SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; } void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; } + + void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; } + SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; } + void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; } + SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCCategoryDecl *D) { return true; } @@ -1521,6 +1535,10 @@ virtual void anchor(); /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; + /// @implementation may have private ivars. + SourceLocation IvarLBraceLoc; + SourceLocation IvarRBraceLoc; + /// Support for ivar initialization. /// IvarInitializers - The arguments used to initialize the ivars CXXCtorInitializer **IvarInitializers; @@ -1535,16 +1553,22 @@ ObjCImplementationDecl(DeclContext *DC, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl, - SourceLocation nameLoc, SourceLocation atStartLoc) + SourceLocation nameLoc, SourceLocation atStartLoc, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()) : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc), - SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0), - HasCXXStructors(false), HasSynthBitfield(false) {} + SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc), + IvarRBraceLoc(IvarRBraceLoc), + IvarInitializers(0), NumIvarInitializers(0), + HasCXXStructors(false), HasSynthBitfield(false){} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl, SourceLocation nameLoc, - SourceLocation atStartLoc); + SourceLocation atStartLoc, + SourceLocation IvarLBraceLoc=SourceLocation(), + SourceLocation IvarRBraceLoc=SourceLocation()); static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1623,6 +1647,11 @@ void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } + void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; } + SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; } + void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; } + SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } + typedef specific_decl_iterator ivar_iterator; ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=150985&r1=150984&r2=150985&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Feb 20 14:09:20 2012 @@ -3088,7 +3088,9 @@ Loc, Importer.Import(D->getCategoryNameLoc()), Name.getAsIdentifierInfo(), - ToInterface); + ToInterface, + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc())); ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToCategory); Importer.Imported(D, ToCategory); @@ -3434,7 +3436,9 @@ Importer.ImportContext(D->getDeclContext()), Iface, Super, Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc())); + Importer.Import(D->getAtStartLoc()), + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc())); if (D->getDeclContext() != D->getLexicalDeclContext()) { DeclContext *LexicalDC Modified: cfe/trunk/lib/AST/DeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=150985&r1=150984&r2=150985&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclObjC.cpp (original) +++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Feb 20 14:09:20 2012 @@ -1070,10 +1070,13 @@ SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id, - ObjCInterfaceDecl *IDecl) { + ObjCInterfaceDecl *IDecl, + SourceLocation IvarLBraceLoc, + SourceLocation IvarRBraceLoc) { ObjCCategoryDecl *CatDecl = new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id, - IDecl); + IDecl, + IvarLBraceLoc, IvarRBraceLoc); if (IDecl) { // Link this category into its class's category list. CatDecl->NextClassCategory = IDecl->getCategoryList(); @@ -1209,11 +1212,14 @@ ObjCInterfaceDecl *ClassInterface, ObjCInterfaceDecl *SuperDecl, SourceLocation nameLoc, - SourceLocation atStartLoc) { + SourceLocation atStartLoc, + SourceLocation IvarLBraceLoc, + SourceLocation IvarRBraceLoc) { if (ClassInterface && ClassInterface->hasDefinition()) ClassInterface = ClassInterface->getDefinition(); return new (C) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, - nameLoc, atStartLoc); + nameLoc, atStartLoc, + IvarLBraceLoc, IvarRBraceLoc); } ObjCImplementationDecl * Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp?rev=150985&r1=150984&r2=150985&view=diff ============================================================================== --- cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp (original) +++ cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Mon Feb 20 14:09:20 2012 @@ -934,14 +934,17 @@ // FIXME: handle category headers that are declared across multiple lines. ReplaceText(LocStart, 0, "// "); - + if (CatDecl->getIvarLBraceLoc().isValid()) + InsertText(CatDecl->getIvarLBraceLoc(), "// "); for (ObjCCategoryDecl::ivar_iterator I = CatDecl->ivar_begin(), E = CatDecl->ivar_end(); I != E; ++I) { ObjCIvarDecl *Ivar = (*I); SourceLocation LocStart = Ivar->getLocStart(); ReplaceText(LocStart, 0, "// "); } - + if (CatDecl->getIvarRBraceLoc().isValid()) + InsertText(CatDecl->getIvarRBraceLoc(), "// "); + for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), E = CatDecl->prop_end(); I != E; ++I) RewriteProperty(*I); @@ -1153,12 +1156,16 @@ if (IMD) { InsertText(IMD->getLocStart(), "// "); - for (ObjCImplementationDecl::ivar_iterator - I = IMD->ivar_begin(), E = IMD->ivar_end(); I != E; ++I) { - ObjCIvarDecl *Ivar = (*I); - SourceLocation LocStart = Ivar->getLocStart(); - ReplaceText(LocStart, 0, "// "); + if (IMD->getIvarLBraceLoc().isValid()) + InsertText(IMD->getIvarLBraceLoc(), "// "); + for (ObjCImplementationDecl::ivar_iterator + I = IMD->ivar_begin(), E = IMD->ivar_end(); I != E; ++I) { + ObjCIvarDecl *Ivar = (*I); + SourceLocation LocStart = Ivar->getLocStart(); + ReplaceText(LocStart, 0, "// "); } + if (IMD->getIvarRBraceLoc().isValid()) + InsertText(IMD->getIvarRBraceLoc(), "// "); } else InsertText(CID->getLocStart(), "// "); Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=150985&r1=150984&r2=150985&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Feb 20 14:09:20 2012 @@ -9585,6 +9585,8 @@ // Only it is in implementation's lexical context. ClsFields[I]->setLexicalDeclContext(IMPDecl); CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); + IMPDecl->setIvarLBraceLoc(LBrac); + IMPDecl->setIvarRBraceLoc(RBrac); } else if (ObjCCategoryDecl *CDecl = dyn_cast(EnclosingDecl)) { // case of ivars in class extension; all other cases have been @@ -9618,6 +9620,8 @@ ClsFields[i]->setLexicalDeclContext(CDecl); CDecl->addDecl(ClsFields[i]); } + CDecl->setIvarLBraceLoc(LBrac); + CDecl->setIvarRBraceLoc(RBrac); } } Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=150985&r1=150984&r2=150985&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Feb 20 14:09:20 2012 @@ -770,6 +770,8 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { VisitObjCContainerDecl(CD); CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx)); + CD->setIvarLBraceLoc(ReadSourceLocation(Record, Idx)); + CD->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); // Note that this category has been deserialized. We do this before // deserializing the interface declaration, so that it will consider this @@ -829,6 +831,8 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); D->setSuperClass(ReadDeclAs(Record, Idx)); + D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx)); + D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); llvm::tie(D->IvarInitializers, D->NumIvarInitializers) = Reader.ReadCXXCtorInitializers(F, Record, Idx); D->setHasSynthBitfield(Record[Idx++]); Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=150985&r1=150984&r2=150985&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Mon Feb 20 14:09:20 2012 @@ -541,6 +541,8 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { VisitObjCContainerDecl(D); Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); + Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record); + Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); Writer.AddDeclRef(D->getClassInterface(), Record); Record.push_back(D->protocol_size()); for (ObjCCategoryDecl::protocol_iterator @@ -593,6 +595,8 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); Writer.AddDeclRef(D->getSuperClass(), Record); + Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record); + Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers, Record); Record.push_back(D->hasSynthBitfield()); Added: cfe/trunk/test/Rewriter/rewrite-modern-class.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-class.mm?rev=150985&view=auto ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-class.mm (added) +++ cfe/trunk/test/Rewriter/rewrite-modern-class.mm Mon Feb 20 14:09:20 2012 @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + + at protocol PROTO @end + + at interface empty_root @end + + at interface root_with_ivars +{ + id ROOT_IVAR; + id ROOT1_IVAR; +} + at end + + at interface MAXIMAL : root_with_ivars +{ + double D_IVAR; + double D_PROPERTY; +} +- (void) V_METH; + at end + + at implementation MAXIMAL +- (void) V_METH {} + at end +//========================================= + at interface empty_class @end + + at implementation empty_class @end +//========================================= + at interface class_empty_root : empty_root @end + + at implementation class_empty_root @end +//========================================= + at interface class_with_ivars : empty_root +{ + int class_with_ivars_IVAR; +} + at end + + at implementation class_with_ivars @end +//========================================= + at interface class_has_no_ivar : root_with_ivars @end + + at implementation class_has_no_ivar @end + +//============================class needs to be synthesized here===================== + at interface SUPER { + at public + double divar; + SUPER *p_super; +} + at end + + at interface INTF @end + + at implementation INTF +- (SUPER *) Meth : (SUPER *)arg { + return arg->p_super; +} + at end Added: cfe/trunk/test/Rewriter/rewrite-modern-ivars.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-ivars.mm?rev=150985&view=auto ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-ivars.mm (added) +++ cfe/trunk/test/Rewriter/rewrite-modern-ivars.mm Mon Feb 20 14:09:20 2012 @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + + at protocol P @end + at protocol P1 @end + at interface INTF +{ + id CLASS_IVAR; + id Q_IVAR; + + void (^_block)(id

); + void (*_fptr)(void (^_block)(id

)); + char CLASS_EXT_IVAR; + id (^ext_block)(id

, INTF*, INTF*); + id IMPL_IVAR; + double D_IMPL_IVAR; + INTF

*(*imp_fptr)(void (^_block)(id

, INTF*)); + id arr[100]; +} + at end + + at implementation INTF @end + + at interface MISC_INTF +{ + id CLASS_IVAR; + id Q_IVAR; + + void (^_block)(id

); + void (*_fptr)(void (^_block)(id

)); + unsigned int BF : 8; +} + at end + + at interface MISC_INTF() +{ + char CLASS_EXT_IVAR; + id (^ext_block)(id

, MISC_INTF*, MISC_INTF*); +} + at end + + at interface MISC_INTF() { + int II1; + double DD1; } + at end + + at interface MISC_INTF() { int II2; double DD2; } + at end + + at interface MISC_INTF() { int II3; + double DD3; } + at end + + at interface MISC_INTF() { int II4; double DD4; +} + at end + + at implementation MISC_INTF +{ + id IMPL_IVAR; + double D_IMPL_IVAR; + MISC_INTF

*(*imp_fptr)(void (^_block)(id

, MISC_INTF*)); +} + at end Added: cfe/trunk/test/Rewriter/rewrite-modern-protocol.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-protocol.mm?rev=150985&view=auto ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-protocol.mm (added) +++ cfe/trunk/test/Rewriter/rewrite-modern-protocol.mm Mon Feb 20 14:09:20 2012 @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + + at protocol ROOT @end + + at protocol P1 @end + + at protocol P2 @end + + at class NSObject; + + at protocol PROTO +- (id) INST_METHOD; ++ (id) CLASS_METHOD : (id)ARG; + at property id Prop_in_PROTO; + at optional +- (id) opt_instance_method; ++ (id) opt_class_method; + at property (readonly, retain) NSObject *AnotherProperty; + at required +- (id) req; + at optional +- (id) X_opt_instance_method; ++ (id) X_opt_class_method; + at end + + at interface INTF + at end + + at implementation INTF + at end From joerg at britannica.bec.de Mon Feb 20 12:21:53 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 21:21:53 +0100 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> Message-ID: <20120220202153.GA20840@britannica.bec.de> On Mon, Feb 20, 2012 at 12:05:41PM -0800, Ted Kremenek wrote: > On Feb 20, 2012, at 11:51 AM, Joerg Sonnenberger wrote: > > > The default behavior for -Wformat would be "check that the format string > > is standard compliant". I think that's a perfectively sane default and > > if someone wants to use non-standard format extensions, clang tells them > > how to get them. > > There's "non-standard" and then there's completely unportable. Warnings like: > > + // Combining 'L' with an integer conversion specifier. > + printf("%Li", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'i' is non-standard}} > + printf("%Lo", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'o' is non-standard}} > > are likely going to just irritate people. What's the value in that? What is that supposed to mean? From looking at analyze_format_string, that should give a warning because (a) L doesn't make sense for integers and (b) because the argument isn't int. Or do you mean the Microsoft extension for dealing with 64bit integers? Note that this is part of the reason why silently accepting them is bad -- I need to have a printf(3) man page for the platform you had in mind when writing this code to even understand what it is really supposed to do. > Consider '%S' and and '%C'. For OS X developers, it may be perfectly > reasonable to use those, especially if they aren't using printf (there > are other printf-like APIs on OS X). Actually, you are pointing to a bigger bug here. I mentioned it in an earlier discussion on the list. At the moment, the GCC attributes for format string checking are very course. It is impossible to distinguish between syslog(3) format strings and printf(3) format strings for example. The former allows '%m', for the latter it is a glibc extension. Other APIs like sqlite_mprint are similar -- they allow an extended subset of the printf(3) formatting, but they don't provide the same set. I am perfectly fine with allowing all kinds of extensions if the function is tagged as having those. That would of course still require glibc to accept patches to tag printf(3) as __attribute__((__format__(__printf__ | __gnuprintf__, 1, 2))) or whatever the syntax should look like, but it would work for the other users of format strings. Joerg From joerg at britannica.bec.de Mon Feb 20 12:40:49 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Mon, 20 Feb 2012 21:40:49 +0100 Subject: [cfe-commits] [llvm-commits] PATCH: Remove lazy-parse support from llvm::Triple In-Reply-To: References: Message-ID: <20120220204049.GB21848@britannica.bec.de> On Mon, Feb 20, 2012 at 11:49:07AM -0800, Chandler Carruth wrote: > This patch removes the lazy-parsing from the Triple class. From what I > could tell, no one deeply relied on this, and it seems unlikely that we > want people to be creating enough triples to need them to parse lazily... Yes, please. Joerg From dgregor at apple.com Mon Feb 20 12:47:06 2012 From: dgregor at apple.com (Douglas Gregor) Date: Mon, 20 Feb 2012 20:47:06 -0000 Subject: [cfe-commits] r150987 - in /cfe/trunk: lib/Sema/SemaLambda.cpp test/CodeGenCXX/lambda-expressions.cpp Message-ID: <20120220204706.A5EDF2A6C12F@llvm.org> Author: dgregor Date: Mon Feb 20 14:47:06 2012 New Revision: 150987 URL: http://llvm.org/viewvc/llvm-project?rev=150987&view=rev Log: Make sure that we set up the right declaration contexts when creating and introducing the lambda closure type and its function call operator. Previously, we assumed that the lambda closure type would land directly in the current context, and not some parent context (as occurs with linkage specifications). Thanks to Richard for the test case. Modified: cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150987&r1=150986&r2=150987&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 20 14:47:06 2012 @@ -28,7 +28,7 @@ // Start constructing the lambda class. CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, IntroducerRange.getBegin()); - CurContext->addDecl(Class); + DC->addDecl(Class); return Class; } @@ -65,7 +65,7 @@ // Temporarily set the lexical declaration context to the current // context, so that the Scope stack matches the lexical nesting. - Method->setLexicalDeclContext(Class->getDeclContext()); + Method->setLexicalDeclContext(CurContext); // Add parameters. if (!Params.empty()) { Modified: cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp?rev=150987&r1=150986&r2=150987&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Mon Feb 20 14:47:06 2012 @@ -3,6 +3,9 @@ // CHECK: @var = internal global auto var = [](int i) { return i+1; }; +// CHECK: @cvar = global +extern "C" auto cvar = []{}; + int a() { return []{ return 1; }(); } // CHECK: define i32 @_Z1av // CHECK: call i32 @_ZZ1avENKUlvE_clEv From kremenek at apple.com Mon Feb 20 13:00:57 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 13:00:57 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <20120220202153.GA20840@britannica.bec.de> References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> <20120220202153.GA20840@britannica.bec.de> Message-ID: On Feb 20, 2012, at 12:21 PM, Joerg Sonnenberger wrote: >> There's "non-standard" and then there's completely unportable. Warnings like: >> >> + // Combining 'L' with an integer conversion specifier. >> + printf("%Li", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'i' is non-standard}} >> + printf("%Lo", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'o' is non-standard}} >> >> are likely going to just irritate people. What's the value in that? > > What is that supposed to mean? AFAIK, it means nothing. My brain segfaulted. I was thinking of something else. > From looking at analyze_format_string, > that should give a warning because (a) L doesn't make sense for integers > and (b) because the argument isn't int. Or do you mean the Microsoft > extension for dealing with 64bit integers? Note that this is part of the > reason why silently accepting them is bad -- I need to have a printf(3) > man page for the platform you had in mind when writing this code to even > understand what it is really supposed to do. Do we really silently accept them? Until very recently (a month ago?), we emitted: t.c:4:12: warning: length modifier 'L' results in undefined behavior or no effect with 'i' conversion specifier [-Wformat] printf("%Li", (long long) 2); ~^~ 1 warning generated. Now I see that TOT doesn't warn here. Is this accepted somewhere? I see no test cases in clang/test that shows we should accept this. Was this an intentional change, or a regression? -------------- next part -------------- An HTML attachment was scrubbed... URL: From kremenek at apple.com Mon Feb 20 13:05:11 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 13:05:11 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <20120220202153.GA20840@britannica.bec.de> References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> <20120220202153.GA20840@britannica.bec.de> Message-ID: <80707074-E43F-40C6-902E-5530E8F039B6@apple.com> On Feb 20, 2012, at 12:21 PM, Joerg Sonnenberger wrote: >> Consider '%S' and and '%C'. For OS X developers, it may be perfectly >> reasonable to use those, especially if they aren't using printf (there >> are other printf-like APIs on OS X). > > Actually, you are pointing to a bigger bug here. I mentioned it in an > earlier discussion on the list. At the moment, the GCC attributes for > format string checking are very course. It is impossible to distinguish > between syslog(3) format strings and printf(3) format strings for > example. The former allows '%m', for the latter it is a glibc extension. > Other APIs like sqlite_mprint are similar -- they allow an extended > subset of the printf(3) formatting, but they don't provide the same set. > I am perfectly fine with allowing all kinds of extensions if the > function is tagged as having those. That would of course still require > glibc to accept patches to tag printf(3) as > __attribute__((__format__(__printf__ | __gnuprintf__, 1, 2))) or > whatever the syntax should look like, but it would work for the other > users of format strings. Exactly. To follow on that thought, it may also be possible to document what extensions a given version of printf supports using similar annotations. Similarly, for specific targets would consider dropping in such annotations onto printf automatically, while still allowing users to tailor their warnings to warn about using non-portable format string specifiers. Without these annotations, however, we cannot distinguish between extensions that are definitely not supported and those that may be unsupported but are non-portable. -------------- next part -------------- An HTML attachment was scrubbed... URL: From kremenek at apple.com Mon Feb 20 13:14:41 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 13:14:41 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> Message-ID: On Feb 20, 2012, at 12:13 PM, Nico Weber wrote: >> I still think that (presently) having no good solution to handling >> non-portable format string specifiers doesn't mean we should just >> unconditionally warn about them. Consider '%S' and and '%C'. For OS X >> developers, it may be perfectly reasonable to use those, especially if they >> aren't using printf (there are other printf-like APIs on OS X). Should we >> just penalize those developers, who are intentionally writing non-portable >> code? I'll admit I'm a bit torn here, but I do know if we just started >> warning about these without any more intelligence on Clang's part to try and >> just warn when it makes sense the push back I'd receive from OS X developers >> would be significant. > > The format checker knows if a string is an objc string literal – it > already does something different for %S and %C in objc string literals > (where these mean unichar) than in c string literals (where these mean > wchar_t, which is usually utf32). So it's possible to have different > defaults for C string literals and objc string literals. Ah true. Point well taken. The inaccuracies of my example aside, one should not consider this hack as a solution to the more general problem that Joerg pointed out. There's essentially a family of format specifiers that a function/method may support. It just so happens we can infer the extended family here by implication of the format string being an Objective-C type, but that's not a hard and fast restriction. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ganna at apple.com Mon Feb 20 13:10:37 2012 From: ganna at apple.com (Anna Zaks) Date: Mon, 20 Feb 2012 21:10:37 -0000 Subject: [cfe-commits] r150988 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/Checkers.td test/Analysis/additive-folding.c test/Analysis/bstring.c test/Analysis/cstring-syntax-cxx.cpp test/Analysis/cstring-syntax.c test/Analysis/free.c test/Analysis/malloc-plist.c test/Analysis/malloc.c test/Analysis/malloc.mm test/Analysis/string.c Message-ID: <20120220211037.C20D72A6C12F@llvm.org> Author: zaks Date: Mon Feb 20 15:10:37 2012 New Revision: 150988 URL: http://llvm.org/viewvc/llvm-project?rev=150988&view=rev Log: [analyzer] Turn on by default the Malloc Checker and a couple of CString checks: - unix.Malloc - Checks for memory leaks, double free, use-after-free. - unix.cstring.NullArg - Checks for null pointers passed as arguments to CString functions + evaluates CString functions. - unix.cstring.BadSizeArg - Checks for common anti-patterns in strncat size argument. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/test/Analysis/additive-folding.c cfe/trunk/test/Analysis/bstring.c cfe/trunk/test/Analysis/cstring-syntax-cxx.cpp cfe/trunk/test/Analysis/cstring-syntax.c cfe/trunk/test/Analysis/free.c cfe/trunk/test/Analysis/malloc-plist.c cfe/trunk/test/Analysis/malloc.c cfe/trunk/test/Analysis/malloc.mm cfe/trunk/test/Analysis/string.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Mon Feb 20 15:10:37 2012 @@ -33,7 +33,8 @@ def Unix : Package<"unix">; def UnixExperimental : Package<"unix">, InPackage, Hidden; -def CString : Package<"cstring">, InPackage, Hidden; +def CString : Package<"cstring">, InPackage, Hidden; +def CStringExperimental : Package<"cstring">, InPackage, Hidden; def OSX : Package<"osx">; def OSXExperimental : Package<"osx">, InPackage, Hidden; @@ -277,6 +278,10 @@ def UnixAPIChecker : Checker<"API">, HelpText<"Check calls to various UNIX/Posix functions">, DescFile<"UnixAPIChecker.cpp">; + +def MallocPessimistic : Checker<"Malloc">, + HelpText<"Check for memory leaks, double free, and use-after-free problems.">, + DescFile<"MallocChecker.cpp">; } // end "unix" @@ -290,10 +295,6 @@ HelpText<"Check for memory leaks, double free, and use-after-free problems. Assumes that all user-defined functions which might free a pointer are annotated.">, DescFile<"MallocChecker.cpp">; -def MallocPessimistic : Checker<"Malloc">, - HelpText<"Check for memory leaks, double free, and use-after-free problems.">, - DescFile<"MallocChecker.cpp">; - def MallocSizeofChecker : Checker<"MallocSizeof">, HelpText<"Check for dubious malloc arguments involving sizeof">, DescFile<"MallocSizeofChecker.cpp">; @@ -314,6 +315,13 @@ HelpText<"Check for null pointers being passed as arguments to C string functions">, DescFile<"CStringChecker.cpp">; +def CStringSyntaxChecker : Checker<"BadSizeArg">, + HelpText<"Check the size argument passed into C string functions for common erroneous patterns">, + DescFile<"CStringSyntaxChecker.cpp">; +} + +let ParentPackage = CStringExperimental in { + def CStringOutOfBounds : Checker<"OutOfBounds">, HelpText<"Check for out-of-bounds access in string functions">, DescFile<"CStringChecker.cpp">; @@ -325,10 +333,6 @@ def CStringNotNullTerm : Checker<"NotNullTerminated">, HelpText<"Check for arguments which are not null-terminating strings">, DescFile<"CStringChecker.cpp">; - -def CStringSyntaxChecker : Checker<"BadSizeArg">, - HelpText<"Check the size argument passed into C string functions for common erroneous patterns">, - DescFile<"CStringSyntaxChecker.cpp">; } //===----------------------------------------------------------------------===// Modified: cfe/trunk/test/Analysis/additive-folding.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/additive-folding.c?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/additive-folding.c (original) +++ cfe/trunk/test/Analysis/additive-folding.c Mon Feb 20 15:10:37 2012 @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,experimental.unix.Malloc -verify -analyzer-constraints=basic %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,experimental.unix.Malloc -verify -analyzer-constraints=range %s +// 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 // These are used to trigger warnings. typedef typeof(sizeof(int)) size_t; Modified: cfe/trunk/test/Analysis/bstring.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/bstring.c?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/bstring.c (original) +++ cfe/trunk/test/Analysis/bstring.c Mon Feb 20 15:10:37 2012 @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s -// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,experimental.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 -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 //===----------------------------------------------------------------------=== // Declarations Modified: cfe/trunk/test/Analysis/cstring-syntax-cxx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cstring-syntax-cxx.cpp?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cstring-syntax-cxx.cpp (original) +++ cfe/trunk/test/Analysis/cstring-syntax-cxx.cpp Mon Feb 20 15:10:37 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.unix.cstring.BadSizeArg -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -verify %s // Ensure we don't crash on C++ declarations with special names. struct X { Modified: cfe/trunk/test/Analysis/cstring-syntax.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cstring-syntax.c?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cstring-syntax.c (original) +++ cfe/trunk/test/Analysis/cstring-syntax.c Mon Feb 20 15:10:37 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.unix.cstring.BadSizeArg -analyzer-store=region -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s typedef __SIZE_TYPE__ size_t; char *strncat(char *, const char *, size_t); Modified: cfe/trunk/test/Analysis/free.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/free.c?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/free.c (original) +++ cfe/trunk/test/Analysis/free.c Mon Feb 20 15:10:37 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-checker=core,experimental.unix.Malloc -fblocks -verify %s +// RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-checker=core,unix.Malloc -fblocks -verify %s // RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-checker=core,experimental.unix.MallocWithAnnotations -fblocks -verify %s void free(void *); Modified: cfe/trunk/test/Analysis/malloc-plist.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-plist.c?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc-plist.c (original) +++ cfe/trunk/test/Analysis/malloc-plist.c Mon Feb 20 15:10:37 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.unix.Malloc -analyzer-output=plist -o - %s | FileCheck %s +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-output=plist -o - %s | FileCheck %s typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Mon Feb 20 15:10:37 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,experimental.core.CastSize,experimental.unix.Malloc -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,experimental.core.CastSize,unix.Malloc -analyzer-store=region -verify %s #include "system-header-simulator.h" typedef __typeof(sizeof(int)) size_t; Modified: cfe/trunk/test/Analysis/malloc.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.mm?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.mm (original) +++ cfe/trunk/test/Analysis/malloc.mm Mon Feb 20 15:10:37 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.unix.Malloc -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify %s typedef unsigned int UInt32; typedef signed long CFIndex; Modified: cfe/trunk/test/Analysis/string.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=150988&r1=150987&r2=150988&view=diff ============================================================================== --- cfe/trunk/test/Analysis/string.c (original) +++ cfe/trunk/test/Analysis/string.c Mon Feb 20 15:10:37 2012 @@ -1,7 +1,7 @@ -// 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 -DVARIANT -analyzer-checker=core,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,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,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 //===----------------------------------------------------------------------=== // Declarations From ganna at apple.com Mon Feb 20 13:10:40 2012 From: ganna at apple.com (Anna Zaks) Date: Mon, 20 Feb 2012 21:10:40 -0000 Subject: [cfe-commits] r150989 - /cfe/trunk/utils/analyzer/SATestBuild.py Message-ID: <20120220211041.037F82A6C12F@llvm.org> Author: zaks Date: Mon Feb 20 15:10:40 2012 New Revision: 150989 URL: http://llvm.org/viewvc/llvm-project?rev=150989&view=rev Log: [analyzer] Testing: These checkers are not experimental anymore. Modified: cfe/trunk/utils/analyzer/SATestBuild.py Modified: cfe/trunk/utils/analyzer/SATestBuild.py URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/analyzer/SATestBuild.py?rev=150989&r1=150988&r2=150989&view=diff ============================================================================== --- cfe/trunk/utils/analyzer/SATestBuild.py (original) +++ cfe/trunk/utils/analyzer/SATestBuild.py Mon Feb 20 15:10:40 2012 @@ -72,7 +72,7 @@ # The list of checkers used during analyzes. # Currently, consists of all the non experimental checkers. -Checkers="experimental.security.taint,core,deadcode,cplusplus,security,unix,osx,cocoa,experimental.osx.cocoa.Containers,experimental.unix.cstring.BadSizeArg,experimental.unix.Malloc" +Checkers="experimental.security.taint,core,deadcode,cplusplus,security,unix,osx,cocoa" Verbose = 1 From kremenek at apple.com Mon Feb 20 13:27:47 2012 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 20 Feb 2012 13:27:47 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <20120220193514.GB19139@britannica.bec.de> References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> <20120220193514.GB19139@britannica.bec.de> Message-ID: On Feb 20, 2012, at 11:35 AM, Joerg Sonnenberger wrote: > On Mon, Feb 20, 2012 at 11:02:25AM -0800, Ted Kremenek wrote: >> (1) Warn about non-standard format strings only when it is an issue >> for the target platform. This is hard to do, but this is basically >> what users will expect. > > IMO most of the format extensions are of questionable value (%m), > outdated historic extensions (q modifier) or just plainly unportable (S > modifier). I hear you, but some extensions continue to be advocated and used. For example, consider this document: https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFStrings/formatSpecifiers.html Here 'q' is plainly advocated as a method for printing out 64-bit integers. This contrasts with Mac OS X's man page for printf, which clearly points to the length modifier 'q' as being deprecated. Maybe the documentation just needs to be updated, or maybe 'q' should just continue to make sense for Objective-C strings, but there's a fair amount of subjectiveness here and it is confusing for developers. I'd be a lot more happy with this discussion if we took the patch with the proposed change, ran it over a ton of code, and observed the warning fallout. If it's insignificant or reasonable, I think that's a reasonable place to start a conversation about having such warnings on by default. -------------- next part -------------- An HTML attachment was scrubbed... URL: From richard at metafoo.co.uk Mon Feb 20 13:57:03 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Mon, 20 Feb 2012 13:57:03 -0800 Subject: [cfe-commits] [PATCH] PR12008: out-of-line definitions of static constexpr member functions Message-ID: Hi, The constexpr specifier implicitly marks non-static member function declarations as const. We currently look at the storage class of the function to determine whether this marking applies, but as PR12008 points out, this is inadequate: for out-of-line definitions of constexpr member functions, we don't know whether the function is static until we have looked up the previous declaration (and performed some other semantic checks). The attached patch fixes this by delaying the addition of the const qualifier to a constexpr non-static member function until the point where we know it's not static. For efficiency, the patch modifies the type of the TypeSourceInfo object in-place; this is safe because the reference to the TypeSourceInfo object is unique, and the addition of a 'const' qualifier does not change the TypeLoc representation. Thanks! Richard -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 12008.diff Type: text/x-patch Size: 6861 bytes Desc: not available URL: From aaron at aaronballman.com Mon Feb 20 14:21:46 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 20 Feb 2012 16:21:46 -0600 Subject: [cfe-commits] [PATCH] Fixing include order for Windows In-Reply-To: References: Message-ID: On Mon, Feb 20, 2012 at 2:06 AM, Chandler Carruth wrote: > On Sun, Feb 19, 2012 at 8:04 PM, Aaron Ballman > wrote: >> >> Here's what we've figured out so far. >> >> Several platform SDK header files include intrin.h from Visual Studio. >>  This file declares all of the intrinsics used by MSVC, including >> chip-specific intrinsics (MMX, SSE, etc) as well as >> platform-independent intrinsics (Interlocked***, etc). >> >> A full list of intrinsics is documented on MSDN at >> and >> >> >> We need to come up with our own intrin.h that supports Microsoft's so >> that we can compile Win32 applications (and Microsoft's STL >> implementation). > > > Here is an initial cut at adding an MSVC compatible 'intrin.h' builtin > header. I've left a FIXME to fill in the MS-specific intrinsics. This should > at least provide a place to begin fleshing out the intrinsics. I think the patch is a good start (with the exception of __has_inclued_next being misspelled). However, it's missing declarations for other intrinsics which may be used by Win32 apps, which are described on MSDN: http://msdn.microsoft.com/en-us/library/26td21ds.aspx However, I think we only need to care about the platform-independent, x86 and x64 intrinsics. We've already got the MMX, SSE, etc intrinsics covered. Some of these are likely covered by other includes (though I do wonder if using the includes will have adverse effects?), so I've broken the intrinsics out based on where MSDN claims they live. It boils down to about 250 or so intrinsics... Since I've been all over the MS headers, I can't cleanly extend Chandler's patch. So hopefully Chandler, or someone else, will be able to pick up the ball and run with it. Of course, I'm happy to answer any questions I can. ------------------------- malloc.h void * __cdecl _alloca(size_t); math.h int __cdecl abs(int); double ceil(double); long __cdecl labs(long); conio.h int __cdecl _inp(unsigned short); int __cdecl inp(unsigned short); unsigned long __cdecl _inpd(unsigned short); unsigned long __cdecl inpd(unsigned short); unsigned short __cdecl _inpw(unsigned short); unsigned short __cdecl inpw(unsigned short); int __cdecl _outp(unsigned short,int); int __cdecl outp(unsigned short,int); unsigned long __cdecl _outpd(unsigned short,unsigned long); unsigned long __cdecl outpd(unsigned short,unsigned long); unsigned short __cdecl _outpw(unsigned short,unsigned short); unsigned short __cdecl outpw(unsigned short,unsigned short); setjmp.h void __cdecl longjmp(jmp_buf, int); int __cdecl _setjmp(jmp_buf); int __cdecl _setjmpex(jmp_buf); stdlib.h unsigned long __cdecl _lrotl( unsigned long, int); unsigned long __cdecl _lrotr( unsigned long, int); unsigned int __cdecl _rotl( unsigned int, int); unsigned int __cdecl _rotr( unsigned int, int); unsigned __int64 __cdecl _rotl64( unsigned __int64, int); unsigned __int64 __cdecl _rotr64( unsigned __int64, int); __int64 __cdecl _abs64(__int64); memory.h int __cdecl memcmp(const void *,const void *, size_t); void * __cdecl memcpy(void *,const void *, size_t); void * __cdecl memset(void *, int, size_t); string.h int __cdecl strcmp(const char *, const char *); size_t __cdecl strlen(const char *); char * __cdecl strset(char *, int); wchar_t * __cdecl wcscat(wchar_t *, const wchar_t *); int __cdecl wcscmp(const wchar_t *, const wchar_t *); wchar_t * __cdecl wcscpy(wchar_t *, const wchar_t *); size_t __cdecl wcslen(const wchar_t *); wchar_t * __cdecl _wcsset(wchar_t *, wchar_t); intrin.h All Architectures: unsigned short __cdecl _byteswap_ushort(unsigned short); unsigned long __cdecl _byteswap_ulong(unsigned long); unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64); void __cdecl __debugbreak(void); All Intel (x86, x64): void __cdecl _disable(void); __int64 __emul(int,int); unsigned __int64 __emulu(unsigned int,unsigned int); void __cdecl _enable(void); long __cdecl _InterlockedDecrement(long volatile *); long _InterlockedExchange(long volatile *, long); short _InterlockedExchange16(short volatile *, short); char _InterlockedExchange8(char volatile *, char); long _InterlockedExchangeAdd(long volatile *, long); short _InterlockedExchangeAdd16(short volatile *, short); char _InterlockedExchangeAdd8(char volatile *, char); long _InterlockedCompareExchange (long volatile *, long, long); long __cdecl _InterlockedIncrement(long volatile *); long _InterlockedOr(long volatile *, long); char _InterlockedOr8(char volatile *, char); short _InterlockedOr16(short volatile *, short); long _InterlockedXor(long volatile *, long); char _InterlockedXor8(char volatile *, char); short _InterlockedXor16(short volatile *, short); long _InterlockedAnd(long volatile *, long); char _InterlockedAnd8(char volatile *, char); short _InterlockedAnd16(short volatile *, short); unsigned __int64 __ll_lshift(unsigned __int64,int); __int64 __ll_rshift(__int64,int); void * _ReturnAddress(void); unsigned __int64 __ull_rshift(unsigned __int64,int); void * _AddressOfReturnAddress(void); void _WriteBarrier(void); void _ReadWriteBarrier(void); unsigned __int64 __rdtsc(void); void __movsb(unsigned char *, unsigned char const *, size_t); void __movsw(unsigned short *, unsigned short const *, size_t); void __movsd(unsigned long *, unsigned long const *, size_t); unsigned char __inbyte(unsigned short); unsigned short __inword(unsigned short); unsigned long __indword(unsigned short); void __outbyte(unsigned short, unsigned char); void __outword(unsigned short, unsigned short); void __outdword(unsigned short, unsigned long); void __inbytestring(unsigned short, unsigned char *, unsigned long); void __inwordstring(unsigned short, unsigned short *, unsigned long); void __indwordstring(unsigned short, unsigned long *, unsigned long); void __outbytestring(unsigned short, unsigned char *, unsigned long); void __outwordstring(unsigned short, unsigned short *, unsigned long); void __outdwordstring(unsigned short, unsigned long *, unsigned long); unsigned int __getcallerseflags(); void __vmx_vmptrst(unsigned __int64 *); void __vmx_off(void); void __svm_clgi(void); void __svm_invlpga(void*, int); void __svm_skinit(int); void __svm_stgi(void); void __svm_vmload(size_t); void __svm_vmrun(size_t); void __svm_vmsave(size_t); void __halt(void); void __sidt(void*); void __lidt(void*); void __ud2(void); void __nop(void); void __stosb(unsigned char *, unsigned char, size_t); void __stosw(unsigned short *, unsigned short, size_t); void __stosd(unsigned long *, unsigned long, size_t); unsigned char _interlockedbittestandset(long volatile *, long); unsigned char _interlockedbittestandreset(long volatile *, long); void __cpuid(int[4], int); void __cpuidex(int[4], int, int); unsigned long __segmentlimit(unsigned long); void __int2c(void); char _InterlockedCompareExchange8(char volatile *, char, char); unsigned short __lzcnt16(unsigned short); unsigned int __lzcnt(unsigned int); unsigned short __popcnt16(unsigned short); unsigned int __popcnt(unsigned int); __m128i _mm_extract_si64(__m128i,__m128i); __m128i _mm_extracti_si64(__m128i, int, int); __m128i _mm_insert_si64(__m128i,__m128i); __m128i _mm_inserti_si64(__m128i, __m128i, int, int); void _mm_stream_sd(double*,__m128d); void _mm_stream_ss(float*,__m128); unsigned __int64 __rdtscp(unsigned int*); Intel x64 Only: __int64 _InterlockedDecrement64(__int64 volatile *); __int64 _InterlockedExchange64(__int64 volatile *, __int64); void * _InterlockedExchangePointer(void * volatile *, void *); __int64 _InterlockedExchangeAdd64(__int64 volatile *, __int64); __int64 _InterlockedCompareExchange64(__int64 volatile *, __int64, __int64); void *_InterlockedCompareExchangePointer (void * volatile *, void *, void *); __int64 _InterlockedIncrement64(__int64 volatile *); __int64 _InterlockedOr64(__int64 volatile *, __int64); __int64 _InterlockedXor64(__int64 volatile *, __int64); __int64 _InterlockedAnd64(__int64 volatile *, __int64); void __faststorefence(void); __int64 __mulh(__int64,__int64); unsigned __int64 __umulh(unsigned __int64,unsigned __int64); unsigned __int64 __readeflags(void); void __writeeflags(unsigned __int64); void __movsq(unsigned long long *, unsigned long long const *, size_t); unsigned char __vmx_vmclear(unsigned __int64*); unsigned char __vmx_vmlaunch(void); unsigned char __vmx_vmptrld(unsigned __int64*); unsigned char __vmx_vmread(size_t, size_t*); unsigned char __vmx_vmresume(void); unsigned char __vmx_vmwrite(size_t, size_t); unsigned char __vmx_on(unsigned __int64*); void __stosq(unsigned __int64 *, unsigned __int64, size_t); unsigned char _interlockedbittestandset64(__int64 volatile *, __int64); unsigned char _interlockedbittestandreset64(__int64 volatile *, __int64); short _InterlockedCompareExchange16_np(short volatile *, short, short); long _InterlockedCompareExchange_np (long volatile *, long, long); __int64 _InterlockedCompareExchange64_np(__int64 volatile *, __int64, __int64); void *_InterlockedCompareExchangePointer_np (void * volatile *, void *, void *); unsigned char _InterlockedCompareExchange128(__int64 volatile *, __int64, __int64, __int64 *); unsigned char _InterlockedCompareExchange128_np(__int64 volatile *, __int64, __int64, __int64 *); long _InterlockedAnd_np(long volatile *, long); char _InterlockedAnd8_np(char volatile *, char); short _InterlockedAnd16_np(short volatile *, short); __int64 _InterlockedAnd64_np(__int64 volatile *, __int64); long _InterlockedOr_np(long volatile *, long); char _InterlockedOr8_np(char volatile *, char); short _InterlockedOr16_np(short volatile *, short); __int64 _InterlockedOr64_np(__int64 volatile *, __int64); long _InterlockedXor_np(long volatile *, long); char _InterlockedXor8_np(char volatile *, char); short _InterlockedXor16_np(short volatile *, short); __int64 _InterlockedXor64_np(__int64 volatile *, __int64); unsigned __int64 __lzcnt64(unsigned __int64); unsigned __int64 __popcnt64(unsigned __int64); Intel x86 Only: long _InterlockedAddLargeStatistic(__int64 volatile *, long); unsigned __readeflags(void); void __writeeflags(unsigned); void __addfsbyte(unsigned long, unsigned char); void __addfsword(unsigned long, unsigned short); void __addfsdword(unsigned long, unsigned long); unsigned char __readfsbyte(unsigned long); unsigned short __readfsword(unsigned long); unsigned long __readfsdword(unsigned long); unsigned __int64 __readfsqword(unsigned long); void __writefsbyte(unsigned long, unsigned char); void __writefsword(unsigned long, unsigned short); void __writefsdword(unsigned long, unsigned long); void __writefsqword(unsigned long, unsigned __int64); Win64, 64-bit compilers only: unsigned char _bittest(long const *, long); unsigned char _bittestandset(long *, long); unsigned char _bittestandreset(long *, long); unsigned char _bittestandcomplement(long *, long); unsigned char _bittest64(__int64 const *, __int64); unsigned char _bittestandset64(__int64 *, __int64); unsigned char _bittestandreset64(__int64 *, __int64); unsigned char _bittestandcomplement64(__int64 *, __int64); unsigned char _BitScanForward(unsigned long*, unsigned long); unsigned char _BitScanReverse(unsigned long*, unsigned long); unsigned char _BitScanForward64(unsigned long*, unsigned __int64); unsigned char _BitScanReverse64(unsigned long*, unsigned __int64); unsigned __int64 __shiftleft128(unsigned __int64, unsigned __int64, unsigned char); unsigned __int64 __shiftright128(unsigned __int64, unsigned __int64, unsigned char); unsigned __int64 _umul128(unsigned __int64, unsigned __int64, unsigned __int64 *); __int64 _mul128(__int64, __int64, __int64 *); void _ReadBarrier(void); unsigned char _rotr8(unsigned char, unsigned char); unsigned short _rotr16(unsigned short, unsigned char); unsigned char _rotl8(unsigned char, unsigned char); unsigned short _rotl16(unsigned short, unsigned char); short _InterlockedIncrement16(short volatile *); short _InterlockedDecrement16(short volatile *); short _InterlockedCompareExchange16(short volatile *, short, short); Kernel-Only: unsigned __int64 __readcr0(void); unsigned __int64 __readcr2(void); unsigned __int64 __readcr3(void); unsigned __int64 __readcr4(void); unsigned __int64 __readcr8(void); unsigned long __readcr0(void); unsigned long __readcr2(void); unsigned long __readcr3(void); unsigned long __readcr4(void); unsigned long __readcr8(void); void __writecr0(unsigned __int64); void __writecr3(unsigned __int64); void __writecr4(unsigned __int64); void __writecr8(unsigned __int64); void __writecr0(unsigned); void __writecr3(unsigned); void __writecr4(unsigned); void __writecr8(unsigned); unsigned __int64 __readdr(unsigned int); unsigned __readdr(unsigned int); void __writedr(unsigned int, unsigned __int64); void __writedr(unsigned int, unsigned); void __wbinvd(void); void __invlpg(void*); unsigned __int64 __readmsr(unsigned long); void __writemsr(unsigned long, unsigned __int64); unsigned char __readgsbyte(unsigned long); unsigned short __readgsword(unsigned long); unsigned long __readgsdword(unsigned long); unsigned __int64 __readgsqword(unsigned long); void __writegsbyte(unsigned long, unsigned char); void __writegsword(unsigned long, unsigned short); void __writegsdword(unsigned long, unsigned long); void __writegsqword(unsigned long, unsigned __int64); void __incfsbyte(unsigned long); void __incfsword(unsigned long); void __incfsdword(unsigned long); void __addgsbyte(unsigned long, unsigned char); void __addgsword(unsigned long, unsigned short); void __addgsdword(unsigned long, unsigned long); void __addgsqword(unsigned long, unsigned __int64); void __incgsbyte(unsigned long); void __incgsword(unsigned long); void __incgsdword(unsigned long); void __incgsqword(unsigned long); unsigned __int64 __readpmc(unsigned long); Entirely Undocumented on MSDN: void __nvreg_save_fence(void); void __nvreg_restore_fence(void); ~Aaron From ganna at apple.com Mon Feb 20 14:25:24 2012 From: ganna at apple.com (Anna Zaks) Date: Mon, 20 Feb 2012 22:25:24 -0000 Subject: [cfe-commits] r150993 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc-interprocedural.c Message-ID: <20120220222524.274262A6C12F@llvm.org> Author: zaks Date: Mon Feb 20 16:25:23 2012 New Revision: 150993 URL: http://llvm.org/viewvc/llvm-project?rev=150993&view=rev Log: [analyzer] Make Malloc aware of inter-procedural execution + basic tests. Added: cfe/trunk/test/Analysis/malloc-interprocedural.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=150993&r1=150992&r2=150993&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Mon Feb 20 16:25:23 2012 @@ -827,6 +827,10 @@ ProgramStateRef state = C.getState(); RegionStateTy M = state->get(); + // If inside inlined call, skip it. + if (C.getLocationContext()->getParent() != 0) + return; + for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) { RefState RS = I->second; if (RS.isAllocated()) { @@ -885,8 +889,9 @@ if (checkUseAfterFree(Sym, C, E)) return; - // Check if the symbol is escaping. - checkEscape(Sym, E, C); + // If this function body is not inlined, check if the symbol is escaping. + if (C.getLocationContext()->getParent() == 0) + checkEscape(Sym, E, C); } bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C, Added: cfe/trunk/test/Analysis/malloc-interprocedural.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-interprocedural.c?rev=150993&view=auto ============================================================================== --- cfe/trunk/test/Analysis/malloc-interprocedural.c (added) +++ cfe/trunk/test/Analysis/malloc-interprocedural.c Mon Feb 20 16:25:23 2012 @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-call -analyzer-store=region -verify %s + +#include "system-header-simulator.h" + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void *valloc(size_t); +void free(void *); +void *realloc(void *ptr, size_t size); +void *reallocf(void *ptr, size_t size); +void *calloc(size_t nmemb, size_t size); +extern void exit(int) __attribute__ ((__noreturn__)); + +static void my_malloc1(void **d, size_t size) { + *d = malloc(size); +} + +static void *my_malloc2(int elevel, size_t size) { + void *data; + data = malloc(size); + if (data == 0) + exit(0); + return data; +} + +static void my_free1(void *p) { + free(p); +} + +static void test1() { + void *data = 0; + my_malloc1(&data, 4); // expected-warning {{Memory is never released; potential memory leak}} +} + +static void test2() { + void * data = my_malloc2(1, 4); + data = my_malloc2(1, 4);// expected-warning {{Memory is never released; potential memory leak}} +} + +static void test3() { + void *data = my_malloc2(1, 4); + free(data); + data = my_malloc2(1, 4); + free(data); +} + +int test4() { + int *data = (int*)my_malloc2(1, 4); + my_free1(data); + data = (int *)my_malloc2(1, 4); + my_free1(data); + return *data; // expected-warning {{Use of memory after it is freed}} +} + From fjahanian at apple.com Mon Feb 20 14:42:22 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Mon, 20 Feb 2012 22:42:22 -0000 Subject: [cfe-commits] r150994 - in /cfe/trunk: lib/CodeGen/CGObjCMac.cpp test/CodeGenObjC/ivar-base-as-invariant-load.m Message-ID: <20120220224222.8B8312A6C12F@llvm.org> Author: fjahanian Date: Mon Feb 20 16:42:22 2012 New Revision: 150994 URL: http://llvm.org/viewvc/llvm-project?rev=150994&view=rev Log: objc IRGen: force CSE of load of ivar offsets by setting the 'invariant.load' metadata tag onto those loads. // rdar://10840980 Added: cfe/trunk/test/CodeGenObjC/ivar-base-as-invariant-load.m Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=150994&r1=150993&r2=150994&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon Feb 20 16:42:22 2012 @@ -5704,8 +5704,13 @@ const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { ObjCInterfaceDecl *ID = ObjectTy->getAs()->getInterface(); + llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar); + if (llvm::LoadInst *LI = dyn_cast(Offset)) + LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"), + llvm::MDNode::get(VMContext, + ArrayRef())); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, - EmitIvarOffset(CGF, ID, Ivar)); + Offset); } llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( Added: cfe/trunk/test/CodeGenObjC/ivar-base-as-invariant-load.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/ivar-base-as-invariant-load.m?rev=150994&view=auto ============================================================================== --- cfe/trunk/test/CodeGenObjC/ivar-base-as-invariant-load.m (added) +++ cfe/trunk/test/CodeGenObjC/ivar-base-as-invariant-load.m Mon Feb 20 16:42:22 2012 @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -x objective-c %s -o - | FileCheck %s +// rdar://10840980 + + at interface A { + struct { + unsigned char a : 1; + unsigned char b : 1; + unsigned char c : 1; + } _flags; +} + + at end + + at implementation A + +- (id)init { + _flags.a = 1; + _flags.b = 1; + _flags.c = 1; + + return self; +} + + at end + +// CHECK: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4 +// CHECK: [[T2:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4 +// CHECK: [[T3:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4 + From akyrtzi at gmail.com Mon Feb 20 14:54:39 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Mon, 20 Feb 2012 22:54:39 -0000 Subject: [cfe-commits] r150995 - /cfe/trunk/include/clang/Frontend/PreprocessorOptions.h Message-ID: <20120220225439.99C402A6C12F@llvm.org> Author: akirtzidis Date: Mon Feb 20 16:54:39 2012 New Revision: 150995 URL: http://llvm.org/viewvc/llvm-project?rev=150995&view=rev Log: Make PreprocessorOptions::DetailedRecordIncludesNestedMacroExpansions false by default. Recording nested macro expansions is not useful, plus it fixes rdar://10893630 Modified: cfe/trunk/include/clang/Frontend/PreprocessorOptions.h Modified: cfe/trunk/include/clang/Frontend/PreprocessorOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PreprocessorOptions.h?rev=150995&r1=150994&r2=150995&view=diff ============================================================================== --- cfe/trunk/include/clang/Frontend/PreprocessorOptions.h (original) +++ cfe/trunk/include/clang/Frontend/PreprocessorOptions.h Mon Feb 20 16:54:39 2012 @@ -162,7 +162,7 @@ public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DetailedRecordIncludesNestedMacroExpansions(true), + DetailedRecordIncludesNestedMacroExpansions(false), DisablePCHValidation(false), DisableStatCache(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), From echristo at apple.com Mon Feb 20 15:02:36 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 23:02:36 -0000 Subject: [cfe-commits] r150996 - /cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Message-ID: <20120220230236.920782A6C12F@llvm.org> Author: echristo Date: Mon Feb 20 17:02:36 2012 New Revision: 150996 URL: http://llvm.org/viewvc/llvm-project?rev=150996&view=rev Log: Formatting. 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=150996&r1=150995&r2=150996&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Feb 20 17:02:36 2012 @@ -337,8 +337,8 @@ return llvm::DIType(); case BuiltinType::ObjCClass: return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_class", getOrCreateMainFile(), - 0); + "objc_class", getOrCreateMainFile(), + 0); case BuiltinType::ObjCId: { // typedef struct objc_class *Class; // typedef struct objc_object { @@ -347,8 +347,8 @@ llvm::DIType OCTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_class", getOrCreateMainFile(), - 0); + "objc_class", getOrCreateMainFile(), + 0); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size); @@ -368,8 +368,8 @@ case BuiltinType::ObjCSel: { return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_selector", getOrCreateMainFile(), - 0); + "objc_selector", getOrCreateMainFile(), + 0); } case BuiltinType::UChar: case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; From richard-llvm at metafoo.co.uk Mon Feb 20 15:28:05 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Mon, 20 Feb 2012 23:28:05 -0000 Subject: [cfe-commits] r151001 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplate.cpp test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Message-ID: <20120220232805.9EB7A2A6C12F@llvm.org> Author: rsmith Date: Mon Feb 20 17:28:05 2012 New Revision: 151001 URL: http://llvm.org/viewvc/llvm-project?rev=151001&view=rev Log: Fix a constexpr FIXME: When implicitly instantiating the primary template for an explicit specialization of a function template, mark the instantiation as constexpr if the specialization is, rather than requiring them to match. Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=151001&r1=151000&r2=151001&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Feb 20 17:28:05 2012 @@ -516,13 +516,9 @@ } } - // C++0x [dcl.constexpr]p1: If any declaration of a function or function + // C++11 [dcl.constexpr]p1: If any declaration of a function or function // template has a constexpr specifier then all its declarations shall - // contain the constexpr specifier. [Note: An explicit specialization can - // differ from the template declaration with respect to the constexpr - // specifier. -- end note] - // - // FIXME: Don't reject changes in constexpr in explicit specializations. + // contain the constexpr specifier. if (New->isConstexpr() != Old->isConstexpr()) { Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) << New << New->isConstexpr(); Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=151001&r1=151000&r2=151001&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Feb 20 17:28:05 2012 @@ -5677,8 +5677,13 @@ // Note: do not overwrite location info if previous template // specialization kind was explicit. TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind(); - if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) + if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) { Specialization->setLocation(FD->getLocation()); + // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr + // function can differ from the template declaration with respect to + // the constexpr specifier. + Specialization->setConstexpr(FD->isConstexpr()); + } // FIXME: Check if the prior specialization has a point of instantiation. // If so, we have run afoul of . Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp?rev=151001&r1=151000&r2=151001&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Mon Feb 20 17:28:05 2012 @@ -75,15 +75,13 @@ }; // explicit specialization can differ in constepxr -// FIXME: When checking the explicit specialization, we implicitly instantiate -// the primary template then claim a constexpr mismatch. -template <> notlit ft(notlit nl) { return nl; } // unexpected-error {{follows constexpr declaration}} unexpected-note {{here}} -template <> char ft(char c) { return c; } // desired-note {{previous}} unexpected-error {{follows constexpr declaration}} unexpected-note {{here}} -template <> constexpr char ft(char nl); // desired-error {{constexpr declaration of 'ft' follows non-constexpr declaration}} -template <> constexpr int gt(int nl) { return nl; } // unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}} -template <> notlit S::f() const { return notlit(); } // unexpected-error {{follows constexpr declaration}} unexpected-note {{here}} -template <> constexpr int S::g() { return 0; } // desired-note {{previous}} unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}} -template <> int S::g() const; // desired-error {{non-constexpr declaration of 'g' follows constexpr declaration}} +template <> notlit ft(notlit nl) { return nl; } +template <> char ft(char c) { return c; } // expected-note {{previous}} +template <> constexpr char ft(char nl); // expected-error {{constexpr declaration of 'ft' follows non-constexpr declaration}} +template <> constexpr int gt(int nl) { return nl; } +template <> notlit S::f() const { return notlit(); } +template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok From aaron at aaronballman.com Mon Feb 20 15:33:43 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 20 Feb 2012 17:33:43 -0600 Subject: [cfe-commits] [PATCH] Getting the driver to understand -working-directory In-Reply-To: <1E506119-68BE-4AF7-8ECE-AC802108D81C@apple.com> References: <1E506119-68BE-4AF7-8ECE-AC802108D81C@apple.com> Message-ID: >>> Also, testcase? :) >> >> I'll add one this evening if I can think of a way to do it sensibly. > > Sounds good to me. Since -working-directory expects an absolute path, I'm hard-pressed to think of a reasonable way to implement a test case for this that would work across all platforms. I could make working-directory support relative paths as well, but it seems like overkill just so we can have a test case. Thoughts or suggestions? Or should I just skip the test case? ~Aaron From gregory.szorc at gmail.com Mon Feb 20 15:54:28 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 15:54:28 -0800 Subject: [cfe-commits] [PATCH] [clang.py] Refactor get_tu and get_cursor test helper functions into util.py Message-ID: There was a lot of repeated code around TU instantiation and obtaining cursors in the test code. So, I factored out the recently-implemented helper methods into a shared module. Ideally, I'd convert the test suite to classes and have these methods hang off a base class. However, that would bit rot a lot of work in my Python feature branch and I don't want to go through the pain of rebasing right now. --- bindings/python/tests/cindex/test_cursor.py | 32 ++++------ bindings/python/tests/cindex/test_diagnostics.py | 33 +++------- bindings/python/tests/cindex/test_location.py | 78 ++++++++++++---------- bindings/python/tests/cindex/test_type.py | 32 +-------- bindings/python/tests/cindex/util.py | 65 ++++++++++++++++++ 5 files changed, 130 insertions(+), 110 deletions(-) create mode 100644 bindings/python/tests/cindex/util.py -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-clang.py-Refactor-get_tu-and-get_cursor-test-helper-.patch Type: text/x-patch Size: 15783 bytes Desc: not available URL: From gregory.szorc at gmail.com Mon Feb 20 15:55:45 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 15:55:45 -0800 Subject: [cfe-commits] [PATCH] [clang.py] Implement Cursor.objc_type_encoding Message-ID: My only question is whether it is acceptable to use abbreviations in the API. "objc" is used elsewhere for constants. --- bindings/python/clang/cindex.py | 13 +++++++++++++ bindings/python/tests/cindex/test_cursor.py | 9 +++++++++ 2 files changed, 22 insertions(+), 0 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-clang.py-Implement-Cursor.objc_type_encoding.patch Type: text/x-patch Size: 2648 bytes Desc: not available URL: From gregory.szorc at gmail.com Mon Feb 20 15:56:00 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 15:56:00 -0800 Subject: [cfe-commits] [PATCH] [clang.py] Implement TypeKind.spelling Message-ID: --- bindings/python/clang/cindex.py | 9 +++++++++ bindings/python/tests/cindex/test_type.py | 9 ++++++++- 2 files changed, 17 insertions(+), 1 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-clang.py-Implement-TypeKind.spelling.patch Type: text/x-patch Size: 2544 bytes Desc: not available URL: From akyrtzi at gmail.com Mon Feb 20 15:58:08 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Mon, 20 Feb 2012 23:58:08 -0000 Subject: [cfe-commits] r151004 - in /cfe/trunk: include/clang/Basic/SourceManager.h lib/Basic/SourceManager.cpp lib/Serialization/ASTReader.cpp Message-ID: <20120220235808.19E952A6C12F@llvm.org> Author: akirtzidis Date: Mon Feb 20 17:58:07 2012 New Revision: 151004 URL: http://llvm.org/viewvc/llvm-project?rev=151004&view=rev Log: [PCH] Recover gracefully if the ASTReader detects that a file is different from the one stored in the PCH/AST, while trying to load a SLocEntry. We verify that all files of the PCH did not change before loading it but this is not enough because: - The AST may have been 1) kept around, 2) to do queries on it. - We may have 1) verified the PCH and 2) started parsing. Between 1) and 2) files may change and we are going to have crashes because the rest of clang cannot deal with the ASTReader failing to read a SLocEntry. Handle this by recovering gracefully in such a case, by initializing the SLocEntry with the info from the PCH/AST as well as reporting failure by the ASTReader. rdar://10888929 Modified: cfe/trunk/include/clang/Basic/SourceManager.h cfe/trunk/lib/Basic/SourceManager.cpp cfe/trunk/lib/Serialization/ASTReader.cpp Modified: cfe/trunk/include/clang/Basic/SourceManager.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=151004&r1=151003&r2=151004&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/SourceManager.h (original) +++ cfe/trunk/include/clang/Basic/SourceManager.h Mon Feb 20 17:58:07 2012 @@ -519,7 +519,7 @@ /// /// Negative FileIDs are indexes into this table. To get from ID to an index, /// use (-ID - 2). - std::vector LoadedSLocEntryTable; + mutable std::vector LoadedSLocEntryTable; /// \brief The starting offset of the next local SLocEntry. /// @@ -576,6 +576,8 @@ // Cache for the "fake" buffer used for error-recovery purposes. mutable llvm::MemoryBuffer *FakeBufferForRecovery; + mutable SrcMgr::ContentCache *FakeContentCacheForRecovery; + /// \brief Lazily computed map of macro argument chunks to their expanded /// source location. typedef std::map MacroArgsMap; @@ -1260,9 +1262,9 @@ const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid = 0) const { assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); - if (!SLocEntryLoaded[Index]) - ExternalSLocEntries->ReadSLocEntry(-(static_cast(Index) + 2)); - return LoadedSLocEntryTable[Index]; + if (SLocEntryLoaded[Index]) + return LoadedSLocEntryTable[Index]; + return loadSLocEntry(Index, Invalid); } const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const { @@ -1313,6 +1315,9 @@ private: const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; + + const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; /// \brief Get the entry with the given unwrapped FileID. const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const { @@ -1322,8 +1327,9 @@ return getLocalSLocEntry(static_cast(ID)); } - const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID) const { - return getLoadedSLocEntry(static_cast(-ID - 2)); + const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID, + bool *Invalid = 0) const { + return getLoadedSLocEntry(static_cast(-ID - 2), Invalid); } /// createExpansionLoc - Implements the common elements of storing an Modified: cfe/trunk/lib/Basic/SourceManager.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=151004&r1=151003&r2=151004&view=diff ============================================================================== --- cfe/trunk/lib/Basic/SourceManager.cpp (original) +++ cfe/trunk/lib/Basic/SourceManager.cpp Mon Feb 20 17:58:07 2012 @@ -370,7 +370,8 @@ SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr) : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), - NumBinaryProbes(0), FakeBufferForRecovery(0) { + NumBinaryProbes(0), FakeBufferForRecovery(0), + FakeContentCacheForRecovery(0) { clearIDTables(); Diag.setSourceManager(this); } @@ -396,6 +397,7 @@ } delete FakeBufferForRecovery; + delete FakeContentCacheForRecovery; for (llvm::DenseMap::iterator I = MacroArgsCacheMap.begin(),E = MacroArgsCacheMap.end(); I!=E; ++I) { @@ -469,6 +471,25 @@ return Entry; } +const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, + bool *Invalid) const { + assert(!SLocEntryLoaded[Index]); + if (ExternalSLocEntries->ReadSLocEntry(-(static_cast(Index) + 2))) { + if (Invalid) + *Invalid = true; + // If the file of the SLocEntry changed we could still have loaded it. + if (!SLocEntryLoaded[Index]) { + // Try to recover; create a SLocEntry so the rest of clang can handle it. + LoadedSLocEntryTable[Index] = SLocEntry::get(0, + FileInfo::get(SourceLocation(), + getFakeContentCacheForRecovery(), + SrcMgr::C_User)); + } + } + + return LoadedSLocEntryTable[Index]; +} + std::pair SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize) { @@ -491,6 +512,18 @@ return FakeBufferForRecovery; } +/// \brief As part of recovering from missing or changed content, produce a +/// fake content cache. +const SrcMgr::ContentCache * +SourceManager::getFakeContentCacheForRecovery() const { + if (!FakeContentCacheForRecovery) { + FakeContentCacheForRecovery = new ContentCache(); + FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), + /*DoNotFree=*/true); + } + return FakeContentCacheForRecovery; +} + //===----------------------------------------------------------------------===// // Methods to create new FileID's and macro expansions. //===----------------------------------------------------------------------===// Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=151004&r1=151003&r2=151004&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Feb 20 17:58:07 2012 @@ -1111,6 +1111,10 @@ return Failure; } + // We will detect whether a file changed and return 'Failure' for it, but + // we will also try to fail gracefully by setting up the SLocEntry. + ASTReader::ASTReadResult Result = Success; + bool OverriddenBuffer = Record[6]; std::string OrigFilename(BlobStart, BlobStart + BlobLen); @@ -1149,7 +1153,7 @@ #endif )) { Error(diag::err_fe_pch_file_modified, Filename); - return Failure; + Result = Failure; } SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); @@ -1193,6 +1197,9 @@ Filename); SourceMgr.overrideFileContents(File, Buffer); } + + if (Result == Failure) + return Failure; break; } From eli.friedman at gmail.com Mon Feb 20 15:58:15 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Mon, 20 Feb 2012 23:58:15 -0000 Subject: [cfe-commits] r151005 - in /cfe/trunk: lib/Sema/SemaType.cpp test/CXX/basic/basic.types/p10.cpp Message-ID: <20120220235815.26E942A6C12F@llvm.org> Author: efriedma Date: Mon Feb 20 17:58:14 2012 New Revision: 151005 URL: http://llvm.org/viewvc/llvm-project?rev=151005&view=rev Log: Make RequireLiteralType work correctly with incomplete array types. PR12037. Modified: cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/test/CXX/basic/basic.types/p10.cpp Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=151005&r1=151004&r2=151005&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Mon Feb 20 17:58:14 2012 @@ -4249,7 +4249,9 @@ const PartialDiagnostic &PD) { assert(!T->isDependentType() && "type should not be dependent"); - RequireCompleteType(Loc, T, 0); + QualType ElemType = Context.getBaseElementType(T); + RequireCompleteType(Loc, ElemType, 0); + if (T->isLiteralType()) return false; @@ -4261,12 +4263,16 @@ if (T->isVariableArrayType()) return true; - const RecordType *RT = T->getBaseElementTypeUnsafe()->getAs(); + const RecordType *RT = ElemType->getAs(); if (!RT) return true; const CXXRecordDecl *RD = cast(RT->getDecl()); + // FIXME: Better diagnostic for incomplete class? + if (!RD->isCompleteDefinition()) + return true; + // If the class has virtual base classes, then it's not an aggregate, and // cannot have any constexpr constructors or a trivial default constructor, // so is non-literal. This is better to diagnose than the resulting absence Modified: cfe/trunk/test/CXX/basic/basic.types/p10.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.types/p10.cpp?rev=151005&r1=151004&r2=151005&view=diff ============================================================================== --- cfe/trunk/test/CXX/basic/basic.types/p10.cpp (original) +++ cfe/trunk/test/CXX/basic/basic.types/p10.cpp Mon Feb 20 17:58:14 2012 @@ -11,8 +11,25 @@ struct S { S(); }; constexpr int f2(S &) { return 0; } +// FIXME: I'm not entirely sure whether the following is legal or not... +struct BeingDefined; +extern BeingDefined beingdefined; +struct BeingDefined { + static constexpr BeingDefined& t = beingdefined; +}; + // - a class type that has all of the following properties: +// (implied) - it is complete + +struct Incomplete; +template struct ClassTemp {}; + +constexpr Incomplete incomplete = {}; // expected-error {{constexpr variable cannot have non-literal type 'const Incomplete'}} +constexpr Incomplete incomplete2[] = {}; // expected-error {{constexpr variable cannot have non-literal type 'Incomplete const[]'}} +constexpr ClassTemp classtemplate = {}; +constexpr ClassTemp classtemplate2[] = {}; + // - it has a trivial destructor struct UserProvDtor { constexpr int f(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}} From ganna at apple.com Mon Feb 20 16:00:48 2012 From: ganna at apple.com (Anna Zaks) Date: Tue, 21 Feb 2012 00:00:48 -0000 Subject: [cfe-commits] r151008 - /cfe/trunk/test/Analysis/malloc-interprocedural.c Message-ID: <20120221000048.DA7F42A6C130@llvm.org> Author: zaks Date: Mon Feb 20 18:00:48 2012 New Revision: 151008 URL: http://llvm.org/viewvc/llvm-project?rev=151008&view=rev Log: [analyzer] + a couple more malloc tests. Modified: cfe/trunk/test/Analysis/malloc-interprocedural.c Modified: cfe/trunk/test/Analysis/malloc-interprocedural.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-interprocedural.c?rev=151008&r1=151007&r2=151008&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc-interprocedural.c (original) +++ cfe/trunk/test/Analysis/malloc-interprocedural.c Mon Feb 20 18:00:48 2012 @@ -32,6 +32,12 @@ my_malloc1(&data, 4); // expected-warning {{Memory is never released; potential memory leak}} } +static void test11() { + void *data = 0; + my_malloc1(&data, 4); + my_free1(data); +} + static void test2() { void * data = my_malloc2(1, 4); data = my_malloc2(1, 4);// expected-warning {{Memory is never released; potential memory leak}} @@ -52,3 +58,14 @@ return *data; // expected-warning {{Use of memory after it is freed}} } +void test6() { + int *data = (int *)my_malloc2(1, 4); + my_free1((int*)data); + my_free1((int*)data); // expected-warning{{Use of memory after it is freed}} +} + +// TODO: We should warn here. +void test5() { + int *data; + my_free1((int*)data); +} From ganna at apple.com Mon Feb 20 16:00:44 2012 From: ganna at apple.com (Anna Zaks) Date: Tue, 21 Feb 2012 00:00:44 -0000 Subject: [cfe-commits] r151007 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp test/Analysis/keychainAPI.m Message-ID: <20120221000044.DC29C2A6C12F@llvm.org> Author: zaks Date: Mon Feb 20 18:00:44 2012 New Revision: 151007 URL: http://llvm.org/viewvc/llvm-project?rev=151007&view=rev Log: [analyzer] Make KeyChainAPI checker inlining-aware. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp cfe/trunk/test/Analysis/keychainAPI.m Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp?rev=151007&r1=151006&r2=151007&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp Mon Feb 20 18:00:44 2012 @@ -447,7 +447,8 @@ const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param); // If the argument entered as an enclosing function parameter, skip it to // avoid false positives. - if (isEnclosingFunctionParam(ArgExpr)) + if (isEnclosingFunctionParam(ArgExpr) && + C.getLocationContext()->getParent() == 0) return; if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C)) { @@ -481,6 +482,10 @@ if (!retExpr) return; + // If inside inlined call, skip it. + if (C.getLocationContext()->getParent() != 0) + return; + // Check if the value is escaping through the return. ProgramStateRef state = C.getState(); const MemRegion *V = @@ -549,6 +554,11 @@ // TODO: Remove this after we ensure that checkDeadSymbols are always called. void MacOSKeychainAPIChecker::checkEndPath(CheckerContext &Ctx) const { ProgramStateRef state = Ctx.getState(); + + // If inside inlined call, skip it. + if (Ctx.getLocationContext()->getParent() != 0) + return; + AllocatedSetTy AS = state->get(); if (AS.isEmpty()) return; Modified: cfe/trunk/test/Analysis/keychainAPI.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/keychainAPI.m?rev=151007&r1=151006&r2=151007&view=diff ============================================================================== --- cfe/trunk/test/Analysis/keychainAPI.m (original) +++ cfe/trunk/test/Analysis/keychainAPI.m Mon Feb 20 18:00:44 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=osx.SecKeychainAPI %s -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=osx.SecKeychainAPI %s -analyzer-inline-call -verify // Fake typedefs. typedef unsigned int OSStatus; @@ -133,7 +133,7 @@ return outData; } // no-warning -// Password was passed in as an argument and does nt have to be deleted. +// Password was passed in as an argument and does not have to be deleted. OSStatus getPasswordAndItem(void** password, UInt32* passwordLength) { OSStatus err; SecKeychainItemRef item; @@ -337,3 +337,63 @@ } while(10 >= row[1]); return row; } + +// Test inter-procedural behaviour. + +void my_FreeParam(void *attrList, void* X) { + SecKeychainItemFreeContent(attrList, X); +} + +void *my_AllocateReturn(OSStatus *st) { + unsigned int *ptr = 0; + UInt32 length; + void *outData; + *st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); + return outData; +} + +OSStatus my_Allocate_Param(void** password, UInt32* passwordLength) { + OSStatus err; + SecKeychainItemRef item; + err = SecKeychainFindGenericPassword(0, 3, "xx", 3, "xx", + passwordLength, password, &item); + return err; +} + +void allocAndFree1() { + unsigned int *ptr = 0; + OSStatus st = 0; + UInt32 length; + void *outData; + st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData); + if (st == noErr) + my_FreeParam(ptr, outData); +} + +void allocNoFree2() { + OSStatus st = 0; + void *outData = my_AllocateReturn(&st); // expected-warning{{Allocated data is not released:}} +} + +void allocAndFree2(void *attrList) { + OSStatus st = 0; + void *outData = my_AllocateReturn(&st); + if (st == noErr) + my_FreeParam(attrList, outData); +} + +void allocNoFree3() { + UInt32 length = 32; + void *outData; + OSStatus st = my_Allocate_Param(&outData, &length); // expected-warning{{Allocated data is not released}} +} + +void allocAndFree3(void *attrList) { + UInt32 length = 32; + void *outData; + OSStatus st = my_Allocate_Param(&outData, &length); + if (st == noErr) + SecKeychainItemFreeContent(attrList, outData); + +} + From nicholas at mxc.ca Mon Feb 20 16:26:58 2012 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 21 Feb 2012 00:26:58 -0000 Subject: [cfe-commits] r151010 - in /cfe/trunk: lib/CodeGen/CGDeclCXX.cpp test/CodeGenCXX/init-invariant.cpp Message-ID: <20120221002658.BCA6E2A6C131@llvm.org> Author: nicholas Date: Mon Feb 20 18:26:58 2012 New Revision: 151010 URL: http://llvm.org/viewvc/llvm-project?rev=151010&view=rev Log: Emit the exact size for the invariant intrinsics. Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp cfe/trunk/test/CodeGenCXX/init-invariant.cpp Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=151010&r1=151009&r2=151010&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Mon Feb 20 18:26:58 2012 @@ -103,7 +103,8 @@ /// Emit code to cause the variable at the given address to be considered as /// constant from this point onwards. -static void EmitDeclInvariant(CodeGenFunction &CGF, llvm::Constant *Addr) { +static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D, + llvm::Constant *Addr) { // Don't emit the intrinsic if we're not optimizing. if (!CGF.CGM.getCodeGenOpts().OptimizationLevel) return; @@ -112,8 +113,10 @@ llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start; llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID); - // Emit a call, with size -1 signifying the whole object. - llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, -1), + // Emit a call with the size in bytes of the object. + CharUnits WidthChars = CGF.getContext().getTypeSizeInChars(D.getType()); + uint64_t Width = WidthChars.getQuantity(); + llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, Width), llvm::ConstantExpr::getBitCast(Addr, CGF.Int8PtrTy)}; CGF.Builder.CreateCall(InvariantStart, Args); } @@ -129,7 +132,7 @@ if (PerformInit) EmitDeclInit(*this, D, DeclPtr); if (CGM.isTypeConstant(D.getType(), true)) - EmitDeclInvariant(*this, DeclPtr); + EmitDeclInvariant(*this, D, DeclPtr); else EmitDeclDestroy(*this, D, DeclPtr); return; Modified: cfe/trunk/test/CodeGenCXX/init-invariant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/init-invariant.cpp?rev=151010&r1=151009&r2=151010&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/init-invariant.cpp (original) +++ cfe/trunk/test/CodeGenCXX/init-invariant.cpp Mon Feb 20 18:26:58 2012 @@ -42,19 +42,19 @@ } // CHECK: call void @_ZN1AC1Ev({{.*}}* @a) -// CHECK: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} @a to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @a to i8*)) // CHECK: call void @_ZN1BC1Ev({{.*}}* @b) -// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} @b to i8*)) +// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @b to i8*)) // CHECK: call void @_ZN1CC1Ev({{.*}}* @c) -// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} @c to i8*)) +// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @c to i8*)) // CHECK: call i32 @_Z1fv( // CHECK: store {{.*}}, i32* @d -// CHECK: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} @d to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @d to i8*)) // CHECK: define void @_Z1ev( // CHECK: call void @_ZN1AC1Ev(%struct.A* @_ZZ1evE1a) -// CHECK: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} @_ZZ1evE1a to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @_ZZ1evE1a to i8*)) // CHECK-NOT: llvm.invariant.end From aaron at aaronballman.com Mon Feb 20 16:41:10 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 20 Feb 2012 18:41:10 -0600 Subject: [cfe-commits] [PATCH] Parsing __declspec properly for enumerations Message-ID: This is a patch to address Bug 8783 -- declspecs can be placed on enum declarations as well. To clarify: __declspec(foo) enum E { x, y } e; // Puts foo on e enum __declspec(foo) enum E { x, y } e; // Puts foo on E This is important for supporting the deprecated declspec. Class, struct and union already function properly. ~Aaron -------------- next part -------------- A non-text attachment was scrubbed... Name: DeclspecEnum.patch Type: application/octet-stream Size: 1505 bytes Desc: not available URL: From dgregor at apple.com Mon Feb 20 16:37:25 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 21 Feb 2012 00:37:25 -0000 Subject: [cfe-commits] r151011 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclCXX.h include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/AST/ExprCXX.cpp lib/AST/ItaniumMangle.cpp lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDecl.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp test/CodeGenCXX/mangle-lambdas.cpp Message-ID: <20120221003726.134562A6C12F@llvm.org> Author: dgregor Date: Mon Feb 20 18:37:24 2012 New Revision: 151011 URL: http://llvm.org/viewvc/llvm-project?rev=151011&view=rev Log: Implement name mangling for lambda expressions that occur within the default arguments of function parameters. This simple-sounding task is complicated greatly by two issues: (1) Default arguments aren't actually a real context, so we need to maintain extra state within lambda expressions to track when a lambda was actually in a default argument. (2) At the time that we parse a default argument, the FunctionDecl doesn't exist yet, so lambda closure types end up in the enclosing context. It's not clear that we ever want to change that, so instead we introduce the notion of the "effective" context of a declaration for the purposes of name mangling. Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ExprCXX.cpp cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Feb 20 18:37:24 2012 @@ -327,12 +327,12 @@ /// expression used to copy the lambda object. llvm::DenseMap LambdaBlockPointerInits; + friend class CXXConversionDecl; + /// \brief Mapping from each declaration context to its corresponding lambda /// mangling context. llvm::DenseMap LambdaMangleContexts; - friend class CXXConversionDecl; - /// \brief Mapping that stores parameterIndex values for ParmVarDecls /// when that value exceeds the bitfield size of /// ParmVarDeclBits.ParameterIndex. Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Feb 20 18:37:24 2012 @@ -561,7 +561,9 @@ typedef LambdaExpr::Capture Capture; LambdaDefinitionData(CXXRecordDecl *D) - : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), Captures(0) { + : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), + ContextDecl(0), Captures(0) + { IsLambda = true; } @@ -575,9 +577,14 @@ /// mangling in the Itanium C++ ABI. unsigned ManglingNumber; - /// \brief The "extra" data associated with the lambda, including - /// captures, capture initializers, the body of the lambda, and the - /// array-index variables for array captures. + /// \brief The declaration that provides context for this lambda, if the + /// actual DeclContext does not suffice. This is used for lambdas that + /// occur within default arguments of function parameters within the class + /// or within a data member initializer. + Decl *ContextDecl; + + /// \brief The list of captures, both explicit and implicit, for this + /// lambda. Capture *Captures; }; @@ -1457,6 +1464,20 @@ return getLambdaData().ManglingNumber; } + /// \brief Retrieve the declaration that provides additional context for a + /// lambda, when the normal declaration context is not specific enough. + /// + /// Certain contexts (default arguments of in-class function parameters and + /// the initializers of data members) have separate name mangling rules for + /// lambdas within the Itanium C++ ABI. For these cases, this routine provides + /// the declaration in which the lambda occurs, e.g., the function parameter + /// or the non-static data member. Otherwise, it returns NULL to imply that + /// the declaration context suffices. + Decl *getLambdaContextDecl() const { + assert(isLambda() && "Not a lambda closure type!"); + return getLambdaData().ContextDecl; + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Feb 20 18:37:24 2012 @@ -1167,7 +1167,8 @@ ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, SourceLocation ClosingBrace, - unsigned ManglingNumber); + unsigned ManglingNumber, + Decl *ContextDecl); /// \brief Construct an empty lambda expression. LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) @@ -1206,7 +1207,8 @@ ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, SourceLocation ClosingBrace, - unsigned ManglingNumber); + unsigned ManglingNumber, + Decl *ContextDecl); /// \brief Construct a new lambda expression that will be deserialized from /// an external source. Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon Feb 20 18:37:24 2012 @@ -572,11 +572,37 @@ /// is indeed an unevaluated context. llvm::SmallVector Lambdas; + /// \brief The declaration that provides context for the lambda expression + /// if the normal declaration context does not suffice, e.g., in a + /// default function argument. + Decl *LambdaContextDecl; + + /// \brief The context information used to mangle lambda expressions + /// within this context. + /// + /// This mangling information is allocated lazily, since most contexts + /// do not have lambda expressions. + LambdaMangleContext *LambdaMangle; + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, - bool ParentNeedsCleanups) + bool ParentNeedsCleanups, + Decl *LambdaContextDecl) : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), - NumCleanupObjects(NumCleanupObjects) { } + NumCleanupObjects(NumCleanupObjects), + LambdaContextDecl(LambdaContextDecl), LambdaMangle() { } + + ~ExpressionEvaluationContextRecord() { + delete LambdaMangle; + } + + /// \brief Retrieve the mangling context for lambdas. + LambdaMangleContext &getLambdaMangleContext() { + assert(LambdaContextDecl && "Need to have a lambda context declaration"); + if (!LambdaMangle) + LambdaMangle = new LambdaMangleContext; + return *LambdaMangle; + } }; /// A stack of expression evaluation contexts. @@ -2288,7 +2314,8 @@ void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs); - void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext); + void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl = 0); void PopExpressionEvaluationContext(); @@ -3558,6 +3585,7 @@ Scope *CurScope, llvm::Optional ManglingNumber = llvm::Optional(), + Decl *ContextDecl = 0, bool IsInstantiation = false); /// \brief Define the "body" of the conversion from a lambda object to a @@ -6541,9 +6569,10 @@ public: EnterExpressionEvaluationContext(Sema &Actions, - Sema::ExpressionEvaluationContext NewContext) + Sema::ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl = 0) : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext); + Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl); } ~EnterExpressionEvaluationContext() { Modified: cfe/trunk/lib/AST/ExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprCXX.cpp (original) +++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Feb 20 18:37:24 2012 @@ -765,7 +765,8 @@ ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, SourceLocation ClosingBrace, - unsigned ManglingNumber) + unsigned ManglingNumber, + Decl *ContextDecl) : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->isDependentType(), /*ContainsUnexpandedParameterPack=*/false), @@ -787,6 +788,7 @@ Data.NumCaptures = NumCaptures; Data.NumExplicitCaptures = 0; Data.ManglingNumber = ManglingNumber; + Data.ContextDecl = ContextDecl; Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures); Capture *ToCapture = Data.Captures; for (unsigned I = 0, N = Captures.size(); I != N; ++I) { @@ -827,7 +829,8 @@ ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, SourceLocation ClosingBrace, - unsigned ManglingNumber) { + unsigned ManglingNumber, + Decl *ContextDecl) { // Determine the type of the expression (i.e., the type of the // function object we're creating). QualType T = Context.getTypeDeclType(Class); @@ -840,7 +843,7 @@ return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, - ClosingBrace, ManglingNumber); + ClosingBrace, ManglingNumber, ContextDecl); } LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures, Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Feb 20 18:37:24 2012 @@ -40,14 +40,38 @@ namespace { +/// \brief Retrieve the declaration context that should be used when mangling +/// the given declaration. +static const DeclContext *getEffectiveDeclContext(const Decl *D) { + // The ABI assumes that lambda closure types that occur within + // default arguments live in the context of the function. However, due to + // the way in which Clang parses and creates function declarations, this is + // not the case: the lambda closure type ends up living in the context + // where the function itself resides, because the function declaration itself + // had not yet been created. Fix the context here. + if (const CXXRecordDecl *RD = dyn_cast(D)) { + if (RD->isLambda()) + if (ParmVarDecl *ContextParam + = dyn_cast_or_null(RD->getLambdaContextDecl())) + return ContextParam->getDeclContext(); + } + + return D->getDeclContext(); +} + +static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { + return getEffectiveDeclContext(cast(DC)); +} + static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) { const DeclContext *DC = dyn_cast(ND); if (!DC) - DC = ND->getDeclContext(); + DC = getEffectiveDeclContext(ND); while (!DC->isNamespace() && !DC->isTranslationUnit()) { - if (isa(DC->getParent())) + const DeclContext *Parent = getEffectiveDeclContext(cast(DC)); + if (isa(Parent)) return dyn_cast(DC); - DC = DC->getParent(); + DC = Parent; } return 0; } @@ -63,7 +87,7 @@ const FunctionDecl *fn = dyn_cast_or_null(decl); return (fn ? getStructor(fn) : decl); } - + static const unsigned UnknownArity = ~0U; class ItaniumMangleContext : public MangleContext { @@ -279,6 +303,7 @@ void mangleUnscopedTemplateName(TemplateName); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); + void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, @@ -339,8 +364,8 @@ static bool isInCLinkageSpecification(const Decl *D) { D = D->getCanonicalDecl(); - for (const DeclContext *DC = D->getDeclContext(); - !DC->isTranslationUnit(); DC = DC->getParent()) { + for (const DeclContext *DC = getEffectiveDeclContext(D); + !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) { if (const LinkageSpecDecl *Linkage = dyn_cast(DC)) return Linkage->getLanguage() == LinkageSpecDecl::lang_c; } @@ -372,17 +397,17 @@ // Variables at global scope with non-internal linkage are not mangled if (!FD) { - const DeclContext *DC = D->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(D); // Check for extern variable declared locally. if (DC->isFunctionOrMethod() && D->hasLinkage()) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage) return false; } // Class members are always mangled. - if (D->getDeclContext()->isRecord()) + if (getEffectiveDeclContext(D)->isRecord()) return true; // C functions and "main" are not mangled. @@ -465,7 +490,7 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { while (isa(DC)) { - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); } return DC; @@ -473,7 +498,8 @@ /// isStd - Return whether a given namespace is the 'std' namespace. static bool isStd(const NamespaceDecl *NS) { - if (!IgnoreLinkageSpecDecls(NS->getParent())->isTranslationUnit()) + if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS)) + ->isTranslationUnit()) return false; const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); @@ -515,20 +541,20 @@ // ::= // ::= // - const DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. if (isa(DC) && ND->hasLinkage()) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { mangleLocalName(ND); return; } while (isa(DC)) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. @@ -554,7 +580,7 @@ void CXXNameMangler::mangleName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { - const DeclContext *DC = IgnoreLinkageSpecDecls(TD->getDeclContext()); + const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD)); if (DC->isTranslationUnit() || isStdNamespace(DC)) { mangleUnscopedTemplateName(TD); @@ -568,7 +594,7 @@ void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) { // ::= // ::= St # ::std:: - if (isStdNamespace(ND->getDeclContext())) + if (isStdNamespace(getEffectiveDeclContext(ND))) Out << "St"; mangleUnqualifiedName(ND); @@ -1028,7 +1054,7 @@ // This naming convention is the same as that followed by GCC, // though it shouldn't actually matter. if (ND && ND->getLinkage() == InternalLinkage && - ND->getDeclContext()->isFileContext()) + getEffectiveDeclContext(ND)->isFileContext()) Out << 'L'; mangleSourceName(II); @@ -1089,28 +1115,7 @@ // ::= + # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast(TD)) { if (Record->isLambda()) { - // FIXME: Figure out if we're in a function body, default argument, - // or initializer for a class member. - - Out << "Ul"; - DeclarationName Name - = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); - const FunctionProtoType *Proto - = cast(*Record->lookup(Name).first)->getType()-> - getAs(); - mangleBareFunctionType(Proto, /*MangleReturnType=*/false); - Out << "E"; - - // The number is omitted for the first closure type with a given - // in a given context; it is n-2 for the nth closure type - // (in lexical order) with that same and context. - // - // The AST keeps track of the number for us. - if (unsigned Number = Record->getLambdaManglingNumber()) { - if (Number > 1) - mangleNumber(Number - 2); - } - Out << '_'; + mangleLambda(Record); break; } } @@ -1243,8 +1248,10 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // := Z E [] // := Z E s [] + // := Z E d [ ] + // _ // := _ - const DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); if (isa(DC) && isa(ND)) { // Don't add objc method name mangling to locally declared function mangleUnqualifiedName(ND); @@ -1256,23 +1263,46 @@ if (const ObjCMethodDecl *MD = dyn_cast(DC)) { mangleObjCMethodName(MD); } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) { - mangleFunctionEncoding(cast(RD->getDeclContext())); + mangleFunctionEncoding(cast(getEffectiveDeclContext(RD))); Out << 'E'; + // The parameter number is omitted for the last parameter, 0 for the + // second-to-last parameter, 1 for the third-to-last parameter, etc. The + // will of course contain a : Its + // numbering will be local to the particular argument in which it appears + // -- other default arguments do not affect its encoding. + bool SkipDiscriminator = false; + if (RD->isLambda()) { + if (const ParmVarDecl *Parm + = dyn_cast_or_null(RD->getLambdaContextDecl())) { + if (const FunctionDecl *Func + = dyn_cast(Parm->getDeclContext())) { + Out << 'd'; + unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex(); + if (Num > 1) + mangleNumber(Num - 2); + Out << '_'; + SkipDiscriminator = true; + } + } + } + // Mangle the name relative to the closest enclosing function. if (ND == RD) // equality ok because RD derived from ND above mangleUnqualifiedName(ND); else mangleNestedName(ND, DC, true /*NoFunction*/); - unsigned disc; - if (Context.getNextDiscriminator(RD, disc)) { - if (disc < 10) - Out << '_' << disc; - else - Out << "__" << disc << '_'; + if (!SkipDiscriminator) { + unsigned disc; + if (Context.getNextDiscriminator(RD, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } } - + return; } else @@ -1282,6 +1312,31 @@ mangleUnqualifiedName(ND); } +void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { + // FIXME: Figure out if we're in a function body, default argument, + // or initializer for a class member. + + Out << "Ul"; + DeclarationName Name + = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + const FunctionProtoType *Proto + = cast(*Lambda->lookup(Name).first)->getType()-> + getAs(); + mangleBareFunctionType(Proto, /*MangleReturnType=*/false); + Out << "E"; + + // The number is omitted for the first closure type with a given + // in a given context; it is n-2 for the nth closure type + // (in lexical order) with that same and context. + // + // The AST keeps track of the number for us. + if (unsigned Number = Lambda->getLambdaManglingNumber()) { + if (Number > 1) + mangleNumber(Number - 2); + } + Out << '_'; +} + void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { switch (qualifier->getKind()) { case NestedNameSpecifier::Global: @@ -1322,13 +1377,13 @@ // ::= while (isa(DC)) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit()) return; if (const BlockDecl *Block = dyn_cast(DC)) { - manglePrefix(DC->getParent(), NoFunction); + manglePrefix(getEffectiveParentContext(DC), NoFunction); SmallString<64> Name; llvm::raw_svector_ostream NameStream(Name); Context.mangleBlock(Block, NameStream); @@ -1352,7 +1407,7 @@ else if (const ObjCMethodDecl *Method = dyn_cast(DC)) mangleObjCMethodName(Method); else { - manglePrefix(DC->getParent(), NoFunction); + manglePrefix(getEffectiveParentContext(DC), NoFunction); mangleUnqualifiedName(cast(DC)); } @@ -1399,7 +1454,7 @@ return; } - manglePrefix(ND->getDeclContext()); + manglePrefix(getEffectiveDeclContext(ND)); mangleUnqualifiedName(ND->getTemplatedDecl()); addSubstitution(ND); } @@ -3159,7 +3214,7 @@ if (!SD) return false; - if (!isStdNamespace(SD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(SD))) return false; const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); @@ -3201,7 +3256,7 @@ } if (const ClassTemplateDecl *TD = dyn_cast(ND)) { - if (!isStdNamespace(TD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(TD))) return false; // ::= Sa # ::std::allocator @@ -3219,7 +3274,7 @@ if (const ClassTemplateSpecializationDecl *SD = dyn_cast(ND)) { - if (!isStdNamespace(SD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(SD))) return false; // ::= Ss # ::std::basic_string ManglingNumber, + Decl *ContextDecl, bool IsInstantiation) { // Leave the expression-evaluation context. DiscardCleanupsInEvaluationContext(); @@ -638,8 +639,34 @@ // If we don't already have a mangling number for this lambda expression, // allocate one now. if (!ManglingNumber) { - // FIXME: Default arguments, data member initializers are special. - ManglingNumber = Context.getLambdaManglingNumber(CallOperator); + ContextDecl = ExprEvalContexts.back().LambdaContextDecl; + + // FIXME: Data member initializers. + enum ContextKind { + Normal, + DefaultArgument + } Kind = Normal; + + // Default arguments of member function parameters that appear in a class + // definition receive special treatment. Identify them. + if (ParmVarDecl *Param = dyn_cast_or_null(ContextDecl)) { + if (const DeclContext *LexicalDC + = Param->getDeclContext()->getLexicalParent()) + if (LexicalDC->isRecord()) + Kind = DefaultArgument; + } + + switch (Kind) { + case Normal: + ManglingNumber = Context.getLambdaManglingNumber(CallOperator); + ContextDecl = 0; + break; + + case DefaultArgument: + ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() + .getManglingNumber(CallOperator); + break; + } } LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, @@ -647,7 +674,7 @@ ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, Body->getLocEnd(), - *ManglingNumber); + *ManglingNumber, ContextDecl); // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Feb 20 18:37:24 2012 @@ -7768,10 +7768,14 @@ /*IsInstantiation=*/true); return ExprError(); } - + + // Note: Once a lambda mangling number and context declaration have been + // assigned, they never change. unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber(); + Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl(); return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), /*CurScope=*/0, ManglingNumber, + ContextDecl, /*IsInstantiation=*/true); } Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Feb 20 18:37:24 2012 @@ -1110,6 +1110,7 @@ Lambda.NumCaptures = Record[Idx++]; Lambda.NumExplicitCaptures = Record[Idx++]; Lambda.ManglingNumber = Record[Idx++]; + Lambda.ContextDecl = ReadDecl(Record, Idx); Lambda.Captures = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); Capture *ToCapture = Lambda.Captures; Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Feb 20 18:37:24 2012 @@ -4333,6 +4333,7 @@ Record.push_back(Lambda.NumCaptures); Record.push_back(Lambda.NumExplicitCaptures); Record.push_back(Lambda.ManglingNumber); + AddDeclRef(Lambda.ContextDecl, Record); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { LambdaExpr::Capture &Capture = Lambda.Captures[I]; AddSourceLocation(Capture.getLocation(), Record); Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=151011&r1=151010&r2=151011&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original) +++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Mon Feb 20 18:37:24 2012 @@ -14,9 +14,64 @@ // CHECK: call i32 @_ZZ11inline_funciENKUliE_clEi int l = [=] (int x) -> int { return x + i; }(n); - // CHECK: ret void + int inner(int i = []{ return 1; }()); + // CHECK: call i32 @_ZZ11inline_funciENKUlvE2_clEv + // CHECK-NEXT: call i32 @_Z5inneri + inner(); + + // CHECK-NEXT: ret void } void call_inline_func() { inline_func(17); } + +struct S { + void f(int = []{return 1;}() + + []{return 2;}(), + int = []{return 3;}()); + void g(int, int); +}; + +void S::g(int i = []{return 1;}(), + int j = []{return 2; }()) {} + +// CHECK: define void @_Z6test_S1S +void test_S(S s) { + // CHECK: call i32 @_ZZN1S1fEiiEd0_NKUlvE_clEv + // CHECK-NEXT: call i32 @_ZZN1S1fEiiEd0_NKUlvE0_clEv + // CHECK-NEXT: add nsw i32 + // CHECK-NEXT: call i32 @_ZZN1S1fEiiEd_NKUlvE_clEv + // CHECK-NEXT: call void @_ZN1S1fEii + s.f(); + + // NOTE: These manglings don't actually matter that much, because + // the lambdas in the default arguments of g() won't be seen by + // multiple translation units. We check them mainly to ensure that they don't + // get the special mangling for lambdas in in-class default arguments. + // CHECK: call i32 @_ZNK1SUlvE_clEv + // CHECK-NEXT: call i32 @_ZNK1SUlvE0_clEv + // CHECK-NEXT: call void @_ZN1S1gEi + s.g(); + + // CHECK-NEXT: ret void +} + +template +struct ST { + void f(T = []{return T() + 1;}() + + []{return T() + 2;}(), + T = []{return T(3);}()); +}; + +// CHECK: define void @_Z7test_ST2STIdE +void test_ST(ST st) { + // CHECK: call double @_ZZN2ST1fET_S0_Ed0_NKUlvE_clEv + // CHECK-NEXT: call double @_ZZN2ST1fET_S0_Ed0_NKUlvE0_clEv + // CHECK-NEXT: fadd double + // CHECK-NEXT: call double @_ZZN2ST1fET_S0_Ed_NKUlvE_clEv + // CHECK-NEXT: call void @_ZN2STIdE1fEdd + st.f(); + + // CHECK-NEXT: ret void +} From echristo at apple.com Mon Feb 20 16:45:44 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 16:45:44 -0800 Subject: [cfe-commits] [PATCH] Getting the driver to understand -working-directory In-Reply-To: References: <1E506119-68BE-4AF7-8ECE-AC802108D81C@apple.com> Message-ID: <88762404-109B-4332-B69A-C8269BA8C693@apple.com> On Feb 20, 2012, at 3:33 PM, Aaron Ballman wrote: >>>> Also, testcase? :) >>> >>> I'll add one this evening if I can think of a way to do it sensibly. >> >> Sounds good to me. > > Since -working-directory expects an absolute path, I'm hard-pressed to > think of a reasonable way to implement a test case for this that would > work across all platforms. > > I could make working-directory support relative paths as well, but it > seems like overkill just so we can have a test case. > > Thoughts or suggestions? Or should I just skip the test case? Oh I was just thinking of something simple like using -cc-print-options to make sure it's being passed down. Nothing complicated. -eric From kremenek at apple.com Mon Feb 20 16:46:29 2012 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 21 Feb 2012 00:46:29 -0000 Subject: [cfe-commits] r151012 - in /cfe/trunk: lib/StaticAnalyzer/Core/Environment.cpp lib/StaticAnalyzer/Core/ProgramState.cpp test/Analysis/misc-ps.c Message-ID: <20120221004629.C247B2A6C12F@llvm.org> Author: kremenek Date: Mon Feb 20 18:46:29 2012 New Revision: 151012 URL: http://llvm.org/viewvc/llvm-project?rev=151012&view=rev Log: Have ScanReachableSymbols reported reachable regions. Fixes a false positive with nested array literals. Modified: cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp cfe/trunk/test/Analysis/misc-ps.c Modified: cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp?rev=151012&r1=151011&r2=151012&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp Mon Feb 20 18:46:29 2012 @@ -139,7 +139,14 @@ SymbolReaper &SymReaper; public: MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} - bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; } + bool VisitSymbol(SymbolRef sym) { + SymReaper.markLive(sym); + return true; + } + bool VisitMemRegion(const MemRegion *R) { + SymReaper.markLive(R); + return true; + } }; } // end anonymous namespace Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=151012&r1=151011&r2=151012&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Mon Feb 20 18:46:29 2012 @@ -553,6 +553,10 @@ if (isVisited) return true; isVisited = 1; + + + if (!visitor.VisitMemRegion(R)) + return false; // If this is a symbolic region, visit the symbol for the region. if (const SymbolicRegion *SR = dyn_cast(R)) Modified: cfe/trunk/test/Analysis/misc-ps.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.c?rev=151012&r1=151011&r2=151012&view=diff ============================================================================== --- cfe/trunk/test/Analysis/misc-ps.c (original) +++ cfe/trunk/test/Analysis/misc-ps.c Mon Feb 20 18:46:29 2012 @@ -111,3 +111,18 @@ void RDar10385775(struct rdar10385775* p) { p->name = L"a"; } + +// Test double loop of array and array literals. Previously this +// resulted in a false positive uninitailized value warning. +void rdar10686586() { + int array1[] = { 1, 2, 3, 0 }; + int array2[] = { 1, 2, 3, 0 }; + int *array[] = { array1, array2 }; + int sum = 0; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 4; j++) { + sum += array[i][j]; // no-warning + } + } +} + From aaron at aaronballman.com Mon Feb 20 16:56:50 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Tue, 21 Feb 2012 00:56:50 -0000 Subject: [cfe-commits] r151014 - /cfe/trunk/test/Driver/working-directory.c Message-ID: <20120221005650.684FD2A6C12F@llvm.org> Author: aaronballman Date: Mon Feb 20 18:56:50 2012 New Revision: 151014 URL: http://llvm.org/viewvc/llvm-project?rev=151014&view=rev Log: Adding a test case for the working-directory fix Added: cfe/trunk/test/Driver/working-directory.c (with props) Added: cfe/trunk/test/Driver/working-directory.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/working-directory.c?rev=151014&view=auto ============================================================================== --- cfe/trunk/test/Driver/working-directory.c (added) +++ cfe/trunk/test/Driver/working-directory.c Mon Feb 20 18:56:50 2012 @@ -0,0 +1,4 @@ +// RUN: %clang -ccc-print-options -working-directory "C:\Test" input 2>&1 | FileCheck %s +// CHECK: Option 0 - Name: "-ccc-print-options", Values: {} +// CHECK: Option 1 - Name: "-working-directory", Values: {"C:\Test"} +// CHECK: Option 2 - Name: "", Values: {"input"} Propchange: cfe/trunk/test/Driver/working-directory.c ------------------------------------------------------------------------------ svn:eol-style = native From aaron at aaronballman.com Mon Feb 20 17:01:40 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 20 Feb 2012 19:01:40 -0600 Subject: [cfe-commits] [PATCH] Getting the driver to understand -working-directory In-Reply-To: <88762404-109B-4332-B69A-C8269BA8C693@apple.com> References: <1E506119-68BE-4AF7-8ECE-AC802108D81C@apple.com> <88762404-109B-4332-B69A-C8269BA8C693@apple.com> Message-ID: On Mon, Feb 20, 2012 at 6:45 PM, Eric Christopher wrote: > > On Feb 20, 2012, at 3:33 PM, Aaron Ballman wrote: > >>>>> Also, testcase? :) >>>> >>>> I'll add one this evening if I can think of a way to do it sensibly. >>> >>> Sounds good to me. >> >> Since -working-directory expects an absolute path, I'm hard-pressed to >> think of a reasonable way to implement a test case for this that would >> work across all platforms. >> >> I could make working-directory support relative paths as well, but it >> seems like overkill just so we can have a test case. >> >> Thoughts or suggestions?  Or should I just skip the test case? > > Oh I was just thinking of something simple like using -cc-print-options to make sure it's being passed down. Nothing complicated. LoL, well I like "not complicated!" ;-) r151014 ~Aaron From dgregor at apple.com Mon Feb 20 18:22:08 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 21 Feb 2012 02:22:08 -0000 Subject: [cfe-commits] r151017 - in /cfe/trunk: include/clang/Parse/Parser.h lib/AST/ItaniumMangle.cpp lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLambda.cpp test/CodeGenCXX/mangle-lambdas.cpp Message-ID: <20120221022208.3AC602A6C12F@llvm.org> Author: dgregor Date: Mon Feb 20 20:22:07 2012 New Revision: 151017 URL: http://llvm.org/viewvc/llvm-project?rev=151017&view=rev Log: Implement name mangling for lambda expressions that occur within the initializers of data members (both static and non-static). Modified: cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=151017&r1=151016&r2=151017&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Mon Feb 20 20:22:07 2012 @@ -2063,7 +2063,7 @@ bool SuppressDeclarations = false); void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, Decl *TagDecl); - ExprResult ParseCXXMemberInitializer(bool IsFunction, + ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc); void ParseCXXClassMemberDeclaration(AccessSpecifier AS, AttributeList *Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=151017&r1=151016&r2=151017&view=diff ============================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Feb 20 20:22:07 2012 @@ -1313,9 +1313,26 @@ } void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { - // FIXME: Figure out if we're in a function body, default argument, - // or initializer for a class member. - + // If the context of a closure type is an initializer for a class member + // (static or nonstatic), it is encoded in a qualified name with a final + // of the form: + // + // := M + // + // Technically, the data-member-prefix is part of the . However, + // since a closure type will always be mangled with a prefix, it's easier + // to emit that last part of the prefix here. + if (Decl *Context = Lambda->getLambdaContextDecl()) { + if ((isa(Context) || isa(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast(Context)->getIdentifier()) { + mangleSourceName(Name); + Out << 'M'; + } + } + } + Out << "Ul"; DeclarationName Name = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); @@ -1392,26 +1409,27 @@ return; } - if (mangleSubstitution(cast(DC))) + const NamedDecl *ND = cast(DC); + if (mangleSubstitution(ND)) return; - + // Check if we have a template. const TemplateArgumentList *TemplateArgs = 0; - if (const TemplateDecl *TD = isTemplate(cast(DC), TemplateArgs)) { + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); mangleTemplateArgs(*TemplateParameters, *TemplateArgs); } - else if(NoFunction && (isa(DC) || isa(DC))) + else if(NoFunction && (isa(ND) || isa(ND))) return; - else if (const ObjCMethodDecl *Method = dyn_cast(DC)) + else if (const ObjCMethodDecl *Method = dyn_cast(ND)) mangleObjCMethodName(Method); else { - manglePrefix(getEffectiveParentContext(DC), NoFunction); - mangleUnqualifiedName(cast(DC)); + manglePrefix(getEffectiveDeclContext(ND), NoFunction); + mangleUnqualifiedName(ND); } - addSubstitution(cast(DC)); + addSubstitution(ND); } void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=151017&r1=151016&r2=151017&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original) +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Mon Feb 20 20:22:07 2012 @@ -478,7 +478,8 @@ ConsumeAnyToken(); SourceLocation EqualLoc; - ExprResult Init = ParseCXXMemberInitializer(/*IsFunction=*/false, EqualLoc); + ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false, + EqualLoc); Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release()); Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=151017&r1=151016&r2=151017&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Feb 20 20:22:07 2012 @@ -2000,7 +2000,7 @@ } else if (HasInitializer) { // Normal initializer. if (!Init.isUsable()) - Init = ParseCXXMemberInitializer( + Init = ParseCXXMemberInitializer(ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); if (Init.isInvalid()) @@ -2096,11 +2096,14 @@ /// /// Prior to C++0x, the assignment-expression in an initializer-clause must /// be a constant-expression. -ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction, +ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc) { assert((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && "Data member initializer not starting with '=' or '{'"); + EnterExpressionEvaluationContext Context(Actions, + Sema::PotentiallyEvaluated, + D); if (Tok.is(tok::equal)) { EqualLoc = ConsumeToken(); if (Tok.is(tok::kw_delete)) { Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=151017&r1=151016&r2=151017&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Feb 20 20:22:07 2012 @@ -10394,6 +10394,14 @@ return true; } +/// \brief Determine whether the given declaration is a static data member. +static bool isStaticDataMember(Decl *D) { + VarDecl *Var = dyn_cast_or_null(D); + if (!Var) + return false; + + return Var->isStaticDataMember(); +} /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse /// an initializer for the out-of-line declaration 'Dcl'. The scope /// is a fresh scope pushed for just this purpose. @@ -10409,6 +10417,12 @@ // int foo::bar; assert(D->isOutOfLine()); EnterDeclaratorContext(S, D->getDeclContext()); + + // If we are parsing the initializer for a static data member, push a + // new expression evaluation context that is associated with this static + // data member. + if (isStaticDataMember(D)) + PushExpressionEvaluationContext(PotentiallyEvaluated, D); } /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an @@ -10417,6 +10431,9 @@ // If there is no declaration, there was an error parsing it. if (D == 0 || D->isInvalidDecl()) return; + if (isStaticDataMember(D)) + PopExpressionEvaluationContext(); + assert(D->isOutOfLine()); ExitDeclaratorContext(S); } Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151017&r1=151016&r2=151017&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 20 20:22:07 2012 @@ -641,20 +641,28 @@ if (!ManglingNumber) { ContextDecl = ExprEvalContexts.back().LambdaContextDecl; - // FIXME: Data member initializers. enum ContextKind { Normal, - DefaultArgument + DefaultArgument, + DataMember } Kind = Normal; // Default arguments of member function parameters that appear in a class - // definition receive special treatment. Identify them. - if (ParmVarDecl *Param = dyn_cast_or_null(ContextDecl)) { - if (const DeclContext *LexicalDC - = Param->getDeclContext()->getLexicalParent()) - if (LexicalDC->isRecord()) - Kind = DefaultArgument; - } + // definition, as well as the initializers of data members, receive special + // treatment. Identify them. + if (ContextDecl) { + if (ParmVarDecl *Param = dyn_cast(ContextDecl)) { + if (const DeclContext *LexicalDC + = Param->getDeclContext()->getLexicalParent()) + if (LexicalDC->isRecord()) + Kind = DefaultArgument; + } else if (VarDecl *Var = dyn_cast(ContextDecl)) { + if (Var->getDeclContext()->isRecord()) + Kind = DataMember; + } else if (isa(ContextDecl)) { + Kind = DataMember; + } + } switch (Kind) { case Normal: @@ -663,6 +671,7 @@ break; case DefaultArgument: + case DataMember: ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() .getManglingNumber(CallOperator); break; Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=151017&r1=151016&r2=151017&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original) +++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Mon Feb 20 20:22:07 2012 @@ -75,3 +75,50 @@ // CHECK-NEXT: ret void } + +template +struct StaticMembers { + static T x; + static T y; + static T z; +}; + +template int accept_lambda(T); + +template +T StaticMembers::x = []{return 1;}() + []{return 2;}(); + +template +T StaticMembers::y = []{return 3;}(); + +template +T StaticMembers::z = accept_lambda([]{return 4;}); + +// CHECK: define internal void @__cxx_global_var_init() +// CHECK: call i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv +// CHECK-NEXT: call i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv +// CHECK-NEXT: add nsw +template float StaticMembers::x; + +// CHECK: define internal void @__cxx_global_var_init1() +// CHECK: call i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv +template float StaticMembers::y; + +// CHECK: define internal void @__cxx_global_var_init2() +// CHECK: call i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_ +template float StaticMembers::z; + +struct Members { + int x = [] { return 1; }() + [] { return 2; }(); + int y = [] { return 3; }(); +}; + +void test_Members() { + // CHECK: define linkonce_odr void @_ZN7MembersC2Ev + // CHECK: call i32 @_ZNK7Members1xMUlvE_clEv + // CHECK-NEXT: call i32 @_ZNK7Members1xMUlvE0_clE + // CHECK-NEXT: add nsw i32 + // CHECK: call i32 @_ZNK7Members1yMUlvE_clEv + Members members; + // CHECK: ret void +} From gregory.szorc at gmail.com Mon Feb 20 19:31:27 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Mon, 20 Feb 2012 19:31:27 -0800 Subject: [cfe-commits] [PATCH] [clang.py] TranslationUnit API improvements Message-ID: * Index.parse() and Index.read() now raise a TanslationUnitLoadException instead of returning None if a TranslationUnit could not be instantiated. This is backwards incompatible. * Ability to save TranslationUnits via TranslationUnit.save(). * TranslationUnit now holds onto Index instance that created. This means the Index can't be GC'd until the TranslationUnit is itself GC'd, making memory management thoughtless. * Richer TranslationUnit.__init__ support. e.g. can now create a TranslationUnit without explicitly creating an Index. * Implemented Index.read() through TranslationUnit.__init__ and documented API as deprecated. * Don't use [] as a default argument value, as the initial value used is reused for the duration of the program. --- bindings/python/clang/cindex.py | 193 +++++++++++++++++--- .../python/tests/cindex/test_translation_unit.py | 75 ++++++++- bindings/python/tests/cindex/util.py | 4 +- 3 files changed, 246 insertions(+), 26 deletions(-) ------ I realize this patch may be a little big. I tried keeping it split locally, but management of all the patches was getting to be quite cumbersome. I gave up. I apologize for my laziness. The most controversial part of this patch will be the backwards-incompatible change to Index.parse() and Index.read(), which now raise an exception instead of returning None. I feel the API is more pleasant because (and I have no empirical evidence to back this up) that the overwhelming majority of consumers assume a TU will be properly created when they try to create one. These consumers are currently penalized because [good programmers] will add the necessary "if tu is not None" check every time they try to obtain a TU. This patch does away with that penalty. Of course, the exception may still be handled explicitly if so chosen and this will result in roughly the same number of lines for error checking. But, I have a hunch most consumers won't want to deal with it and will have the exception bubble up. I held off adding exception throwing to TranslationUnit.reparse(). I can certainly add that if we want things to be consistent everywhere. Or, I can revert the exception throwing altogether. Or, maybe I could make the new TranslationUnit.__init__ raise and have the old Index APIs swallow the exception and keep returning None. Choices. I'd eventually like to roll Index.parse's main implementation into TranslationUnit.__init__, effectively deprecating Index.parse. I've already done this with Index.read() because it was trivial. I held off because I wanted to get blessing first. In the long term I'd like to move away from APIs on Index and towards the use of constructors on other objects. If Index had more direct APIs, I could be convinced otherwise. But, as it stands, it just feels that Index is unnecessary baggage in Python land. If we can make its existence invisible, I think that's a net win. This is why I've marked Index.read() as deprecated. I can certainly remove that comment if people don't agree with me. -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-clang.py-TranslationUnit-API-improvements.patch Type: text/x-patch Size: 17657 bytes Desc: not available URL: From nicolasweber at gmx.de Mon Feb 20 19:52:06 2012 From: nicolasweber at gmx.de (Nico Weber) Date: Tue, 21 Feb 2012 03:52:06 -0000 Subject: [cfe-commits] r151027 - /cfe/trunk/test/CodeGenObjCXX/debug-info.mm Message-ID: <20120221035206.287372A6C12F@llvm.org> Author: nico Date: Mon Feb 20 21:52:05 2012 New Revision: 151027 URL: http://llvm.org/viewvc/llvm-project?rev=151027&view=rev Log: Add a test case for r150976. Added: cfe/trunk/test/CodeGenObjCXX/debug-info.mm (with props) Added: cfe/trunk/test/CodeGenObjCXX/debug-info.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/debug-info.mm?rev=151027&view=auto ============================================================================== --- cfe/trunk/test/CodeGenObjCXX/debug-info.mm (added) +++ cfe/trunk/test/CodeGenObjCXX/debug-info.mm Mon Feb 20 21:52:05 2012 @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-obj %s + +// This test passes if clang doesn't crash. + +template class scoped_ptr { +public: + C* operator->() const { return 0; } +}; + + at class NSWindow; + at class NSImage; + at interface NSWindow { + NSImage *_miniIcon; +} +-(id)windowController; + at end + +class AutomationResourceTracker { +public: + NSWindow* GetResource(int handle) { return 0; } +}; + +# 13 "automation/automation_window_tracker.h" +class AutomationWindowTracker : public AutomationResourceTracker { }; + +template class scoped_nsobject { }; + + at interface TabStripController{ + scoped_nsobject defaultFavicon_; +} + at end + + at interface BrowserWindowController { + TabStripController* tabStripController_; +} + at end + +void WindowGetViewBounds(scoped_ptr window_tracker_) { + NSWindow* window = window_tracker_->GetResource(42); + BrowserWindowController* controller = [window windowController]; +} Propchange: cfe/trunk/test/CodeGenObjCXX/debug-info.mm ------------------------------------------------------------------------------ svn:eol-style = LF From nicolasweber at gmx.de Mon Feb 20 19:52:52 2012 From: nicolasweber at gmx.de (Nico Weber) Date: Tue, 21 Feb 2012 03:52:52 -0000 Subject: [cfe-commits] r151028 - /cfe/trunk/test/CodeGenObjCXX/debug-info.mm Message-ID: <20120221035252.D4FDC2A6C12F@llvm.org> Author: nico Date: Mon Feb 20 21:52:52 2012 New Revision: 151028 URL: http://llvm.org/viewvc/llvm-project?rev=151028&view=rev Log: Remove svn:eol-style on the test I just added. Modified: cfe/trunk/test/CodeGenObjCXX/debug-info.mm (props changed) Propchange: cfe/trunk/test/CodeGenObjCXX/debug-info.mm ------------------------------------------------------------------------------ --- svn:eol-style (original) +++ svn:eol-style (removed) @@ -1 +0,0 @@ -LF From thakis at chromium.org Mon Feb 20 20:06:40 2012 From: thakis at chromium.org (Nico Weber) Date: Mon, 20 Feb 2012 20:06:40 -0800 Subject: [cfe-commits] r150976 - /cfe/trunk/lib/CodeGen/CGDebugInfo.cpp In-Reply-To: <20120220180504.454872A6C12F@llvm.org> References: <20120220180504.454872A6C12F@llvm.org> Message-ID: Thanks! I added a test for this in r151027. Nico On Mon, Feb 20, 2012 at 10:05 AM, Eric Christopher wrote: > Author: echristo > Date: Mon Feb 20 12:05:04 2012 > New Revision: 150976 > > URL: http://llvm.org/viewvc/llvm-project?rev=150976&view=rev > Log: > Make forward declarations for objective-c types use the new > temporary forward declaration nodes. Fixes a problem building > Chrome. > > 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=150976&r1=150975&r2=150976&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Feb 20 12:05:04 2012 > @@ -336,21 +336,19 @@ >   case BuiltinType::Void: >     return llvm::DIType(); >   case BuiltinType::ObjCClass: > -    return DBuilder.createStructType(TheCU, "objc_class", > -                                     getOrCreateMainFile(), 0, 0, 0, > -                                     llvm::DIDescriptor::FlagFwdDecl, > -                                     llvm::DIArray()); > +    return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, > +                                       "objc_class", getOrCreateMainFile(), > +                                       0); >   case BuiltinType::ObjCId: { >     // typedef struct objc_class *Class; >     // typedef struct objc_object { >     //  Class isa; >     // } *id; > > -    llvm::DIType OCTy = > -      DBuilder.createStructType(TheCU, "objc_class", > -                                getOrCreateMainFile(), 0, 0, 0, > -                                llvm::DIDescriptor::FlagFwdDecl, > -                                llvm::DIArray()); > +    llvm::DIType OCTy = > +      DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, > +                                  "objc_class", getOrCreateMainFile(), > +                                  0); >     unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); > >     llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size); > @@ -368,10 +366,10 @@ >                                      0, 0, 0, 0, Elements); >   } >   case BuiltinType::ObjCSel: { > -    return  DBuilder.createStructType(TheCU, "objc_selector", > -                                      getOrCreateMainFile(), 0, 0, 0, > -                                      llvm::DIDescriptor::FlagFwdDecl, > -                                      llvm::DIArray()); > +    return > +      DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, > +                                  "objc_selector", getOrCreateMainFile(), > +                                  0); >   } >   case BuiltinType::UChar: >   case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; > @@ -1224,10 +1222,9 @@ >   ObjCInterfaceDecl *Def = ID->getDefinition(); >   if (!Def) { >     llvm::DIType FwdDecl = > -      DBuilder.createStructType(Unit, ID->getName(), > -                                DefUnit, Line, 0, 0, > -                                llvm::DIDescriptor::FlagFwdDecl, > -                                llvm::DIArray(), RuntimeLang); > +      DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, > +                                ID->getName(), DefUnit, Line, > +                                RuntimeLang); >     return FwdDecl; >   } >   ID = Def; > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From dgregor at apple.com Mon Feb 20 20:17:39 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 21 Feb 2012 04:17:39 -0000 Subject: [cfe-commits] r151029 - in /cfe/trunk: lib/AST/Decl.cpp lib/AST/ExprCXX.cpp lib/AST/ItaniumMangle.cpp lib/Sema/SemaLambda.cpp test/CodeGenCXX/lambda-expressions.cpp test/CodeGenCXX/mangle-lambdas.cpp Message-ID: <20120221041739.5B99C2A6C12F@llvm.org> Author: dgregor Date: Mon Feb 20 22:17:39 2012 New Revision: 151029 URL: http://llvm.org/viewvc/llvm-project?rev=151029&view=rev Log: Implement non-internal linkage for lambda closure types that need a stable mangling, since these lambdas can end up in multiple translation units. Sema is responsible for deciding when this is the case, because it's already responsible for choosing the mangling number. Modified: cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/AST/ExprCXX.cpp cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=151029&r1=151028&r2=151029&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Mon Feb 20 22:17:39 2012 @@ -734,6 +734,32 @@ case Decl::ObjCPropertyImpl: case Decl::ObjCProtocol: return LinkageInfo::external(); + + case Decl::CXXRecord: { + const CXXRecordDecl *Record = cast(D); + if (Record->isLambda()) { + if (!Record->getLambdaManglingNumber()) { + // This lambda has no mangling number, so it's internal. + return LinkageInfo::internal(); + } + + // This lambda has its linkage/visibility determined by its owner. + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + if (Decl *ContextDecl = Record->getLambdaContextDecl()) { + if (isa(ContextDecl)) + DC = ContextDecl->getDeclContext()->getRedeclContext(); + else + return getLVForDecl(cast(ContextDecl), Flags); + } + + if (const NamedDecl *ND = dyn_cast(DC)) + return getLVForDecl(ND, Flags); + + return LinkageInfo::external(); + } + + break; + } } // Handle linkage for namespace-scope names. Modified: cfe/trunk/lib/AST/ExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=151029&r1=151028&r2=151029&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprCXX.cpp (original) +++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Feb 20 22:17:39 2012 @@ -815,7 +815,10 @@ memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), sizeof(unsigned) * Captures.size()); getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size(); - } + } + + if (ManglingNumber) + Class->ClearLinkageCache(); } LambdaExpr *LambdaExpr::Create(ASTContext &Context, Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=151029&r1=151028&r2=151029&view=diff ============================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Feb 20 22:17:39 2012 @@ -52,7 +52,7 @@ if (const CXXRecordDecl *RD = dyn_cast(D)) { if (RD->isLambda()) if (ParmVarDecl *ContextParam - = dyn_cast_or_null(RD->getLambdaContextDecl())) + = dyn_cast_or_null(RD->getLambdaContextDecl())) return ContextParam->getDeclContext(); } @@ -1114,7 +1114,7 @@ // ::= Ul E [ ] _ // ::= + # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast(TD)) { - if (Record->isLambda()) { + if (Record->isLambda() && Record->getLambdaManglingNumber()) { mangleLambda(Record); break; } @@ -1347,10 +1347,10 @@ // (in lexical order) with that same and context. // // The AST keeps track of the number for us. - if (unsigned Number = Lambda->getLambdaManglingNumber()) { - if (Number > 1) - mangleNumber(Number - 2); - } + unsigned Number = Lambda->getLambdaManglingNumber(); + assert(Number > 0 && "Lambda should be mangled as an unnamed class"); + if (Number > 1) + mangleNumber(Number - 2); Out << '_'; } Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151029&r1=151028&r2=151029&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 20 22:17:39 2012 @@ -13,6 +13,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Lex/Preprocessor.h" @@ -482,6 +483,20 @@ Class->addDecl(Conversion); } +/// \brief Determine whether the given context is or is enclosed in an inline +/// function. +static bool isInInlineFunction(const DeclContext *DC) { + while (!DC->isFileContext()) { + if (const FunctionDecl *FD = dyn_cast(DC)) + if (FD->isInlined()) + return true; + + DC = DC->getLexicalParent(); + } + + return false; +} + ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope, llvm::Optional ManglingNumber, @@ -644,7 +659,8 @@ enum ContextKind { Normal, DefaultArgument, - DataMember + DataMember, + StaticDataMember, } Kind = Normal; // Default arguments of member function parameters that appear in a class @@ -658,7 +674,7 @@ Kind = DefaultArgument; } else if (VarDecl *Var = dyn_cast(ContextDecl)) { if (Var->getDeclContext()->isRecord()) - Kind = DataMember; + Kind = StaticDataMember; } else if (isa(ContextDecl)) { Kind = DataMember; } @@ -666,12 +682,25 @@ switch (Kind) { case Normal: - ManglingNumber = Context.getLambdaManglingNumber(CallOperator); - ContextDecl = 0; + if (CurContext->isDependentContext() || isInInlineFunction(CurContext)) + ManglingNumber = Context.getLambdaManglingNumber(CallOperator); + else + ManglingNumber = 0; + + // There is no special context for this lambda. + ContextDecl = 0; break; - case DefaultArgument: + case StaticDataMember: + if (!CurContext->isDependentContext()) { + ManglingNumber = 0; + ContextDecl = 0; + break; + } + // Fall through to assign a mangling number. + case DataMember: + case DefaultArgument: ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() .getManglingNumber(CallOperator); break; Modified: cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp?rev=151029&r1=151028&r2=151029&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Mon Feb 20 22:17:39 2012 @@ -8,8 +8,8 @@ int a() { return []{ return 1; }(); } // CHECK: define i32 @_Z1av -// CHECK: call i32 @_ZZ1avENKUlvE_clEv -// CHECK: define internal i32 @_ZZ1avENKUlvE_clEv +// CHECK: call i32 @"_ZZ1avENK3$_0clEv" +// CHECK: define internal i32 @"_ZZ1avENK3$_0clEv" // CHECK: ret i32 1 int b(int x) { return [x]{return x;}(); } @@ -17,8 +17,8 @@ // CHECK: store i32 // CHECK: load i32* // CHECK: store i32 -// CHECK: call i32 @_ZZ1biENKUlvE_clEv -// CHECK: define internal i32 @_ZZ1biENKUlvE_clEv +// CHECK: call i32 @"_ZZ1biENK3$_1clEv" +// CHECK: define internal i32 @"_ZZ1biENK3$_1clEv" // CHECK: load i32* // CHECK: ret i32 @@ -26,8 +26,8 @@ // CHECK: define i32 @_Z1ci // CHECK: store i32 // CHECK: store i32* -// CHECK: call i32 @_ZZ1ciENKUlvE_clEv -// CHECK: define internal i32 @_ZZ1ciENKUlvE_clEv +// CHECK: call i32 @"_ZZ1ciENK3$_2clEv" +// CHECK: define internal i32 @"_ZZ1ciENK3$_2clEv" // CHECK: load i32** // CHECK: load i32* // CHECK: ret i32 @@ -39,8 +39,8 @@ // CHECK: call void @_ZN1DC1Ev // CHECK: icmp ult i64 %{{.*}}, 10 // CHECK: call void @_ZN1DC1ERKS_ -// CHECK: call i32 @_ZZ1diENKUlvE_clEv -// CHECK: define internal i32 @_ZZ1diENKUlvE_clEv +// CHECK: call i32 @"_ZZ1diENK3$_3clEv" +// CHECK: define internal i32 @"_ZZ1diENK3$_3clEv" // CHECK: load i32* // CHECK: load i32* // CHECK: ret i32 @@ -50,29 +50,29 @@ // CHECK: define i32 @_Z1e1ES_b // CHECK: call void @_ZN1EC1ERKS_ // CHECK: invoke void @_ZN1EC1ERKS_ -// CHECK: invoke i32 @_ZZ1e1ES_bENKUlvE_clEv -// CHECK: call void @_ZZ1e1ES_bENUlvE_D1Ev -// CHECK: call void @_ZZ1e1ES_bENUlvE_D1Ev +// CHECK: invoke i32 @"_ZZ1e1ES_bENK3$_4clEv" +// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev" +// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev" -// CHECK: define internal i32 @_ZZ1e1ES_bENKUlvE_clEv +// CHECK: define internal i32 @"_ZZ1e1ES_bENK3$_4clEv" // CHECK: trunc i8 // CHECK: load i32* // CHECK: ret i32 void f() { // CHECK: define void @_Z1fv() - // CHECK: {{call.*@_ZZ1fvENKUliiE_cvPFiiiEEv}} + // CHECK: @"_ZZ1fvENK3$_5cvPFiiiEEv" // CHECK-NEXT: store i32 (i32, i32)* // CHECK-NEXT: ret void int (*fp)(int, int) = [](int x, int y){ return x + y; }; } -// CHECK: define internal i32 @_ZZ1fvENUliiE_8__invokeEii +// CHECK: define internal i32 @"_ZZ1fvEN3$_58__invokeEii" // CHECK: store i32 // CHECK-NEXT: store i32 // CHECK-NEXT: load i32* // CHECK-NEXT: load i32* -// CHECK-NEXT: call i32 @_ZZ1fvENKUliiE_clEii +// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_5clEii" // CHECK-NEXT: ret i32 -// CHECK: define internal void @_ZZ1e1ES_bENUlvE_D2Ev +// CHECK: define internal void @"_ZZ1e1ES_bEN3$_4D2Ev" Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=151029&r1=151028&r2=151029&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original) +++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Mon Feb 20 22:17:39 2012 @@ -14,7 +14,7 @@ // CHECK: call i32 @_ZZ11inline_funciENKUliE_clEi int l = [=] (int x) -> int { return x + i; }(n); - int inner(int i = []{ return 1; }()); + int inner(int i = []{ return 17; }()); // CHECK: call i32 @_ZZ11inline_funciENKUlvE2_clEv // CHECK-NEXT: call i32 @_Z5inneri inner(); @@ -49,14 +49,26 @@ // the lambdas in the default arguments of g() won't be seen by // multiple translation units. We check them mainly to ensure that they don't // get the special mangling for lambdas in in-class default arguments. - // CHECK: call i32 @_ZNK1SUlvE_clEv - // CHECK-NEXT: call i32 @_ZNK1SUlvE0_clEv + // CHECK: call i32 @"_ZNK1S3$_0clEv" + // CHECK-NEXT: call i32 @"_ZNK1S3$_1clEv" // CHECK-NEXT: call void @_ZN1S1gEi s.g(); // CHECK-NEXT: ret void } +// Check the linkage of the lambda call operators used in test_S. +// CHECK: define linkonce_odr i32 @_ZZN1S1fEiiEd0_NKUlvE_clEv +// CHECK: ret i32 1 +// CHECK: define linkonce_odr i32 @_ZZN1S1fEiiEd0_NKUlvE0_clEv +// CHECK: ret i32 2 +// CHECK: define linkonce_odr i32 @_ZZN1S1fEiiEd_NKUlvE_clEv +// CHECK: ret i32 3 +// CHECK: define internal i32 @"_ZNK1S3$_0clEv" +// CHECK: ret i32 1 +// CHECK: define internal i32 @"_ZNK1S3$_1clEv" +// CHECK: ret i32 2 + template struct ST { void f(T = []{return T() + 1;}() @@ -76,6 +88,14 @@ // CHECK-NEXT: ret void } +// Check the linkage of the lambda call operators used in test_ST. +// CHECK: define linkonce_odr double @_ZZN2ST1fET_S0_Ed0_NKUlvE_clEv +// CHECK: ret double 1 +// CHECK: define linkonce_odr double @_ZZN2ST1fET_S0_Ed0_NKUlvE0_clEv +// CHECK: ret double 2 +// CHECK: define linkonce_odr double @_ZZN2ST1fET_S0_Ed_NKUlvE_clEv +// CHECK: ret double 3 + template struct StaticMembers { static T x; @@ -98,16 +118,38 @@ // CHECK: call i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv // CHECK-NEXT: call i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv // CHECK-NEXT: add nsw +// CHECK: define linkonce_odr i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv +// CHECK: ret i32 1 +// CHECK: define linkonce_odr i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv +// CHECK: ret i32 2 template float StaticMembers::x; // CHECK: define internal void @__cxx_global_var_init1() // CHECK: call i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv +// CHECK: define linkonce_odr i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv +// CHECK: ret i32 3 template float StaticMembers::y; // CHECK: define internal void @__cxx_global_var_init2() // CHECK: call i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_ +// CHECK: declare i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_() template float StaticMembers::z; +// CHECK: define internal void @__cxx_global_var_init3 +// CHECK: call i32 @"_ZNK13StaticMembersIdE3$_2clEv" +// CHECK: define internal i32 @"_ZNK13StaticMembersIdE3$_2clEv" +// CHECK: ret i32 42 +template<> double StaticMembers::z = []{return 42; }(); + +template +void func_template(T = []{ return T(); }()); + +// CHECK: define void @_Z17use_func_templatev() +void use_func_template() { + // CHECK: call i32 @"_ZZ13func_templateIiEvT_ENKS_IiE3$_3clEv" + func_template(); +} + struct Members { int x = [] { return 1; }() + [] { return 2; }(); int y = [] { return 3; }(); @@ -122,3 +164,23 @@ Members members; // CHECK: ret void } + +// Check the linkage of the lambdas used in test_Members. +// CHECK: define linkonce_odr i32 @_ZNK7Members1xMUlvE_clEv +// CHECK: ret i32 1 +// CHECK: define linkonce_odr i32 @_ZNK7Members1xMUlvE0_clEv +// CHECK: ret i32 2 +// CHECK: define linkonce_odr i32 @_ZNK7Members1yMUlvE_clEv +// CHECK: ret i32 3 + +// Check linkage of the various lambdas. +// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE_clEv +// CHECK: ret i32 1 +// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE0_clEv +// CHECK: ret i32 +// CHECK: define linkonce_odr double @_ZZ11inline_funciENKUlvE1_clEv +// CHECK: ret double +// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUliE_clEi +// CHECK: ret i32 +// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE2_clEv +// CHECK: ret i32 17 From echristo at apple.com Mon Feb 20 20:32:12 2012 From: echristo at apple.com (Eric Christopher) Date: Mon, 20 Feb 2012 20:32:12 -0800 Subject: [cfe-commits] r150976 - /cfe/trunk/lib/CodeGen/CGDebugInfo.cpp In-Reply-To: References: <20120220180504.454872A6C12F@llvm.org> Message-ID: <402957C3-1D66-4452-9737-5E41D416F21F@apple.com> Thank you very much! -eric On Feb 20, 2012, at 8:06 PM, Nico Weber wrote: > Thanks! I added a test for this in r151027. > > Nico > > On Mon, Feb 20, 2012 at 10:05 AM, Eric Christopher wrote: >> Author: echristo >> Date: Mon Feb 20 12:05:04 2012 >> New Revision: 150976 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=150976&view=rev >> Log: >> Make forward declarations for objective-c types use the new >> temporary forward declaration nodes. Fixes a problem building >> Chrome. >> >> 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=150976&r1=150975&r2=150976&view=diff >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Feb 20 12:05:04 2012 >> @@ -336,21 +336,19 @@ >> case BuiltinType::Void: >> return llvm::DIType(); >> case BuiltinType::ObjCClass: >> - return DBuilder.createStructType(TheCU, "objc_class", >> - getOrCreateMainFile(), 0, 0, 0, >> - llvm::DIDescriptor::FlagFwdDecl, >> - llvm::DIArray()); >> + return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, >> + "objc_class", getOrCreateMainFile(), >> + 0); >> case BuiltinType::ObjCId: { >> // typedef struct objc_class *Class; >> // typedef struct objc_object { >> // Class isa; >> // } *id; >> >> - llvm::DIType OCTy = >> - DBuilder.createStructType(TheCU, "objc_class", >> - getOrCreateMainFile(), 0, 0, 0, >> - llvm::DIDescriptor::FlagFwdDecl, >> - llvm::DIArray()); >> + llvm::DIType OCTy = >> + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, >> + "objc_class", getOrCreateMainFile(), >> + 0); >> unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); >> >> llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size); >> @@ -368,10 +366,10 @@ >> 0, 0, 0, 0, Elements); >> } >> case BuiltinType::ObjCSel: { >> - return DBuilder.createStructType(TheCU, "objc_selector", >> - getOrCreateMainFile(), 0, 0, 0, >> - llvm::DIDescriptor::FlagFwdDecl, >> - llvm::DIArray()); >> + return >> + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, >> + "objc_selector", getOrCreateMainFile(), >> + 0); >> } >> case BuiltinType::UChar: >> case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; >> @@ -1224,10 +1222,9 @@ >> ObjCInterfaceDecl *Def = ID->getDefinition(); >> if (!Def) { >> llvm::DIType FwdDecl = >> - DBuilder.createStructType(Unit, ID->getName(), >> - DefUnit, Line, 0, 0, >> - llvm::DIDescriptor::FlagFwdDecl, >> - llvm::DIArray(), RuntimeLang); >> + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, >> + ID->getName(), DefUnit, Line, >> + RuntimeLang); >> return FwdDecl; >> } >> ID = Def; >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From akyrtzi at gmail.com Mon Feb 20 21:04:44 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 21 Feb 2012 05:04:44 -0000 Subject: [cfe-commits] r151033 - in /cfe/trunk/include/clang: AST/DeclBase.h Basic/SourceLocation.h Message-ID: <20120221050444.886792A6C12F@llvm.org> Author: akirtzidis Date: Mon Feb 20 23:04:44 2012 New Revision: 151033 URL: http://llvm.org/viewvc/llvm-project?rev=151033&view=rev Log: Mark a few 'dump' methods as 'used' to make sure they are included in libclang and useable while debugging. Modified: cfe/trunk/include/clang/AST/DeclBase.h cfe/trunk/include/clang/Basic/SourceLocation.h Modified: cfe/trunk/include/clang/AST/DeclBase.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=151033&r1=151032&r2=151033&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclBase.h (original) +++ cfe/trunk/include/clang/AST/DeclBase.h Mon Feb 20 23:04:44 2012 @@ -848,8 +848,8 @@ static void printGroup(Decl** Begin, unsigned NumDecls, raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); - void dump() const; - void dumpXML() const; + LLVM_ATTRIBUTE_USED void dump() const; + LLVM_ATTRIBUTE_USED void dumpXML() const; void dumpXML(raw_ostream &OS) const; private: @@ -1490,7 +1490,7 @@ static bool classof(const NAME##Decl *D) { return true; } #include "clang/AST/DeclNodes.inc" - void dumpDeclContext() const; + LLVM_ATTRIBUTE_USED void dumpDeclContext() const; private: void LoadLexicalDeclsFromExternalStorage() const; Modified: cfe/trunk/include/clang/Basic/SourceLocation.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceLocation.h?rev=151033&r1=151032&r2=151033&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/SourceLocation.h (original) +++ cfe/trunk/include/clang/Basic/SourceLocation.h Mon Feb 20 23:04:44 2012 @@ -16,6 +16,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/Compiler.h" #include #include #include @@ -324,7 +325,7 @@ /// Prints information about this FullSourceLoc to stderr. Useful for /// debugging. - void dump() const { SourceLocation::dump(*SrcMgr); } + LLVM_ATTRIBUTE_USED void dump() const { SourceLocation::dump(*SrcMgr); } friend inline bool operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { From craig.topper at gmail.com Mon Feb 20 21:39:58 2012 From: craig.topper at gmail.com (Craig Topper) Date: Tue, 21 Feb 2012 05:39:58 -0000 Subject: [cfe-commits] r151036 - /cfe/trunk/lib/Sema/SemaLambda.cpp Message-ID: <20120221053958.12A492A6C12F@llvm.org> Author: ctopper Date: Mon Feb 20 23:39:57 2012 New Revision: 151036 URL: http://llvm.org/viewvc/llvm-project?rev=151036&view=rev Log: Remove comma from end of enum to silence build warning. Modified: cfe/trunk/lib/Sema/SemaLambda.cpp Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151036&r1=151035&r2=151036&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 20 23:39:57 2012 @@ -660,7 +660,7 @@ Normal, DefaultArgument, DataMember, - StaticDataMember, + StaticDataMember } Kind = Normal; // Default arguments of member function parameters that appear in a class From akyrtzi at gmail.com Mon Feb 20 22:12:38 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 21 Feb 2012 06:12:38 -0000 Subject: [cfe-commits] r151037 - /cfe/trunk/include/clang/AST/Type.h Message-ID: <20120221061239.0CADE2A6C12F@llvm.org> Author: akirtzidis Date: Tue Feb 21 00:12:38 2012 New Revision: 151037 URL: http://llvm.org/viewvc/llvm-project?rev=151037&view=rev Log: Also mark Type's dump() as 'used' to make it available in libclang. Modified: cfe/trunk/include/clang/AST/Type.h Modified: cfe/trunk/include/clang/AST/Type.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=151037&r1=151036&r2=151037&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Type.h (original) +++ cfe/trunk/include/clang/AST/Type.h Tue Feb 21 00:12:38 2012 @@ -1706,7 +1706,7 @@ return CanonicalType; } CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h - void dump() const; + LLVM_ATTRIBUTE_USED void dump() const; static bool classof(const Type *) { return true; } From hans at chromium.org Tue Feb 21 01:57:23 2012 From: hans at chromium.org (Hans Wennborg) Date: Tue, 21 Feb 2012 09:57:23 +0000 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> <20120220202153.GA20840@britannica.bec.de> Message-ID: On Mon, Feb 20, 2012 at 21:00, Ted Kremenek wrote: > On Feb 20, 2012, at 12:21 PM, Joerg Sonnenberger > wrote: > > There's "non-standard" and then there's completely unportable.  Warnings > like: > > +  // Combining 'L' with an integer conversion specifier. > +  printf("%Li", (long long)42); // expected-warning{{using the length > modifier 'L' with the conversion specifier 'i' is non-standard}} > +  printf("%Lo", (long long)42); // expected-warning{{using the length > modifier 'L' with the conversion specifier 'o' is non-standard}} > [...] > Do we really silently accept them?  Until very recently (a month ago?), we > emitted: > > t.c:4:12: warning: length modifier 'L' results in undefined behavior or no >       effect with 'i' conversion specifier [-Wformat] >   printf("%Li", (long long) 2); >           ~^~ > 1 warning generated. > > > Now I see that TOT doesn't warn here.  Is this accepted somewhere?  I see no > test cases in clang/test that shows we should accept this.  Was this an > intentional change, or a regression? r148859 made them accepted about a month ago. Looks intentional to me :) From hans at chromium.org Tue Feb 21 03:39:37 2012 From: hans at chromium.org (Hans Wennborg) Date: Tue, 21 Feb 2012 11:39:37 +0000 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> Message-ID: On Mon, Feb 20, 2012 at 19:37, Ted Kremenek wrote: > On Feb 20, 2012, at 11:25 AM, Hans Wennborg wrote: >> Keeping -Wformat-nonstandard out of -Wformat and having it in >> -pedantic sounds perfectly fine to me. I expect that lines up with >> what gcc does too. > > Ok, I think that approach is worth experimenting with. Cool. I think getting this warning in under -pedantic is a good step in the right direction. > I've looked at the patch, and other than the default configuration of the > warnings, it looks okay to me. I've updated the patch to make the warning DefaultIgnore and ExtWarn. I've also changed it to not make a difference between -std=c99 and -std=gnu99. If the user specifies -pedantic, I think we should warn for '%ms' even if the user has selected -std=gnu99. This matches gcc behavior too, and it's extra important because if the user doesn't specify the -std flag, then gnu99 seems the be the default c mode. > One nit on wording in the diagnostic: "non-standard" or "non-portable"?  The > former is more technically accurate, but the latter is the implication the > user cares about.  What do you think? I'd prefer "non-standard", but I don't feel strongly about it. I noticed that this sparks new failures in "clang-tests/gcc-4_2-testsuite" (excess warning), so I'm attaching a patch for that too. Please take a look. - Hans -------------- next part -------------- A non-text attachment was scrubbed... Name: clang-testsuite.diff Type: application/octet-stream Size: 745 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: non-standard-format-strings-2.diff Type: application/octet-stream Size: 14061 bytes Desc: not available URL: From tobias at grosser.es Tue Feb 21 06:22:38 2012 From: tobias at grosser.es (Tobias Grosser) Date: Tue, 21 Feb 2012 15:22:38 +0100 Subject: [cfe-commits] r150969 - in /cfe/trunk/bindings/python: clang/cindex.py tests/cindex/test_type.py In-Reply-To: <20120220174449.BBA0B2A6C131@llvm.org> References: <20120220174449.BBA0B2A6C131@llvm.org> Message-ID: <4F43A8AE.5010308@grosser.es> On 02/20/2012 06:44 PM, Gregory Szorc wrote: > Author: gps > Date: Mon Feb 20 11:44:49 2012 > New Revision: 150969 > > URL: http://llvm.org/viewvc/llvm-project?rev=150969&view=rev > Log: > [clang.py] Implement Type.__eq__ and Type.__ne__ Hi Gregory, could you post the svn revision of your commit in a reply to the mail in which you submitted the original patch. With both Manuel and me review the patches, it is difficult to see which patches were not yet reviewed. (In general it is good because it help to understand if a patch review was completed). Thanks Tobi From jyasskin at google.com Tue Feb 21 08:20:13 2012 From: jyasskin at google.com (Jeffrey Yasskin) Date: Tue, 21 Feb 2012 16:20:13 -0000 Subject: [cfe-commits] r151058 - /cfe/trunk/lib/Headers/unwind.h Message-ID: <20120221162013.32EB22A6C12F@llvm.org> Author: jyasskin Date: Tue Feb 21 10:20:12 2012 New Revision: 151058 URL: http://llvm.org/viewvc/llvm-project?rev=151058&view=rev Log: Allow linux builds to take advantage of libunwind to get unwind.h if that's installed. Modified: cfe/trunk/lib/Headers/unwind.h Modified: cfe/trunk/lib/Headers/unwind.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/unwind.h?rev=151058&r1=151057&r2=151058&view=diff ============================================================================== --- cfe/trunk/lib/Headers/unwind.h (original) +++ cfe/trunk/lib/Headers/unwind.h Tue Feb 21 10:20:12 2012 @@ -23,9 +23,19 @@ /* See "Data Definitions for libgcc_s" in the Linux Standard Base.*/ -#if defined(__APPLE__) && __has_include_next() -/* Darwin typically has its own unwind.h; use it. */ -# include_next +#if __has_include_next() +/* Darwin and libunwind provide an unwind.h. If that's available, use + * it. libunwind wraps some of its definitions in #ifdef _GNU_SOURCE, + * so define that around the include.*/ +# ifndef _GNU_SOURCE +# define _SHOULD_UNDEFINE_GNU_SOURCE +# define _GNU_SOURCE +# endif +# include_next +# ifdef _SHOULD_UNDEFINE_GNU_SOURCE +# undef _GNU_SOURCE +# undef _SHOULD_UNDEFINE_GNU_SOURCE +# endif #else #include From gregory.szorc at gmail.com Tue Feb 21 09:22:26 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 21 Feb 2012 09:22:26 -0800 Subject: [cfe-commits] [PATCH 2/5] [clang.py] Implement Type.__eq__ and Type.__ne__ In-Reply-To: References: Message-ID: Author: gps Date: Mon Feb 20 11:44:49 2012 New Revision: 150969 URL: http://llvm.org/viewvc/llvm-project?rev=150969&view=rev Log: [clang.py] Implement Type.__eq__ and Type.__ne__ On Mon, Feb 20, 2012 at 8:28 AM, Manuel Klimek wrote: > Looks good. > > On Sat, Feb 18, 2012 at 8:26 PM, Gregory Szorc > wrote: > > I've made the implementation of Type.__eq__ more robust and added tests. > > > > > > On Fri, Feb 17, 2012 at 1:37 AM, Manuel Klimek > wrote: > >> > >> On Fri, Feb 17, 2012 at 8:56 AM, Gregory Szorc > > >> wrote: > >> > The implementation could probably be a bit more robust (looking for > >> > None, comparing types, etc). Do we care? > >> > >> Regarding looking for None: what happens if one calls t == None on a > >> Type? Perhaps add a test? > >> > >> Cheers, > >> /Manuel > >> > >> > >> > --- > >> > bindings/python/clang/cindex.py | 10 ++++++++++ > >> > bindings/python/tests/cindex/test_type.py | 17 +++++++++++++++++ > >> > 2 files changed, 27 insertions(+), 0 deletions(-) > >> > > >> > _______________________________________________ > >> > 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: From kremenek at apple.com Tue Feb 21 09:49:30 2012 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 21 Feb 2012 09:49:30 -0800 Subject: [cfe-commits] [patch] -Wformat fixup for vprintf (and friends) In-Reply-To: <3D271A4B-EF5F-4012-9E33-810DDF9758BD@shadowlab.org> References: <85F50322-F747-4463-8256-9D1A8C06310C@shadowlab.org> <3D271A4B-EF5F-4012-9E33-810DDF9758BD@shadowlab.org> Message-ID: <7C017E30-5C53-41A4-98B2-D7F22C60F056@apple.com> Hi Jean-Daniel, Overall this looks good. Do we have test cases for this not firing on vprintf, etc., when the user does the right thing? I didn't notice anything in the patch. There may be some existing test cases, but it's probably worth showing that purely correct behavior doesn't trigger a warning. Ted On Feb 20, 2012, at 10:23 AM, Jean-Daniel Dupas wrote: > ping. > > Le 16 févr. 2012 à 23:39, Jean-Daniel Dupas a écrit : > >> >> Le 16 févr. 2012 à 19:17, Ted Kremenek a écrit : >> >>> On Feb 16, 2012, at 1:57 AM, Jean-Daniel Dupas wrote: >>> >>>> Hi, >>>> >>>> This patch implements a long standing FIXME. >>>> When calling a non variadic format function(vprintf, vscanf, NSLogv, …), is the format argument references a parameter of the enclosing function, clang never warned. >>>> With this change, clang will inhibit the warning only if the parameter is declared as a format string with a compatible type. >>>> >>>> >>>> -- Jean-Daniel >>>> >>> >>> Hi Jean-Daniel, >>> >>> I've noticed this patch contains seemingly unrelated changes, e.g.: >>> >>> >>>> // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s >>>> >>>> +#include >>>> + >>>> extern "C" { >>>> -extern int scanf(const char *restrict, ...); >>>> -extern int printf(const char *restrict, ...); >>>> +extern int scanf(const char *, ...); >>>> +extern int printf(const char *, ...); >>>> +extern int vprintf(const char *, va_list ap); >>>> } >>>> >>> >>> >>> What is the motivation for removing the 'restrict' in these test cases? It seems completely unrelated, unnecessary, and actually incorrect since clang defaults to c99. >> >> My bad. >> I noticed that the restrict keyword was not supported in C++ member declaration and was interpreted as the parameter name instead, so I removed it to avoid confusion, and I erroneously removed it from the C functions too. >> >> Is this new patch OK ? >> >> -- Jean-Daniel >> >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > -- Jean-Daniel > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From devlists at shadowlab.org Tue Feb 21 10:32:38 2012 From: devlists at shadowlab.org (Jean-Daniel Dupas) Date: Tue, 21 Feb 2012 19:32:38 +0100 Subject: [cfe-commits] [patch] -Wformat fixup for vprintf (and friends) In-Reply-To: <7C017E30-5C53-41A4-98B2-D7F22C60F056@apple.com> References: <85F50322-F747-4463-8256-9D1A8C06310C@shadowlab.org> <3D271A4B-EF5F-4012-9E33-810DDF9758BD@shadowlab.org> <7C017E30-5C53-41A4-98B2-D7F22C60F056@apple.com> Message-ID: <982EB0E0-F5E6-4FA4-A042-53FBC2B62D0F@shadowlab.org> Thanks, What do you mean by "the right thing". In the C test, the function check_string_literal2() test that the warning does not trigger when the user forward a format string argument. In the C++ test, the "int Foo::printf(const char *fmt, …)" contains a case with vprintf() and no warning, and finally, the objc test case contains a similar test (+ [Bar log2:(NSString *)fmt] ) with NSLogv(). Le 21 févr. 2012 à 18:49, Ted Kremenek a écrit : > Hi Jean-Daniel, > > Overall this looks good. Do we have test cases for this not firing on vprintf, etc., when the user does the right thing? I didn't notice anything in the patch. There may be some existing test cases, but it's probably worth showing that purely correct behavior doesn't trigger a warning. > > Ted > > On Feb 20, 2012, at 10:23 AM, Jean-Daniel Dupas wrote: > >> ping. >> >> Le 16 févr. 2012 à 23:39, Jean-Daniel Dupas a écrit : >> >>> >>> Le 16 févr. 2012 à 19:17, Ted Kremenek a écrit : >>> >>>> On Feb 16, 2012, at 1:57 AM, Jean-Daniel Dupas wrote: >>>> >>>>> Hi, >>>>> >>>>> This patch implements a long standing FIXME. >>>>> When calling a non variadic format function(vprintf, vscanf, NSLogv, …), is the format argument references a parameter of the enclosing function, clang never warned. >>>>> With this change, clang will inhibit the warning only if the parameter is declared as a format string with a compatible type. >>>>> >>>>> >>>>> -- Jean-Daniel >>>>> >>>> >>>> Hi Jean-Daniel, >>>> >>>> I've noticed this patch contains seemingly unrelated changes, e.g.: >>>> >>>> >>>>> // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s >>>>> >>>>> +#include >>>>> + >>>>> extern "C" { >>>>> -extern int scanf(const char *restrict, ...); >>>>> -extern int printf(const char *restrict, ...); >>>>> +extern int scanf(const char *, ...); >>>>> +extern int printf(const char *, ...); >>>>> +extern int vprintf(const char *, va_list ap); >>>>> } >>>>> >>>> >>>> >>>> What is the motivation for removing the 'restrict' in these test cases? It seems completely unrelated, unnecessary, and actually incorrect since clang defaults to c99. >>> >>> My bad. >>> I noticed that the restrict keyword was not supported in C++ member declaration and was interpreted as the parameter name instead, so I removed it to avoid confusion, and I erroneously removed it from the C functions too. >>> >>> Is this new patch OK ? >>> >>> -- Jean-Daniel >>> >>> >>> >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> >> -- Jean-Daniel >> >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > -- Jean-Daniel From dgregor at apple.com Tue Feb 21 11:11:17 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 21 Feb 2012 19:11:17 -0000 Subject: [cfe-commits] r151076 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Sema/Sema.h lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp Message-ID: <20120221191117.BBF782A6C12F@llvm.org> Author: dgregor Date: Tue Feb 21 13:11:17 2012 New Revision: 151076 URL: http://llvm.org/viewvc/llvm-project?rev=151076&view=rev Log: Improve our handling of lambda expressions that occur within default arguments. There are two aspects to this: - Make sure that when marking the declarations referenced in a default argument, we don't try to mark local variables, both because it's a waste of time and because the semantics are wrong: we're not in a place where we could capture these variables again even if it did make sense. - When a lambda expression occurs in a default argument of a function template, make sure that the corresponding closure type is considered dependent, so that it will get properly instantiated. The second bit is a bit of a hack; to fix it properly, we may have to rearchitect our handling of default arguments, parsing them only after creating the function definition. However, I'd like to separate that work from the lambdas work. Modified: cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/lib/AST/DeclCXX.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Feb 21 13:11:17 2012 @@ -560,18 +560,28 @@ struct LambdaDefinitionData : public DefinitionData { typedef LambdaExpr::Capture Capture; - LambdaDefinitionData(CXXRecordDecl *D) - : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), - ContextDecl(0), Captures(0) + LambdaDefinitionData(CXXRecordDecl *D, bool Dependent) + : DefinitionData(D), Dependent(Dependent), NumCaptures(0), + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0) { IsLambda = true; } + /// \brief Whether this lambda is known to be dependent, even if its + /// context isn't dependent. + /// + /// A lambda with a non-dependent context can be dependent if it occurs + /// within the default argument of a function template, because the + /// lambda will have been created with the enclosing context as its + /// declaration context, rather than function. This is an unfortunate + /// artifact of having to parse the default arguments before + unsigned Dependent : 1; + /// \brief The number of captures in this lambda. unsigned NumCaptures : 16; /// \brief The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 16; + unsigned NumExplicitCaptures : 15; /// \brief The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. @@ -689,7 +699,7 @@ IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, - SourceLocation Loc); + SourceLocation Loc, bool DependentLambda); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); bool isDynamicClass() const { @@ -1478,6 +1488,21 @@ return getLambdaData().ContextDecl; } + /// \brief Determine whether this lambda expression was known to be dependent + /// at the time it was created, even if its context does not appear to be + /// dependent. + /// + /// This flag is a workaround for an issue with parsing, where default + /// arguments are parsed before their enclosing function declarations have + /// been created. This means that any lambda expressions within those + /// default arguments will have as their DeclContext the context enclosing + /// the function declaration, which may be non-dependent even when the + /// function declaration itself is dependent. This flag indicates when we + /// know that the lambda is dependent despite that. + bool isDependentLambda() const { + return isLambda() && getLambdaData().Dependent; + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 21 13:11:17 2012 @@ -2386,7 +2386,8 @@ QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); - void MarkDeclarationsReferencedInExpr(Expr *E); + void MarkDeclarationsReferencedInExpr(Expr *E, + bool SkipLocalVariables = false); /// \brief Try to recover by turning the given expression into a /// call. Returns true if recovery was attempted or an error was @@ -3543,7 +3544,8 @@ void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); /// \brief Create a new lambda closure type. - CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange); + CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, + bool KnownDependent = false); /// \brief Start the definition of a lambda expression. CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Tue Feb 21 13:11:17 2012 @@ -741,10 +741,14 @@ if (isa(this)) return true; - if (const CXXRecordDecl *Record = dyn_cast(this)) + if (const CXXRecordDecl *Record = dyn_cast(this)) { if (Record->getDescribedClassTemplate()) return true; - + + if (Record->isDependentLambda()) + return true; + } + if (const FunctionDecl *Function = dyn_cast(this)) { if (Function->getDescribedFunctionTemplate()) return true; Modified: cfe/trunk/lib/AST/DeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclCXX.cpp (original) +++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Feb 21 13:11:17 2012 @@ -83,11 +83,11 @@ } CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, - SourceLocation Loc) { + SourceLocation Loc, bool Dependent) { CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, 0, 0); R->IsBeingDefined = true; - R->DefinitionData = new (C) struct LambdaDefinitionData(R); + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Dependent); C.getTypeDeclType(R, /*PrevDecl=*/0); return R; } Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb 21 13:11:17 2012 @@ -3146,7 +3146,8 @@ // We already type-checked the argument, so we know it works. // Just mark all of the declarations in this potentially-evaluated expression // as being "referenced". - MarkDeclarationsReferencedInExpr(Param->getDefaultArg()); + MarkDeclarationsReferencedInExpr(Param->getDefaultArg(), + /*SkipLocalVariables=*/true); return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); } @@ -10145,13 +10146,22 @@ /// potentially-evaluated subexpressions as "referenced". class EvaluatedExprMarker : public EvaluatedExprVisitor { Sema &S; + bool SkipLocalVariables; public: typedef EvaluatedExprVisitor Inherited; - explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { } + EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) + : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { } void VisitDeclRefExpr(DeclRefExpr *E) { + // If we were asked not to visit local variables, don't. + if (SkipLocalVariables) { + if (VarDecl *VD = dyn_cast(E->getDecl())) + if (VD->hasLocalStorage()) + return; + } + S.MarkDeclRefReferenced(E); } @@ -10193,6 +10203,10 @@ } void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { + // If we were asked not to visit local variables, don't. + if (SkipLocalVariables && E->getDecl()->hasLocalStorage()) + return; + S.MarkBlockDeclRefReferenced(E); } @@ -10211,8 +10225,12 @@ /// \brief Mark any declarations that appear within this expression or any /// potentially-evaluated subexpressions as "referenced". -void Sema::MarkDeclarationsReferencedInExpr(Expr *E) { - EvaluatedExprMarker(*this).Visit(E); +/// +/// \param SkipLocalVariables If true, don't mark local variables as +/// 'referenced'. +void Sema::MarkDeclarationsReferencedInExpr(Expr *E, + bool SkipLocalVariables) { + EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E); } /// \brief Emit a diagnostic that describes an effect on the run-time behavior Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Tue Feb 21 13:11:17 2012 @@ -21,14 +21,16 @@ using namespace clang; using namespace sema; -CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange) { +CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, + bool KnownDependent) { DeclContext *DC = CurContext; while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); // Start constructing the lambda class. CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, - IntroducerRange.getBegin()); + IntroducerRange.getBegin(), + KnownDependent); DC->addDecl(Class); return Class; @@ -142,7 +144,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, Declarator &ParamInfo, Scope *CurScope) { - CXXRecordDecl *Class = createLambdaClosureType(Intro.Range); + // Determine if we're within a context where we know that the lambda will + // be dependent, because there are template parameters in scope. + bool KnownDependent = false; + if (Scope *TmplScope = CurScope->getTemplateParamParent()) + if (!TmplScope->decl_empty()) + KnownDependent = true; + + CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, KnownDependent); // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Feb 21 13:11:17 2012 @@ -1107,6 +1107,7 @@ typedef LambdaExpr::Capture Capture; CXXRecordDecl::LambdaDefinitionData &Lambda = static_cast(Data); + Lambda.Dependent = Record[Idx++]; Lambda.NumCaptures = Record[Idx++]; Lambda.NumExplicitCaptures = Record[Idx++]; Lambda.ManglingNumber = Record[Idx++]; @@ -1134,7 +1135,7 @@ // allocate the appropriate DefinitionData structure. bool IsLambda = Record[Idx++]; if (IsLambda) - D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D); + D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, false); else D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Feb 21 13:11:17 2012 @@ -4330,6 +4330,7 @@ // Add lambda-specific data. if (Data.IsLambda) { CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData(); + Record.push_back(Lambda.Dependent); Record.push_back(Lambda.NumCaptures); Record.push_back(Lambda.NumExplicitCaptures); Record.push_back(Lambda.ManglingNumber); Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp?rev=151076&r1=151075&r2=151076&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp Tue Feb 21 13:11:17 2012 @@ -8,3 +8,9 @@ void g4(int = ([=]{ return 0; })()); void g5(int = ([]{ return sizeof i; })()); } + +namespace lambda_in_default_args { + int f(int = [] () -> int { int n; return ++n; } ()); + template T g(T = [] () -> T { T n; return ++n; } ()); + int k = f() + g(); +} From kremenek at apple.com Tue Feb 21 11:53:23 2012 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 21 Feb 2012 11:53:23 -0800 Subject: [cfe-commits] [patch] -Wformat fixup for vprintf (and friends) In-Reply-To: <982EB0E0-F5E6-4FA4-A042-53FBC2B62D0F@shadowlab.org> References: <85F50322-F747-4463-8256-9D1A8C06310C@shadowlab.org> <3D271A4B-EF5F-4012-9E33-810DDF9758BD@shadowlab.org> <7C017E30-5C53-41A4-98B2-D7F22C60F056@apple.com> <982EB0E0-F5E6-4FA4-A042-53FBC2B62D0F@shadowlab.org> Message-ID: On Feb 21, 2012, at 10:32 AM, Jean-Daniel Dupas wrote: > Thanks, > > What do you mean by "the right thing". > > In the C test, the function check_string_literal2() test that the warning does not trigger when the user forward a format string argument. > > In the C++ test, the "int Foo::printf(const char *fmt, …)" contains a case with vprintf() and no warning, and finally, the objc test case contains a similar test (+ [Bar log2:(NSString *)fmt] ) with NSLogv(). > Those are great tests. I was just talking about the obvious case. Here your patch introduces the following test change: - vprintf(s,ap); // // no-warning + vprintf(s,ap); // expected-warning {{format string is not a string literal}} I'm just asking for a test case that shows vprintf being called with a string literal and the warning not firing, etc. Yes I know this should work, but our tests should reflect that. I did another scan of our tests, and it looks like we have such a test case. So I think this patch is good as is. -------------- next part -------------- An HTML attachment was scrubbed... URL: From devlists at shadowlab.org Tue Feb 21 11:59:45 2012 From: devlists at shadowlab.org (Jean-Daniel Dupas) Date: Tue, 21 Feb 2012 20:59:45 +0100 Subject: [cfe-commits] [patch] -Wformat fixup for vprintf (and friends) In-Reply-To: References: <85F50322-F747-4463-8256-9D1A8C06310C@shadowlab.org> <3D271A4B-EF5F-4012-9E33-810DDF9758BD@shadowlab.org> <7C017E30-5C53-41A4-98B2-D7F22C60F056@apple.com> <982EB0E0-F5E6-4FA4-A042-53FBC2B62D0F@shadowlab.org> Message-ID: <15D774C5-8F44-47D4-B546-DA7355EFDBAF@shadowlab.org> Le 21 févr. 2012 à 20:53, Ted Kremenek a écrit : > > On Feb 21, 2012, at 10:32 AM, Jean-Daniel Dupas wrote: > >> Thanks, >> >> What do you mean by "the right thing". >> >> In the C test, the function check_string_literal2() test that the warning does not trigger when the user forward a format string argument. >> >> In the C++ test, the "int Foo::printf(const char *fmt, …)" contains a case with vprintf() and no warning, and finally, the objc test case contains a similar test (+ [Bar log2:(NSString *)fmt] ) with NSLogv(). >> > > Those are great tests. I was just talking about the obvious case. Here your patch introduces the following test change: > > - vprintf(s,ap); // // no-warning > + vprintf(s,ap); // expected-warning {{format string is not a string literal}} > > I'm just asking for a test case that shows vprintf being called with a string literal and the warning not firing, etc. > Yes I know this should work, but our tests should reflect that. I did another scan of our tests, and it looks like we have such a test case. So I think this patch is good as is. OK. Thank you for the review. -- Jean-Daniel -------------- next part -------------- An HTML attachment was scrubbed... URL: From devlists at shadowlab.org Tue Feb 21 12:00:53 2012 From: devlists at shadowlab.org (Jean-Daniel Dupas) Date: Tue, 21 Feb 2012 20:00:53 -0000 Subject: [cfe-commits] r151080 - in /cfe/trunk: lib/Sema/SemaChecking.cpp test/Sema/format-strings.c test/SemaCXX/format-strings.cpp test/SemaObjC/format-strings-objc.m Message-ID: <20120221200053.E94D92A6C12F@llvm.org> Author: jddupas Date: Tue Feb 21 14:00:53 2012 New Revision: 151080 URL: http://llvm.org/viewvc/llvm-project?rev=151080&view=rev Log: When calling a non variadic format function(vprintf, vscanf, NSLogv, …), warn if the format string argument is a parameter that is not itself declared as a format string with compatible format. Modified: cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/Sema/format-strings.c cfe/trunk/test/SemaCXX/format-strings.cpp cfe/trunk/test/SemaObjC/format-strings-objc.m Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=151080&r1=151079&r2=151080&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Feb 21 14:00:53 2012 @@ -1447,13 +1447,27 @@ // vprintf(fmt, ap); // Do NOT emit a warning about "fmt". // ... // - // - // FIXME: We don't have full attribute support yet, so just check to see - // if the argument is a DeclRefExpr that references a parameter. We'll - // add proper support for checking the attribute later. - if (HasVAListArg) - if (isa(VD)) - return true; + if (HasVAListArg) { + if (const ParmVarDecl *PV = dyn_cast(VD)) { + if (const NamedDecl *ND = dyn_cast(PV->getDeclContext())) { + int PVIndex = PV->getFunctionScopeIndex() + 1; + for (specific_attr_iterator + i = ND->specific_attr_begin(), + e = ND->specific_attr_end(); i != e ; ++i) { + FormatAttr *PVFormat = *i; + // adjust for implicit parameter + if (const CXXMethodDecl *MD = dyn_cast(ND)) + if (MD->isInstance()) + ++PVIndex; + // We also check if the formats are compatible. + // We can't pass a 'scanf' string to a 'printf' function. + if (PVIndex == PVFormat->getFormatIdx() && + Type == GetFormatStringType(PVFormat)) + return true; + } + } + } + } } return false; Modified: cfe/trunk/test/Sema/format-strings.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings.c?rev=151080&r1=151079&r2=151080&view=diff ============================================================================== --- cfe/trunk/test/Sema/format-strings.c (original) +++ cfe/trunk/test/Sema/format-strings.c Tue Feb 21 14:00:53 2012 @@ -14,6 +14,8 @@ int vsnprintf(char *, size_t, const char *, va_list); int vsprintf(char *restrict, const char *restrict, va_list); // expected-note{{passing argument to parameter here}} +int vscanf(const char *restrict format, va_list arg); + char * global_fmt; void check_string_literal( FILE* fp, const char* s, char *buf, ... ) { @@ -23,21 +25,23 @@ va_start(ap,buf); printf(s); // expected-warning {{format string is not a string literal}} - vprintf(s,ap); // // no-warning + vprintf(s,ap); // expected-warning {{format string is not a string literal}} fprintf(fp,s); // expected-warning {{format string is not a string literal}} - vfprintf(fp,s,ap); // no-warning + vfprintf(fp,s,ap); // expected-warning {{format string is not a string literal}} asprintf(&b,s); // expected-warning {{format string is not a string lit}} - vasprintf(&b,s,ap); // no-warning + vasprintf(&b,s,ap); // expected-warning {{format string is not a string literal}} sprintf(buf,s); // expected-warning {{format string is not a string literal}} snprintf(buf,2,s); // expected-warning {{format string is not a string lit}} __builtin___sprintf_chk(buf,0,-1,s); // expected-warning {{format string is not a string literal}} __builtin___snprintf_chk(buf,2,0,-1,s); // expected-warning {{format string is not a string lit}} - vsprintf(buf,s,ap); // no-warning - vsnprintf(buf,2,s,ap); // no-warning + vsprintf(buf,s,ap); // expected-warning {{format string is not a string lit}} + vsnprintf(buf,2,s,ap); // expected-warning {{format string is not a string lit}} vsnprintf(buf,2,global_fmt,ap); // expected-warning {{format string is not a string literal}} - __builtin___vsnprintf_chk(buf,2,0,-1,s,ap); // no-warning + __builtin___vsnprintf_chk(buf,2,0,-1,s,ap); // expected-warning {{format string is not a string lit}} __builtin___vsnprintf_chk(buf,2,0,-1,global_fmt,ap); // expected-warning {{format string is not a string literal}} + vscanf(s, ap); // expected-warning {{format string is not a string literal}} + // rdar://6079877 printf("abc" "%*d", 1, 1); // no-warning @@ -51,6 +55,25 @@ printf("%*d", (unsigned) 1, 1); // no-warning } +__attribute__((__format__ (__printf__, 2, 4))) +void check_string_literal2( FILE* fp, const char* s, char *buf, ... ) { + char * b; + va_list ap; + va_start(ap,buf); + + printf(s); // expected-warning {{format string is not a string literal}} + vprintf(s,ap); // no-warning + fprintf(fp,s); // expected-warning {{format string is not a string literal}} + vfprintf(fp,s,ap); // no-warning + asprintf(&b,s); // expected-warning {{format string is not a string lit}} + vasprintf(&b,s,ap); // no-warning + sprintf(buf,s); // expected-warning {{format string is not a string literal}} + snprintf(buf,2,s); // expected-warning {{format string is not a string lit}} + __builtin___vsnprintf_chk(buf,2,0,-1,s,ap); // no-warning + + vscanf(s, ap); // expected-warning {{format string is not a string literal}} +} + void check_conditional_literal(const char* s, int i) { printf(i == 1 ? "yes" : "no"); // no-warning printf(i == 0 ? (i == 1 ? "yes" : "no") : "dont know"); // no-warning Modified: cfe/trunk/test/SemaCXX/format-strings.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/format-strings.cpp?rev=151080&r1=151079&r2=151080&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/format-strings.cpp (original) +++ cfe/trunk/test/SemaCXX/format-strings.cpp Tue Feb 21 14:00:53 2012 @@ -1,8 +1,11 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s +#include + extern "C" { extern int scanf(const char *restrict, ...); extern int printf(const char *restrict, ...); +extern int vprintf(const char *restrict, va_list); } void f(char **sp, float *fp) { @@ -23,11 +26,12 @@ public: const char *gettext(const char *fmt) __attribute__((format_arg(2))); - int scanf(const char *restrict, ...) __attribute__((format(scanf, 2, 3))); - int printf(const char *restrict, ...) __attribute__((format(printf, 2, 3))); + int scanf(const char *, ...) __attribute__((format(scanf, 2, 3))); + int printf(const char *, ...) __attribute__((format(printf, 2, 3))); + int printf2(const char *, ...); static const char *gettext_static(const char *fmt) __attribute__((format_arg(1))); - static int printf_static(const char *restrict, ...) __attribute__((format(printf, 1, 2))); + static int printf_static(const char *fmt, ...) __attribute__((format(printf, 1, 2))); }; void h(int *i) { @@ -52,3 +56,23 @@ test_null_format(__null); // no-warning test_null_format(f); // expected-warning {{not a string literal}} } + +int Foo::printf(const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + const char * const format = fmt; + vprintf(format, ap); // no-warning + + const char *format2 = fmt; + vprintf(format2, ap); // expected-warning{{format string is not a string literal}} + + return 0; +} + +int Foo::printf2(const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + vprintf(fmt, ap); // expected-warning{{format string is not a string literal}} + + return 0; +} Modified: cfe/trunk/test/SemaObjC/format-strings-objc.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/format-strings-objc.m?rev=151080&r1=151079&r2=151080&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/format-strings-objc.m (original) +++ cfe/trunk/test/SemaObjC/format-strings-objc.m Tue Feb 21 14:00:53 2012 @@ -9,11 +9,13 @@ // portable to non-Mac platforms. //===----------------------------------------------------------------------===// +#include + typedef signed char BOOL; typedef unsigned int NSUInteger; @class NSString, Protocol; -extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); -extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); +extern void NSLog(NSString *format, ...); +extern void NSLogv(NSString *format, va_list args); typedef struct _NSZone NSZone; @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; @protocol NSObject - (BOOL)isEqual:(id)object; @end @@ -151,3 +153,26 @@ void test_toll_free_bridging(CFStringRef x) { NSLog(@"%@", x); // no-warning } + + at interface Bar ++ (void)log:(NSString *)fmt, ...; ++ (void)log2:(NSString *)fmt, ... __attribute__((format(NSString, 1, 2))); + at end + + at implementation Bar + ++ (void)log:(NSString *)fmt, ... { + va_list ap; + va_start(ap,fmt); + NSLogv(fmt, ap); // expected-warning{{format string is not a string literal}} + va_end(ap); +} + ++ (void)log2:(NSString *)fmt, ... { + va_list ap; + va_start(ap,fmt); + NSLogv(fmt, ap); // no-warning + va_end(ap); +} + + at end From richard-llvm at metafoo.co.uk Tue Feb 21 12:01:35 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Tue, 21 Feb 2012 20:01:35 -0000 Subject: [cfe-commits] r151081 - in /cfe/trunk: lib/Parse/ParseStmt.cpp test/SemaCXX/for-range-examples.cpp Message-ID: <20120221200135.436502A6C12F@llvm.org> Author: rsmith Date: Tue Feb 21 14:01:35 2012 New Revision: 151081 URL: http://llvm.org/viewvc/llvm-project?rev=151081&view=rev Log: Don't assume that a valid expression for the first part of a for-statement is non-null when diagnosing a broken attempt to write a for-range-statement. Modified: cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/test/SemaCXX/for-range-examples.cpp Modified: cfe/trunk/lib/Parse/ParseStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=151081&r1=151080&r2=151081&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue Feb 21 14:01:35 2012 @@ -1396,8 +1396,7 @@ return StmtError(); } Collection = ParseExpression(); - } else if (getLang().CPlusPlus0x && Tok.is(tok::colon) && - !FirstPart.isInvalid()) { + } else if (getLang().CPlusPlus0x && Tok.is(tok::colon) && FirstPart.get()) { // User tried to write the reasonable, but ill-formed, for-range-statement // for (expr : expr) { ... } Diag(Tok, diag::err_for_range_expected_decl) Modified: cfe/trunk/test/SemaCXX/for-range-examples.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-examples.cpp?rev=151081&r1=151080&r2=151081&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/for-range-examples.cpp (original) +++ cfe/trunk/test/SemaCXX/for-range-examples.cpp Tue Feb 21 14:01:35 2012 @@ -169,3 +169,14 @@ template void f() { for (auto a : A()) {} } void g() { f(); } } + +namespace test4 { + void f() { + int y; + + // Make sure these don't crash. Better diagnostics would be nice. + for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}} + for (x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} + for (y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} + } +} From kremenek at apple.com Tue Feb 21 12:08:40 2012 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 21 Feb 2012 12:08:40 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> <20120220202153.GA20840@britannica.bec.de> Message-ID: <8ED5B26D-061E-4127-A92A-1C47D498BE2B@apple.com> On Feb 21, 2012, at 1:57 AM, Hans Wennborg wrote: >> Now I see that TOT doesn't warn here. Is this accepted somewhere? I see no >> test cases in clang/test that shows we should accept this. Was this an >> intentional change, or a regression? > > r148859 made them accepted about a month ago. Looks intentional to me :) Yes, I'm losing it. Too much going on these days. Thanks for pointing it out. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dgregor at apple.com Tue Feb 21 12:05:31 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 21 Feb 2012 20:05:31 -0000 Subject: [cfe-commits] r151082 - in /cfe/trunk: lib/Sema/SemaLambda.cpp test/SemaCXX/lambda-expressions.cpp Message-ID: <20120221200532.A39F92A6C12F@llvm.org> Author: dgregor Date: Tue Feb 21 14:05:31 2012 New Revision: 151082 URL: http://llvm.org/viewvc/llvm-project?rev=151082&view=rev Log: Only pop the expression evaluation context corresponding to a lambda expression after we've finished the function body of the corresponding function call operator. Otherwise, ActOnFinishFunctionBody() will see the (unfinished) evaluation context of the lambda expression itself. Fixes PR12031. Modified: cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/test/SemaCXX/lambda-expressions.cpp Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151082&r1=151081&r2=151082&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Tue Feb 21 14:05:31 2012 @@ -511,10 +511,6 @@ llvm::Optional ManglingNumber, Decl *ContextDecl, bool IsInstantiation) { - // Leave the expression-evaluation context. - DiscardCleanupsInEvaluationContext(); - PopExpressionEvaluationContext(); - // Collect information from the lambda scope. llvm::SmallVector Captures; llvm::SmallVector CaptureInits; @@ -631,6 +627,7 @@ ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation); CallOperator->setLexicalDeclContext(Class); Class->addDecl(CallOperator); + PopExpressionEvaluationContext(); // C++11 [expr.prim.lambda]p6: // The closure type for a lambda-expression with no lambda-capture @@ -654,7 +651,6 @@ ActOnFields(0, Class->getLocation(), Class, Fields, SourceLocation(), SourceLocation(), 0); CheckCompletedCXXClass(Class); - } if (LambdaExprNeedsCleanups) Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=151082&r1=151081&r2=151082&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Tue Feb 21 14:05:31 2012 @@ -87,3 +87,17 @@ []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} } } + +namespace PR12031 { + struct X { + template + X(const T&); + ~X(); + }; + + void f(int i, X x); + void g() { + const int v = 10; + f(v, [](){}); + } +} From eli.friedman at gmail.com Tue Feb 21 12:15:14 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 21 Feb 2012 12:15:14 -0800 Subject: [cfe-commits] r151076 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Sema/Sema.h lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cp Message-ID: On Tue, Feb 21, 2012 at 11:11 AM, Douglas Gregor wrote: > Author: dgregor > Date: Tue Feb 21 13:11:17 2012 > New Revision: 151076 > > URL: http://llvm.org/viewvc/llvm-project?rev=151076&view=rev > Log: > Improve our handling of lambda expressions that occur within default > arguments. There are two aspects to this: > >  - Make sure that when marking the declarations referenced in a >  default argument, we don't try to mark local variables, both because >  it's a waste of time and because the semantics are wrong: we're not >  in a place where we could capture these variables again even if it >  did make sense. >  - When a lambda expression occurs in a default argument of a >  function template, make sure that the corresponding closure type is >  considered dependent, so that it will get properly instantiated. The >  second bit is a bit of a hack; to fix it properly, we may have to >  rearchitect our handling of default arguments, parsing them only >  after creating the function definition. However, I'd like to >  separate that work from the lambdas work. > > > Modified: >    cfe/trunk/include/clang/AST/DeclCXX.h >    cfe/trunk/include/clang/Sema/Sema.h >    cfe/trunk/lib/AST/DeclBase.cpp >    cfe/trunk/lib/AST/DeclCXX.cpp >    cfe/trunk/lib/Sema/SemaExpr.cpp >    cfe/trunk/lib/Sema/SemaLambda.cpp >    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp >    cfe/trunk/lib/Serialization/ASTWriter.cpp >    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp > > Modified: cfe/trunk/include/clang/AST/DeclCXX.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=151076&r1=151075&r2=151076&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/DeclCXX.h (original) > +++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Feb 21 13:11:17 2012 > @@ -560,18 +560,28 @@ >   struct LambdaDefinitionData : public DefinitionData { >     typedef LambdaExpr::Capture Capture; > > -    LambdaDefinitionData(CXXRecordDecl *D) > -      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), > -        ContextDecl(0), Captures(0) > +    LambdaDefinitionData(CXXRecordDecl *D, bool Dependent) > +      : DefinitionData(D), Dependent(Dependent), NumCaptures(0), > +        NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0) >     { >       IsLambda = true; >     } > > +    /// \brief Whether this lambda is known to be dependent, even if its > +    /// context isn't dependent. > +    /// > +    /// A lambda with a non-dependent context can be dependent if it occurs > +    /// within the default argument of a function template, because the > +    /// lambda will have been created with the enclosing context as its > +    /// declaration context, rather than function. This is an unfortunate > +    /// artifact of having to parse the default arguments before > +    unsigned Dependent : 1; > + >     /// \brief The number of captures in this lambda. >     unsigned NumCaptures : 16; > >     /// \brief The number of explicit captures in this lambda. > -    unsigned NumExplicitCaptures : 16; > +    unsigned NumExplicitCaptures : 15; > >     /// \brief The number used to indicate this lambda expression for name >     /// mangling in the Itanium C++ ABI. > @@ -689,7 +699,7 @@ >                                IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, >                                bool DelayTypeCreation = false); >   static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, > -                                     SourceLocation Loc); > +                                     SourceLocation Loc, bool DependentLambda); >   static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); > >   bool isDynamicClass() const { > @@ -1478,6 +1488,21 @@ >     return getLambdaData().ContextDecl; >   } > > +  /// \brief Determine whether this lambda expression was known to be dependent > +  /// at the time it was created, even if its context does not appear to be > +  /// dependent. > +  /// > +  /// This flag is a workaround for an issue with parsing, where default > +  /// arguments are parsed before their enclosing function declarations have > +  /// been created. This means that any lambda expressions within those > +  /// default arguments will have as their DeclContext the context enclosing > +  /// the function declaration, which may be non-dependent even when the > +  /// function declaration itself is dependent. This flag indicates when we > +  /// know that the lambda is dependent despite that. > +  bool isDependentLambda() const { > +    return isLambda() && getLambdaData().Dependent; > +  } > + >   static bool classof(const Decl *D) { return classofKind(D->getKind()); } >   static bool classofKind(Kind K) { >     return K >= firstCXXRecord && K <= lastCXXRecord; > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151076&r1=151075&r2=151076&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 21 13:11:17 2012 > @@ -2386,7 +2386,8 @@ >   QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); > >   void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); > -  void MarkDeclarationsReferencedInExpr(Expr *E); > +  void MarkDeclarationsReferencedInExpr(Expr *E, > +                                        bool SkipLocalVariables = false); > >   /// \brief Try to recover by turning the given expression into a >   /// call.  Returns true if recovery was attempted or an error was > @@ -3543,7 +3544,8 @@ >   void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); > >   /// \brief Create a new lambda closure type. > -  CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange); > +  CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, > +                                         bool KnownDependent = false); > >   /// \brief Start the definition of a lambda expression. >   CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, > > Modified: cfe/trunk/lib/AST/DeclBase.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=151076&r1=151075&r2=151076&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/DeclBase.cpp (original) > +++ cfe/trunk/lib/AST/DeclBase.cpp Tue Feb 21 13:11:17 2012 > @@ -741,10 +741,14 @@ >   if (isa(this)) >     return true; > > -  if (const CXXRecordDecl *Record = dyn_cast(this)) > +  if (const CXXRecordDecl *Record = dyn_cast(this)) { >     if (Record->getDescribedClassTemplate()) >       return true; > - > + > +    if (Record->isDependentLambda()) > +      return true; > +  } > + >   if (const FunctionDecl *Function = dyn_cast(this)) { >     if (Function->getDescribedFunctionTemplate()) >       return true; > > Modified: cfe/trunk/lib/AST/DeclCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=151076&r1=151075&r2=151076&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/DeclCXX.cpp (original) > +++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Feb 21 13:11:17 2012 > @@ -83,11 +83,11 @@ >  } > >  CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, > -                                           SourceLocation Loc) { > +                                           SourceLocation Loc, bool Dependent) { >   CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, >                                            0, 0); >   R->IsBeingDefined = true; > -  R->DefinitionData = new (C) struct LambdaDefinitionData(R); > +  R->DefinitionData = new (C) struct LambdaDefinitionData(R, Dependent); >   C.getTypeDeclType(R, /*PrevDecl=*/0); >   return R; >  } > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=151076&r1=151075&r2=151076&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb 21 13:11:17 2012 > @@ -3146,7 +3146,8 @@ >   // We already type-checked the argument, so we know it works. >   // Just mark all of the declarations in this potentially-evaluated expression >   // as being "referenced". > -  MarkDeclarationsReferencedInExpr(Param->getDefaultArg()); > +  MarkDeclarationsReferencedInExpr(Param->getDefaultArg(), > +                                   /*SkipLocalVariables=*/true); >   return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); >  } > > @@ -10145,13 +10146,22 @@ >   /// potentially-evaluated subexpressions as "referenced". >   class EvaluatedExprMarker : public EvaluatedExprVisitor { >     Sema &S; > +    bool SkipLocalVariables; > >   public: >     typedef EvaluatedExprVisitor Inherited; > > -    explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { } > +    EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) > +      : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { } > >     void VisitDeclRefExpr(DeclRefExpr *E) { > +      // If we were asked not to visit local variables, don't. > +      if (SkipLocalVariables) { > +        if (VarDecl *VD = dyn_cast(E->getDecl())) > +          if (VD->hasLocalStorage()) > +            return; > +      } > + >       S.MarkDeclRefReferenced(E); >     } > > @@ -10193,6 +10203,10 @@ >     } > >     void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { > +      // If we were asked not to visit local variables, don't. > +      if (SkipLocalVariables && E->getDecl()->hasLocalStorage()) > +          return; What exactly are the rules for odr-use marking inside a lambda in a default argument, actually? -Eli From kremenek at apple.com Tue Feb 21 12:15:47 2012 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 21 Feb 2012 12:15:47 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> Message-ID: On Feb 21, 2012, at 3:39 AM, Hans Wennborg wrote: > On Mon, Feb 20, 2012 at 19:37, Ted Kremenek wrote: >> On Feb 20, 2012, at 11:25 AM, Hans Wennborg wrote: >>> Keeping -Wformat-nonstandard out of -Wformat and having it in >>> -pedantic sounds perfectly fine to me. I expect that lines up with >>> what gcc does too. >> >> Ok, I think that approach is worth experimenting with. > > Cool. I think getting this warning in under -pedantic is a good step > in the right direction. Me too. > >> I've looked at the patch, and other than the default configuration of the >> warnings, it looks okay to me. > > I've updated the patch to make the warning DefaultIgnore and ExtWarn. > > I've also changed it to not make a difference between -std=c99 and > -std=gnu99. If the user specifies -pedantic, I think we should warn > for '%ms' even if the user has selected -std=gnu99. This matches gcc > behavior too, and it's extra important because if the user doesn't > specify the -std flag, then gnu99 seems the be the default c mode. Sounds great. > >> One nit on wording in the diagnostic: "non-standard" or "non-portable"? The >> former is more technically accurate, but the latter is the implication the >> user cares about. What do you think? > > I'd prefer "non-standard", but I don't feel strongly about it. I don't either. I'm fine with staying with non-standard. > > I noticed that this sparks new failures in > "clang-tests/gcc-4_2-testsuite" (excess warning), so I'm attaching a > patch for that too. Please take a look. I did. The change looks reasonable. Please commit! -------------- next part -------------- An HTML attachment was scrubbed... URL: From dgregor at apple.com Tue Feb 21 12:17:47 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 21 Feb 2012 12:17:47 -0800 Subject: [cfe-commits] r151076 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Sema/Sema.h lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cp In-Reply-To: References: Message-ID: On Feb 21, 2012, at 12:15 PM, Eli Friedman wrote: > On Tue, Feb 21, 2012 at 11:11 AM, Douglas Gregor wrote: >> Author: dgregor >> Date: Tue Feb 21 13:11:17 2012 >> New Revision: 151076 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=151076&view=rev >> Log: >> Improve our handling of lambda expressions that occur within default >> arguments. There are two aspects to this: >> >> - Make sure that when marking the declarations referenced in a >> default argument, we don't try to mark local variables, both because >> it's a waste of time and because the semantics are wrong: we're not >> in a place where we could capture these variables again even if it >> did make sense. >> - When a lambda expression occurs in a default argument of a >> function template, make sure that the corresponding closure type is >> considered dependent, so that it will get properly instantiated. The >> second bit is a bit of a hack; to fix it properly, we may have to >> rearchitect our handling of default arguments, parsing them only >> after creating the function definition. However, I'd like to >> separate that work from the lambdas work. >> >> >> Modified: >> cfe/trunk/include/clang/AST/DeclCXX.h >> cfe/trunk/include/clang/Sema/Sema.h >> cfe/trunk/lib/AST/DeclBase.cpp >> cfe/trunk/lib/AST/DeclCXX.cpp >> cfe/trunk/lib/Sema/SemaExpr.cpp >> cfe/trunk/lib/Sema/SemaLambda.cpp >> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp >> cfe/trunk/lib/Serialization/ASTWriter.cpp >> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp >> >> Modified: cfe/trunk/include/clang/AST/DeclCXX.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=151076&r1=151075&r2=151076&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/AST/DeclCXX.h (original) >> +++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Feb 21 13:11:17 2012 >> @@ -560,18 +560,28 @@ >> struct LambdaDefinitionData : public DefinitionData { >> typedef LambdaExpr::Capture Capture; >> >> - LambdaDefinitionData(CXXRecordDecl *D) >> - : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), >> - ContextDecl(0), Captures(0) >> + LambdaDefinitionData(CXXRecordDecl *D, bool Dependent) >> + : DefinitionData(D), Dependent(Dependent), NumCaptures(0), >> + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0) >> { >> IsLambda = true; >> } >> >> + /// \brief Whether this lambda is known to be dependent, even if its >> + /// context isn't dependent. >> + /// >> + /// A lambda with a non-dependent context can be dependent if it occurs >> + /// within the default argument of a function template, because the >> + /// lambda will have been created with the enclosing context as its >> + /// declaration context, rather than function. This is an unfortunate >> + /// artifact of having to parse the default arguments before >> + unsigned Dependent : 1; >> + >> /// \brief The number of captures in this lambda. >> unsigned NumCaptures : 16; >> >> /// \brief The number of explicit captures in this lambda. >> - unsigned NumExplicitCaptures : 16; >> + unsigned NumExplicitCaptures : 15; >> >> /// \brief The number used to indicate this lambda expression for name >> /// mangling in the Itanium C++ ABI. >> @@ -689,7 +699,7 @@ >> IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, >> bool DelayTypeCreation = false); >> static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, >> - SourceLocation Loc); >> + SourceLocation Loc, bool DependentLambda); >> static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); >> >> bool isDynamicClass() const { >> @@ -1478,6 +1488,21 @@ >> return getLambdaData().ContextDecl; >> } >> >> + /// \brief Determine whether this lambda expression was known to be dependent >> + /// at the time it was created, even if its context does not appear to be >> + /// dependent. >> + /// >> + /// This flag is a workaround for an issue with parsing, where default >> + /// arguments are parsed before their enclosing function declarations have >> + /// been created. This means that any lambda expressions within those >> + /// default arguments will have as their DeclContext the context enclosing >> + /// the function declaration, which may be non-dependent even when the >> + /// function declaration itself is dependent. This flag indicates when we >> + /// know that the lambda is dependent despite that. >> + bool isDependentLambda() const { >> + return isLambda() && getLambdaData().Dependent; >> + } >> + >> static bool classof(const Decl *D) { return classofKind(D->getKind()); } >> static bool classofKind(Kind K) { >> return K >= firstCXXRecord && K <= lastCXXRecord; >> >> Modified: cfe/trunk/include/clang/Sema/Sema.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151076&r1=151075&r2=151076&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/Sema/Sema.h (original) >> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 21 13:11:17 2012 >> @@ -2386,7 +2386,8 @@ >> QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); >> >> void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); >> - void MarkDeclarationsReferencedInExpr(Expr *E); >> + void MarkDeclarationsReferencedInExpr(Expr *E, >> + bool SkipLocalVariables = false); >> >> /// \brief Try to recover by turning the given expression into a >> /// call. Returns true if recovery was attempted or an error was >> @@ -3543,7 +3544,8 @@ >> void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); >> >> /// \brief Create a new lambda closure type. >> - CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange); >> + CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, >> + bool KnownDependent = false); >> >> /// \brief Start the definition of a lambda expression. >> CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, >> >> Modified: cfe/trunk/lib/AST/DeclBase.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=151076&r1=151075&r2=151076&view=diff >> ============================================================================== >> --- cfe/trunk/lib/AST/DeclBase.cpp (original) >> +++ cfe/trunk/lib/AST/DeclBase.cpp Tue Feb 21 13:11:17 2012 >> @@ -741,10 +741,14 @@ >> if (isa(this)) >> return true; >> >> - if (const CXXRecordDecl *Record = dyn_cast(this)) >> + if (const CXXRecordDecl *Record = dyn_cast(this)) { >> if (Record->getDescribedClassTemplate()) >> return true; >> - >> + >> + if (Record->isDependentLambda()) >> + return true; >> + } >> + >> if (const FunctionDecl *Function = dyn_cast(this)) { >> if (Function->getDescribedFunctionTemplate()) >> return true; >> >> Modified: cfe/trunk/lib/AST/DeclCXX.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=151076&r1=151075&r2=151076&view=diff >> ============================================================================== >> --- cfe/trunk/lib/AST/DeclCXX.cpp (original) >> +++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Feb 21 13:11:17 2012 >> @@ -83,11 +83,11 @@ >> } >> >> CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, >> - SourceLocation Loc) { >> + SourceLocation Loc, bool Dependent) { >> CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, >> 0, 0); >> R->IsBeingDefined = true; >> - R->DefinitionData = new (C) struct LambdaDefinitionData(R); >> + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Dependent); >> C.getTypeDeclType(R, /*PrevDecl=*/0); >> return R; >> } >> >> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=151076&r1=151075&r2=151076&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb 21 13:11:17 2012 >> @@ -3146,7 +3146,8 @@ >> // We already type-checked the argument, so we know it works. >> // Just mark all of the declarations in this potentially-evaluated expression >> // as being "referenced". >> - MarkDeclarationsReferencedInExpr(Param->getDefaultArg()); >> + MarkDeclarationsReferencedInExpr(Param->getDefaultArg(), >> + /*SkipLocalVariables=*/true); >> return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); >> } >> >> @@ -10145,13 +10146,22 @@ >> /// potentially-evaluated subexpressions as "referenced". >> class EvaluatedExprMarker : public EvaluatedExprVisitor { >> Sema &S; >> + bool SkipLocalVariables; >> >> public: >> typedef EvaluatedExprVisitor Inherited; >> >> - explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { } >> + EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) >> + : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { } >> >> void VisitDeclRefExpr(DeclRefExpr *E) { >> + // If we were asked not to visit local variables, don't. >> + if (SkipLocalVariables) { >> + if (VarDecl *VD = dyn_cast(E->getDecl())) >> + if (VD->hasLocalStorage()) >> + return; >> + } >> + >> S.MarkDeclRefReferenced(E); >> } >> >> @@ -10193,6 +10203,10 @@ >> } >> >> void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { >> + // If we were asked not to visit local variables, don't. >> + if (SkipLocalVariables && E->getDecl()->hasLocalStorage()) >> + return; > > What exactly are the rules for odr-use marking inside a lambda in a > default argument, actually? That is an *excellent* question. We're trying to emulate what would have happened if the expression had been written in a potentially evaluated context, by walking the resulting tree, and it's fairly likely that we don't get all of the cases right. - Doug From joerg at britannica.bec.de Tue Feb 21 12:23:33 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Tue, 21 Feb 2012 21:23:33 +0100 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> <20120220202153.GA20840@britannica.bec.de> Message-ID: <20120221202333.GA19817@britannica.bec.de> On Tue, Feb 21, 2012 at 09:57:23AM +0000, Hans Wennborg wrote: > On Mon, Feb 20, 2012 at 21:00, Ted Kremenek wrote: > > On Feb 20, 2012, at 12:21 PM, Joerg Sonnenberger > > wrote: > > > > There's "non-standard" and then there's completely unportable.  Warnings > > like: > > > > +  // Combining 'L' with an integer conversion specifier. > > +  printf("%Li", (long long)42); // expected-warning{{using the length > > modifier 'L' with the conversion specifier 'i' is non-standard}} > > +  printf("%Lo", (long long)42); // expected-warning{{using the length > > modifier 'L' with the conversion specifier 'o' is non-standard}} > > > > [...] > > > Do we really silently accept them?  Until very recently (a month ago?), we > > emitted: > > > > t.c:4:12: warning: length modifier 'L' results in undefined behavior or no > >       effect with 'i' conversion specifier [-Wformat] > >   printf("%Li", (long long) 2); > >           ~^~ > > 1 warning generated. > > > > > > Now I see that TOT doesn't warn here.  Is this accepted somewhere?  I see no > > test cases in clang/test that shows we should accept this.  Was this an > > intentional change, or a regression? > > r148859 made them accepted about a month ago. Looks intentional to me :) Which brings up the question, where is that documented? At least the Linux documentation is silent on this being valid. Joerg From kremenek at apple.com Tue Feb 21 12:27:16 2012 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 21 Feb 2012 12:27:16 -0800 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <20120221202333.GA19817@britannica.bec.de> References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> <20120220202153.GA20840@britannica.bec.de> <20120221202333.GA19817@britannica.bec.de> Message-ID: <7215BD39-1E25-425D-9BD5-ED0F44842D64@apple.com> On Feb 21, 2012, at 12:23 PM, Joerg Sonnenberger wrote: >>> Do we really silently accept them? Until very recently (a month ago?), we >>> emitted: >>> >>> t.c:4:12: warning: length modifier 'L' results in undefined behavior or no >>> effect with 'i' conversion specifier [-Wformat] >>> printf("%Li", (long long) 2); >>> ~^~ >>> 1 warning generated. >>> >>> >>> Now I see that TOT doesn't warn here. Is this accepted somewhere? I see no >>> test cases in clang/test that shows we should accept this. Was this an >>> intentional change, or a regression? >> >> r148859 made them accepted about a month ago. Looks intentional to me :) > > Which brings up the question, where is that documented? At least the > Linux documentation is silent on this being valid. According to PR 9466, this is a general GNU extension: http://www.gnu.org/software/libc/manual/html_node/Integer-Conversions.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From joerg at britannica.bec.de Tue Feb 21 12:58:40 2012 From: joerg at britannica.bec.de (Joerg Sonnenberger) Date: Tue, 21 Feb 2012 21:58:40 +0100 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: <7215BD39-1E25-425D-9BD5-ED0F44842D64@apple.com> References: <20120220190432.GA18744@britannica.bec.de> <20120220195103.GA19546@britannica.bec.de> <01FA9739-8C2F-46CE-81F0-E95635C6599F@apple.com> <20120220202153.GA20840@britannica.bec.de> <20120221202333.GA19817@britannica.bec.de> <7215BD39-1E25-425D-9BD5-ED0F44842D64@apple.com> Message-ID: <20120221205840.GA20762@britannica.bec.de> On Tue, Feb 21, 2012 at 12:27:16PM -0800, Ted Kremenek wrote: > > On Feb 21, 2012, at 12:23 PM, Joerg Sonnenberger wrote: > > >>> Do we really silently accept them? Until very recently (a month ago?), we > >>> emitted: > >>> > >>> t.c:4:12: warning: length modifier 'L' results in undefined behavior or no > >>> effect with 'i' conversion specifier [-Wformat] > >>> printf("%Li", (long long) 2); > >>> ~^~ > >>> 1 warning generated. > >>> > >>> > >>> Now I see that TOT doesn't warn here. Is this accepted somewhere? I see no > >>> test cases in clang/test that shows we should accept this. Was this an > >>> intentional change, or a regression? > >> > >> r148859 made them accepted about a month ago. Looks intentional to me :) > > > > Which brings up the question, where is that documented? At least the > > Linux documentation is silent on this being valid. > > > According to PR 9466, this is a general GNU extension: > > http://www.gnu.org/software/libc/manual/html_node/Integer-Conversions.html The printf(3) man page doesn't list it in the normal section and contains: Linux libc5 knows about the five C standard flags and the ' flag, locale, "%m$" and "*m$". It knows about the length modifiers h, l, L, Z, and q, but accepts L and q both for long double and for long long int (this is a bug). under CONFORMING TO. That sounds a lot like the consensus in the BSD camp for q -- it exists and can't be killed for historic reasons, but it should strongly be discouraged. Joerg From hhinnant at apple.com Tue Feb 21 13:02:58 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Tue, 21 Feb 2012 21:02:58 -0000 Subject: [cfe-commits] [libcxx] r151084 - in /libcxx/trunk: include/__functional_base include/functional include/memory test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp Message-ID: <20120221210258.747AF2A6C12F@llvm.org> Author: hhinnant Date: Tue Feb 21 15:02:58 2012 New Revision: 151084 URL: http://llvm.org/viewvc/llvm-project?rev=151084&view=rev Log: Modernize relational operators for shared_ptr and unique_ptr. This includes adding support for nullptr, and using less. Fixes http://llvm.org/bugs/show_bug.cgi?id=12056. Added: libcxx/trunk/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp libcxx/trunk/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp Modified: libcxx/trunk/include/__functional_base libcxx/trunk/include/functional libcxx/trunk/include/memory Modified: libcxx/trunk/include/__functional_base URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__functional_base?rev=151084&r1=151083&r2=151084&view=diff ============================================================================== --- libcxx/trunk/include/__functional_base (original) +++ libcxx/trunk/include/__functional_base Tue Feb 21 15:02:58 2012 @@ -50,6 +50,13 @@ static const bool value = sizeof(__test<_Tp>(0)) == 1; }; +template +struct _LIBCPP_VISIBLE less : binary_function<_Tp, _Tp, bool> +{ + _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x < __y;} +}; + #ifdef _LIBCPP_HAS_NO_VARIADICS #include <__functional_base_03> Modified: libcxx/trunk/include/functional URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=151084&r1=151083&r2=151084&view=diff ============================================================================== --- libcxx/trunk/include/functional (original) +++ libcxx/trunk/include/functional Tue Feb 21 15:02:58 2012 @@ -536,12 +536,7 @@ {return __x > __y;} }; -template -struct _LIBCPP_VISIBLE less : binary_function<_Tp, _Tp, bool> -{ - _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const _Tp& __y) const - {return __x < __y;} -}; +// less in <__functional_base> template struct _LIBCPP_VISIBLE greater_equal : binary_function<_Tp, _Tp, bool> Modified: libcxx/trunk/include/memory URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=151084&r1=151083&r2=151084&view=diff ============================================================================== --- libcxx/trunk/include/memory (original) +++ libcxx/trunk/include/memory Tue Feb 21 15:02:58 2012 @@ -2964,7 +2964,13 @@ template inline _LIBCPP_INLINE_VISIBILITY bool -operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() < __y.get();} +operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) +{ + typedef typename unique_ptr<_T1, _D1>::pointer _P1; + typedef typename unique_ptr<_T2, _D2>::pointer _P2; + typedef typename common_type<_P1, _P2>::type _V; + return less<_V>()(__x.get(), __y.get()); +} template inline _LIBCPP_INLINE_VISIBILITY @@ -2981,6 +2987,104 @@ bool operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + typedef typename unique_ptr<_T1, _D1>::pointer _P1; + return less<_P1>()(__x.get(), nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + typedef typename unique_ptr<_T1, _D1>::pointer _P1; + return less<_P1>()(nullptr, __x.get()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return nullptr < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return __x < nullptr; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return !(nullptr < __x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return !(nullptr < __x); +} + template struct hash; // We use murmur2 when size_t is 32 bits, and cityhash64 when size_t @@ -4620,7 +4724,128 @@ bool operator<(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { - return __x.get() < __y.get(); + typedef typename common_type<_Tp*, _Up*>::type _V; + return less<_V>()(__x.get(), __y.get()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT +{ + return __y < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT +{ + return !(__y < __x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT +{ + return !(__x < __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return less<_Tp*>()(__x.get(), nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return less<_Tp*>()(nullptr, __x.get()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return nullptr < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return __x < nullptr; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return !(nullptr < __x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return !(nullptr < __x); } template Added: libcxx/trunk/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp?rev=151084&view=auto ============================================================================== --- libcxx/trunk/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp (added) +++ libcxx/trunk/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp Tue Feb 21 15:02:58 2012 @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template +// bool operator==(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator==(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator!=(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator!=(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator<(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator<(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator<=(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator<=(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator>(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator>(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator>=(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator>=(nullptr_t, const unique_ptr& y) noexcept; + +#include +#include + +void do_nothing(int*) {} + +int main() +{ + int* ptr1(new int); + int* ptr2(new int); + const std::unique_ptr p1(new int(1)); + assert(!(p1 == nullptr)); + assert(!(nullptr == p1)); + assert(!(p1 < nullptr)); + assert( (nullptr < p1)); + assert(!(p1 <= nullptr)); + assert( (nullptr <= p1)); + assert( (p1 > nullptr)); + assert(!(nullptr > p1)); + assert( (p1 >= nullptr)); + assert(!(nullptr >= p1)); + + const std::unique_ptr p2; + assert( (p2 == nullptr)); + assert( (nullptr == p2)); + assert(!(p2 < nullptr)); + assert(!(nullptr < p2)); + assert( (p2 <= nullptr)); + assert( (nullptr <= p2)); + assert(!(p2 > nullptr)); + assert(!(nullptr > p2)); + assert( (p2 >= nullptr)); + assert( (nullptr >= p2)); +} Added: libcxx/trunk/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp?rev=151084&view=auto ============================================================================== --- libcxx/trunk/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp (added) +++ libcxx/trunk/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp Tue Feb 21 15:02:58 2012 @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template +// bool operator==(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator==(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator!=(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator!=(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator<(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator<(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator<=(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator<=(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator>(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator>(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator>=(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator>=(nullptr_t, const shared_ptr& y) noexcept; + +#include +#include + +void do_nothing(int*) {} + +int main() +{ + int* ptr1(new int); + int* ptr2(new int); + const std::shared_ptr p1(new int(1)); + assert(!(p1 == nullptr)); + assert(!(nullptr == p1)); + assert(!(p1 < nullptr)); + assert( (nullptr < p1)); + assert(!(p1 <= nullptr)); + assert( (nullptr <= p1)); + assert( (p1 > nullptr)); + assert(!(nullptr > p1)); + assert( (p1 >= nullptr)); + assert(!(nullptr >= p1)); + + const std::shared_ptr p2; + assert( (p2 == nullptr)); + assert( (nullptr == p2)); + assert(!(p2 < nullptr)); + assert(!(nullptr < p2)); + assert( (p2 <= nullptr)); + assert( (nullptr <= p2)); + assert(!(p2 > nullptr)); + assert(!(nullptr > p2)); + assert( (p2 >= nullptr)); + assert( (nullptr >= p2)); +} From gregory.szorc at gmail.com Tue Feb 21 10:06:02 2012 From: gregory.szorc at gmail.com (Gregory Szorc) Date: Tue, 21 Feb 2012 10:06:02 -0800 Subject: [cfe-commits] [PATCH 3/5] [clang.py] Implement Type.arguments() In-Reply-To: References: <4F40B783.2020709@grosser.es> <4F4145B7.20504@gmail.com> Message-ID: Author: gps Date: Mon Feb 20 11:45:30 2012 New Revision: 150970 URL: http://llvm.org/viewvc/llvm-project?rev=150970&view=rev Log: [clang.py] Implement Type.argument_types() Modified: cfe/trunk/bindings/python/clang/cindex.py cfe/trunk/bindings/python/tests/cindex/test_type.py On 2/20/12 9:06 AM, Manuel Klimek wrote: > On Sun, Feb 19, 2012 at 10:55 AM, Gregory Szorc wrote: >> On 2/19/2012 12:49 AM, Tobias Grosser wrote: >>> On 02/19/2012 05:39 AM, Gregory Szorc wrote: >>>> Does anyone else think that "arguments" may not be the best name? >>>> Perhaps "argument_types" would be more suitable... >>> >>> Yes. I agree. Either name it argument_types, or return a class called >>> 'argument' that than has a .type() function. Returning a class is >>> probably overhead, as it would only have a single function. I would >>> just name the iterator argument_types(). >>> >>> Also, I just realized you define the __iter__(self) method. Why is >>> that needed? Diagnostic.ranges() gets away without using it? >> >> argument_types() it is. It seems __iter__ has a default implementation >> somewhere (I guess in object). In the current patch, I changed the class >> to derive from collections.Sequence. This is more appropriate than >> deriving from object and the default implementation of __iter__ there >> works as expected (it calls __getitem__ from 0..n until __getitem__ >> throws IndexError). > > The one thing that strikes me as odd is that the method is on the > "Type", but it looks like that's a design decision that was made > earlier (just wandering what this will become in the future if *all* > methods of all Type subclasses in the AST become accessible from that > one class) > > Otherwise looks good. > > Cheers, > /Manuel > > >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> From rtrieu at google.com Tue Feb 21 13:40:05 2012 From: rtrieu at google.com (Richard Trieu) Date: Tue, 21 Feb 2012 21:40:05 -0000 Subject: [cfe-commits] r151087 - /cfe/trunk/test/CodeGenObjCXX/debug-info.mm Message-ID: <20120221214006.0B6752A6C12F@llvm.org> Author: rtrieu Date: Tue Feb 21 15:40:05 2012 New Revision: 151087 URL: http://llvm.org/viewvc/llvm-project?rev=151087&view=rev Log: Redirect the output to /dev/null. This prevents the output from cluttering up the build enviroment. Modified: cfe/trunk/test/CodeGenObjCXX/debug-info.mm Modified: cfe/trunk/test/CodeGenObjCXX/debug-info.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/debug-info.mm?rev=151087&r1=151086&r2=151087&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjCXX/debug-info.mm (original) +++ cfe/trunk/test/CodeGenObjCXX/debug-info.mm Tue Feb 21 15:40:05 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-obj %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-obj %s -o /dev/null // This test passes if clang doesn't crash. From hhinnant at apple.com Tue Feb 21 13:46:43 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Tue, 21 Feb 2012 21:46:43 -0000 Subject: [cfe-commits] [libcxx] r151088 - in /libcxx/trunk/include: __config __mutex_base exception functional ios istream memory ostream system_error Message-ID: <20120221214644.0EA092A6C12F@llvm.org> Author: hhinnant Date: Tue Feb 21 15:46:43 2012 New Revision: 151088 URL: http://llvm.org/viewvc/llvm-project?rev=151088&view=rev Log: Modernize conversion to bool to the explicit bool conversion operator (library wide). This fixes http://llvm.org/bugs/show_bug.cgi?id=12058. Modified: libcxx/trunk/include/__config libcxx/trunk/include/__mutex_base libcxx/trunk/include/exception libcxx/trunk/include/functional libcxx/trunk/include/ios libcxx/trunk/include/istream libcxx/trunk/include/memory libcxx/trunk/include/ostream libcxx/trunk/include/system_error Modified: libcxx/trunk/include/__config URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/__config (original) +++ libcxx/trunk/include/__config Tue Feb 21 15:46:43 2012 @@ -376,6 +376,12 @@ #define __has_feature(__x) 0 #endif +#if __has_feature(cxx_explicit_conversions) +# define _LIBCPP_EXPLICIT explicit +#else +# define _LIBCPP_EXPLICIT +#endif + #ifdef _LIBCPP_HAS_NO_STRONG_ENUMS #define _LIBCPP_DECLARE_STRONG_ENUM(x) struct _LIBCPP_VISIBLE x { enum _ #define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ Modified: libcxx/trunk/include/__mutex_base URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__mutex_base?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/__mutex_base (original) +++ libcxx/trunk/include/__mutex_base Tue Feb 21 15:46:43 2012 @@ -207,7 +207,7 @@ _LIBCPP_INLINE_VISIBILITY bool owns_lock() const {return __owns_;} _LIBCPP_INLINE_VISIBILITY -// explicit + _LIBCPP_EXPLICIT operator bool () const {return __owns_;} _LIBCPP_INLINE_VISIBILITY mutex_type* mutex() const {return __m_;} Modified: libcxx/trunk/include/exception URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/exception?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/exception (original) +++ libcxx/trunk/include/exception Tue Feb 21 15:46:43 2012 @@ -132,7 +132,7 @@ ~exception_ptr() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY - // explicit + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __ptr_ != nullptr;} friend _LIBCPP_INLINE_VISIBILITY Modified: libcxx/trunk/include/functional URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/functional (original) +++ libcxx/trunk/include/functional Tue Feb 21 15:46:43 2012 @@ -1163,7 +1163,7 @@ // function capacity: _LIBCPP_INLINE_VISIBILITY - /*explicit*/ operator bool() const _NOEXCEPT {return __f_;} + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __f_;} // deleted overloads close possible hole in the type system template Modified: libcxx/trunk/include/ios URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/ios?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/ios (original) +++ libcxx/trunk/include/ios Tue Feb 21 15:46:43 2012 @@ -572,7 +572,8 @@ typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; - _LIBCPP_ALWAYS_INLINE // explicit + _LIBCPP_ALWAYS_INLINE + _LIBCPP_EXPLICIT operator bool() const {return !fail();} _LIBCPP_ALWAYS_INLINE bool operator!() const {return fail();} _LIBCPP_ALWAYS_INLINE iostate rdstate() const {return ios_base::rdstate();} Modified: libcxx/trunk/include/istream URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/istream?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/istream (original) +++ libcxx/trunk/include/istream Tue Feb 21 15:46:43 2012 @@ -256,7 +256,7 @@ // ~sentry() = default; _LIBCPP_INLINE_VISIBILITY - // explicit + _LIBCPP_EXPLICIT operator bool() const {return __ok_;} }; Modified: libcxx/trunk/include/memory URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/memory (original) +++ libcxx/trunk/include/memory Tue Feb 21 15:46:43 2012 @@ -2688,9 +2688,9 @@ {return __ptr_.second();} _LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT {return __ptr_.second();} - _LIBCPP_INLINE_VISIBILITY operator int __nat::*() const - _NOEXCEPT - {return __ptr_.first() ? &__nat::__for_bool_ : 0;} + _LIBCPP_INLINE_VISIBILITY + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT + {return __ptr_.first() != nullptr;} _LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT { @@ -2881,8 +2881,9 @@ {return __ptr_.second();} _LIBCPP_INLINE_VISIBILITY _Dp_const_reference get_deleter() const _NOEXCEPT {return __ptr_.second();} - _LIBCPP_INLINE_VISIBILITY operator int __nat::*() const _NOEXCEPT - {return __ptr_.first() ? &__nat::__for_bool_ : 0;} + _LIBCPP_INLINE_VISIBILITY + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT + {return __ptr_.first() != nullptr;} _LIBCPP_INLINE_VISIBILITY pointer release() _NOEXCEPT { @@ -3937,7 +3938,7 @@ _LIBCPP_INLINE_VISIBILITY bool unique() const _NOEXCEPT {return use_count() == 1;} _LIBCPP_INLINE_VISIBILITY - /*explicit*/ operator bool() const _NOEXCEPT {return get() != 0;} + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return get() != 0;} template _LIBCPP_INLINE_VISIBILITY bool owner_before(shared_ptr<_Up> const& __p) const Modified: libcxx/trunk/include/ostream URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/ostream?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/ostream (original) +++ libcxx/trunk/include/ostream Tue Feb 21 15:46:43 2012 @@ -220,7 +220,7 @@ ~sentry(); _LIBCPP_ALWAYS_INLINE - // explicit + _LIBCPP_EXPLICIT operator bool() const {return __ok_;} }; Modified: libcxx/trunk/include/system_error URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/system_error?rev=151088&r1=151087&r2=151088&view=diff ============================================================================== --- libcxx/trunk/include/system_error (original) +++ libcxx/trunk/include/system_error Tue Feb 21 15:46:43 2012 @@ -451,7 +451,7 @@ string message() const; _LIBCPP_ALWAYS_INLINE - //explicit + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; @@ -528,7 +528,7 @@ string message() const; _LIBCPP_ALWAYS_INLINE - //explicit + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; From rjmccall at apple.com Tue Feb 21 13:48:06 2012 From: rjmccall at apple.com (John McCall) Date: Tue, 21 Feb 2012 21:48:06 -0000 Subject: [cfe-commits] r151089 - in /cfe/trunk: lib/Sema/SemaObjCProperty.cpp test/SemaObjC/arc-property.m Message-ID: <20120221214806.36A332A6C12F@llvm.org> Author: rjmccall Date: Tue Feb 21 15:48:05 2012 New Revision: 151089 URL: http://llvm.org/viewvc/llvm-project?rev=151089&view=rev Log: Don't crash on attempts to synthesize an invalid property. rdar://problem/10904479 Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp cfe/trunk/test/SemaObjC/arc-property.m Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=151089&r1=151088&r2=151089&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original) +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Tue Feb 21 15:48:05 2012 @@ -1777,6 +1777,7 @@ Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)"); Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong); + PropertyDecl->setInvalidDecl(); } // Check for more than one of { assign, copy, retain }. Modified: cfe/trunk/test/SemaObjC/arc-property.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-property.m?rev=151089&r1=151088&r2=151089&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/arc-property.m (original) +++ cfe/trunk/test/SemaObjC/arc-property.m Tue Feb 21 15:48:05 2012 @@ -46,3 +46,12 @@ @synthesize z; // suppressed @end +// rdar://problem/10904479 +// Don't crash. + at interface Test2 +// Minor FIXME: kill the redundant error + at property (strong) UndeclaredClass *test2; // expected-error {{unknown type name 'UndeclaredClass'}} expected-error {{must be of object type}} + at end + at implementation Test2 + at synthesize test2; + at end From chandlerc at gmail.com Tue Feb 21 13:51:40 2012 From: chandlerc at gmail.com (Chandler Carruth) Date: Tue, 21 Feb 2012 21:51:40 -0000 Subject: [cfe-commits] r151090 - /cfe/trunk/test/Driver/gcc-toolchain.cpp Message-ID: <20120221215140.9851B2A6C12F@llvm.org> Author: chandlerc Date: Tue Feb 21 15:51:40 2012 New Revision: 151090 URL: http://llvm.org/viewvc/llvm-project?rev=151090&view=rev Log: Clean up, add some documentation, and make this test return to checking the linker toolchainness a bit more thoroughly. It used to work this way, but hit buildbot issues. Hopefully subsequent fixes have addressed those problems, but I'll be watching the bots. Modified: cfe/trunk/test/Driver/gcc-toolchain.cpp Modified: cfe/trunk/test/Driver/gcc-toolchain.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/gcc-toolchain.cpp?rev=151090&r1=151089&r2=151090&view=diff ============================================================================== --- cfe/trunk/test/Driver/gcc-toolchain.cpp (original) +++ cfe/trunk/test/Driver/gcc-toolchain.cpp Tue Feb 21 15:51:40 2012 @@ -4,22 +4,20 @@ // RUN: -target i386-unknown-linux \ // RUN: -gcc-toolchain %S/Inputs/ubuntu_11.04_multiarch_tree/usr \ // RUN: | FileCheck %s - +// +// Test for header search toolchain detection. // CHECK: "-internal-isystem" // CHECK: "[[TOOLCHAIN:[^"]+]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../../../include/c++/4.5" // CHECK: "-internal-isystem" // CHECK: "[[TOOLCHAIN]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../../../include/c++/4.5/i686-linux-gnu" // CHECK: "-internal-isystem" // CHECK: "[[TOOLCHAIN]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../../../include/c++/4.5/backward" -// CHECK: "-internal-isystem" -// CHECK: "/usr/local/include" -// CHECK: "-internal-isystem" -// CHECK: lib/clang/3.1/include" -// CHECK: "-internal-externc-isystem" -// CHECK: "/include" -// CHECK: "-internal-externc-isystem" -// CHECK: "/usr/include" +// CHECK: "-internal-isystem" "/usr/local/include" +// +// Test for linker toolchain detection. Note that we use a separate variable +// because the '/'s may be different in the linker invocation than in the +// header search. // CHECK: "{{[^"]*}}ld{{(.exe)?}}" -// CHECK: "{{[^"]*}}/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/crtbegin.o" -// CHECK: "-L{{[^"]*}}/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5" -// CHECK: "-L{{[^"]*}}/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../.." +// CHECK: "[[TOOLCHAIN2:[^"]*]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/crtbegin.o" +// CHECK: "-L[[TOOLCHAIN2]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5" +// CHECK: "-L[[TOOLCHAIN2]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../.." From chandlerc at gmail.com Tue Feb 21 14:21:50 2012 From: chandlerc at gmail.com (Chandler Carruth) Date: Tue, 21 Feb 2012 22:21:50 -0000 Subject: [cfe-commits] r151094 - /cfe/trunk/test/Driver/gcc-toolchain.cpp Message-ID: <20120221222150.7C6DE2A6C12F@llvm.org> Author: chandlerc Date: Tue Feb 21 16:21:50 2012 New Revision: 151094 URL: http://llvm.org/viewvc/llvm-project?rev=151094&view=rev Log: Skip testing the crtbegin.o, and resume using a single variable for the prefixes. It seems only crtbegin.o uses the strange formatting. Modified: cfe/trunk/test/Driver/gcc-toolchain.cpp Modified: cfe/trunk/test/Driver/gcc-toolchain.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/gcc-toolchain.cpp?rev=151094&r1=151093&r2=151094&view=diff ============================================================================== --- cfe/trunk/test/Driver/gcc-toolchain.cpp (original) +++ cfe/trunk/test/Driver/gcc-toolchain.cpp Tue Feb 21 16:21:50 2012 @@ -14,10 +14,10 @@ // CHECK: "[[TOOLCHAIN]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../../../include/c++/4.5/backward" // CHECK: "-internal-isystem" "/usr/local/include" // -// Test for linker toolchain detection. Note that we use a separate variable -// because the '/'s may be different in the linker invocation than in the -// header search. +// Test for linker toolchain detection. Note that only the '-L' flags will use +// the same precise formatting of the path as the '-internal-system' flags +// above, so we just blanket wildcard match the 'crtbegin.o'. // CHECK: "{{[^"]*}}ld{{(.exe)?}}" -// CHECK: "[[TOOLCHAIN2:[^"]*]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/crtbegin.o" -// CHECK: "-L[[TOOLCHAIN2]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5" -// CHECK: "-L[[TOOLCHAIN2]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../.." +// CHECK: "{{[^"]*}}/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/crtbegin.o" +// CHECK: "-L[[TOOLCHAIN]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5" +// CHECK: "-L[[TOOLCHAIN]]/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5/../../../.." From echristo at apple.com Tue Feb 21 14:25:20 2012 From: echristo at apple.com (Eric Christopher) Date: Tue, 21 Feb 2012 22:25:20 -0000 Subject: [cfe-commits] r151095 - /cfe/trunk/test/CodeGenObjCXX/debug-info.mm Message-ID: <20120221222520.99A292A6C12F@llvm.org> Author: echristo Date: Tue Feb 21 16:25:20 2012 New Revision: 151095 URL: http://llvm.org/viewvc/llvm-project?rev=151095&view=rev Log: No need to go to object file, -emit-llvm is sufficient to see if clang itself crashes. Modified: cfe/trunk/test/CodeGenObjCXX/debug-info.mm Modified: cfe/trunk/test/CodeGenObjCXX/debug-info.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/debug-info.mm?rev=151095&r1=151094&r2=151095&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjCXX/debug-info.mm (original) +++ cfe/trunk/test/CodeGenObjCXX/debug-info.mm Tue Feb 21 16:25:20 2012 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-obj %s -o /dev/null +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-llvm %s -o /dev/null // This test passes if clang doesn't crash. From eli.friedman at gmail.com Tue Feb 21 14:41:33 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 21 Feb 2012 22:41:33 -0000 Subject: [cfe-commits] r151100 - in /cfe/trunk: lib/AST/ExprConstant.cpp test/Sema/const-eval.c Message-ID: <20120221224133.8DF2F2A6C12F@llvm.org> Author: efriedma Date: Tue Feb 21 16:41:33 2012 New Revision: 151100 URL: http://llvm.org/viewvc/llvm-project?rev=151100&view=rev Log: Fix a crash in the diangostic code in EvalConstant. PR12043. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/Sema/const-eval.c Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=151100&r1=151099&r2=151100&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Feb 21 16:41:33 2012 @@ -538,8 +538,10 @@ = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { // Don't override a previous diagnostic. - if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) + if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) { + HasActiveDiagnostic = false; return OptionalDiagnostic(); + } return Diag(Loc, DiagId, ExtraNotes); } Modified: cfe/trunk/test/Sema/const-eval.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/const-eval.c?rev=151100&r1=151099&r2=151100&view=diff ============================================================================== --- cfe/trunk/test/Sema/const-eval.c (original) +++ cfe/trunk/test/Sema/const-eval.c Tue Feb 21 16:41:33 2012 @@ -112,3 +112,8 @@ // PR11391. struct PR11391 { _Complex float f; } pr11391; EVAL_EXPR(42, __builtin_constant_p(pr11391.f = 1)) + +// PR12043 +float varfloat; +const float constfloat = 0; +EVAL_EXPR(43, varfloat && constfloat) // expected-error {{must have a constant size}} From dgregor at apple.com Tue Feb 21 14:51:27 2012 From: dgregor at apple.com (Douglas Gregor) Date: Tue, 21 Feb 2012 22:51:27 -0000 Subject: [cfe-commits] r151101 - in /cfe/trunk: lib/Parse/ParseExprCXX.cpp test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp Message-ID: <20120221225128.0E18E2A6C12F@llvm.org> Author: dgregor Date: Tue Feb 21 16:51:27 2012 New Revision: 151101 URL: http://llvm.org/viewvc/llvm-project?rev=151101&view=rev Log: In the conflict between C++11 [expr.prim.general]p4, which declares that 'this' can be used in the brace-or-equal-initializer of a non-static data member, and C++11 [expr.prim.lambda]p9, which says that lambda expressions not in block scope can have no captures, side fully with C++11 [expr.prim.general]p4 by allowing 'this' to be captured within these initializers. This seems to be the intent of non-static data member initializers. Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=151101&r1=151100&r2=151101&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Feb 21 16:51:27 2012 @@ -870,8 +870,10 @@ // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using // it. - ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope | - Scope::DeclScope); + unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope; + if (getCurScope()->getFlags() & Scope::ThisScope) + ScopeFlags |= Scope::ThisScope; + ParseScope BodyScope(this, ScopeFlags); Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope()); Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp?rev=151101&r1=151100&r2=151101&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp Tue Feb 21 16:51:27 2012 @@ -7,3 +7,14 @@ int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} int sz = sizeof(this); // ok }; + +namespace CaptureThis { + struct X { + int n = 10; + int m = [&]{return n + 1; }(); + int o = [&]{return this->m + 1; }(); + int p = [&]{return [&](int x) { return this->m + x;}(o); }(); + }; + + X x; +} From akyrtzi at gmail.com Tue Feb 21 15:41:58 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Tue, 21 Feb 2012 23:41:58 -0000 Subject: [cfe-commits] r151102 - /cfe/trunk/include/clang/AST/Stmt.h Message-ID: <20120221234158.5F0682A6C12F@llvm.org> Author: akirtzidis Date: Tue Feb 21 17:41:58 2012 New Revision: 151102 URL: http://llvm.org/viewvc/llvm-project?rev=151102&view=rev Log: Make sure Stmt::dump() is included in libclang. Modified: cfe/trunk/include/clang/AST/Stmt.h Modified: cfe/trunk/include/clang/AST/Stmt.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=151102&r1=151101&r2=151102&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Stmt.h (original) +++ cfe/trunk/include/clang/AST/Stmt.h Tue Feb 21 17:41:58 2012 @@ -307,8 +307,8 @@ /// dump - This does a local dump of the specified AST fragment. It dumps the /// specified node and a few nodes underneath it, but not the whole subtree. /// This is useful in a debugger. - void dump() const; - void dump(SourceManager &SM) const; + LLVM_ATTRIBUTE_USED void dump() const; + LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; void dump(raw_ostream &OS, SourceManager &SM) const; /// dumpAll - This does a dump of the specified AST fragment and all subtrees. From fjahanian at apple.com Tue Feb 21 15:46:49 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Tue, 21 Feb 2012 23:46:49 -0000 Subject: [cfe-commits] r151103 - in /cfe/trunk: lib/Rewrite/RewriteModernObjC.cpp test/Rewriter/rewrite-modern-class.mm Message-ID: <20120221234649.1ABDA2A6C12F@llvm.org> Author: fjahanian Date: Tue Feb 21 17:46:48 2012 New Revision: 151103 URL: http://llvm.org/viewvc/llvm-project?rev=151103&view=rev Log: objective-c modern translator. accessing ivars using modern abi - wip. Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp cfe/trunk/test/Rewriter/rewrite-modern-class.mm Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp?rev=151103&r1=151102&r2=151103&view=diff ============================================================================== --- cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp (original) +++ cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Tue Feb 21 17:46:48 2012 @@ -6408,7 +6408,7 @@ ObjCIvarDecl *D = IV->getDecl(); Expr *Replacement = IV; - if (CurMethodDef) { + if (BaseExpr->getType()->isObjCObjectPointerType()) { const ObjCInterfaceType *iFaceDecl = dyn_cast(BaseExpr->getType()->getPointeeType()); @@ -6419,70 +6419,46 @@ clsDeclared); assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); - // Synthesize an explicit cast to gain access to the ivar. - std::string RecName = clsDeclared->getIdentifier()->getName(); - RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName); - RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), SourceLocation(), - II); - assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); - QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); - CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, + // Build name of symbol holding ivar offset. + std::string IvarOffsetName = "OBJC_IVAR_$_"; + IvarOffsetName += clsDeclared->getIdentifier()->getName(); + IvarOffsetName += "_"; + IvarOffsetName += D->getName(); + // cast offset to "char *". + CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(Context->CharTy), CK_BitCast, - IV->getBase()); + BaseExpr); + VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), + SourceLocation(), &Context->Idents.get(IvarOffsetName), + Context->UnsignedLongTy, 0, SC_Extern, SC_None); + DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, Context->UnsignedLongTy, VK_LValue, + SourceLocation()); + BinaryOperator *addExpr = + new (Context) BinaryOperator(castExpr, DRE, BO_Add, + Context->getPointerType(Context->CharTy), + VK_RValue, OK_Ordinary, SourceLocation()); // Don't forget the parens to enforce the proper binding. - ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(), - OldRange.getEnd(), - castExpr); - if (IV->isFreeIvar() && - declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) { - MemberExpr *ME = new (Context) MemberExpr(PE, true, D, - IV->getLocation(), - D->getType(), - VK_LValue, OK_Ordinary); - Replacement = ME; - } else { - IV->setBase(PE); - } - } - } else { // we are outside a method. - assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); - - // Explicit ivar refs need to have a cast inserted. - // FIXME: consider sharing some of this code with the code above. - if (BaseExpr->getType()->isObjCObjectPointerType()) { - const ObjCInterfaceType *iFaceDecl = - dyn_cast(BaseExpr->getType()->getPointeeType()); - // lookup which class implements the instance variable. - ObjCInterfaceDecl *clsDeclared = 0; - iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), - clsDeclared); - assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); + ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), + SourceLocation(), + addExpr); - // Synthesize an explicit cast to gain access to the ivar. - std::string RecName = clsDeclared->getIdentifier()->getName(); - RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName); - RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), SourceLocation(), - II); - assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); - QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); - CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, - CK_BitCast, - IV->getBase()); - // Don't forget the parens to enforce the proper binding. - ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), - IV->getBase()->getLocEnd(), castExpr); - // Cannot delete IV->getBase(), since PE points to it. - // Replace the old base with the cast. This is important when doing - // embedded rewrites. For example, [newInv->_container addObject:0]. - IV->setBase(PE); + QualType castT = Context->getPointerType(D->getType()); + castExpr = NoTypeInfoCStyleCastExpr(Context, + castT, + CK_BitCast, + PE); + Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, castT, + VK_LValue, OK_Ordinary, + SourceLocation()); + PE = new (Context) ParenExpr(OldRange.getBegin(), + OldRange.getEnd(), + Exp); + + Replacement = PE; } - } - ReplaceStmtWithRange(IV, Replacement, OldRange); - return Replacement; + ReplaceStmtWithRange(IV, Replacement, OldRange); + return Replacement; } Modified: cfe/trunk/test/Rewriter/rewrite-modern-class.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-class.mm?rev=151103&r1=151102&r2=151103&view=diff ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-class.mm (original) +++ cfe/trunk/test/Rewriter/rewrite-modern-class.mm Tue Feb 21 17:46:48 2012 @@ -56,6 +56,7 @@ @implementation INTF - (SUPER *) Meth : (SUPER *)arg { - return arg->p_super; +// NYI - return arg->p_super; + return (SUPER *)0; } @end From fjahanian at apple.com Tue Feb 21 15:58:42 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Tue, 21 Feb 2012 23:58:42 -0000 Subject: [cfe-commits] r151106 - in /cfe/trunk: lib/Rewrite/RewriteModernObjC.cpp test/Rewriter/rewrite-modern-class.mm Message-ID: <20120221235842.20BF32A6C12F@llvm.org> Author: fjahanian Date: Tue Feb 21 17:58:41 2012 New Revision: 151106 URL: http://llvm.org/viewvc/llvm-project?rev=151106&view=rev Log: modern objc translator: fixes a bug where a class declaration with not any implementation in tu was not being translated. Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp cfe/trunk/test/Rewriter/rewrite-modern-class.mm Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp?rev=151106&r1=151105&r2=151106&view=diff ============================================================================== --- cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp (original) +++ cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Tue Feb 21 17:58:41 2012 @@ -3230,16 +3230,6 @@ /// and emits meta-data. void RewriteModernObjC::RewriteImplementations() { - - for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) { - ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i]; - // Write struct declaration for the class matching its ivar declarations. - // Note that for modern abi, this is postponed until the end of TU - // because class extensions and the implementation might declare their own - // private ivars. - RewriteInterfaceDecl(CDecl); - } - int ClsDefCount = ClassImplementation.size(); int CatDefCount = CategoryImplementation.size(); @@ -5022,6 +5012,15 @@ RewriteObjCProtocolMetaData(*I, Preamble); InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); + for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) { + ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i]; + // Write struct declaration for the class matching its ivar declarations. + // Note that for modern abi, this is postponed until the end of TU + // because class extensions and the implementation might declare their own + // private ivars. + RewriteInterfaceDecl(CDecl); + } + if (ClassImplementation.size() || CategoryImplementation.size()) RewriteImplementations(); Modified: cfe/trunk/test/Rewriter/rewrite-modern-class.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-class.mm?rev=151106&r1=151105&r2=151106&view=diff ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-class.mm (original) +++ cfe/trunk/test/Rewriter/rewrite-modern-class.mm Tue Feb 21 17:58:41 2012 @@ -60,3 +60,12 @@ return (SUPER *)0; } @end + + at class FORM_CLASS; + at interface INTF_DECL { +} + at end + +double Meth(INTF_DECL *p, FORM_CLASS *f) { + return 1.34; +} From jfreeman at cse.tamu.edu Tue Feb 21 16:09:59 2012 From: jfreeman at cse.tamu.edu (John Freeman) Date: Tue, 21 Feb 2012 18:09:59 -0600 Subject: [cfe-commits] [Patch] Tests for C++11 lambda expressions Message-ID: <4F443257.5020306@cse.tamu.edu> This is a small start based on a run-through of the FDIS. Some errors seem poorly diagnosed in the revision I used (b09ab8c on the Git mirror; I believe after r151076 in the Subversion repo). I wrote the tests as I would like to see them diagnosed instead of how they are currently, so those show up as unexpected failures. A missing feature (specifically conversion to function-to-pointer) also appears as an unexpected failure. Please let me know what other tests would be desired, and I'll write them up. Please also point out any mistakes I made with these tests. I want to make sure they conform to Clang's standards. - John -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: lambda-tests.patch URL: From zarzycki at apple.com Tue Feb 21 16:20:30 2012 From: zarzycki at apple.com (Dave Zarzycki) Date: Wed, 22 Feb 2012 00:20:30 -0000 Subject: [cfe-commits] [libcxx] r151108 - /libcxx/trunk/test/testit Message-ID: <20120222002030.D3AD62A6C12F@llvm.org> Author: zarzycki Date: Tue Feb 21 18:20:30 2012 New Revision: 151108 URL: http://llvm.org/viewvc/llvm-project?rev=151108&view=rev Log: Use Xcode relative compilers when possible Modified: libcxx/trunk/test/testit Modified: libcxx/trunk/test/testit URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/testit?rev=151108&r1=151107&r2=151108&view=diff ============================================================================== --- libcxx/trunk/test/testit (original) +++ libcxx/trunk/test/testit Tue Feb 21 18:20:30 2012 @@ -10,7 +10,12 @@ if [ -z $CC ] then - CC=clang++ + if which xcrun >/dev/null + then + CC="xcrun clang++" + else + CC=clang++ + fi fi if [ -z "$OPTIONS" ] From mcrosier at apple.com Tue Feb 21 16:30:39 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 22 Feb 2012 00:30:39 -0000 Subject: [cfe-commits] r151109 - in /cfe/trunk: include/clang/Driver/Options.td lib/Driver/Driver.cpp Message-ID: <20120222003039.C2FCD2A6C12F@llvm.org> Author: mcrosier Date: Tue Feb 21 18:30:39 2012 New Revision: 151109 URL: http://llvm.org/viewvc/llvm-project?rev=151109&view=rev Log: Provide a way to disable auto-generation of preprocessed files during clang crash. This can speedup the process of generating a delta reduced test case. rdar://10905465 Modified: cfe/trunk/include/clang/Driver/Options.td cfe/trunk/lib/Driver/Driver.cpp Modified: cfe/trunk/include/clang/Driver/Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=151109&r1=151108&r2=151109&view=diff ============================================================================== --- cfe/trunk/include/clang/Driver/Options.td (original) +++ cfe/trunk/include/clang/Driver/Options.td Tue Feb 21 18:30:39 2012 @@ -292,6 +292,7 @@ def fconstexpr_depth_EQ : Joined<"-fconstexpr-depth=">, Group; def fconstexpr_backtrace_limit_EQ : Joined<"-fconstexpr-backtrace-limit=">, Group; +def fno_crash_diagnostics : Flag<"-fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>; def fcreate_profile : Flag<"-fcreate-profile">, Group; def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group; def fcxx_modules : Flag <"-fcxx-modules">, Group, Flags<[NoForward]>; Modified: cfe/trunk/lib/Driver/Driver.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=151109&r1=151108&r2=151109&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Driver.cpp (original) +++ cfe/trunk/lib/Driver/Driver.cpp Tue Feb 21 18:30:39 2012 @@ -363,6 +363,9 @@ // diagnostic information to a bug report. void Driver::generateCompilationDiagnostics(Compilation &C, const Command *FailingCommand) { + if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) + return; + Diag(clang::diag::note_drv_command_failed_diag_msg) << "Please submit a bug report to " BUG_REPORT_URL " and include command" " line arguments and all diagnostic information."; From thakis at chromium.org Tue Feb 21 16:42:43 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 21 Feb 2012 16:42:43 -0800 Subject: [cfe-commits] r150685 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/AST/Expr.cpp lib/AST/ExprCXX.cpp lib/AST/ItaniumMangle.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtProfile.cpp lib/CodeGen/CGExprCXX.cpp lib/Parse/ParseE Message-ID: It looks like this caused http://llvm.org/pr12061 (mentioning here to potentially save others some bisecting). Nico On Thu, Feb 16, 2012 at 4:22 AM, Sebastian Redl wrote: > Author: cornedbee > Date: Thu Feb 16 06:22:20 2012 > New Revision: 150685 > > URL: http://llvm.org/viewvc/llvm-project?rev=150685&view=rev > Log: > Revert "Revert "Make CXXNewExpr contain only a single initialier, and not hold the used constructor itself."" > > This reintroduces commit r150682 with a fix for the Bullet benchmark crash. > > Modified: >    cfe/trunk/include/clang/AST/ExprCXX.h >    cfe/trunk/include/clang/Sema/Sema.h >    cfe/trunk/lib/AST/Expr.cpp >    cfe/trunk/lib/AST/ExprCXX.cpp >    cfe/trunk/lib/AST/ItaniumMangle.cpp >    cfe/trunk/lib/AST/StmtPrinter.cpp >    cfe/trunk/lib/AST/StmtProfile.cpp >    cfe/trunk/lib/CodeGen/CGExprCXX.cpp >    cfe/trunk/lib/Parse/ParseExprCXX.cpp >    cfe/trunk/lib/Sema/SemaExpr.cpp >    cfe/trunk/lib/Sema/SemaExprCXX.cpp >    cfe/trunk/lib/Sema/TreeTransform.h >    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp >    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp >    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp >    cfe/trunk/test/Analysis/new.cpp >    cfe/trunk/test/SemaCXX/new-delete.cpp >    cfe/trunk/tools/libclang/CIndex.cpp > > Modified: cfe/trunk/include/clang/AST/ExprCXX.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/ExprCXX.h (original) > +++ cfe/trunk/include/clang/AST/ExprCXX.h Thu Feb 16 06:22:20 2012 > @@ -1359,34 +1359,24 @@ >  class CXXNewExpr : public Expr { >   // Was the usage ::new, i.e. is the global new to be used? >   bool GlobalNew : 1; > -  // Is there an initializer? If not, built-ins are uninitialized, else they're > -  // value-initialized. > -  bool Initializer : 1; >   // Do we allocate an array? If so, the first SubExpr is the size expression. >   bool Array : 1; >   // If this is an array allocation, does the usual deallocation >   // function for the allocated type want to know the allocated size? >   bool UsualArrayDeleteWantsSize : 1; > -  // Whether the referred constructor (if any) was resolved from an > -  // overload set having size greater than 1. > -  bool HadMultipleCandidates : 1; >   // The number of placement new arguments. >   unsigned NumPlacementArgs : 13; > -  // The number of constructor arguments. This may be 1 even for non-class > -  // types; use the pseudo copy constructor. > -  unsigned NumConstructorArgs : 14; > -  // Contains an optional array size expression, any number of optional > -  // placement arguments, and any number of optional constructor arguments, > -  // in that order. > +  // What kind of initializer do we have? Could be none, parens, or braces. > +  // In storage, we distinguish between "none, and no initializer expr", and > +  // "none, but an implicit initializer expr". > +  unsigned StoredInitializationStyle : 2; > +  // Contains an optional array size expression, an optional initialization > +  // expression, and any number of optional placement arguments, in that order. >   Stmt **SubExprs; >   // Points to the allocation function used. >   FunctionDecl *OperatorNew; >   // Points to the deallocation function used in case of error. May be null. >   FunctionDecl *OperatorDelete; > -  // Points to the constructor used. Cannot be null if AllocType is a record; > -  // it would still point at the default constructor (even an implicit one). > -  // Must be null for all other types. > -  CXXConstructorDecl *Constructor; > >   /// \brief The allocated type-source information, as written in the source. >   TypeSourceInfo *AllocatedTypeInfo; > @@ -1395,29 +1385,33 @@ >   /// the source range covering the parenthesized type-id. >   SourceRange TypeIdParens; > > +  /// \brief Location of the first token. >   SourceLocation StartLoc; > -  SourceLocation EndLoc; > -  SourceLocation ConstructorLParen; > -  SourceLocation ConstructorRParen; > + > +  /// \brief Source-range of a paren-delimited initializer. > +  SourceRange DirectInitRange; > >   friend class ASTStmtReader; > +  friend class ASTStmtWriter; >  public: > +  enum InitializationStyle { > +    NoInit,   ///< New-expression has no initializer as written. > +    CallInit, ///< New-expression has a C++98 paren-delimited initializer. > +    ListInit  ///< New-expression has a C++11 list-initializer. > +  }; > + >   CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, > -             Expr **placementArgs, unsigned numPlaceArgs, > -             SourceRange TypeIdParens, > -             Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, > -             Expr **constructorArgs, unsigned numConsArgs, > -             bool HadMultipleCandidates, >              FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, > +             Expr **placementArgs, unsigned numPlaceArgs, > +             SourceRange typeIdParens, Expr *arraySize, > +             InitializationStyle initializationStyle, Expr *initializer, >              QualType ty, TypeSourceInfo *AllocatedTypeInfo, > -             SourceLocation startLoc, SourceLocation endLoc, > -             SourceLocation constructorLParen, > -             SourceLocation constructorRParen); > +             SourceLocation startLoc, SourceRange directInitRange); >   explicit CXXNewExpr(EmptyShell Shell) >     : Expr(CXXNewExprClass, Shell), SubExprs(0) { } > >   void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, > -                         unsigned numConsArgs); > +                         bool hasInitializer); > >   QualType getAllocatedType() const { >     assert(getType()->isPointerType()); > @@ -1443,8 +1437,6 @@ >   void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } >   FunctionDecl *getOperatorDelete() const { return OperatorDelete; } >   void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } > -  CXXConstructorDecl *getConstructor() const { return Constructor; } > -  void setConstructor(CXXConstructorDecl *D) { Constructor = D; } > >   bool isArray() const { return Array; } >   Expr *getArraySize() { > @@ -1456,23 +1448,40 @@ > >   unsigned getNumPlacementArgs() const { return NumPlacementArgs; } >   Expr **getPlacementArgs() { > -    return reinterpret_cast(SubExprs + Array); > +    return reinterpret_cast(SubExprs + Array + hasInitializer()); >   } > >   Expr *getPlacementArg(unsigned i) { >     assert(i < NumPlacementArgs && "Index out of range"); > -    return cast(SubExprs[Array + i]); > +    return getPlacementArgs()[i]; >   } >   const Expr *getPlacementArg(unsigned i) const { >     assert(i < NumPlacementArgs && "Index out of range"); > -    return cast(SubExprs[Array + i]); > +    return const_cast(this)->getPlacementArg(i); >   } > >   bool isParenTypeId() const { return TypeIdParens.isValid(); } >   SourceRange getTypeIdParens() const { return TypeIdParens; } > >   bool isGlobalNew() const { return GlobalNew; } > -  bool hasInitializer() const { return Initializer; } > + > +  /// \brief Whether this new-expression has any initializer at all. > +  bool hasInitializer() const { return StoredInitializationStyle > 0; } > + > +  /// \brief The kind of initializer this new-expression has. > +  InitializationStyle getInitializationStyle() const { > +    if (StoredInitializationStyle == 0) > +      return NoInit; > +    return static_cast(StoredInitializationStyle-1); > +  } > + > +  /// \brief The initializer of this new-expression. > +  Expr *getInitializer() { > +    return hasInitializer() ? cast(SubExprs[Array]) : 0; > +  } > +  const Expr *getInitializer() const { > +    return hasInitializer() ? cast(SubExprs[Array]) : 0; > +  } > >   /// Answers whether the usual array deallocation function for the >   /// allocated type expects the size of the allocation as a > @@ -1481,71 +1490,39 @@ >     return UsualArrayDeleteWantsSize; >   } > > -  unsigned getNumConstructorArgs() const { return NumConstructorArgs; } > - > -  Expr **getConstructorArgs() { > -    return reinterpret_cast(SubExprs + Array + NumPlacementArgs); > -  } > - > -  Expr *getConstructorArg(unsigned i) { > -    assert(i < NumConstructorArgs && "Index out of range"); > -    return cast(SubExprs[Array + NumPlacementArgs + i]); > -  } > -  const Expr *getConstructorArg(unsigned i) const { > -    assert(i < NumConstructorArgs && "Index out of range"); > -    return cast(SubExprs[Array + NumPlacementArgs + i]); > -  } > - > -  /// \brief Whether the new expression refers a constructor that was > -  /// resolved from an overloaded set having size greater than 1. > -  bool hadMultipleCandidates() const { return HadMultipleCandidates; } > -  void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } > - >   typedef ExprIterator arg_iterator; >   typedef ConstExprIterator const_arg_iterator; > >   arg_iterator placement_arg_begin() { > -    return SubExprs + Array; > +    return SubExprs + Array + hasInitializer(); >   } >   arg_iterator placement_arg_end() { > -    return SubExprs + Array + getNumPlacementArgs(); > +    return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); >   } >   const_arg_iterator placement_arg_begin() const { > -    return SubExprs + Array; > +    return SubExprs + Array + hasInitializer(); >   } >   const_arg_iterator placement_arg_end() const { > -    return SubExprs + Array + getNumPlacementArgs(); > -  } > - > -  arg_iterator constructor_arg_begin() { > -    return SubExprs + Array + getNumPlacementArgs(); > -  } > -  arg_iterator constructor_arg_end() { > -    return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); > -  } > -  const_arg_iterator constructor_arg_begin() const { > -    return SubExprs + Array + getNumPlacementArgs(); > -  } > -  const_arg_iterator constructor_arg_end() const { > -    return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); > +    return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); >   } > >   typedef Stmt **raw_arg_iterator; >   raw_arg_iterator raw_arg_begin() { return SubExprs; } >   raw_arg_iterator raw_arg_end() { > -    return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); > +    return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); >   } >   const_arg_iterator raw_arg_begin() const { return SubExprs; } > -  const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } > +  const_arg_iterator raw_arg_end() const { > +    return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); > +  } > >   SourceLocation getStartLoc() const { return StartLoc; } > -  SourceLocation getEndLoc() const { return EndLoc; } > +  SourceLocation getEndLoc() const; > > -  SourceLocation getConstructorLParen() const { return ConstructorLParen; } > -  SourceLocation getConstructorRParen() const { return ConstructorRParen; } > +  SourceRange getDirectInitRange() const { return DirectInitRange; } > >   SourceRange getSourceRange() const { > -    return SourceRange(StartLoc, EndLoc); > +    return SourceRange(getStartLoc(), getEndLoc()); >   } > >   static bool classof(const Stmt *T) { > @@ -1555,9 +1532,7 @@ > >   // Iterators >   child_range children() { > -    return child_range(&SubExprs[0], > -                       &SubExprs[0] + Array + getNumPlacementArgs() > -                         + getNumConstructorArgs()); > +    return child_range(raw_arg_begin(), raw_arg_end()); >   } >  }; > > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb 16 06:22:20 2012 > @@ -3194,9 +3194,7 @@ >                          MultiExprArg PlacementArgs, >                          SourceLocation PlacementRParen, >                          SourceRange TypeIdParens, Declarator &D, > -                         SourceLocation ConstructorLParen, > -                         MultiExprArg ConstructorArgs, > -                         SourceLocation ConstructorRParen); > +                         Expr *Initializer); >   ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, >                          SourceLocation PlacementLParen, >                          MultiExprArg PlacementArgs, > @@ -3205,9 +3203,8 @@ >                          QualType AllocType, >                          TypeSourceInfo *AllocTypeInfo, >                          Expr *ArraySize, > -                         SourceLocation ConstructorLParen, > -                         MultiExprArg ConstructorArgs, > -                         SourceLocation ConstructorRParen, > +                         SourceRange DirectInitRange, > +                         Expr *Initializer, >                          bool TypeMayContainAuto = true); > >   bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, > > Modified: cfe/trunk/lib/AST/Expr.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/Expr.cpp (original) > +++ cfe/trunk/lib/AST/Expr.cpp Thu Feb 16 06:22:20 2012 > @@ -2041,10 +2041,7 @@ >     if (isTypeDependent()) >       CT = CT_Dependent; >     else > -      CT = MergeCanThrow( > -        CanCalleeThrow(C, this, cast(this)->getOperatorNew()), > -        CanCalleeThrow(C, this, cast(this)->getConstructor(), > -                       /*NullThrows*/false)); > +      CT = CanCalleeThrow(C, this, cast(this)->getOperatorNew()); >     if (CT == CT_Can) >       return CT; >     return MergeCanThrow(CT, CanSubExprsThrow(C, this)); > > Modified: cfe/trunk/lib/AST/ExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ExprCXX.cpp (original) > +++ cfe/trunk/lib/AST/ExprCXX.cpp Thu Feb 16 06:22:20 2012 > @@ -45,30 +45,26 @@ > >  // CXXNewExpr >  CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, > -                       Expr **placementArgs, unsigned numPlaceArgs, > -                       SourceRange TypeIdParens, Expr *arraySize, > -                       CXXConstructorDecl *constructor, bool initializer, > -                       Expr **constructorArgs, unsigned numConsArgs, > -                       bool HadMultipleCandidates, >                        FunctionDecl *operatorDelete, > -                       bool usualArrayDeleteWantsSize, QualType ty, > -                       TypeSourceInfo *AllocatedTypeInfo, > -                       SourceLocation startLoc, SourceLocation endLoc, > -                       SourceLocation constructorLParen, > -                       SourceLocation constructorRParen) > +                       bool usualArrayDeleteWantsSize, > +                       Expr **placementArgs, unsigned numPlaceArgs, > +                       SourceRange typeIdParens, Expr *arraySize, > +                       InitializationStyle initializationStyle, > +                       Expr *initializer, QualType ty, > +                       TypeSourceInfo *allocatedTypeInfo, > +                       SourceLocation startLoc, SourceRange directInitRange) >   : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, >          ty->isDependentType(), ty->isDependentType(), >          ty->isInstantiationDependentType(), >          ty->containsUnexpandedParameterPack()), > -    GlobalNew(globalNew), Initializer(initializer), > -    UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), > -    HadMultipleCandidates(HadMultipleCandidates), > -    SubExprs(0), OperatorNew(operatorNew), > -    OperatorDelete(operatorDelete), Constructor(constructor), > -    AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens), > -    StartLoc(startLoc), EndLoc(endLoc), ConstructorLParen(constructorLParen), > -    ConstructorRParen(constructorRParen) { > -  AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); > +    GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), > +    SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), > +    AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), > +    StartLoc(startLoc), DirectInitRange(directInitRange) { > +  assert((initializer != 0 || initializationStyle == NoInit) && > +         "Only NoInit can have no initializer."); > +  StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; > +  AllocateArgsArray(C, arraySize != 0, numPlaceArgs, initializer != 0); >   unsigned i = 0; >   if (Array) { >     if (arraySize->isInstantiationDependent()) > @@ -80,33 +76,33 @@ >     SubExprs[i++] = arraySize; >   } > > -  for (unsigned j = 0; j < NumPlacementArgs; ++j) { > -    if (placementArgs[j]->isInstantiationDependent()) > +  if (initializer) { > +    if (initializer->isInstantiationDependent()) >       ExprBits.InstantiationDependent = true; > -    if (placementArgs[j]->containsUnexpandedParameterPack()) > + > +    if (initializer->containsUnexpandedParameterPack()) >       ExprBits.ContainsUnexpandedParameterPack = true; > > -    SubExprs[i++] = placementArgs[j]; > +    SubExprs[i++] = initializer; >   } > > -  for (unsigned j = 0; j < NumConstructorArgs; ++j) { > -    if (constructorArgs[j]->isInstantiationDependent()) > +  for (unsigned j = 0; j < NumPlacementArgs; ++j) { > +    if (placementArgs[j]->isInstantiationDependent()) >       ExprBits.InstantiationDependent = true; > -    if (constructorArgs[j]->containsUnexpandedParameterPack()) > +    if (placementArgs[j]->containsUnexpandedParameterPack()) >       ExprBits.ContainsUnexpandedParameterPack = true; > > -    SubExprs[i++] = constructorArgs[j]; > +    SubExprs[i++] = placementArgs[j]; >   } >  } > >  void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, > -                                   unsigned numPlaceArgs, unsigned numConsArgs){ > +                                   unsigned numPlaceArgs, bool hasInitializer){ >   assert(SubExprs == 0 && "SubExprs already allocated"); >   Array = isArray; >   NumPlacementArgs = numPlaceArgs; > -  NumConstructorArgs = numConsArgs; > - > -  unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; > + > +  unsigned TotalSize = Array + hasInitializer + NumPlacementArgs; >   SubExprs = new (C) Stmt*[TotalSize]; >  } > > @@ -115,6 +111,17 @@ >     castAs()->isNothrow(Ctx); >  } > > +SourceLocation CXXNewExpr::getEndLoc() const { > +  switch (getInitializationStyle()) { > +  case NoInit: > +    return AllocatedTypeInfo->getTypeLoc().getEndLoc(); > +  case CallInit: > +    return DirectInitRange.getEnd(); > +  case ListInit: > +    return getInitializer()->getSourceRange().getEnd(); > +  } > +} > + >  // CXXDeleteExpr >  QualType CXXDeleteExpr::getDestroyedType() const { >   const Expr *Arg = getArgument(); > > Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) > +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Feb 16 06:22:20 2012 > @@ -2351,10 +2351,20 @@ >     Out << '_'; >     mangleType(New->getAllocatedType()); >     if (New->hasInitializer()) { > +      // FIXME: Does this mean "parenthesized initializer"? >       Out << "pi"; > -      for (CXXNewExpr::const_arg_iterator I = New->constructor_arg_begin(), > -             E = New->constructor_arg_end(); I != E; ++I) > -        mangleExpression(*I); > +      const Expr *Init = New->getInitializer(); > +      if (const CXXConstructExpr *CCE = dyn_cast(Init)) { > +        // Directly inline the initializers. > +        for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(), > +                                                  E = CCE->arg_end(); > +             I != E; ++I) > +          mangleExpression(*I); > +      } else if (const ParenListExpr *PLE = dyn_cast(Init)) { > +        for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i) > +          mangleExpression(PLE->getExpr(i)); > +      } else > +        mangleExpression(Init); >     } >     Out << 'E'; >     break; > > Modified: cfe/trunk/lib/AST/StmtPrinter.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/StmtPrinter.cpp (original) > +++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu Feb 16 06:22:20 2012 > @@ -1390,17 +1390,13 @@ >   if (E->isParenTypeId()) >     OS << ")"; > > -  if (E->hasInitializer()) { > -    OS << "("; > -    unsigned NumCons = E->getNumConstructorArgs(); > -    if (NumCons > 0) { > -      PrintExpr(E->getConstructorArg(0)); > -      for (unsigned i = 1; i < NumCons; ++i) { > -        OS << ", "; > -        PrintExpr(E->getConstructorArg(i)); > -      } > -    } > -    OS << ")"; > +  CXXNewExpr::InitializationStyle InitStyle = E->getInitializationStyle(); > +  if (InitStyle) { > +    if (InitStyle == CXXNewExpr::CallInit) > +      OS << "("; > +    PrintExpr(E->getInitializer()); > +    if (InitStyle == CXXNewExpr::CallInit) > +      OS << ")"; >   } >  } > > > Modified: cfe/trunk/lib/AST/StmtProfile.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/StmtProfile.cpp (original) > +++ cfe/trunk/lib/AST/StmtProfile.cpp Thu Feb 16 06:22:20 2012 > @@ -825,13 +825,11 @@ >   VisitType(S->getAllocatedType()); >   VisitDecl(S->getOperatorNew()); >   VisitDecl(S->getOperatorDelete()); > -  VisitDecl(S->getConstructor()); >   ID.AddBoolean(S->isArray()); >   ID.AddInteger(S->getNumPlacementArgs()); >   ID.AddBoolean(S->isGlobalNew()); >   ID.AddBoolean(S->isParenTypeId()); > -  ID.AddBoolean(S->hasInitializer()); > -  ID.AddInteger(S->getNumConstructorArgs()); > +  ID.AddInteger(S->getInitializationStyle()); >  } > >  void > > Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Feb 16 06:22:20 2012 > @@ -743,11 +743,8 @@ > >  static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E, >                                     llvm::Value *NewPtr) { > - > -  assert(E->getNumConstructorArgs() == 1 && > -         "Can only have one argument to initializer of POD type."); > - > -  const Expr *Init = E->getConstructorArg(0); > + > +  const Expr *Init = E->getInitializer(); >   QualType AllocType = E->getAllocatedType(); > >   CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType); > @@ -773,9 +770,8 @@ >                                          QualType elementType, >                                          llvm::Value *beginPtr, >                                          llvm::Value *numElements) { > -  // We have a POD type. > -  if (E->getNumConstructorArgs() == 0) > -    return; > +  if (!E->hasInitializer()) > +    return; // We have a POD type. > >   // Check if the number of elements is constant. >   bool checkZero = true; > @@ -858,13 +854,15 @@ >                                llvm::Value *NewPtr, >                                llvm::Value *NumElements, >                                llvm::Value *AllocSizeWithoutCookie) { > +  const Expr *Init = E->getInitializer(); >   if (E->isArray()) { > -    if (CXXConstructorDecl *Ctor = E->getConstructor()) { > +    if (const CXXConstructExpr *CCE = dyn_cast_or_null(Init)){ > +      CXXConstructorDecl *Ctor = CCE->getConstructor(); >       bool RequiresZeroInitialization = false; >       if (Ctor->getParent()->hasTrivialDefaultConstructor()) { >         // If new expression did not specify value-initialization, then there >         // is no initialization. > -        if (!E->hasInitializer() || Ctor->getParent()->isEmpty()) > +        if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty()) >           return; > >         if (CGF.CGM.getTypes().isZeroInitializable(ElementType)) { > @@ -877,43 +875,38 @@ >         RequiresZeroInitialization = true; >       } > > -      CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, > -                                     E->constructor_arg_begin(), > -                                     E->constructor_arg_end(), > +      CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, > +                                     CCE->arg_begin(),  CCE->arg_end(), >                                      RequiresZeroInitialization); >       return; > -    } else if (E->getNumConstructorArgs() == 1 && > -               isa(E->getConstructorArg(0)) && > +    } else if (Init && isa(Init) && >                CGF.CGM.getTypes().isZeroInitializable(ElementType)) { >       // Optimization: since zero initialization will just set the memory >       // to all zeroes, generate a single memset to do it in one shot. >       EmitZeroMemSet(CGF, ElementType, NewPtr, AllocSizeWithoutCookie); >       return; > -    } else { > -      CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements); > -      return; >     } > +    CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements); > +    return; >   } > > -  if (CXXConstructorDecl *Ctor = E->getConstructor()) { > +  if (const CXXConstructExpr *CCE = dyn_cast_or_null(Init)) { > +    CXXConstructorDecl *Ctor = CCE->getConstructor(); >     // Per C++ [expr.new]p15, if we have an initializer, then we're performing >     // direct initialization. C++ [dcl.init]p5 requires that we >     // zero-initialize storage if there are no user-declared constructors. > -    if (E->hasInitializer() && > -        !Ctor->getParent()->hasUserDeclaredConstructor() && > +    if (!Ctor->getParent()->hasUserDeclaredConstructor() && >         !Ctor->getParent()->isEmpty()) >       CGF.EmitNullInitialization(NewPtr, ElementType); > - > -    CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false, > -                               NewPtr, E->constructor_arg_begin(), > -                               E->constructor_arg_end()); > > +    CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false, > +                               NewPtr, CCE->arg_begin(), CCE->arg_end()); >     return; >   } >   // We have a POD type. > -  if (E->getNumConstructorArgs() == 0) > +  if (!Init) >     return; > - > + >   StoreAnyExprIntoOneUnit(CGF, E, NewPtr); >  } > > @@ -1145,7 +1138,7 @@ >   // CXXNewExpr::shouldNullCheckAllocation()) and we have an >   // interesting initializer. >   bool nullCheck = allocatorType->isNothrow(getContext()) && > -    !(allocType.isPODType(getContext()) && !E->hasInitializer()); > +    (!allocType.isPODType(getContext()) || E->hasInitializer()); > >   llvm::BasicBlock *nullCheckBB = 0; >   llvm::BasicBlock *contBB = 0; > @@ -1211,7 +1204,7 @@ >     DeactivateCleanupBlock(operatorDeleteCleanup, cleanupDominator); >     cleanupDominator->eraseFromParent(); >   } > - > + >   if (nullCheck) { >     conditional.end(*this); > > > Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) > +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Feb 16 06:22:20 2012 > @@ -2193,10 +2193,11 @@ >     return ExprError(); >   } > > -  ExprVector ConstructorArgs(Actions); > -  SourceLocation ConstructorLParen, ConstructorRParen; > +  ExprResult Initializer; > >   if (Tok.is(tok::l_paren)) { > +    SourceLocation ConstructorLParen, ConstructorRParen; > +    ExprVector ConstructorArgs(Actions); >     BalancedDelimiterTracker T(*this, tok::l_paren); >     T.consumeOpen(); >     ConstructorLParen = T.getOpenLocation(); > @@ -2213,19 +2214,20 @@ >       SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); >       return ExprError(); >     } > +    Initializer = Actions.ActOnParenListExpr(ConstructorLParen, > +                                             ConstructorRParen, > +                                             move_arg(ConstructorArgs)); >   } else if (Tok.is(tok::l_brace) && getLang().CPlusPlus0x) { >     Diag(Tok.getLocation(), >          diag::warn_cxx98_compat_generalized_initializer_lists); > -    ExprResult InitList = ParseBraceInitializer(); > -    if (InitList.isInvalid()) > -      return InitList; > -    ConstructorArgs.push_back(InitList.take()); > +    Initializer = ParseBraceInitializer(); >   } > +  if (Initializer.isInvalid()) > +    return Initializer; > >   return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, >                              move_arg(PlacementArgs), PlacementRParen, > -                             TypeIdParens, DeclaratorInfo, ConstructorLParen, > -                             move_arg(ConstructorArgs), ConstructorRParen); > +                             TypeIdParens, DeclaratorInfo, Initializer.take()); >  } > >  /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Feb 16 06:22:20 2012 > @@ -10148,15 +10148,13 @@ >     } > >     void VisitCXXNewExpr(CXXNewExpr *E) { > -      if (E->getConstructor()) > -        S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); >       if (E->getOperatorNew()) >         S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew()); >       if (E->getOperatorDelete()) >         S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); >       Inherited::VisitCXXNewExpr(E); >     } > - > + >     void VisitCXXDeleteExpr(CXXDeleteExpr *E) { >       if (E->getOperatorDelete()) >         S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Feb 16 06:22:20 2012 > @@ -914,9 +914,7 @@ >  Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, >                   SourceLocation PlacementLParen, MultiExprArg PlacementArgs, >                   SourceLocation PlacementRParen, SourceRange TypeIdParens, > -                  Declarator &D, SourceLocation ConstructorLParen, > -                  MultiExprArg ConstructorArgs, > -                  SourceLocation ConstructorRParen) { > +                  Declarator &D, Expr *Initializer) { >   bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; > >   Expr *ArraySize = 0; > @@ -961,6 +959,10 @@ >   if (D.isInvalidType()) >     return ExprError(); > > +  SourceRange DirectInitRange; > +  if (ParenListExpr *List = dyn_cast_or_null(Initializer)) > +    DirectInitRange = List->getSourceRange(); > + >   return BuildCXXNew(StartLoc, UseGlobal, >                      PlacementLParen, >                      move(PlacementArgs), > @@ -969,12 +971,27 @@ >                      AllocType, >                      TInfo, >                      ArraySize, > -                     ConstructorLParen, > -                     move(ConstructorArgs), > -                     ConstructorRParen, > +                     DirectInitRange, > +                     Initializer, >                      TypeContainsAuto); >  } > > +static bool isLegalArrayNewInitializer(Expr *Init) { > +  if (!Init) > +    return true; > +  if (ParenListExpr *PLE = dyn_cast(Init)) { > +    if (PLE->getNumExprs() != 1) > +      return PLE->getNumExprs() == 0; > +    Init = PLE->getExpr(0); > +  } > +  if (isa(Init)) > +    return true; > +  else if (CXXConstructExpr *CCE = dyn_cast(Init)) > +    return !CCE->isListInitialization() && > +           CCE->getConstructor()->isDefaultConstructor(); > +  return false; > +} > + >  ExprResult >  Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, >                   SourceLocation PlacementLParen, > @@ -984,29 +1001,56 @@ >                   QualType AllocType, >                   TypeSourceInfo *AllocTypeInfo, >                   Expr *ArraySize, > -                  SourceLocation ConstructorLParen, > -                  MultiExprArg ConstructorArgs, > -                  SourceLocation ConstructorRParen, > +                  SourceRange DirectInitRange, > +                  Expr *Initializer, >                   bool TypeMayContainAuto) { >   SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); > > +  CXXNewExpr::InitializationStyle initStyle; > +  if (DirectInitRange.isValid()) { > +    assert(Initializer && "Have parens but no initializer."); > +    initStyle = CXXNewExpr::CallInit; > +  } else if (Initializer && isa(Initializer)) > +    initStyle = CXXNewExpr::ListInit; > +  else { > +    assert((!Initializer || isa(Initializer) || > +            isa(Initializer)) && > +           "Initializer expression that cannot have been implicitly created."); > +    initStyle = CXXNewExpr::NoInit; > +  } > + > +  Expr **Inits = &Initializer; > +  unsigned NumInits = Initializer ? 1 : 0; > +  if (initStyle == CXXNewExpr::CallInit) { > +    if (ParenListExpr *List = dyn_cast(Initializer)) { > +      Inits = List->getExprs(); > +      NumInits = List->getNumExprs(); > +    } else if (CXXConstructExpr *CCE = dyn_cast(Initializer)){ > +      if (!isa(CCE)) { > +        // Can happen in template instantiation. Since this is just an implicit > +        // construction, we just take it apart and rebuild it. > +        Inits = CCE->getArgs(); > +        NumInits = CCE->getNumArgs(); > +      } > +    } > +  } > + >   // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. >   if (TypeMayContainAuto && AllocType->getContainedAutoType()) { > -    if (ConstructorArgs.size() == 0) > +    if (initStyle == CXXNewExpr::NoInit || NumInits == 0) >       return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) >                        << AllocType << TypeRange); > -    if (ConstructorArgs.size() != 1) { > -      Expr *FirstBad = ConstructorArgs.get()[1]; > +    if (initStyle == CXXNewExpr::ListInit) > +      return ExprError(Diag(Inits[0]->getSourceRange().getBegin(), > +                            diag::err_auto_new_requires_parens) > +                       << AllocType << TypeRange); > +    if (NumInits > 1) { > +      Expr *FirstBad = Inits[1]; >       return ExprError(Diag(FirstBad->getSourceRange().getBegin(), >                             diag::err_auto_new_ctor_multiple_expressions) >                        << AllocType << TypeRange); >     } > -    Expr *Deduce = ConstructorArgs.get()[0]; > -    if (ConstructorLParen.isInvalid()) { > -      return ExprError(Diag(Deduce->getSourceRange().getBegin(), > -                            diag::err_auto_new_requires_parens) > -                       << AllocType << TypeRange); > -    } > +    Expr *Deduce = Inits[0]; >     TypeSourceInfo *DeducedType = 0; >     if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == >             DAR_Failed) > @@ -1035,15 +1079,10 @@ >   if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange)) >     return ExprError(); > > -  bool ListInitialization = ConstructorLParen.isInvalid() && > -                            ConstructorArgs.size() > 0; > -  assert((!ListInitialization || (ConstructorArgs.size() == 1 && > -                                  isa(ConstructorArgs.get()[0]))) > -         && "List initialization means a braced-init-list for arguments."); > -  if (ListInitialization && isStdInitializerList(AllocType, 0)) { > +  if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) { >     Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(), >          diag::warn_dangling_std_initializer_list) > -      << /*at end of FE*/0 << ConstructorArgs.get()[0]->getSourceRange(); > +      << /*at end of FE*/0 << Inits[0]->getSourceRange(); >   } > >   // In ARC, infer 'retaining' for the allocated > @@ -1201,25 +1240,18 @@ >     } >   } > > -  bool Init = ConstructorLParen.isValid() || ConstructorArgs.size() > 0; > -  // --- Choosing a constructor --- > -  CXXConstructorDecl *Constructor = 0; > -  bool HadMultipleCandidates = false; > -  Expr **ConsArgs = (Expr**)ConstructorArgs.get(); > -  unsigned NumConsArgs = ConstructorArgs.size(); > -  ASTOwningVector ConvertedConstructorArgs(*this); > - > -  // Array 'new' can't have any initializers. > -  if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) { > -    SourceRange InitRange(ConsArgs[0]->getLocStart(), > -                          ConsArgs[NumConsArgs - 1]->getLocEnd()); > +  // Array 'new' can't have any initializers except empty parentheses. > +  if (!isLegalArrayNewInitializer(Initializer) && > +      (ResultType->isArrayType() || ArraySize)) { > +    SourceRange InitRange(Inits[0]->getLocStart(), > +                          Inits[NumInits - 1]->getLocEnd()); > >     Diag(StartLoc, diag::err_new_array_init_args) << InitRange; >     return ExprError(); >   } > >   if (!AllocType->isDependentType() && > -      !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) { > +      !Expr::hasAnyTypeDependentArguments(Inits, NumInits)) { >     // C++11 [expr.new]p15: >     //   A new-expression that creates an object of type T initializes that >     //   object as follows: > @@ -1227,49 +1259,31 @@ >     //     - If the new-initializer is omitted, the object is default- >     //       initialized (8.5); if no initialization is performed, >     //       the object has indeterminate value > -      = !Init? InitializationKind::CreateDefault(TypeRange.getBegin()) > +      = initStyle == CXXNewExpr::NoInit > +          ? InitializationKind::CreateDefault(TypeRange.getBegin()) >     //     - Otherwise, the new-initializer is interpreted according to the >     //       initialization rules of 8.5 for direct-initialization. > -             : ListInitialization ? InitializationKind::CreateDirectList( > -                                                          TypeRange.getBegin()) > -                                  : InitializationKind::CreateDirect( > -                                                          TypeRange.getBegin(), > -                                                          ConstructorLParen, > -                                                          ConstructorRParen); > +          : initStyle == CXXNewExpr::ListInit > +              ? InitializationKind::CreateDirectList(TypeRange.getBegin()) > +              : InitializationKind::CreateDirect(TypeRange.getBegin(), > +                                                 DirectInitRange.getBegin(), > +                                                 DirectInitRange.getEnd()); > >     InitializedEntity Entity >       = InitializedEntity::InitializeNew(StartLoc, AllocType); > -    InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs); > +    InitializationSequence InitSeq(*this, Entity, Kind, Inits, NumInits); >     ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, > -                                                move(ConstructorArgs)); > +                                          MultiExprArg(Inits, NumInits)); >     if (FullInit.isInvalid()) >       return ExprError(); > > -    // FullInit is our initializer; walk through it to determine if it's a > -    // constructor call, which CXXNewExpr handles directly. > -    if (Expr *FullInitExpr = (Expr *)FullInit.get()) { > -      if (CXXBindTemporaryExpr *Binder > -            = dyn_cast(FullInitExpr)) > -        FullInitExpr = Binder->getSubExpr(); > -      if (CXXConstructExpr *Construct > -                    = dyn_cast(FullInitExpr)) { > -        Constructor = Construct->getConstructor(); > -        HadMultipleCandidates = Construct->hadMultipleCandidates(); > -        for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(), > -                                         AEnd = Construct->arg_end(); > -             A != AEnd; ++A) > -          ConvertedConstructorArgs.push_back(*A); > -      } else { > -        // Take the converted initializer. > -        ConvertedConstructorArgs.push_back(FullInit.release()); > -      } > -    } else { > -      // No initialization required. > -    } > +    // FullInit is our initializer; strip off CXXBindTemporaryExprs, because > +    // we don't want the initialized object to be destructed. > +    if (CXXBindTemporaryExpr *Binder = > +            dyn_cast_or_null(FullInit.get())) > +      FullInit = Owned(Binder->getSubExpr()); > > -    // Take the converted arguments and use them for the new expression. > -    NumConsArgs = ConvertedConstructorArgs.size(); > -    ConsArgs = (Expr **)ConvertedConstructorArgs.take(); > +    Initializer = FullInit.take(); >   } > >   // Mark the new and delete operators as referenced. > @@ -1281,8 +1295,9 @@ >   // C++0x [expr.new]p17: >   //   If the new expression creates an array of objects of class type, >   //   access and ambiguity control are done for the destructor. > -  if (ArraySize && Constructor) { > -    if (CXXDestructorDecl *dtor = LookupDestructor(Constructor->getParent())) { > +  if (ArraySize && AllocType->isRecordType() && !AllocType->isDependentType()) { > +    if (CXXDestructorDecl *dtor = LookupDestructor( > +            cast(AllocType->getAs()->getDecl()))) { >       MarkFunctionReferenced(StartLoc, dtor); >       CheckDestructorAccess(StartLoc, dtor, >                             PDiag(diag::err_access_dtor) > @@ -1291,25 +1306,18 @@ >   } > >   PlacementArgs.release(); > -  ConstructorArgs.release(); > >   return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, > -                                        PlaceArgs, NumPlaceArgs, TypeIdParens, > -                                        ArraySize, Constructor, Init, > -                                        ConsArgs, NumConsArgs, > -                                        HadMultipleCandidates, >                                         OperatorDelete, >                                         UsualArrayDeleteWantsSize, > +                                        PlaceArgs, NumPlaceArgs, TypeIdParens, > +                                        ArraySize, initStyle, Initializer, >                                         ResultType, AllocTypeInfo, > -                                        StartLoc, > -                                        Init ? ConstructorRParen : > -                                               TypeRange.getEnd(), > -                                        ConstructorLParen, ConstructorRParen)); > +                                        StartLoc, DirectInitRange)); >  } > > -/// CheckAllocatedType - Checks that a type is suitable as the allocated type > +/// \brief Checks that a type is suitable as the allocated type >  /// in a new-expression. > -/// dimension off and stores the size expression in ArraySize. >  bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, >                               SourceRange R) { >   // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an > > Modified: cfe/trunk/lib/Sema/TreeTransform.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/TreeTransform.h (original) > +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Feb 16 06:22:20 2012 > @@ -1976,9 +1976,8 @@ >                                QualType AllocatedType, >                                TypeSourceInfo *AllocatedTypeInfo, >                                Expr *ArraySize, > -                               SourceLocation ConstructorLParen, > -                               MultiExprArg ConstructorArgs, > -                               SourceLocation ConstructorRParen) { > +                               SourceRange DirectInitRange, > +                               Expr *Initializer) { >     return getSema().BuildCXXNew(StartLoc, UseGlobal, >                                  PlacementLParen, >                                  move(PlacementArgs), > @@ -1987,9 +1986,8 @@ >                                  AllocatedType, >                                  AllocatedTypeInfo, >                                  ArraySize, > -                                 ConstructorLParen, > -                                 move(ConstructorArgs), > -                                 ConstructorRParen); > +                                 DirectInitRange, > +                                 Initializer); >   } > >   /// \brief Build a new C++ "delete" expression. > @@ -7106,29 +7104,17 @@ >   if (getDerived().TransformExprs(E->getPlacementArgs(), >                                   E->getNumPlacementArgs(), true, >                                   PlacementArgs, &ArgumentChanged)) > -    return ExprError(); > +    return ExprError(); > > -  // Transform the constructor arguments (if any). > -  // As an annoying corner case, we may have introduced an implicit value- > -  // initialization expression when allocating a new array, which we implicitly > -  // drop. It will be re-created during type checking. > -  ASTOwningVector ConstructorArgs(SemaRef); > -  if (!(E->isArray() && E->getNumConstructorArgs() == 1 && > -        isa(E->getConstructorArgs()[0])) && > -      TransformExprs(E->getConstructorArgs(), E->getNumConstructorArgs(), true, > -                     ConstructorArgs, &ArgumentChanged)) > -    return ExprError(); > - > -  // Transform constructor, new operator, and delete operator. > -  CXXConstructorDecl *Constructor = 0; > -  if (E->getConstructor()) { > -    Constructor = cast_or_null( > -                                   getDerived().TransformDecl(E->getLocStart(), > -                                                         E->getConstructor())); > -    if (!Constructor) > -      return ExprError(); > -  } > +  // Transform the initializer (if any). > +  Expr *OldInit = E->getInitializer(); > +  ExprResult NewInit; > +  if (OldInit) > +    NewInit = getDerived().TransformExpr(OldInit); > +  if (NewInit.isInvalid()) > +    return ExprError(); > > +  // Transform new operator and delete operator. >   FunctionDecl *OperatorNew = 0; >   if (E->getOperatorNew()) { >     OperatorNew = cast_or_null( > @@ -7150,21 +7136,18 @@ >   if (!getDerived().AlwaysRebuild() && >       AllocTypeInfo == E->getAllocatedTypeSourceInfo() && >       ArraySize.get() == E->getArraySize() && > -      Constructor == E->getConstructor() && > +      NewInit.get() == OldInit && >       OperatorNew == E->getOperatorNew() && >       OperatorDelete == E->getOperatorDelete() && >       !ArgumentChanged) { >     // Mark any declarations we need as referenced. >     // FIXME: instantiation-specific. > -    if (Constructor) > -      SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); >     if (OperatorNew) >       SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew); >     if (OperatorDelete) >       SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); > > -    if (E->isArray() && Constructor && > -        !E->getAllocatedType()->isDependentType()) { > +    if (E->isArray() && !E->getAllocatedType()->isDependentType()) { >       QualType ElementType >         = SemaRef.Context.getBaseElementType(E->getAllocatedType()); >       if (const RecordType *RecordT = ElementType->getAs()) { > @@ -7174,7 +7157,7 @@ >         } >       } >     } > - > + >     return SemaRef.Owned(E); >   } > > @@ -7204,7 +7187,7 @@ >       } >     } >   } > - > + >   return getDerived().RebuildCXXNewExpr(E->getLocStart(), >                                         E->isGlobalNew(), >                                         /*FIXME:*/E->getLocStart(), > @@ -7214,9 +7197,8 @@ >                                         AllocType, >                                         AllocTypeInfo, >                                         ArraySize.get(), > -                                        E->getConstructorLParen(), > -                                        move_arg(ConstructorArgs), > -                                        E->getConstructorRParen()); > +                                        E->getDirectInitRange(), > +                                        NewInit.take()); >  } > >  template > > Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Thu Feb 16 06:22:20 2012 > @@ -1167,27 +1167,24 @@ >  void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { >   VisitExpr(E); >   E->GlobalNew = Record[Idx++]; > -  E->Initializer = Record[Idx++]; > -  E->UsualArrayDeleteWantsSize = Record[Idx++]; >   bool isArray = Record[Idx++]; > -  E->setHadMultipleCandidates(Record[Idx++]); > +  E->UsualArrayDeleteWantsSize = Record[Idx++]; >   unsigned NumPlacementArgs = Record[Idx++]; > -  unsigned NumCtorArgs = Record[Idx++]; > +  E->StoredInitializationStyle = Record[Idx++]; >   E->setOperatorNew(ReadDeclAs(Record, Idx)); >   E->setOperatorDelete(ReadDeclAs(Record, Idx)); > -  E->setConstructor(ReadDeclAs(Record, Idx)); >   E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx); >   SourceRange TypeIdParens; >   TypeIdParens.setBegin(ReadSourceLocation(Record, Idx)); >   TypeIdParens.setEnd(ReadSourceLocation(Record, Idx)); >   E->TypeIdParens = TypeIdParens; >   E->StartLoc = ReadSourceLocation(Record, Idx); > -  E->EndLoc = ReadSourceLocation(Record, Idx); > -  E->ConstructorLParen = ReadSourceLocation(Record, Idx); > -  E->ConstructorRParen = ReadSourceLocation(Record, Idx); > +  SourceRange DirectInitRange; > +  DirectInitRange.setBegin(ReadSourceLocation(Record, Idx)); > +  DirectInitRange.setEnd(ReadSourceLocation(Record, Idx)); > >   E->AllocateArgsArray(Reader.getContext(), isArray, NumPlacementArgs, > -                       NumCtorArgs); > +                       E->StoredInitializationStyle != 0); > >   // Install all the subexpressions. >   for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end(); > > Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Thu Feb 16 06:22:20 2012 > @@ -1158,25 +1158,20 @@ >  void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { >   VisitExpr(E); >   Record.push_back(E->isGlobalNew()); > -  Record.push_back(E->hasInitializer()); > -  Record.push_back(E->doesUsualArrayDeleteWantSize()); >   Record.push_back(E->isArray()); > -  Record.push_back(E->hadMultipleCandidates()); > +  Record.push_back(E->doesUsualArrayDeleteWantSize()); >   Record.push_back(E->getNumPlacementArgs()); > -  Record.push_back(E->getNumConstructorArgs()); > +  Record.push_back(E->StoredInitializationStyle); >   Writer.AddDeclRef(E->getOperatorNew(), Record); >   Writer.AddDeclRef(E->getOperatorDelete(), Record); > -  Writer.AddDeclRef(E->getConstructor(), Record); >   Writer.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo(), Record); >   Writer.AddSourceRange(E->getTypeIdParens(), Record); >   Writer.AddSourceLocation(E->getStartLoc(), Record); > -  Writer.AddSourceLocation(E->getEndLoc(), Record); > -  Writer.AddSourceLocation(E->getConstructorLParen(), Record); > -  Writer.AddSourceLocation(E->getConstructorRParen(), Record); > +  Writer.AddSourceRange(E->getDirectInitRange(), Record); >   for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); >        I != e; ++I) >     Writer.AddStmt(*I); > - > + >   Code = serialization::EXPR_CXX_NEW; >  } > > > Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original) > +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Thu Feb 16 06:22:20 2012 > @@ -268,6 +268,8 @@ >     return; >   } > > +  // FIXME: Update for AST changes. > +#if 0 >   // Evaluate constructor arguments. >   const FunctionProtoType *FnType = NULL; >   const CXXConstructorDecl *CD = CNE->getConstructor(); > @@ -327,6 +329,7 @@ >                             loc::MemRegionVal(EleReg)); >     Bldr.generateNode(CNE, *I, state); >   } > +#endif >  } > >  void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, > > Modified: cfe/trunk/test/Analysis/new.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/new.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/test/Analysis/new.cpp (original) > +++ cfe/trunk/test/Analysis/new.cpp Thu Feb 16 06:22:20 2012 > @@ -1,4 +1,5 @@ >  // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -verify %s > +// XFAIL: * > >  void f1() { >   int *n = new int; > > Modified: cfe/trunk/test/SemaCXX/new-delete.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/test/SemaCXX/new-delete.cpp (original) > +++ cfe/trunk/test/SemaCXX/new-delete.cpp Thu Feb 16 06:22:20 2012 > @@ -417,3 +417,32 @@ >   }; >   void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}} >  } > + > +struct PlacementArg {}; > +inline void *operator new[](size_t, const PlacementArg &) throw () { > +  return 0; > +} > +inline void operator delete[](void *, const PlacementArg &) throw () { > +} > + > +namespace r150682 { > + > +  template > +  struct S { > +    struct Inner {}; > +    S() { new Inner[1]; } > +  }; > + > +  struct T { > +  }; > + > +  template > +  void tfn() { > +    new (*(PlacementArg*)0) T[1]; > +  } > + > +  void fn() { > +    tfn(); > +  } > + > +} > > Modified: cfe/trunk/tools/libclang/CIndex.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=150685&r1=150684&r2=150685&view=diff > ============================================================================== > --- cfe/trunk/tools/libclang/CIndex.cpp (original) > +++ cfe/trunk/tools/libclang/CIndex.cpp Thu Feb 16 06:22:20 2012 > @@ -1856,9 +1856,8 @@ >     AddStmt(E->getBase()); >  } >  void EnqueueVisitor::VisitCXXNewExpr(CXXNewExpr *E) { > -  // Enqueue the initializer or constructor arguments. > -  for (unsigned I = E->getNumConstructorArgs(); I > 0; --I) > -    AddStmt(E->getConstructorArg(I-1)); > +  // Enqueue the initializer , if any. > +  AddStmt(E->getInitializer()); >   // Enqueue the array size, if any. >   AddStmt(E->getArraySize()); >   // Enqueue the allocated type. > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From Michael.Han at autodesk.com Tue Feb 21 16:45:48 2012 From: Michael.Han at autodesk.com (Michael Han) Date: Wed, 22 Feb 2012 00:45:48 +0000 Subject: [cfe-commits] [Patch][Review Request] Improve Clang attribute system Message-ID: <2C9935343FDB104E8F3175A2729BC31421C648@005-TK5MPN1-011.MGDADSK.autodesk.com> Hi, I am starting working on a set of patches that aim at making the process of adding attribute extensions to Clang more automated, and less error prone. Currently, to add an attribute, besides modify the attribute TD file, one has to modify several entries in Sema, and such manual effort could be automated the same way attribute parsing is automated in parser via table gen. This will hopefully save a lot of boilerplate code, and make maintaining attributes easier. So, my plan is to try to kill the attribute code in Sema that looks like could be generated in table gen. I remember someone mentioned that ultimately the AttributeList should be removed also but I felt it is too aggressive for me so I am going the incremental approach by starting refactoring existing attributes code in Sema into table gen, with the hope once it is done we don't need AttributeList anymore : ) Here is the first patch that generate the attribute kind enumeration list from Attr.td. I noticed that some attributes in Attr.td does not have an entry in Sema AttributeList, for example, here is the list AlignMac68k AsmLabel Final MBlazeInterruptHandler MBlazeSaveVoliles MSP430Interrupt MaxFieldAlignment Override I added a bit field "SemaHandler" in Attr.td and this value is by default set to 1 since most of attributes described in Attr.td has entry in AttributeList. For the attributes in the above list, this field is set to 0 so there would not be entry generated for them in AttributeList (though.. it seems no harm to generate the entries for them..) Also, some entries in AttributeList are not present in Attr.td, here is the list _address_space _base_check _cf_returns_autoreleased _ext_vector_type _mode _neon_polyvector_type _neon_vector_type _objc_gc _objc_ownership _opencl_image_access _vector_size, I simply hard code them in the enumeration list with the enumerators generated by table gen together. Also, since the enumerator names are generated automatically they may differ slightly in spelling comparing to some of hand coded enumerators, so I also updated several places to use new enumerator. Please review and let me know if this is the right direction to go. Then, I will start moving more code into table gen, like the AttributeList::getKind, and refactor common semantic checking code like argument checking into table gen too. Thanks! Cheers Michael -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: sema_attr.patch Type: application/octet-stream Size: 17179 bytes Desc: sema_attr.patch URL: From eli.friedman at gmail.com Tue Feb 21 17:02:54 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 21 Feb 2012 17:02:54 -0800 Subject: [cfe-commits] [Patch] Tests for C++11 lambda expressions In-Reply-To: <4F443257.5020306@cse.tamu.edu> References: <4F443257.5020306@cse.tamu.edu> Message-ID: On Tue, Feb 21, 2012 at 4:09 PM, John Freeman wrote: > This is a small start based on a run-through of the FDIS. > > Some errors seem poorly diagnosed in the revision I used (b09ab8c on the Git > mirror; I believe after r151076 in the Subversion repo). I wrote the tests > as I would like to see them diagnosed instead of how they are currently, so > those show up as unexpected failures. Please file bugs on bad diagnostics. > A missing feature (specifically conversion to function-to-pointer) also > appears as an unexpected failure. Please try a newer clang; the conversion-to-function-pointer should be working now. > Please let me know what other tests would be desired, and I'll write them > up. Please also point out any mistakes I made with these tests. I want to > make sure they conform to Clang's standards. It looks like we already have coverage for a lot of the features you're trying to test... see test/CXX/expr/expr.prim/expr.prim.lambda/ . I'm not entirely sure what you're trying to do with the test involving noexcept... -Eli From rikka at google.com Tue Feb 21 17:03:07 2012 From: rikka at google.com (Kaelyn Uhrain) Date: Wed, 22 Feb 2012 01:03:07 -0000 Subject: [cfe-commits] r151112 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseExpr.cpp lib/Parse/ParseTemplate.cpp test/SemaCXX/typo-correction.cpp Message-ID: <20120222010307.5E0C42A6C12F@llvm.org> Author: rikka Date: Tue Feb 21 19:03:07 2012 New Revision: 151112 URL: http://llvm.org/viewvc/llvm-project?rev=151112&view=rev Log: Fix typo correction of template arguments to once again allow type names. Modified: cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseExpr.cpp cfe/trunk/lib/Parse/ParseTemplate.cpp cfe/trunk/test/SemaCXX/typo-correction.cpp Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=151112&r1=151111&r2=151112&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Tue Feb 21 19:03:07 2012 @@ -1288,7 +1288,7 @@ }; ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast); - ExprResult ParseConstantExpression(); + ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast); // Expr that doesn't include commas. ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast); Modified: cfe/trunk/lib/Parse/ParseExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=151112&r1=151111&r2=151112&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) +++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Feb 21 19:03:07 2012 @@ -249,7 +249,7 @@ } -ExprResult Parser::ParseConstantExpression() { +ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { // C++03 [basic.def.odr]p2: // An expression is potentially evaluated unless it appears where an // integral constant expression is required (see 5.19) [...]. @@ -257,7 +257,7 @@ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::ConstantEvaluated); - ExprResult LHS(ParseCastExpression(false)); + ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); return ParseRHSOfBinaryExpression(LHS, prec::Conditional); } Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=151112&r1=151111&r2=151112&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original) +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Tue Feb 21 19:03:07 2012 @@ -1037,7 +1037,7 @@ // Parse a non-type template argument. SourceLocation Loc = Tok.getLocation(); - ExprResult ExprArg = ParseConstantExpression(); + ExprResult ExprArg = ParseConstantExpression(MaybeTypeCast); if (ExprArg.isInvalid() || !ExprArg.get()) return ParsedTemplateArgument(); Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=151112&r1=151111&r2=151112&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/typo-correction.cpp (original) +++ cfe/trunk/test/SemaCXX/typo-correction.cpp Tue Feb 21 19:03:07 2012 @@ -167,3 +167,19 @@ }; class Child: public Parent {}; void Child::add_types(int value) {} // expected-error{{out-of-line definition of 'add_types' does not match any declaration in 'Child'}} + +// Fix the callback based filtering of typo corrections within +// Sema::ActOnIdExpression by Parser::ParseCastExpression to allow type names as +// potential corrections for template arguments. +namespace clash { +class ConstructExpr {}; // expected-note{{'clash::ConstructExpr' declared here}} +} +class ClashTool { + bool HaveConstructExpr(); + template T* getExprAs(); + + void test() { + ConstructExpr *expr = // expected-error{{unknown type name 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}} + getExprAs(); // expected-error{{use of undeclared identifier 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}} + } +}; From eli.friedman at gmail.com Tue Feb 21 17:45:14 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 21 Feb 2012 17:45:14 -0800 Subject: [cfe-commits] [PATCH] Supporting thiscall compatibility with MSVC In-Reply-To: References: Message-ID: On Sat, Feb 18, 2012 at 9:36 AM, Aaron Ballman wrote: > On Fri, Feb 17, 2012 at 7:30 PM, Eli Friedman wrote: >> On Fri, Feb 17, 2012 at 3:41 PM, Aaron Ballman wrote: >>> On Thu, Feb 16, 2012 at 10:42 PM, Eli Friedman wrote: >>>> On Thu, Feb 16, 2012 at 8:39 PM, Aaron Ballman wrote: >>>>> On Thu, Feb 16, 2012 at 9:50 PM, Eli Friedman wrote: >>>>>> On Thu, Feb 16, 2012 at 7:38 PM, Aaron Ballman wrote: >>>>>>> On Thu, Feb 16, 2012 at 8:52 PM, Eli Friedman wrote: >>>>>>>> On Thu, Feb 16, 2012 at 6:25 PM, Aaron Ballman wrote: >>>>>>>>> Here's the next attempt at the MSVC thiscall support patch, this time >>>>>>>>> with test cases and an improved tablegen declaration. >>>>>>>>> >>>>>>>>> This is the first time I've done a test case for clang or llvm >>>>>>>>> codegen, so please pay special attention to the test cases and let me >>>>>>>>> know if I'm off-base (and what I should do differently). >>>>>>>> >>>>>>>> You might want to make the LLVM testcase a bit stronger by using CHECK-NEXT. >>>>>>> >>>>>>> Does CHECK-NEXT basically chain the checks together to check several >>>>>>> lines as a group? >>>>>> >>>>>> Basically, yes. >>>>> >>>>> The problem is that the assembly is different between O levels.  So >>>>> -O0 does leal, leal, but -O1 does leal, movl. >>>>> >>>>> Is there a way for me to handle this in the test case, or should I >>>>> just be explicit about the O level and its behavior? >>>> >>>> We always run tests at the same -O level, so you shouldn't worry about >>>> that.  That said, if you think splitting your testcase into multiple >>>> functions would make it more stable, please do that. >>> >>> Here's another shot at the patch -- this time, I am using the proper >>> way to test for the Win32 ABI, and I've updated the X86 codegen test >>> case so that it's a bit more clear. >> >> Your test somehow disappeared form the clang patch. >> >> Please rename IsWin32FloatStructABI if you're going to use it this >> way.  I'm still not convinced it's necessary to behave differently >> when targeting MinGW, though. > > That was truly odd -- no idea how the test case got missed, but it's > back again.  I've also removed the check for the Win32 ABI as it > appears this is used by gcc (4.6 and up) for MS compat as well. Both patches look good. -Eli From eli.friedman at gmail.com Tue Feb 21 17:50:48 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 21 Feb 2012 17:50:48 -0800 Subject: [cfe-commits] r151076 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Sema/Sema.h lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cp In-Reply-To: References: Message-ID: On Tue, Feb 21, 2012 at 12:17 PM, Douglas Gregor wrote: >>>     void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { >>> +      // If we were asked not to visit local variables, don't. >>> +      if (SkipLocalVariables && E->getDecl()->hasLocalStorage()) >>> +          return; >> >> What exactly are the rules for odr-use marking inside a lambda in a >> default argument, actually? > > That is an *excellent* question. We're trying to emulate what would have happened if the expression had been written in a potentially evaluated context, by walking the resulting tree, and it's fairly likely that we don't get all of the cases right. Filed PR12064; there are probably some other issues, but it's probably not worth looking for them until we figure out how to fix that one. -Eli From echristo at apple.com Tue Feb 21 17:57:40 2012 From: echristo at apple.com (Eric Christopher) Date: Tue, 21 Feb 2012 17:57:40 -0800 Subject: [cfe-commits] [patch][pr12001] Avoid increasing visibility in some cases In-Reply-To: <4F41B9E8.4020407@gmail.com> References: <4F41B060.9020500@gmail.com> <4F41B9E8.4020407@gmail.com> Message-ID: On Feb 19, 2012, at 7:11 PM, Rafael Ávila de Espíndola wrote: > Nico noticed that the patch included an infinite loop from when I > renamed merge2 to mergeWithMin. > > An updated patch is attached. I think this is ok. Some more comments on the visibility that should be happening in the various testcases and where you use mergeWithMin would be helpful next time I need to review something through there. -eric From richard-llvm at metafoo.co.uk Tue Feb 21 18:04:18 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Wed, 22 Feb 2012 02:04:18 -0000 Subject: [cfe-commits] r151117 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp test/SemaCXX/overload-call.cpp Message-ID: <20120222020419.2B3102A6C12F@llvm.org> Author: rsmith Date: Tue Feb 21 20:04:18 2012 New Revision: 151117 URL: http://llvm.org/viewvc/llvm-project?rev=151117&view=rev Log: Implement C++11 [expr.call]p11: If the operand to a decltype-specifier is a function call (or a comma expression with a function call on its right-hand side), possibly parenthesized, then the return type is not required to be complete and a temporary is not bound. Other subexpressions inside a decltype expression do not get this treatment. This is implemented by deferring the relevant checks for all calls immediately within a decltype expression, then, when the expression is fully-parsed, checking the relevant constraints and stripping off any top-level temporary binding. Deferring the completion of the return type exposed a bug in overload resolution where completion of the argument types was not attempted, which is also fixed by this change. Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp Modified: cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/test/SemaCXX/overload-call.cpp Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Feb 21 20:04:18 2012 @@ -736,6 +736,9 @@ const CXXDestructorDecl *Destructor); const CXXDestructorDecl *getDestructor() const { return Destructor; } + void setDestructor(const CXXDestructorDecl *Dtor) { + Destructor = Dtor; + } }; /// \brief Represents binding an expression to a temporary. Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 21 20:04:18 2012 @@ -59,6 +59,7 @@ class BlockDecl; class CXXBasePath; class CXXBasePaths; + class CXXBindTemporaryExpr; typedef SmallVector CXXCastPath; class CXXConstructorDecl; class CXXConversionDecl; @@ -562,6 +563,9 @@ /// \brief Whether the enclosing context needed a cleanup. bool ParentNeedsCleanups; + /// \brief Whether we are in a decltype expression. + bool IsDecltype; + /// \brief The number of active cleanup objects when we entered /// this expression evaluation context. unsigned NumCleanupObjects; @@ -583,13 +587,22 @@ /// This mangling information is allocated lazily, since most contexts /// do not have lambda expressions. LambdaMangleContext *LambdaMangle; + + /// \brief If we are processing a decltype type, a set of call expressions + /// for which we have deferred checking the completeness of the return type. + llvm::SmallVector DelayedDecltypeCalls; + + /// \brief If we are processing a decltype type, a set of temporary binding + /// expressions for which we have deferred checking the destructor. + llvm::SmallVector DelayedDecltypeBinds; ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, bool ParentNeedsCleanups, - Decl *LambdaContextDecl) + Decl *LambdaContextDecl, + bool IsDecltype) : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), - NumCleanupObjects(NumCleanupObjects), + IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), LambdaContextDecl(LambdaContextDecl), LambdaMangle() { } ~ExpressionEvaluationContextRecord() { @@ -2315,7 +2328,8 @@ Expr **Args, unsigned NumArgs); void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = 0); + Decl *LambdaContextDecl = 0, + bool IsDecltype = false); void PopExpressionEvaluationContext(); @@ -3446,6 +3460,8 @@ bool EnteringContext, CXXScopeSpec &SS); + ExprResult ActOnDecltypeExpression(Expr *E); + bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, const DeclSpec &DS, SourceLocation ColonColonLoc); @@ -6572,9 +6588,11 @@ public: EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = 0) + Decl *LambdaContextDecl = 0, + bool IsDecltype = false) : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl); + Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, + IsDecltype); } ~EnterExpressionEvaluationContext() { Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Feb 21 20:04:18 2012 @@ -667,8 +667,8 @@ // C++0x [dcl.type.simple]p4: // The operand of the decltype specifier is an unevaluated operand. - EnterExpressionEvaluationContext Unevaluated(Actions, - Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, + 0, /*IsDecltype=*/true); Result = ParseExpression(); if (Result.isInvalid()) { SkipUntil(tok::r_paren, true, true); @@ -685,6 +685,12 @@ return T.getCloseLocation(); } + Result = Actions.ActOnDecltypeExpression(Result.take()); + if (Result.isInvalid()) { + DS.SetTypeSpecError(); + return T.getCloseLocation(); + } + EndLoc = T.getCloseLocation(); } Modified: cfe/trunk/lib/Sema/Sema.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/lib/Sema/Sema.cpp (original) +++ cfe/trunk/lib/Sema/Sema.cpp Tue Feb 21 20:04:18 2012 @@ -111,7 +111,8 @@ &Context); ExprEvalContexts.push_back( - ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, false, 0)); + ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, + false, 0, false)); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); } Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb 21 20:04:18 2012 @@ -9277,12 +9277,14 @@ void Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl) { + Decl *LambdaContextDecl, + bool IsDecltype) { ExprEvalContexts.push_back( ExpressionEvaluationContextRecord(NewContext, ExprCleanupObjects.size(), ExprNeedsCleanups, - LambdaContextDecl)); + LambdaContextDecl, + IsDecltype)); ExprNeedsCleanups = false; if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); @@ -10280,6 +10282,13 @@ if (ReturnType->isVoidType() || !ReturnType->isIncompleteType()) return false; + // If we're inside a decltype's expression, don't check for a valid return + // type or construct temporaries until we know whether this is the last call. + if (ExprEvalContexts.back().IsDecltype) { + ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE); + return false; + } + PartialDiagnostic Note = FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here) << FD->getDeclName() : PDiag(); Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Feb 21 20:04:18 2012 @@ -4315,11 +4315,14 @@ } } - // That should be enough to guarantee that this type is complete. + // That should be enough to guarantee that this type is complete, if we're + // not processing a decltype expression. CXXRecordDecl *RD = cast(RT->getDecl()); if (RD->isInvalidDecl() || RD->isDependentContext()) return Owned(E); - CXXDestructorDecl *Destructor = LookupDestructor(RD); + + bool IsDecltype = ExprEvalContexts.back().IsDecltype; + CXXDestructorDecl *Destructor = IsDecltype ? 0 : LookupDestructor(RD); if (Destructor) { MarkFunctionReferenced(E->getExprLoc(), Destructor); @@ -4327,18 +4330,22 @@ PDiag(diag::err_access_dtor_temp) << E->getType()); DiagnoseUseOfDecl(Destructor, E->getExprLoc()); - } - // If destructor is trivial, we can avoid the extra copy. - if (Destructor->isTrivial()) - return Owned(E); + // If destructor is trivial, we can avoid the extra copy. + if (Destructor->isTrivial()) + return Owned(E); - if (Destructor) // We need a cleanup, but we don't need to remember the temporary. ExprNeedsCleanups = true; + } CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); - return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E)); + CXXBindTemporaryExpr *Bind = CXXBindTemporaryExpr::Create(Context, Temp, E); + + if (IsDecltype) + ExprEvalContexts.back().DelayedDecltypeBinds.push_back(Bind); + + return Owned(Bind); } ExprResult @@ -4390,6 +4397,95 @@ return MaybeCreateExprWithCleanups(E); } +/// Process the expression contained within a decltype. For such expressions, +/// certain semantic checks on temporaries are delayed until this point, and +/// are omitted for the 'topmost' call in the decltype expression. If the +/// topmost call bound a temporary, strip that temporary off the expression. +ExprResult Sema::ActOnDecltypeExpression(Expr *E) { + ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back(); + assert(Rec.IsDecltype && "not in a decltype expression"); + + // C++11 [expr.call]p11: + // If a function call is a prvalue of object type, + // -- if the function call is either + // -- the operand of a decltype-specifier, or + // -- the right operand of a comma operator that is the operand of a + // decltype-specifier, + // a temporary object is not introduced for the prvalue. + + // Recursively rebuild ParenExprs and comma expressions to strip out the + // outermost CXXBindTemporaryExpr, if any. + if (ParenExpr *PE = dyn_cast(E)) { + ExprResult SubExpr = ActOnDecltypeExpression(PE->getSubExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + if (SubExpr.get() == PE->getSubExpr()) + return Owned(E); + return ActOnParenExpr(PE->getLParen(), PE->getRParen(), SubExpr.take()); + } + if (BinaryOperator *BO = dyn_cast(E)) { + if (BO->getOpcode() == BO_Comma) { + ExprResult RHS = ActOnDecltypeExpression(BO->getRHS()); + if (RHS.isInvalid()) + return ExprError(); + if (RHS.get() == BO->getRHS()) + return Owned(E); + return Owned(new (Context) BinaryOperator(BO->getLHS(), RHS.take(), + BO_Comma, BO->getType(), + BO->getValueKind(), + BO->getObjectKind(), + BO->getOperatorLoc())); + } + } + + CXXBindTemporaryExpr *TopBind = dyn_cast(E); + if (TopBind) + E = TopBind->getSubExpr(); + + // Disable the special decltype handling now. + Rec.IsDecltype = false; + + // Perform the semantic checks we delayed until this point. + CallExpr *TopCall = dyn_cast(E); + for (unsigned I = 0, N = Rec.DelayedDecltypeCalls.size(); I != N; ++I) { + CallExpr *Call = Rec.DelayedDecltypeCalls[I]; + if (Call == TopCall) + continue; + + if (CheckCallReturnType(Call->getCallReturnType(), + Call->getSourceRange().getBegin(), + Call, Call->getDirectCallee())) + return ExprError(); + } + + // Now all relevant types are complete, check the destructors are accessible + // and non-deleted, and annotate them on the temporaries. + for (unsigned I = 0, N = Rec.DelayedDecltypeBinds.size(); I != N; ++I) { + CXXBindTemporaryExpr *Bind = Rec.DelayedDecltypeBinds[I]; + if (Bind == TopBind) + continue; + + CXXTemporary *Temp = Bind->getTemporary(); + + CXXRecordDecl *RD = + Bind->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + CXXDestructorDecl *Destructor = LookupDestructor(RD); + Temp->setDestructor(Destructor); + + MarkFunctionReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_temp) + << E->getType()); + DiagnoseUseOfDecl(Destructor, E->getExprLoc()); + + // We need a cleanup, but we don't need to remember the temporary. + ExprNeedsCleanups = true; + } + + // Possibly strip off the top CXXBindTemporaryExpr. + return Owned(E); +} + ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, ParsedType &ObjectType, Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Feb 21 20:04:18 2012 @@ -740,6 +740,8 @@ /// Return true on unrecoverable error. static bool checkPlaceholderForOverload(Sema &S, Expr *&E, UnbridgedCastsSet *unbridgedCasts = 0) { + S.RequireCompleteType(E->getExprLoc(), E->getType(), 0); + if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) { // We can't handle overloaded expressions here because overload // resolution might reasonably tweak them. Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Tue Feb 21 20:04:18 2012 @@ -4305,12 +4305,17 @@ const DecltypeType *T = TL.getTypePtr(); // decltype expressions are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, 0, + /*IsDecltype=*/ true); ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr()); if (E.isInvalid()) return QualType(); + E = getSema().ActOnDecltypeExpression(E.take()); + if (E.isInvalid()) + return QualType(); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || E.get() != T->getUnderlyingExpr()) { Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp?rev=151117&view=auto ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp (added) +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp Tue Feb 21 20:04:18 2012 @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace std_example { + +template struct A { ~A() = delete; }; // expected-note {{deleted here}} +template auto h() -> A; +template auto i(T) -> T; +template auto f(T) -> decltype(i(h())); // #1 +template auto f(T) -> void; // #2 +auto g() -> void { + f(42); // ok, calls #2, since #1 is not viable. +} +template auto q(T) -> decltype((h())); +void r() { + // Deduction against q succeeds, but results in a temporary which can't be + // destroyed. + q(42); // expected-error {{attempt to use a deleted function}} +} + +} + +class PD { + friend struct A; + ~PD(); // expected-note 4{{here}} +public: + typedef int n; +}; +struct DD { + ~DD() = delete; // expected-note 2{{here}} + typedef int n; +}; + +struct A { + decltype(PD()) s; // ok + decltype(PD())::n n; // ok + decltype(DD()) *p = new decltype(DD()); // ok +}; + +// Two errors here: one for the decltype, one for the variable. +decltype(PD(), PD()) pd1; // expected-error 2{{private destructor}} +decltype(DD(), DD()) dd1; // expected-error 2{{deleted function}} + +decltype(((13, ((DD())))))::n dd_parens; // ok +decltype(((((42)), PD())))::n pd_parens_comma; // ok + +// Ensure parens aren't stripped from a decltype node. +extern decltype(PD()) pd_ref; // ok +decltype((pd_ref)) pd_ref3 = pd_ref; // ok, PD & +decltype(pd_ref) pd_ref2 = pd_ref; // expected-error {{private destructor}} + +namespace libcxx_example { + struct nat { + nat() = delete; + nat(const nat&) = delete; + nat &operator=(const nat&) = delete; + ~nat() = delete; + }; + struct any { + any(...); + }; + + template struct is_same { static const bool value = false; }; + template struct is_same { static const bool value = true; }; + + template T declval(); + + void swap(int &a, int &b); + nat swap(any, any); + + template struct swappable { + typedef decltype(swap(declval(), declval())) type; + static const bool value = !is_same::value; + constexpr operator bool() { return value; } + }; + + static_assert(swappable(), ""); + static_assert(!swappable(), ""); +} + +namespace RequireCompleteType { + template struct S { + static_assert(OK, "boom!"); // expected-error 2{{boom!}} + }; + + template T make(); + template S make(); + void consume(...); + + decltype(make<0, false>()) *p1; // ok + decltype((make<1, false>())) *p2; // ok + + // A complete type is required here in order to detect an overloaded 'operator,'. + decltype(123, make<2, false>()) *p3; // expected-note {{here}} + + decltype(consume(make<3, false>())) *p4; // expected-note {{here}} + + decltype(make())>()) *p5; // ok +} + +namespace Overload { + DD operator+(PD &a, PD &b); + decltype(PD()) *pd_ptr; + decltype(*pd_ptr + *pd_ptr) *dd_ptr; // ok + + decltype(0, *pd_ptr) pd_ref2 = pd_ref; // ok + DD operator,(int a, PD b); + decltype(0, *pd_ptr) *dd_ptr2; // expected-error {{private destructor}} +} Modified: cfe/trunk/test/SemaCXX/overload-call.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=151117&r1=151116&r2=151117&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/overload-call.cpp (original) +++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue Feb 21 20:04:18 2012 @@ -534,3 +534,12 @@ int &ir = (&foo)(0); } } + +namespace IncompleteArg { + // Ensure that overload resolution attempts to complete argument types. + template struct S { + friend int f(const S&); + }; + extern S s; + int k = f(s); +} From akyrtzi at gmail.com Tue Feb 21 18:10:41 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Wed, 22 Feb 2012 02:10:41 -0000 Subject: [cfe-commits] r151118 - in /cfe/trunk: test/Index/index-refs.cpp tools/libclang/IndexBody.cpp Message-ID: <20120222021041.B1E482A6C12F@llvm.org> Author: akirtzidis Date: Tue Feb 21 20:10:41 2012 New Revision: 151118 URL: http://llvm.org/viewvc/llvm-project?rev=151118&view=rev Log: [libclang] Index the field references of a designated initializer, rdar://10906206 Modified: cfe/trunk/test/Index/index-refs.cpp cfe/trunk/tools/libclang/IndexBody.cpp Modified: cfe/trunk/test/Index/index-refs.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/index-refs.cpp?rev=151118&r1=151117&r2=151118&view=diff ============================================================================== --- cfe/trunk/test/Index/index-refs.cpp (original) +++ cfe/trunk/test/Index/index-refs.cpp Tue Feb 21 20:10:41 2012 @@ -61,6 +61,14 @@ const int default_param = 3; void foo4(int p = default_param); +struct S2 { + int x,y; +}; + +void foo5() { + struct S2 s = { .y = 1, .x = 4}; +} + // RUN: c-index-test -index-file %s | FileCheck %s // CHECK: [indexDeclaration]: kind: namespace | name: NS // CHECK-NEXT: [indexDeclaration]: kind: variable | name: gx @@ -108,3 +116,6 @@ // CHECK: [indexEntityReference]: kind: variable | name: array_size | {{.*}} | loc: 59:22 // CHECK: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 // CHECK-NOT: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 + +// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20 +// CHECK-NEXT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 69:28 Modified: cfe/trunk/tools/libclang/IndexBody.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexBody.cpp?rev=151118&r1=151117&r2=151118&view=diff ============================================================================== --- cfe/trunk/tools/libclang/IndexBody.cpp (original) +++ cfe/trunk/tools/libclang/IndexBody.cpp Tue Feb 21 20:10:41 2012 @@ -51,6 +51,17 @@ return true; } + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { + for (DesignatedInitExpr::reverse_designators_iterator + D = E->designators_rbegin(), DEnd = E->designators_rend(); + D != DEnd; ++D) { + if (D->isFieldDesignator()) + IndexCtx.handleReference(D->getField(), D->getFieldLoc(), + Parent, ParentDC, E); + } + return true; + } + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { IndexCtx.handleReference(E->getDecl(), E->getLocation(), Parent, ParentDC, E); From ganna at apple.com Tue Feb 21 18:35:58 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 22 Feb 2012 02:35:58 -0000 Subject: [cfe-commits] r151120 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp test/Analysis/taint-generic.c Message-ID: <20120222023558.C5AD32A6C12F@llvm.org> Author: zaks Date: Tue Feb 21 20:35:58 2012 New Revision: 151120 URL: http://llvm.org/viewvc/llvm-project?rev=151120&view=rev Log: [analyzer] Change naming in bug reports "tainted" -> "untrusted" Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp cfe/trunk/test/Analysis/taint-generic.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp?rev=151120&r1=151119&r2=151120&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp Tue Feb 21 20:35:58 2012 @@ -45,7 +45,7 @@ mutable OwningPtr BT; inline void initBugType() const { if (!BT) - BT.reset(new BugType("Taint Analysis", "General")); + BT.reset(new BugType("Use of Untrusted Data", "Untrusted Data")); } /// \brief Catch taint related bugs. Check if tainted data is passed to a @@ -174,14 +174,15 @@ const unsigned GenericTaintChecker::InvalidArgIndex; const char GenericTaintChecker::MsgUncontrolledFormatString[] = - "Tainted format string (CWE-134: Uncontrolled Format String)"; + "Untrusted data is used as a format string " + "(CWE-134: Uncontrolled Format String)"; const char GenericTaintChecker::MsgSanitizeSystemArgs[] = - "Tainted data passed to a system call " + "Untrusted data is passed to a system call " "(CERT/STR02-C. Sanitize data passed to complex subsystems)"; const char GenericTaintChecker::MsgTaintedBufferSize[] = - "Tainted data is used to specify the buffer size " + "Untrusted data is used to specify the buffer size " "(CERT/STR31-C. Guarantee that storage for strings has sufficient space for " "character data and the null terminator)"; Modified: cfe/trunk/test/Analysis/taint-generic.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-generic.c?rev=151120&r1=151119&r2=151120&view=diff ============================================================================== --- cfe/trunk/test/Analysis/taint-generic.c (original) +++ cfe/trunk/test/Analysis/taint-generic.c Tue Feb 21 20:35:58 2012 @@ -111,11 +111,11 @@ char buffer[156]; char addr[128]; scanf("%s", addr); - system(addr); // expected-warning {{Tainted data passed to a system call}} + system(addr); // expected-warning {{Untrusted data is passed to a system call}} // Test that spintf transfers taint. sprintf(buffer, "/bin/mail %s < /tmp/email", addr); - system(buffer); // expected-warning {{Tainted data passed to a system call}} + system(buffer); // expected-warning {{Untrusted data is passed to a system call}} } void testTaintSystemCall2() { @@ -124,7 +124,7 @@ char addr[128]; scanf("%s", addr); __builtin_snprintf(buffern, 10, "/bin/mail %s < /tmp/email", addr); - system(buffern); // expected-warning {{Tainted data passed to a system call}} + system(buffern); // expected-warning {{Untrusted data is passed to a system call}} } void testTaintSystemCall3() { @@ -133,20 +133,20 @@ char addr[128]; scanf("%s %d", addr, &numt); __builtin_snprintf(buffern2, numt, "/bin/mail %s < /tmp/email", "abcd"); - system(buffern2); // expected-warning {{Tainted data passed to a system call}} + system(buffern2); // expected-warning {{Untrusted data is passed to a system call}} } void testTaintedBufferSize() { size_t ts; scanf("%zd", &ts); - int *buf1 = (int*)malloc(ts*sizeof(int)); // expected-warning {{Tainted data is used to specify the buffer size}} - char *dst = (char*)calloc(ts, sizeof(char)); //expected-warning {{Tainted data is used to specify the buffer size}} - bcopy(buf1, dst, ts); // expected-warning {{Tainted data is used to specify the buffer size}} - __builtin_memcpy(dst, buf1, (ts + 4)*sizeof(char)); // expected-warning {{Tainted data is used to specify the buffer size}} + int *buf1 = (int*)malloc(ts*sizeof(int)); // expected-warning {{Untrusted data is used to specify the buffer size}} + char *dst = (char*)calloc(ts, sizeof(char)); //expected-warning {{Untrusted data is used to specify the buffer size}} + bcopy(buf1, dst, ts); // expected-warning {{Untrusted data is used to specify the buffer size}} + __builtin_memcpy(dst, buf1, (ts + 4)*sizeof(char)); // expected-warning {{Untrusted data is used to specify the buffer size}} // If both buffers are trusted, do not issue a warning. - char *dst2 = (char*)malloc(ts*sizeof(char)); // expected-warning {{Tainted data is used to specify the buffer size}} + char *dst2 = (char*)malloc(ts*sizeof(char)); // expected-warning {{Untrusted data is used to specify the buffer size}} strncat(dst2, dst, ts); // no-warning } @@ -164,7 +164,7 @@ sock = socket(AF_INET, SOCK_STREAM, 0); read(sock, buffer, 100); - execl(buffer, "filename", 0); // expected-warning {{Tainted data passed to a system call}} + execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}} sock = socket(AF_LOCAL, SOCK_STREAM, 0); read(sock, buffer, 100); From ganna at apple.com Tue Feb 21 18:36:01 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 22 Feb 2012 02:36:01 -0000 Subject: [cfe-commits] r151121 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c Message-ID: <20120222023601.E6F682A6C12F@llvm.org> Author: zaks Date: Tue Feb 21 20:36:01 2012 New Revision: 151121 URL: http://llvm.org/viewvc/llvm-project?rev=151121&view=rev Log: [analyzer] Malloc: fix another false positive. , when we return a symbol reachable to the malloced one via pointer arithmetic. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/malloc.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=151121&r1=151120&r2=151121&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Tue Feb 21 20:36:01 2012 @@ -881,7 +881,17 @@ return; // Check if we are returning a symbol. - SymbolRef Sym = C.getState()->getSVal(E, C.getLocationContext()).getAsSymbol(); + SVal RetVal = C.getState()->getSVal(E, C.getLocationContext()); + SymbolRef Sym = RetVal.getAsSymbol(); + if (!Sym) + // If we are returning a field of the allocated struct or an array element, + // the callee could still free the memory. + // TODO: This logic should be a part of generic symbol escape callback. + if (const MemRegion *MR = RetVal.getAsRegion()) + if (isa(MR) || isa(MR)) + if (const SymbolicRegion *BMR = + dyn_cast(MR->getBaseRegion())) + Sym = BMR->getSymbol(); if (!Sym) return; Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=151121&r1=151120&r2=151121&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Tue Feb 21 20:36:01 2012 @@ -631,6 +631,27 @@ p = ((__builtin_object_size (p, 0) != (size_t) -1) ? __builtin___strcpy_chk (p, s, __builtin_object_size (p, 2 > 1)) : __inline_strcpy_chk (p, s)); free(p); } + +// Here we are returning a pointer one past the allocated value. An idiom which +// can be used for implementing special malloc. The correct uses of this might +// be rare enough so that we could keep this as a warning. +static void *specialMalloc(int n){ + int *p; + p = malloc( n+8 ); + if( p ){ + p[0] = n; + p++; + } + return p; +} + +// Potentially, the user could free the struct by performing pointer arithmetic on the return value. +// This is a variation of the specialMalloc issue, though probably would be more rare in correct code. +int *specialMallocWithStruct() { + struct StructWithInt *px= malloc(sizeof(struct StructWithInt)); + return &(px->g); +} + // Below are the known false positives. // TODO: There should be no warning here. This one might be difficult to get rid of. @@ -650,20 +671,6 @@ return; } -// TODO: Should this be a warning? -// Here we are returning a pointer one past the allocated value. An idiom which -// can be used for implementing special malloc. The correct uses of this might -// be rare enough so that we could keep this as a warning. -static void *specialMalloc(int n){ - int *p; - p = malloc( n+8 ); - if( p ){ - p[0] = n; - p++; - } - return p;// expected-warning {{Memory is never released; potential memory leak}} -} - // False negatives. // TODO: This requires tracking symbols stored inside the structs/arrays. @@ -673,6 +680,16 @@ pSt->memP = malloc(12); } +// TODO: This is another false negative. +void testMallocWithParam(int **p) { + *p = (int*) malloc(sizeof(int)); + *p = 0; +} + +void testMallocWithParam_2(int **p) { + *p = (int*) malloc(sizeof(int)); +} + // TODO: This should produce a warning, similar to the previous issue. void localArrayTest() { char *p = (char*)malloc(12); From aaron at aaronballman.com Tue Feb 21 19:04:13 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Wed, 22 Feb 2012 03:04:13 -0000 Subject: [cfe-commits] r151122 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/thiscall-struct-return.cpp Message-ID: <20120222030413.B97902A6C12F@llvm.org> Author: aaronballman Date: Tue Feb 21 21:04:13 2012 New Revision: 151122 URL: http://llvm.org/viewvc/llvm-project?rev=151122&view=rev Log: Adding support for Microsoft's thiscall calling convention. Clang side of the patch. Added: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp (with props) Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=151122&r1=151121&r2=151122&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Feb 21 21:04:13 2012 @@ -424,7 +424,8 @@ return (Size == 8 || Size == 16 || Size == 32 || Size == 64); } - static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context); + static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, + unsigned callingConvention); /// getIndirectResult - Give a source type \arg Ty, return a suitable result /// such that the argument will be passed in memory. @@ -435,11 +436,13 @@ public: - ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyReturnType(QualType RetTy, + unsigned callingConvention) const; ABIArgInfo classifyArgumentType(QualType RetTy) const; virtual void computeInfo(CGFunctionInfo &FI) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), + FI.getCallingConvention()); for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) it->info = classifyArgumentType(it->type); @@ -485,7 +488,8 @@ /// shouldReturnTypeInRegister - Determine if the given type should be /// passed in a register (for the Darwin ABI). bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, - ASTContext &Context) { + ASTContext &Context, + unsigned callingConvention) { uint64_t Size = Context.getTypeSize(Ty); // Type must be register sized. @@ -510,7 +514,8 @@ // Arrays are treated like records. if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) - return shouldReturnTypeInRegister(AT->getElementType(), Context); + return shouldReturnTypeInRegister(AT->getElementType(), Context, + callingConvention); // Otherwise, it must be a record type. const RecordType *RT = Ty->getAs(); @@ -518,6 +523,13 @@ // FIXME: Traverse bases here too. + // For thiscall conventions, structures will never be returned in + // a register. This is for compatibility with the MSVC ABI + if (callingConvention == llvm::CallingConv::X86_ThisCall && + RT->isStructureType()) { + return false; + } + // Structure types are passed in register if all fields would be // passed in a register. for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(), @@ -529,14 +541,15 @@ continue; // Check fields recursively. - if (!shouldReturnTypeInRegister(FD->getType(), Context)) + if (!shouldReturnTypeInRegister(FD->getType(), Context, + callingConvention)) return false; } - return true; } -ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const { +ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, + unsigned callingConvention) const { if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); @@ -583,7 +596,8 @@ // Small structures which are register sized are generally returned // in a register. - if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) { + if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext(), + callingConvention)) { uint64_t Size = getContext().getTypeSize(RetTy); // As a special-case, if the struct is a "single-element" struct, and Added: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp?rev=151122&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp (added) +++ cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp Tue Feb 21 21:04:13 2012 @@ -0,0 +1,41 @@ +// For MSVC ABI compatibility, all structures returned by value using the +// thiscall calling convention must use the hidden parameter. +// +// RUN: %clang_cc1 -triple i386-PC-Win32 %s -fms-compatibility -O0 -emit-llvm -o - | FileCheck %s + +// This structure would normally be returned via EAX +struct S { + int i; +}; + +// This structure would normally be returned via EAX/EDX +struct M { + int i; + int j; +}; + +class C { +public: + C() {} + + struct S __attribute__((thiscall)) Small() const { + struct S s = { 0 }; + return s; + } + + struct M __attribute__((thiscall)) Medium() const { + struct M m = { 0 }; + return m; + } +}; + +// CHECK: define void @_Z4testv() +void test( void ) { +// CHECK: call void @_ZN1CC1Ev(%class.C* %c) + C c; + +// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(%struct.S* sret %tmp, %class.C* %c) + (void)c.Small(); +// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(%struct.M* sret %tmp1, %class.C* %c) + (void)c.Medium(); +} Propchange: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp ------------------------------------------------------------------------------ svn:eol-style = native From thakis at chromium.org Tue Feb 21 19:17:50 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 21 Feb 2012 19:17:50 -0800 Subject: [cfe-commits] [patch] Warn in string literal + integral Message-ID: Hi, the attached patch adds -Wstring-plus-int (I'm open to more creative names :-) ), which warns on code like |"error code: " + err|. The warning found 4 bugs in 2 files in chromium. The bugs it found look like this: File 1: if (!read_node.InitByIdLookup(it->id)) { error_handler()->OnUnrecoverableError(FROM_HERE, "Failed to look up " " data for received change with id " + it->id); return; } File 2: ResetStream(stream_id, spdy::INVALID_ASSOCIATED_STREAM, "Received OnSyn with inactive associated stream " + associated_stream_id); (Fix: http://codereview.chromium.org/9372076/diff/1/net/spdy/spdy_session.cc ) (A coworker found the bug in the one file, which prompted me writing the warning. The warning then found the bug in the other file.) When building all of chromium and its many dependencies, the warning did also find 3 false positives, but they all look alike: Ffmepg contains three different functions that all look like this: const char *avformat_license(void) { #define LICENSE_PREFIX "libavformat license: " return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } I don't quite get what this is for (a coworker suggested it's so that "libavformat license: " shows up in `strings` output, but is omitted from the return), but I think warning on code like this is kind of ok. Here's how the warning looks in this case: ../../third_party/ffmpeg/patched-ffmpeg/libavformat/utils.c:68:42: warning: Adding an integral to a string does not append to the string [-Wstring-plus-int] return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ ../../third_party/ffmpeg/patched-ffmpeg/libavformat/utils.c:68:42: note: use &(str[index]) if pointer arithmetic is intended 1 warning generated. I'm looking forward to comments :-) Nico -------------- next part -------------- A non-text attachment was scrubbed... Name: clang-str-plus-int.patch Type: application/octet-stream Size: 5658 bytes Desc: not available URL: From ganna at apple.com Tue Feb 21 19:14:20 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 22 Feb 2012 03:14:20 -0000 Subject: [cfe-commits] r151124 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c Message-ID: <20120222031420.A64182A6C130@llvm.org> Author: zaks Date: Tue Feb 21 21:14:20 2012 New Revision: 151124 URL: http://llvm.org/viewvc/llvm-project?rev=151124&view=rev Log: [analyzer] Malloc checker: mark 'strdup' and 'strndup' as allocators. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/malloc.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=151124&r1=151123&r2=151124&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Tue Feb 21 21:14:20 2012 @@ -26,6 +26,8 @@ #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include + using namespace clang; using namespace ento; @@ -97,11 +99,13 @@ mutable OwningPtr BT_UseFree; mutable OwningPtr BT_BadFree; mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc, - *II_valloc, *II_reallocf; + *II_valloc, *II_reallocf, *II_strndup, *II_strdup; + + static const unsigned InvalidArgIndex = UINT_MAX; public: MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0), - II_valloc(0), II_reallocf(0) {} + II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0) {} /// In pessimistic mode, the checker assumes that it does not know which /// functions might free the memory. @@ -140,7 +144,8 @@ /// pointed to by one of its arguments. bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const; - static void MallocMem(CheckerContext &C, const CallExpr *CE); + static void MallocMem(CheckerContext &C, const CallExpr *CE, + unsigned SizeIdx); static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, const OwnershipAttr* Att); static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, @@ -283,6 +288,10 @@ II_calloc = &Ctx.Idents.get("calloc"); if (!II_valloc) II_valloc = &Ctx.Idents.get("valloc"); + if (!II_strdup) + II_strdup = &Ctx.Idents.get("strdup"); + if (!II_strndup) + II_strndup = &Ctx.Idents.get("strndup"); } bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const { @@ -294,9 +303,9 @@ initIdentifierInfo(C); - // TODO: Add more here : ex: reallocf! if (FunI == II_malloc || FunI == II_free || FunI == II_realloc || - FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc) + FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc || + FunI == II_strdup || FunI == II_strndup) return true; if (Filter.CMallocOptimistic && FD->hasAttrs() && @@ -319,7 +328,7 @@ return; if (FunI == II_malloc || FunI == II_valloc) { - MallocMem(C, CE); + MallocMem(C, CE, 0); return; } else if (FunI == II_realloc) { ReallocMem(C, CE, false); @@ -330,9 +339,15 @@ } else if (FunI == II_calloc) { CallocMem(C, CE); return; - }else if (FunI == II_free) { + } else if (FunI == II_free) { FreeMem(C, CE); return; + } else if (FunI == II_strdup) { + MallocMem(C, CE, InvalidArgIndex); + return; + } else if (FunI == II_strndup) { + MallocMem(C, CE, 1); + return; } if (Filter.CMallocOptimistic) @@ -358,10 +373,16 @@ } } -void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) { - ProgramStateRef state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), - C.getState()); - C.addTransition(state); +void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE, + unsigned SizeIdx) { + SVal Undef = UndefinedVal(); + ProgramStateRef State; + if (SizeIdx != InvalidArgIndex) + State = MallocMemAux(C, CE, CE->getArg(SizeIdx), Undef, C.getState()); + else + State = MallocMemAux(C, CE, Undef, Undef, C.getState()); + + C.addTransition(State); } void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, @@ -400,16 +421,17 @@ // Set the region's extent equal to the Size parameter. const SymbolicRegion *R = dyn_cast_or_null(retVal.getAsRegion()); - if (!R || !isa(Size)) + if (!R) return 0; + if (isa(Size)) { + DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); + DefinedOrUnknownSVal DefinedSize = cast(Size); + DefinedOrUnknownSVal extentMatchesSize = + svalBuilder.evalEQ(state, Extent, DefinedSize); - DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); - DefinedOrUnknownSVal DefinedSize = cast(Size); - DefinedOrUnknownSVal extentMatchesSize = - svalBuilder.evalEQ(state, Extent, DefinedSize); - - state = state->assume(extentMatchesSize, true); - assert(state); + state = state->assume(extentMatchesSize, true); + assert(state); + } SymbolRef Sym = retVal.getAsLocSymbol(); assert(Sym); Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=151124&r1=151123&r2=151124&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Tue Feb 21 21:14:20 2012 @@ -652,6 +652,25 @@ return &(px->g); } +// Test various allocation/deallocation functions. + +char *strdup(const char *s); +char *strndup(const char *s, size_t n); + +void testStrdup(const char *s, unsigned validIndex) { + char *s2 = strdup(s); + s2[validIndex + 1] = 'b';// expected-warning {{Memory is never released; potential memory leak}} +} + +int testStrndup(const char *s, unsigned validIndex, unsigned size) { + char *s2 = strndup(s, size); + s2 [validIndex + 1] = 'b'; + if (s2[validIndex] != 'a') + return 0;// expected-warning {{Memory is never released; potential memory leak}} + else + return 1;// expected-warning {{Memory is never released; potential memory leak}} +} + // Below are the known false positives. // TODO: There should be no warning here. This one might be difficult to get rid of. From thakis at chromium.org Tue Feb 21 19:32:14 2012 From: thakis at chromium.org (Nico Weber) Date: Tue, 21 Feb 2012 19:32:14 -0800 Subject: [cfe-commits] r151122 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/thiscall-struct-return.cpp In-Reply-To: <20120222030413.B97902A6C12F@llvm.org> References: <20120222030413.B97902A6C12F@llvm.org> Message-ID: On Tue, Feb 21, 2012 at 7:04 PM, Aaron Ballman wrote: > Author: aaronballman > Date: Tue Feb 21 21:04:13 2012 > New Revision: 151122 > > URL: http://llvm.org/viewvc/llvm-project?rev=151122&view=rev > Log: > Adding support for Microsoft's thiscall calling convention.  Clang side of the patch. > > Added: >    cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp   (with props) > Modified: >    cfe/trunk/lib/CodeGen/TargetInfo.cpp > > Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=151122&r1=151121&r2=151122&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) > +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Feb 21 21:04:13 2012 > @@ -424,7 +424,8 @@ >     return (Size == 8 || Size == 16 || Size == 32 || Size == 64); >   } > > -  static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context); > +  static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, > +                                          unsigned callingConvention); > >   /// getIndirectResult - Give a source type \arg Ty, return a suitable result >   /// such that the argument will be passed in memory. > @@ -435,11 +436,13 @@ > >  public: > > -  ABIArgInfo classifyReturnType(QualType RetTy) const; > +  ABIArgInfo classifyReturnType(QualType RetTy, > +                                unsigned callingConvention) const; >   ABIArgInfo classifyArgumentType(QualType RetTy) const; > >   virtual void computeInfo(CGFunctionInfo &FI) const { > -    FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); > +    FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), > +                                            FI.getCallingConvention()); >     for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); >          it != ie; ++it) >       it->info = classifyArgumentType(it->type); > @@ -485,7 +488,8 @@ >  /// shouldReturnTypeInRegister - Determine if the given type should be >  /// passed in a register (for the Darwin ABI). >  bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, > -                                               ASTContext &Context) { > +                                               ASTContext &Context, > +                                               unsigned callingConvention) { >   uint64_t Size = Context.getTypeSize(Ty); > >   // Type must be register sized. > @@ -510,7 +514,8 @@ > >   // Arrays are treated like records. >   if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) > -    return shouldReturnTypeInRegister(AT->getElementType(), Context); > +    return shouldReturnTypeInRegister(AT->getElementType(), Context, > +                                      callingConvention); > >   // Otherwise, it must be a record type. >   const RecordType *RT = Ty->getAs(); > @@ -518,6 +523,13 @@ > >   // FIXME: Traverse bases here too. > > +  // For thiscall conventions, structures will never be returned in > +  // a register.  This is for compatibility with the MSVC ABI > +  if (callingConvention == llvm::CallingConv::X86_ThisCall && > +      RT->isStructureType()) { > +    return false; > +  } > + >   // Structure types are passed in register if all fields would be >   // passed in a register. >   for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(), > @@ -529,14 +541,15 @@ >       continue; > >     // Check fields recursively. > -    if (!shouldReturnTypeInRegister(FD->getType(), Context)) > +    if (!shouldReturnTypeInRegister(FD->getType(), Context, > +                                    callingConvention)) >       return false; >   } > - >   return true; >  } > > -ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const { > +ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, > +                                            unsigned callingConvention) const { >   if (RetTy->isVoidType()) >     return ABIArgInfo::getIgnore(); > > @@ -583,7 +596,8 @@ > >     // Small structures which are register sized are generally returned >     // in a register. > -    if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) { > +    if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext(), > +                                                  callingConvention)) { >       uint64_t Size = getContext().getTypeSize(RetTy); > >       // As a special-case, if the struct is a "single-element" struct, and > > Added: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp?rev=151122&view=auto > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp (added) > +++ cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp Tue Feb 21 21:04:13 2012 > @@ -0,0 +1,41 @@ > +// For MSVC ABI compatibility, all structures returned by value using the > +// thiscall calling convention must use the hidden parameter. > +// > +// RUN: %clang_cc1 -triple i386-PC-Win32 %s -fms-compatibility -O0 -emit-llvm -o - | FileCheck %s > + > +// This structure would normally be returned via EAX > +struct S { > +  int i; > +}; > + > +// This structure would normally be returned via EAX/EDX > +struct M { > +  int i; > +  int j; > +}; > + > +class C { > +public: > +  C() {} > + > +  struct S __attribute__((thiscall)) Small() const { > +    struct S s = { 0 }; > +    return s; > +  } > + > +  struct M __attribute__((thiscall)) Medium() const { > +    struct M m = { 0 }; > +    return m; > +  } > +}; > + > +// CHECK: define void @_Z4testv() > +void test( void ) { > +// CHECK: call void @_ZN1CC1Ev(%class.C* %c) > +  C c; > + > +// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(%struct.S* sret %tmp, %class.C* %c) > +  (void)c.Small(); > +// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(%struct.M* sret %tmp1, %class.C* %c) > +  (void)c.Medium(); > +} > > Propchange: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp > ------------------------------------------------------------------------------ >    svn:eol-style = native I think I was told once that clang prefers no svn:eol-style property on its files. Nico From aaron at aaronballman.com Tue Feb 21 19:35:27 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Tue, 21 Feb 2012 21:35:27 -0600 Subject: [cfe-commits] [patch] Warn in string literal + integral In-Reply-To: References: Message-ID: On Tue, Feb 21, 2012 at 9:17 PM, Nico Weber wrote: > Hi, > > the attached patch adds -Wstring-plus-int (I'm open to more creative > names :-) ), which warns on code like |"error code: " + err|. The > warning found 4 bugs in 2 files in chromium. The bugs it found look > like this: > > File 1: >    if (!read_node.InitByIdLookup(it->id)) { >      error_handler()->OnUnrecoverableError(FROM_HERE, "Failed to look up " >          " data for received change with id " + it->id); >      return; >    } > > File 2: >    ResetStream(stream_id, spdy::INVALID_ASSOCIATED_STREAM, >      "Received OnSyn with inactive associated stream " + >      associated_stream_id); > (Fix: http://codereview.chromium.org/9372076/diff/1/net/spdy/spdy_session.cc ) > > (A coworker found the bug in the one file, which prompted me writing > the warning. The warning then found the bug in the other file.) > > > When building all of chromium and its many dependencies, the warning > did also find 3 false positives, but they all look alike: Ffmepg > contains three different functions that all look like this: > > const char *avformat_license(void) > { > #define LICENSE_PREFIX "libavformat license: " >    return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; > } > > I don't quite get what this is for (a coworker suggested it's so that > "libavformat license: " shows up in `strings` output, but is omitted > from the return), but I think warning on code like this is kind of ok. > Here's how the warning looks in this case: > > ../../third_party/ffmpeg/patched-ffmpeg/libavformat/utils.c:68:42: > warning: Adding an integral to a string does not append to the string > [-Wstring-plus-int] >    return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; >           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ > ../../third_party/ffmpeg/patched-ffmpeg/libavformat/utils.c:68:42: > note: use &(str[index]) if pointer arithmetic is intended > 1 warning generated. > > > I'm looking forward to comments :-) Patch LGTM ~Aaron From aaron at aaronballman.com Tue Feb 21 19:37:18 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Tue, 21 Feb 2012 21:37:18 -0600 Subject: [cfe-commits] r151122 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/thiscall-struct-return.cpp In-Reply-To: References: <20120222030413.B97902A6C12F@llvm.org> Message-ID: On Tue, Feb 21, 2012 at 9:32 PM, Nico Weber wrote: > On Tue, Feb 21, 2012 at 7:04 PM, Aaron Ballman wrote: >> Author: aaronballman >> Date: Tue Feb 21 21:04:13 2012 >> New Revision: 151122 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=151122&view=rev >> Log: >> Adding support for Microsoft's thiscall calling convention.  Clang side of the patch. >> >> Added: >>    cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp   (with props) >> Modified: >>    cfe/trunk/lib/CodeGen/TargetInfo.cpp >> >> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=151122&r1=151121&r2=151122&view=diff >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) >> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Feb 21 21:04:13 2012 >> @@ -424,7 +424,8 @@ >>     return (Size == 8 || Size == 16 || Size == 32 || Size == 64); >>   } >> >> -  static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context); >> +  static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, >> +                                          unsigned callingConvention); >> >>   /// getIndirectResult - Give a source type \arg Ty, return a suitable result >>   /// such that the argument will be passed in memory. >> @@ -435,11 +436,13 @@ >> >>  public: >> >> -  ABIArgInfo classifyReturnType(QualType RetTy) const; >> +  ABIArgInfo classifyReturnType(QualType RetTy, >> +                                unsigned callingConvention) const; >>   ABIArgInfo classifyArgumentType(QualType RetTy) const; >> >>   virtual void computeInfo(CGFunctionInfo &FI) const { >> -    FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); >> +    FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), >> +                                            FI.getCallingConvention()); >>     for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); >>          it != ie; ++it) >>       it->info = classifyArgumentType(it->type); >> @@ -485,7 +488,8 @@ >>  /// shouldReturnTypeInRegister - Determine if the given type should be >>  /// passed in a register (for the Darwin ABI). >>  bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, >> -                                               ASTContext &Context) { >> +                                               ASTContext &Context, >> +                                               unsigned callingConvention) { >>   uint64_t Size = Context.getTypeSize(Ty); >> >>   // Type must be register sized. >> @@ -510,7 +514,8 @@ >> >>   // Arrays are treated like records. >>   if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) >> -    return shouldReturnTypeInRegister(AT->getElementType(), Context); >> +    return shouldReturnTypeInRegister(AT->getElementType(), Context, >> +                                      callingConvention); >> >>   // Otherwise, it must be a record type. >>   const RecordType *RT = Ty->getAs(); >> @@ -518,6 +523,13 @@ >> >>   // FIXME: Traverse bases here too. >> >> +  // For thiscall conventions, structures will never be returned in >> +  // a register.  This is for compatibility with the MSVC ABI >> +  if (callingConvention == llvm::CallingConv::X86_ThisCall && >> +      RT->isStructureType()) { >> +    return false; >> +  } >> + >>   // Structure types are passed in register if all fields would be >>   // passed in a register. >>   for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(), >> @@ -529,14 +541,15 @@ >>       continue; >> >>     // Check fields recursively. >> -    if (!shouldReturnTypeInRegister(FD->getType(), Context)) >> +    if (!shouldReturnTypeInRegister(FD->getType(), Context, >> +                                    callingConvention)) >>       return false; >>   } >> - >>   return true; >>  } >> >> -ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const { >> +ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, >> +                                            unsigned callingConvention) const { >>   if (RetTy->isVoidType()) >>     return ABIArgInfo::getIgnore(); >> >> @@ -583,7 +596,8 @@ >> >>     // Small structures which are register sized are generally returned >>     // in a register. >> -    if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) { >> +    if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext(), >> +                                                  callingConvention)) { >>       uint64_t Size = getContext().getTypeSize(RetTy); >> >>       // As a special-case, if the struct is a "single-element" struct, and >> >> Added: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp?rev=151122&view=auto >> ============================================================================== >> --- cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp (added) >> +++ cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp Tue Feb 21 21:04:13 2012 >> @@ -0,0 +1,41 @@ >> +// For MSVC ABI compatibility, all structures returned by value using the >> +// thiscall calling convention must use the hidden parameter. >> +// >> +// RUN: %clang_cc1 -triple i386-PC-Win32 %s -fms-compatibility -O0 -emit-llvm -o - | FileCheck %s >> + >> +// This structure would normally be returned via EAX >> +struct S { >> +  int i; >> +}; >> + >> +// This structure would normally be returned via EAX/EDX >> +struct M { >> +  int i; >> +  int j; >> +}; >> + >> +class C { >> +public: >> +  C() {} >> + >> +  struct S __attribute__((thiscall)) Small() const { >> +    struct S s = { 0 }; >> +    return s; >> +  } >> + >> +  struct M __attribute__((thiscall)) Medium() const { >> +    struct M m = { 0 }; >> +    return m; >> +  } >> +}; >> + >> +// CHECK: define void @_Z4testv() >> +void test( void ) { >> +// CHECK: call void @_ZN1CC1Ev(%class.C* %c) >> +  C c; >> + >> +// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(%struct.S* sret %tmp, %class.C* %c) >> +  (void)c.Small(); >> +// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(%struct.M* sret %tmp1, %class.C* %c) >> +  (void)c.Medium(); >> +} >> >> Propchange: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp >> ------------------------------------------------------------------------------ >>    svn:eol-style = native > > I think I was told once that clang prefers no svn:eol-style property > on its files. Hmm, I may have heard wrong then. If that's the case, I'll take care of it. Confirmation? ~Aaron From geek4civic at gmail.com Tue Feb 21 19:36:55 2012 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 22 Feb 2012 03:36:55 -0000 Subject: [cfe-commits] r151126 - /cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp Message-ID: <20120222033655.23D2B2A6C12F@llvm.org> Author: chapuni Date: Tue Feb 21 21:36:54 2012 New Revision: 151126 URL: http://llvm.org/viewvc/llvm-project?rev=151126&view=rev Log: test/CodeGenCXX/thiscall-struct-return.cpp: Relax expressions for -Asserts. Modified: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp Modified: cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp?rev=151126&r1=151125&r2=151126&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp (original) +++ cfe/trunk/test/CodeGenCXX/thiscall-struct-return.cpp Tue Feb 21 21:36:54 2012 @@ -31,11 +31,11 @@ // CHECK: define void @_Z4testv() void test( void ) { -// CHECK: call void @_ZN1CC1Ev(%class.C* %c) +// CHECK: call void @_ZN1CC1Ev(%class.C* [[C:%.+]]) C c; -// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(%struct.S* sret %tmp, %class.C* %c) +// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(%struct.S* sret %{{.+}}, %class.C* [[C]]) (void)c.Small(); -// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(%struct.M* sret %tmp1, %class.C* %c) +// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(%struct.M* sret %{{.+}}, %class.C* [[C]]) (void)c.Medium(); } From richard at metafoo.co.uk Tue Feb 21 20:07:56 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Tue, 21 Feb 2012 20:07:56 -0800 Subject: [cfe-commits] [patch] Warn in string literal + integral In-Reply-To: References: Message-ID: Hi Nico, On Tue, Feb 21, 2012 at 7:17 PM, Nico Weber wrote: > the attached patch adds -Wstring-plus-int (I'm open to more creative > names :-) ), which warns on code like |"error code: " + err|. The > warning found 4 bugs in 2 files in chromium. The bugs it found look > like this: > > File 1: > if (!read_node.InitByIdLookup(it->id)) { > error_handler()->OnUnrecoverableError(FROM_HERE, "Failed to look up " > " data for received change with id " + it->id); > return; > } > > File 2: > ResetStream(stream_id, spdy::INVALID_ASSOCIATED_STREAM, > "Received OnSyn with inactive associated stream " + > associated_stream_id); > (Fix: > http://codereview.chromium.org/9372076/diff/1/net/spdy/spdy_session.cc ) > > (A coworker found the bug in the one file, which prompted me writing > the warning. The warning then found the bug in the other file.) > > > When building all of chromium and its many dependencies, the warning > did also find 3 false positives, but they all look alike: Ffmepg > contains three different functions that all look like this: > 4 bugs and 3 false positives doesn't sound great to me. Have you considered relaxing the warning in cases where the integral summand is a constant expression and is in-bounds? Would this pattern have matched any of your real bugs? Onto the patch... Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td (revision 150418) +++ include/clang/Basic/DiagnosticGroups.td (working copy) @@ -320,6 +321,7 @@ ReturnType, SelfAssignment, SizeofArrayArgument, + StringPlusInt, Trigraphs, Uninitialized, UnknownPragmas, Given the current level of false positives, I'm not completely convinced this should go into -Wmost. I imagine we'll know more once we've run this on more code. Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td (revision 150418) +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy) @@ -3414,6 +3414,12 @@ "explicitly assigning a variable of type %0 to itself">, InGroup, DefaultIgnore; +def warn_string_plus_int : Warning< + "Adding an integral to a string does not append to the string">, Diagnostics outside the static analyzer should not be capitalized. + InGroup; +def note_string_plus_int_silence : Note< + "use &(str[index]) if pointer arithmetic is intended">; The parentheses here are redundant. I think I'd prefer for the suggestion to be provided via fixits (and to reword this as something like "use array indexing to silence this warning"). Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp (revision 150418) +++ lib/Sema/SemaExpr.cpp (working copy) @@ -7798,6 +7798,20 @@ ParensRange); } +/// DiagnoseStringPlusInt - Emit a warning when adding an integer to a string +/// literal. +static void DiagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + bool IsStringPlusInt = dyn_cast(LHSExpr) && + RHSExpr->getType()->isIntegralType(Self.getASTContext()); We should probably also check for (unscoped) enumeration types, and for class types with implicit conversion to int. Doing so will require moving this check to checkArithmeticOpPointerOperand (after we've checked for an overloaded operator+). + if (!IsStringPlusInt) + return; + + SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + Self.Diag(OpLoc, diag::warn_string_plus_int) << DiagRange; + Self.Diag(OpLoc, diag::note_string_plus_int_silence); +} We should also catch the case where the integer is on the LHS (and skip the fixit in that case). Richard -------------- next part -------------- An HTML attachment was scrubbed... URL: From clattner at apple.com Tue Feb 21 20:08:43 2012 From: clattner at apple.com (Chris Lattner) Date: Tue, 21 Feb 2012 20:08:43 -0800 Subject: [cfe-commits] r151109 - in /cfe/trunk: include/clang/Driver/Options.td lib/Driver/Driver.cpp In-Reply-To: <20120222003039.C2FCD2A6C12F@llvm.org> References: <20120222003039.C2FCD2A6C12F@llvm.org> Message-ID: <9AC1F911-8484-444E-B862-1F293EAF8EE5@apple.com> On Feb 21, 2012, at 4:30 PM, Chad Rosier wrote: > Author: mcrosier > Date: Tue Feb 21 18:30:39 2012 > New Revision: 151109 > > URL: http://llvm.org/viewvc/llvm-project?rev=151109&view=rev > Log: > Provide a way to disable auto-generation of preprocessed files during clang > crash. This can speedup the process of generating a delta reduced test case. > rdar://10905465 Hi Chad, Please document this in the Clang user's manual. -Chris > > Modified: > cfe/trunk/include/clang/Driver/Options.td > cfe/trunk/lib/Driver/Driver.cpp > > Modified: cfe/trunk/include/clang/Driver/Options.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=151109&r1=151108&r2=151109&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Driver/Options.td (original) > +++ cfe/trunk/include/clang/Driver/Options.td Tue Feb 21 18:30:39 2012 > @@ -292,6 +292,7 @@ > def fconstexpr_depth_EQ : Joined<"-fconstexpr-depth=">, Group; > def fconstexpr_backtrace_limit_EQ : Joined<"-fconstexpr-backtrace-limit=">, > Group; > +def fno_crash_diagnostics : Flag<"-fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>; > def fcreate_profile : Flag<"-fcreate-profile">, Group; > def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group; > def fcxx_modules : Flag <"-fcxx-modules">, Group, Flags<[NoForward]>; > > Modified: cfe/trunk/lib/Driver/Driver.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=151109&r1=151108&r2=151109&view=diff > ============================================================================== > --- cfe/trunk/lib/Driver/Driver.cpp (original) > +++ cfe/trunk/lib/Driver/Driver.cpp Tue Feb 21 18:30:39 2012 > @@ -363,6 +363,9 @@ > // diagnostic information to a bug report. > void Driver::generateCompilationDiagnostics(Compilation &C, > const Command *FailingCommand) { > + if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) > + return; > + > Diag(clang::diag::note_drv_command_failed_diag_msg) > << "Please submit a bug report to " BUG_REPORT_URL " and include command" > " line arguments and all diagnostic information."; > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From mimomorin at gmail.com Tue Feb 21 20:38:50 2012 From: mimomorin at gmail.com (Michel Morin) Date: Wed, 22 Feb 2012 13:38:50 +0900 Subject: [cfe-commits] r151117 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/CXX/d Message-ID: > Log: > Implement C++11 [expr.call]p11: If the operand to a decltype-specifier is a > function call (or a comma expression with a function call on its right-hand > side), possibly parenthesized, then the return type is not required to be > complete and a temporary is not bound. Other subexpressions inside a decltype > expression do not get this treatment. Is there any way to detect this C++11 decltype feature? `__has_feature(cxx_decltype)` does not work, since this macro also detects pre-N3276 decltype. (Boost.Config needs to detect N3276 decltype.) Regards, Michel From rtrieu at google.com Tue Feb 21 20:47:51 2012 From: rtrieu at google.com (Richard Trieu) Date: Tue, 21 Feb 2012 20:47:51 -0800 Subject: [cfe-commits] [Patch] New warning for scopes that start in one file and end in another. In-Reply-To: References: <7D65511B-8240-4CB0-8EAE-6914EBA4FC3E@getdesigned.at> Message-ID: On Fri, Feb 17, 2012 at 4:51 AM, Manuel Klimek wrote: > On Thu, Feb 16, 2012 at 5:31 PM, Matt Beaumont-Gay > wrote: > > On Thu, Feb 16, 2012 at 02:46, Sebastian Redl > > wrote: > >> > >> On 16.02.2012, at 08:11, Matt Beaumont-Gay wrote: > >> > >>> On Wed, Feb 15, 2012 at 20:47, Eli Friedman > wrote: > >>>> Mechanically, the patch looks fine... > >>>> > >>>> What sort of testing have you done with this patch? Has this caught > >>>> any interesting issues in existing code? If not, why is this warning > >>>> useful? Any false positives we should be aware of? > >>> > >>> I imagine that this will not have a lot of hits on checked-in code. > >>> However, I can see it being very useful during development, e.g. when > >>> you forget to close a namespace at the bottom of a header file. > >> > >> But you'd most likely get an error anyway, complaining about unmatched > braces. > > > > Maybe, maybe not -- failing to close a namespace can cause a lot of > > cascading errors, which could easily hit -ferror-limit. > > How does this patch address that? It's still only warning on the > closing brace, right? > > Cheers, > /Manuel > > This patch moves the checking from the parser to the lexer. This allows the error to be emitted at the end of the file instead of at the closing brace. Since it doesn't know where the closing brace is, the warning will only point to the opening brace. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: scopes.patch Type: application/octet-stream Size: 5218 bytes Desc: not available URL: From peter at pcc.me.uk Tue Feb 21 20:47:39 2012 From: peter at pcc.me.uk (Peter Collingbourne) Date: Wed, 22 Feb 2012 04:47:39 -0000 Subject: [cfe-commits] [libclc] r151129 - in /libclc/trunk: LICENSE.TXT www/index.html Message-ID: <20120222044739.E89062A6C12F@llvm.org> Author: pcc Date: Tue Feb 21 22:47:39 2012 New Revision: 151129 URL: http://llvm.org/viewvc/llvm-project?rev=151129&view=rev Log: Switch to BSD/MIT dual license. Modified: libclc/trunk/LICENSE.TXT libclc/trunk/www/index.html Modified: libclc/trunk/LICENSE.TXT URL: http://llvm.org/viewvc/llvm-project/libclc/trunk/LICENSE.TXT?rev=151129&r1=151128&r2=151129&view=diff ============================================================================== --- libclc/trunk/LICENSE.TXT (original) +++ libclc/trunk/LICENSE.TXT Tue Feb 21 22:47:39 2012 @@ -1,4 +1,17 @@ -Copyright (c) 2011 by the contributors listed in CREDITS.TXT +============================================================================== +libclc License +============================================================================== + +The libclc library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +Copyright (c) 2011-2012 by the contributors listed in CREDITS.TXT All rights reserved. @@ -27,3 +40,25 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. + +============================================================================== + +Copyright (c) 2011-2012 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. Modified: libclc/trunk/www/index.html URL: http://llvm.org/viewvc/llvm-project/libclc/trunk/www/index.html?rev=151129&r1=151128&r2=151129&view=diff ============================================================================== --- libclc/trunk/www/index.html (original) +++ libclc/trunk/www/index.html Tue Feb 21 22:47:39 2012 @@ -5,7 +5,7 @@

libclc

-libclc is an open source, BSD licensed +libclc is an open source, BSD/MIT dual licensed implementation of the library requirements of the OpenCL C programming language, as specified by the OpenCL From eli.friedman at gmail.com Tue Feb 21 20:49:04 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 22 Feb 2012 04:49:04 -0000 Subject: [cfe-commits] r151130 - in /cfe/trunk: lib/Parse/ParseCXXInlineMethods.cpp test/CXX/temp/temp.decls/temp.variadic/p4.cpp test/SemaCXX/PR9461.cpp test/SemaCXX/constructor-initializer.cpp Message-ID: <20120222044904.D3A302A6C12F@llvm.org> Author: efriedma Date: Tue Feb 21 22:49:04 2012 New Revision: 151130 URL: http://llvm.org/viewvc/llvm-project?rev=151130&view=rev Log: Improve diagnostics a bit for bad member initializers, and fix an obscure bug involving packs. Fixes PR12049. Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp cfe/trunk/test/SemaCXX/PR9461.cpp cfe/trunk/test/SemaCXX/constructor-initializer.cpp Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=151130&r1=151129&r2=151130&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original) +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Tue Feb 21 22:49:04 2012 @@ -145,16 +145,14 @@ // function body. if (ConsumeAndStoreFunctionPrologue(Toks)) { // We didn't find the left-brace we expected after the - // constructor initializer. - if (Tok.is(tok::semi)) { - // We found a semicolon; complain, consume the semicolon, and - // don't try to parse this method later. - Diag(Tok.getLocation(), diag::err_expected_lbrace); - ConsumeAnyToken(); - delete getCurrentClass().LateParsedDeclarations.back(); - getCurrentClass().LateParsedDeclarations.pop_back(); - return FnD; - } + // constructor initializer; we already printed an error, and it's likely + // impossible to recover, so don't try to parse this method later. + // If we stopped at a semicolon, consume it to avoid an extra warning. + if (Tok.is(tok::semi)) + ConsumeToken(); + delete getCurrentClass().LateParsedDeclarations.back(); + getCurrentClass().LateParsedDeclarations.pop_back(); + return FnD; } else { // Consume everything up to (and including) the matching right brace. ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); @@ -606,6 +604,7 @@ Toks.push_back(Tok); ConsumeToken(); } + bool ReadInitializer = false; if (Tok.is(tok::colon)) { // Initializers can contain braces too. Toks.push_back(Tok); @@ -613,37 +612,52 @@ while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) { if (Tok.is(tok::eof) || Tok.is(tok::semi)) - return true; + return Diag(Tok.getLocation(), diag::err_expected_lbrace); // Grab the identifier. if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks, /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false)) - return true; + return Diag(Tok.getLocation(), diag::err_expected_lparen); tok::TokenKind kind = Tok.getKind(); Toks.push_back(Tok); - if (kind == tok::l_paren) + bool IsLParen = (kind == tok::l_paren); + SourceLocation LOpen = Tok.getLocation(); + + if (IsLParen) { ConsumeParen(); - else { + } else { assert(kind == tok::l_brace && "Must be left paren or brace here."); ConsumeBrace(); // In C++03, this has to be the start of the function body, which - // means the initializer is malformed. + // means the initializer is malformed; we'll diagnose it later. if (!getLang().CPlusPlus0x) return false; } // Grab the initializer - if (!ConsumeAndStoreUntil(kind == tok::l_paren ? tok::r_paren : - tok::r_brace, - Toks, /*StopAtSemi=*/true)) + if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace, + Toks, /*StopAtSemi=*/true)) { + Diag(Tok, IsLParen ? diag::err_expected_rparen : + diag::err_expected_rbrace); + Diag(LOpen, diag::note_matching) << (IsLParen ? "(" : "{"); return true; + } + + // Grab pack ellipsis, if present + if (Tok.is(tok::ellipsis)) { + Toks.push_back(Tok); + ConsumeToken(); + } // Grab the separating comma, if any. if (Tok.is(tok::comma)) { Toks.push_back(Tok); ConsumeToken(); + } else if (Tok.isNot(tok::l_brace)) { + ReadInitializer = true; + break; } } } @@ -651,11 +665,14 @@ // Grab any remaining garbage to be diagnosed later. We stop when we reach a // brace: an opening one is the function body, while a closing one probably // means we've reached the end of the class. - if (!ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks, - /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false)) - return true; - if(Tok.isNot(tok::l_brace)) - return true; + ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks, + /*StopAtSemi=*/true, + /*ConsumeFinalToken=*/false); + if (Tok.isNot(tok::l_brace)) { + if (ReadInitializer) + return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma); + return Diag(Tok.getLocation(), diag::err_expected_lbrace); + } Toks.push_back(Tok); ConsumeBrace(); Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp?rev=151130&r1=151129&r2=151130&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp Tue Feb 21 22:49:04 2012 @@ -91,6 +91,16 @@ X() : member()... { } // expected-error{{pack expansion for initialization of member 'member'}} }; +// There was a bug in the delayed parsing code for the +// following case. +template +struct DelayedParseTest : T... +{ + int a; + DelayedParseTest(T... i) : T{i}..., a{10} {} +}; + + // In a template-argument-list (14.3); the pattern is a template-argument. template struct tuple_of_refs { Modified: cfe/trunk/test/SemaCXX/PR9461.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR9461.cpp?rev=151130&r1=151129&r2=151130&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/PR9461.cpp (original) +++ cfe/trunk/test/SemaCXX/PR9461.cpp Tue Feb 21 22:49:04 2012 @@ -26,7 +26,7 @@ :us(_S_construct) {string a;} -struct runtime_error{runtime_error(string);}; // expected-note 2 {{candidate constructor}} +struct runtime_error{runtime_error(string);}; -struct system_error:runtime_error{ // expected-note {{to match}} expected-note {{specified here}} -system_error():time_error("" // expected-error 4 {{expected}} expected-error {{initializer}} expected-note {{to match}} expected-error {{no matching constructor}} +struct system_error:runtime_error{ // expected-note {{to match}} +system_error():time_error("" // expected-error 3 {{expected}} expected-note {{to match}} Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=151130&r1=151129&r2=151130&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original) +++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Tue Feb 21 22:49:04 2012 @@ -268,3 +268,15 @@ }; } + +namespace PR12049 { + int function(); + + class Class + { + public: + Class() : member(function() {} // expected-note {{to match this '('}} + + int member; // expected-error {{expected ')'}} + }; +} From richard at metafoo.co.uk Tue Feb 21 21:00:08 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Tue, 21 Feb 2012 21:00:08 -0800 Subject: [cfe-commits] r151117 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/CXX/d In-Reply-To: References: Message-ID: On Tue, Feb 21, 2012 at 8:38 PM, Michel Morin wrote: > > Log: > > Implement C++11 [expr.call]p11: If the operand to a decltype-specifier > is a > > function call (or a comma expression with a function call on its > right-hand > > side), possibly parenthesized, then the return type is not required to be > > complete and a temporary is not bound. Other subexpressions inside a > decltype > > expression do not get this treatment. > > Is there any way to detect this C++11 decltype feature? > `__has_feature(cxx_decltype)` does not work, > since this macro also detects pre-N3276 decltype. > (Boost.Config needs to detect N3276 decltype.) > There's no __has_feature check for it, but it's pretty easy to detect with SFINAE (check for SFINAE access control first if you want to use this particular approach): template struct enable_if_type { typedef U type; }; template false_type has_decltype_no_temp(...); template typename enable_if_type::type has_decltype_no_temp(int); class S { ~S(); }; using has_feature_decltype_no_temp = decltype(has_decltype_no_temp(0)); - Richard -------------- next part -------------- An HTML attachment was scrubbed... URL: From dgregor at apple.com Tue Feb 21 21:02:48 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 22 Feb 2012 05:02:48 -0000 Subject: [cfe-commits] r151131 - in /cfe/trunk: include/clang/AST/ lib/AST/ lib/CodeGen/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/CXX/expr/expr.prim/expr.prim.lambda/ test/PCH/ Message-ID: <20120222050249.3AC012A6C12F@llvm.org> Author: dgregor Date: Tue Feb 21 23:02:47 2012 New Revision: 151131 URL: http://llvm.org/viewvc/llvm-project?rev=151131&view=rev Log: Generate an AST for the conversion from a lambda closure type to a block pointer that returns a block literal which captures (by copy) the lambda closure itself. Some aspects of the block literal are left unspecified, namely the capture variable (which doesn't actually exist) and the body (which will be filled in by IRgen because it can't be written as an AST). Because we're switching to this model, this patch also eliminates tracking the copy-initialization expression for the block capture of the conversion function, since that information is now embedded in the synthesized block literal. -1 side tables FTW. Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm - copied unchanged from r151057, cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp cfe/trunk/test/PCH/cxx11-lambdas.mm - copied unchanged from r151057, cfe/trunk/test/PCH/cxx11-lambdas.cpp Removed: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp cfe/trunk/test/PCH/cxx11-lambdas.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/include/clang/AST/OperationKinds.h cfe/trunk/lib/AST/DeclCXX.cpp cfe/trunk/lib/AST/Expr.cpp cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/AST/StmtDumper.cpp cfe/trunk/lib/CodeGen/CGExpr.cpp cfe/trunk/lib/CodeGen/CGExprAgg.cpp cfe/trunk/lib/CodeGen/CGExprComplex.cpp cfe/trunk/lib/CodeGen/CGExprConstant.cpp cfe/trunk/lib/CodeGen/CGExprScalar.cpp cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaLambda.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Tue Feb 21 23:02:47 2012 @@ -323,12 +323,6 @@ typedef UsuallyTinyPtrVector CXXMethodVector; llvm::DenseMap OverriddenMethods; - /// \brief Mapping from lambda-to-block-pointer conversion functions to the - /// expression used to copy the lambda object. - llvm::DenseMap LambdaBlockPointerInits; - - friend class CXXConversionDecl; - /// \brief Mapping from each declaration context to its corresponding lambda /// mangling context. llvm::DenseMap LambdaMangleContexts; Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Feb 21 23:02:47 2012 @@ -2261,15 +2261,6 @@ /// a lambda closure type to a block pointer. bool isLambdaToBlockPointerConversion() const; - /// \brief For an implicit conversion function that converts a lambda - /// closure type to a block pointer, retrieve the expression used to - /// copy the closure object into the block. - Expr *getLambdaToBlockPointerCopyInit() const; - - /// \brief Set the copy-initialization expression to be used when converting - /// a lambda object to a block pointer. - void setLambdaToBlockPointerCopyInit(Expr *Init); - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConversionDecl *D) { return true; } Modified: cfe/trunk/include/clang/AST/OperationKinds.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OperationKinds.h?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/OperationKinds.h (original) +++ cfe/trunk/include/clang/AST/OperationKinds.h Tue Feb 21 23:02:47 2012 @@ -281,7 +281,14 @@ /// \brief Converts from _Atomic(T) to T. CK_AtomicToNonAtomic, /// \brief Converts from T to _Atomic(T). - CK_NonAtomicToAtomic + CK_NonAtomicToAtomic, + + /// \brief Causes a block literal to by copied to the heap and then + /// autoreleased. + /// + /// This particular cast kind is used for the conversion from a C++11 + /// lambda expression to a block pointer. + CK_CopyAndAutoreleaseBlockObject }; #define CK_Invalid ((CastKind) -1) Modified: cfe/trunk/lib/AST/DeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclCXX.cpp (original) +++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Feb 21 23:02:47 2012 @@ -1770,16 +1770,6 @@ getConversionType()->isBlockPointerType(); } -Expr *CXXConversionDecl::getLambdaToBlockPointerCopyInit() const { - assert(isLambdaToBlockPointerConversion()); - return getASTContext().LambdaBlockPointerInits[this]; -} - -void CXXConversionDecl::setLambdaToBlockPointerCopyInit(Expr *Init) { - assert(isLambdaToBlockPointerConversion()); - getASTContext().LambdaBlockPointerInits[this] = Init; -} - void LinkageSpecDecl::anchor() { } LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Tue Feb 21 23:02:47 2012 @@ -1076,6 +1076,11 @@ !getSubExpr()->getType()->isBlockPointerType()); goto CheckNoBasePath; + case CK_CopyAndAutoreleaseBlockObject: + assert(getType()->isBlockPointerType()); + assert(getSubExpr()->getType()->isBlockPointerType()); + goto CheckNoBasePath; + // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -1231,6 +1236,8 @@ return "AtomicToNonAtomic"; case CK_NonAtomicToAtomic: return "NonAtomicToAtomic"; + case CK_CopyAndAutoreleaseBlockObject: + return "CopyAndAutoreleaseBlockObject"; } llvm_unreachable("Unhandled cast kind!"); Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Feb 21 23:02:47 2012 @@ -5209,6 +5209,7 @@ case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: + case CK_CopyAndAutoreleaseBlockObject: return Error(E); case CK_UserDefinedConversion: @@ -5684,6 +5685,7 @@ case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: + case CK_CopyAndAutoreleaseBlockObject: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: Modified: cfe/trunk/lib/AST/StmtDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtDumper.cpp (original) +++ cfe/trunk/lib/AST/StmtDumper.cpp Tue Feb 21 23:02:47 2012 @@ -516,7 +516,8 @@ OS << "(capture "; if (i->isByRef()) OS << "byref "; if (i->isNested()) OS << "nested "; - DumpDeclRef(i->getVariable()); + if (i->getVariable()) + DumpDeclRef(i->getVariable()); if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr()); OS << ")"; } Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Feb 21 23:02:47 2012 @@ -2096,7 +2096,8 @@ case CK_ARCProduceObject: case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: - case CK_ARCExtendBlockObject: { + case CK_ARCExtendBlockObject: + case CK_CopyAndAutoreleaseBlockObject: { // These casts only produce lvalues when we're binding a reference to a // temporary realized from a (converted) pure rvalue. Emit the expression // as a value, copy it into a temporary, and return an lvalue referring to Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Tue Feb 21 23:02:47 2012 @@ -614,6 +614,7 @@ case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: + case CK_CopyAndAutoreleaseBlockObject: llvm_unreachable("cast kind invalid for aggregate types"); } } Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Tue Feb 21 23:02:47 2012 @@ -413,6 +413,7 @@ case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: + case CK_CopyAndAutoreleaseBlockObject: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Tue Feb 21 23:02:47 2012 @@ -636,6 +636,7 @@ case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: + case CK_CopyAndAutoreleaseBlockObject: return 0; // These don't need to be handled here because Evaluate knows how to Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Feb 21 23:02:47 2012 @@ -1148,6 +1148,10 @@ case CK_ARCExtendBlockObject: return CGF.EmitARCExtendBlockObject(E); + case CK_CopyAndAutoreleaseBlockObject: + CGF.ErrorUnsupported(E, "copy/autorelease block object"); + return 0; + case CK_FloatingRealToComplex: case CK_FloatingComplexCast: case CK_IntegralRealToComplex: Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Feb 21 23:02:47 2012 @@ -3000,9 +3000,11 @@ Expr* SubExpr = cast(E)->getSubExpr(); QualType T = SubExpr->getType(); - if (SubExpr->getType()->isPointerType() || - SubExpr->getType()->isBlockPointerType() || - SubExpr->getType()->isObjCQualifiedIdType()) + if (cast(E)->getCastKind() == CK_CopyAndAutoreleaseBlockObject) + return 0; + else if (SubExpr->getType()->isPointerType() || + SubExpr->getType()->isBlockPointerType() || + SubExpr->getType()->isObjCQualifiedIdType()) return EvalAddr(SubExpr, refVars); else if (T->isArrayType()) return EvalVal(SubExpr, refVars); Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Feb 21 23:02:47 2012 @@ -8755,9 +8755,9 @@ /// \brief Mark the call operator of the given lambda closure type as "used". static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { CXXMethodDecl *CallOperator - = cast( - *Lambda->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + = cast( + *Lambda->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); CallOperator->setReferenced(); CallOperator->setUsed(); } @@ -8805,14 +8805,21 @@ SourceLocation CurrentLocation, CXXConversionDecl *Conv) { + CXXRecordDecl *Lambda = Conv->getParent(); + // Make sure that the lambda call operator is marked used. - markLambdaCallOperatorUsed(*this, Conv->getParent()); + CXXMethodDecl *CallOperator + = cast( + *Lambda->lookup( + Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + CallOperator->setReferenced(); + CallOperator->setUsed(); Conv->setUsed(); ImplicitlyDefinedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); - // Copy-initialize the lambda object as needed to capture + // Copy-initialize the lambda object as needed to capture it. Expr *This = ActOnCXXThis(CurrentLocation).take(); Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).take(); ExprResult Init = PerformCopyInitialization( @@ -8823,16 +8830,78 @@ if (!Init.isInvalid()) Init = ActOnFinishFullExpr(Init.take()); - if (!Init.isInvalid()) - Conv->setLambdaToBlockPointerCopyInit(Init.take()); - else { + if (Init.isInvalid()) { Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; } - // Introduce a bogus body, which IR generation will override anyway. - Conv->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(), + // Create the new block to be returned. + BlockDecl *Block = BlockDecl::Create(Context, Conv, Conv->getLocation()); + + // Set the type information. + Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo()); + Block->setIsVariadic(CallOperator->isVariadic()); + Block->setBlockMissingReturnType(false); + + // Add parameters. + SmallVector BlockParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + BlockParams.push_back(ParmVarDecl::Create(Context, Block, + From->getLocStart(), + From->getLocation(), + From->getIdentifier(), + From->getType(), + From->getTypeSourceInfo(), + From->getStorageClass(), + From->getStorageClassAsWritten(), + /*DefaultArg=*/0)); + } + Block->setParams(BlockParams); + + // Add capture. The capture is uses a fake (NULL) variable, since we don't + // actually want to have to name a capture variable. However, the + // initializer copy-initializes the lambda object. + BlockDecl::Capture Capture(/*Variable=*/0, /*ByRef=*/false, /*Nested=*/false, + /*Copy=*/Init.take()); + Block->setCaptures(Context, &Capture, &Capture + 1, + /*CapturesCXXThis=*/false); + + // Add a fake function body to the block. IR generation is responsible + // for filling in the actual body, which cannot be expressed as an AST. + Block->setBody(new (Context) CompoundStmt(Context, 0, 0, + Conv->getLocation(), + Conv->getLocation())); + + // Create the block literal expression. + Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType()); + ExprCleanupObjects.push_back(Block); + ExprNeedsCleanups = true; + + // If we're not under ARC, make sure we still get the _Block_copy/autorelease + // behavior. + if (!getLangOptions().ObjCAutoRefCount) + BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock->getType(), + CK_CopyAndAutoreleaseBlockObject, + BuildBlock, 0, VK_RValue); + + // Create the return statement that returns the block from the conversion + // function. + StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock); + if (Return.isInvalid()) { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; + } + + // Set the body of the conversion function. + Stmt *ReturnS = Return.take(); + Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1, + Conv->getLocation(), Conv->getLocation())); + // We're done; notify the mutation listener, if any. if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Conv); } Modified: cfe/trunk/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLambda.cpp (original) +++ cfe/trunk/lib/Sema/SemaLambda.cpp Tue Feb 21 23:02:47 2012 @@ -643,7 +643,7 @@ // non-explicit const conversion function to a block pointer having the // same parameter and return types as the closure type's function call // operator. - if (getLangOptions().Blocks) + if (getLangOptions().Blocks && getLangOptions().ObjC1) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Feb 21 23:02:47 2012 @@ -1213,8 +1213,6 @@ void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { VisitCXXMethodDecl(D); D->IsExplicitSpecified = Record[Idx++]; - if (D->isLambdaToBlockPointerConversion()) - D->setLambdaToBlockPointerCopyInit(Reader.ReadExpr(F)); } void ASTDeclReader::VisitImportDecl(ImportDecl *D) { Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Feb 21 23:02:47 2012 @@ -965,8 +965,6 @@ void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { VisitCXXMethodDecl(D); Record.push_back(D->IsExplicitSpecified); - if (D->isLambdaToBlockPointerConversion()) - Writer.AddStmt(D->getLambdaToBlockPointerCopyInit()); Code = serialization::DECL_CXX_CONVERSION; } Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=151131&r1=151130&r2=151131&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Tue Feb 21 23:02:47 2012 @@ -218,6 +218,7 @@ case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: // Fall-through. + case CK_CopyAndAutoreleaseBlockObject: // The analyser can ignore atomic casts for now, although some future // checkers may want to make certain that you're not modifying the same // value through atomic and nonatomic pointers. Removed: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp?rev=151130&view=auto ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp (removed) @@ -1,57 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -fblocks %s -verify - -void block_capture_errors() { - __block int var; // expected-note 2{{'var' declared here}} - (void)[var] { }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} - - (void)[=] { var = 17; }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} -} - -void conversion_to_block(int captured) { - int (^b1)(int) = [=](int x) { return x + captured; }; - - const auto lambda = [=](int x) { return x + captured; }; - int (^b2)(int) = lambda; -} - -template -class ConstCopyConstructorBoom { -public: - ConstCopyConstructorBoom(ConstCopyConstructorBoom&); - - ConstCopyConstructorBoom(const ConstCopyConstructorBoom&) { - T *ptr = 1; // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} - } - - void foo() const; -}; - -void conversion_to_block_init(ConstCopyConstructorBoom boom, - ConstCopyConstructorBoom boom2) { - const auto& lambda1([=] { boom.foo(); }); // okay - - const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}} - void (^block)(void) = lambda2; -} - - -void nesting() { - int array[7]; // expected-note 2{{'array' declared here}} - [=] () mutable { - [&] { - ^ { - int i = array[2]; - i += array[3]; - }(); - }(); - }(); - - [&] { - [=] () mutable { - ^ { - int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}} - i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}} - }(); - }(); - }(); -} Removed: cfe/trunk/test/PCH/cxx11-lambdas.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx11-lambdas.cpp?rev=151130&view=auto ============================================================================== --- cfe/trunk/test/PCH/cxx11-lambdas.cpp (original) +++ cfe/trunk/test/PCH/cxx11-lambdas.cpp (removed) @@ -1,48 +0,0 @@ -// RUN: %clang_cc1 -pedantic-errors -fblocks -std=c++11 -emit-pch %s -o %t-cxx11 -// RUN: %clang_cc1 -ast-print -pedantic-errors -fblocks -std=c++11 -include-pch %t-cxx11 %s | FileCheck -check-prefix=CHECK-PRINT %s - -#ifndef HEADER_INCLUDED - -#define HEADER_INCLUDED -template -T add_slowly(const T& x, const T &y) { - return [=, &y] { return x + y; }(); -}; - -inline int add_int_slowly_twice(int x, int y) { - int i = add_slowly(x, y); - auto lambda = [&](int z) { return x + z; }; - return i + lambda(y); -} - -inline int sum_array(int n) { - int array[5] = { 1, 2, 3, 4, 5}; - auto lambda = [=](int N) -> int { - int sum = 0; - for (unsigned I = 0; I < N; ++I) - sum += array[N]; - return sum; - }; - - return lambda(n); -} - -inline int to_block_pointer(int n) { - auto lambda = [=](int m) { return n + m; }; - int (^block)(int) = lambda; - return block(17); -} - -#else - -// CHECK-PRINT: T add_slowly -// CHECK-PRINT: return [=, &y] -template float add_slowly(const float&, const float&); - -int add(int x, int y) { - return add_int_slowly_twice(x, y) + sum_array(4) + to_block_pointer(5); -} - -// CHECK-PRINT: inline int add_int_slowly_twice -// CHECK-PRINT: lambda = [&] (int z) -#endif From mimomorin at gmail.com Tue Feb 21 21:22:00 2012 From: mimomorin at gmail.com (Michel Morin) Date: Wed, 22 Feb 2012 14:22:00 +0900 Subject: [cfe-commits] r151117 - in /cfe/trunk: include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/CXX/d In-Reply-To: References: Message-ID: Richard Smith wrote: > On Tue, Feb 21, 2012 at 8:38 PM, Michel Morin wrote: >> Is there any way to detect this C++11 decltype feature? >> `__has_feature(cxx_decltype)` does not work, >> since this macro also detects pre-N3276 decltype. >> (Boost.Config needs to detect N3276 decltype.) > > There's no __has_feature check for it, but it's pretty easy to detect with > SFINAE (check for SFINAE access control first if you want to use this > particular approach): Thanks, Richard! This works for compile-time detection, but Boost.Config needs preprocessing-time detection… Regards, Michel From zarzycki at apple.com Tue Feb 21 21:25:00 2012 From: zarzycki at apple.com (Dave Zarzycki) Date: Wed, 22 Feb 2012 05:25:00 -0000 Subject: [cfe-commits] [libcxxabi] r151132 - in /libcxxabi/trunk: lib/buildit src/cxa_exception.hpp Message-ID: <20120222052500.8ABD62A6C12F@llvm.org> Author: zarzycki Date: Tue Feb 21 23:25:00 2012 New Revision: 151132 URL: http://llvm.org/viewvc/llvm-project?rev=151132&view=rev Log: Pedantic fix: missing newline at EOF Modified: libcxxabi/trunk/lib/buildit libcxxabi/trunk/src/cxa_exception.hpp Modified: libcxxabi/trunk/lib/buildit URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/lib/buildit?rev=151132&r1=151131&r2=151132&view=diff ============================================================================== --- libcxxabi/trunk/lib/buildit (original) +++ libcxxabi/trunk/lib/buildit Tue Feb 21 23:25:00 2012 @@ -27,7 +27,7 @@ RC_ProjectSourceVersion=1 fi -EXTRA_FLAGS="-std=c++0x -stdlib=libc++ -fstrict-aliasing -Wstrict-aliasing=2" +EXTRA_FLAGS="-std=c++0x -stdlib=libc++ -fstrict-aliasing -Wstrict-aliasing=2 -Wnewline-eof" case $TRIPLE in *-apple-*) Modified: libcxxabi/trunk/src/cxa_exception.hpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception.hpp?rev=151132&r1=151131&r2=151132&view=diff ============================================================================== --- libcxxabi/trunk/src/cxa_exception.hpp (original) +++ libcxxabi/trunk/src/cxa_exception.hpp Tue Feb 21 23:25:00 2012 @@ -115,4 +115,4 @@ extern "C" void __cxa_free_dependent_exception (void * dependent_exception); #pragma GCC visibility pop -} \ No newline at end of file +} From eli.friedman at gmail.com Tue Feb 21 21:38:59 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 22 Feb 2012 05:38:59 -0000 Subject: [cfe-commits] r151133 - in /cfe/trunk: lib/CodeGen/CGExprAgg.cpp test/CodeGenObjC/arc.m Message-ID: <20120222053859.6E9FB2A6C12F@llvm.org> Author: efriedma Date: Tue Feb 21 23:38:59 2012 New Revision: 151133 URL: http://llvm.org/viewvc/llvm-project?rev=151133&view=rev Log: Make sure null initialization in arrays works correctly with ARC types. . Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp cfe/trunk/test/CodeGenObjC/arc.m Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=151133&r1=151132&r2=151133&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Tue Feb 21 23:38:59 2012 @@ -853,9 +853,14 @@ return; if (!CGF.hasAggregateLLVMType(type)) { - // For non-aggregates, we can store zero + // For non-aggregates, we can store zero. llvm::Value *null = llvm::Constant::getNullValue(CGF.ConvertType(type)); - CGF.EmitStoreThroughLValue(RValue::get(null), lv); + // Note that the following is not equivalent to + // EmitStoreThroughBitfieldLValue for ARC types. + if (lv.isBitField()) + CGF.EmitStoreThroughBitfieldLValue(RValue::get(null), lv); + assert(lv.isSimple()); + CGF.EmitStoreOfScalar(null, lv, /* isInitialization */ true); } else { // There's a potential optimization opportunity in combining // memsets; that would be easy for arrays, but relatively Modified: cfe/trunk/test/CodeGenObjC/arc.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=151133&r1=151132&r2=151133&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/arc.m (original) +++ cfe/trunk/test/CodeGenObjC/arc.m Tue Feb 21 23:38:59 2012 @@ -1533,3 +1533,15 @@ // CHECK: [[T0:%.*]] = load [[TEST69]]** [[SELF]], align 8 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST69]]* [[T0]] to i8* // CHECK-NEXT: ret i8* [[T1]] + +// rdar://problem/10907547 +void test70(id i) { + // CHECK: define void @test70 + // CHECK: store i8* null, i8** + // CHECK: store i8* null, i8** + // CHECK: [[ID:%.*]] = call i8* @objc_retain(i8* + // CHECK: store i8* [[ID]], i8** + id x[3] = { + [2] = i + }; +} From jfreeman at cse.tamu.edu Tue Feb 21 21:57:11 2012 From: jfreeman at cse.tamu.edu (John Freeman) Date: Tue, 21 Feb 2012 23:57:11 -0600 Subject: [cfe-commits] [Patch] Tests for C++11 lambda expressions In-Reply-To: References: <4F443257.5020306@cse.tamu.edu> Message-ID: <4F4483B7.6040309@cse.tamu.edu> On 2/21/2012 7:02 PM, Eli Friedman wrote: > Please try a newer clang; the conversion-to-function-pointer should be > working now. I wrote the test wrong. It didn't deduce the return type I expected. > It looks like we already have coverage for a lot of the features > you're trying to test... see test/CXX/expr/expr.prim/expr.prim.lambda/ > . My file search missed this. > I'm not entirely sure what you're trying to do with the test involving > noexcept... The FDIS appears to indicate noexcept takes any expression. I could be just be ignorant of the intention. - John From eli.friedman at gmail.com Tue Feb 21 22:21:54 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 21 Feb 2012 22:21:54 -0800 Subject: [cfe-commits] [Patch] Tests for C++11 lambda expressions In-Reply-To: <4F4483B7.6040309@cse.tamu.edu> References: <4F443257.5020306@cse.tamu.edu> <4F4483B7.6040309@cse.tamu.edu> Message-ID: On Tue, Feb 21, 2012 at 9:57 PM, John Freeman wrote: > On 2/21/2012 7:02 PM, Eli Friedman wrote: >> >> Please try a newer clang; the conversion-to-function-pointer should be >> working now. > > > I wrote the test wrong. It didn't deduce the return type I expected. > > >> It looks like we already have coverage for a lot of the features >> you're trying to test... see test/CXX/expr/expr.prim/expr.prim.lambda/ >> . > > > My file search missed this. > > >> I'm not entirely sure what you're trying to do with the test involving >> noexcept... > > > The FDIS appears to indicate noexcept takes any expression. I could be just > be ignorant of the intention. A noexcept expression does, yes, but you wrote it in namespace scope, so I wasn't sure whether you meant to use it as an expression or attach it to a declaration. -Eli From richard-llvm at metafoo.co.uk Tue Feb 21 22:49:10 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Wed, 22 Feb 2012 06:49:10 -0000 Subject: [cfe-commits] r151137 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Sema/DeclSpec.h lib/Parse/ParseExprCXX.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp test/Parser/cxx-condition.cpp test/Parser/cxx0x-condition.cpp test/SemaCXX/cxx0x-initializer-scalars.cpp Message-ID: <20120222064910.27F452A6C12F@llvm.org> Author: rsmith Date: Wed Feb 22 00:49:09 2012 New Revision: 151137 URL: http://llvm.org/viewvc/llvm-project?rev=151137&view=rev Log: Accept braced-init-lists in conditions, and, in passing, dramatically improve the diagnostic for using a parenthesized direct-initializer in a condition. Added: cfe/trunk/test/Parser/cxx0x-condition.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Sema/DeclSpec.h cfe/trunk/lib/Parse/ParseExprCXX.cpp cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp cfe/trunk/test/Parser/cxx-condition.cpp cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151137&r1=151136&r2=151137&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Feb 22 00:49:09 2012 @@ -381,8 +381,10 @@ "function definition does not declare parameters">; def err_expected_lparen_after_type : Error< "expected '(' for function-style cast or type construction">; -def err_expected_equal_after_declarator : Error< - "expected '=' after declarator">; +def err_expected_init_in_condition : Error< + "variable declaration in condition must have an initializer">; +def err_expected_init_in_condition_lparen : Error< + "variable declaration in condition cannot have a parenthesized initializer">; def warn_parens_disambiguated_as_function_decl : Warning< "parentheses were disambiguated as a function declarator">, InGroup; Modified: cfe/trunk/include/clang/Sema/DeclSpec.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=151137&r1=151136&r2=151137&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/DeclSpec.h (original) +++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Feb 22 00:49:09 2012 @@ -1645,9 +1645,14 @@ case ForContext: return true; + case ConditionContext: + // This may not be followed by a direct initializer, but it can't be a + // function declaration either, and we'd prefer to perform a tentative + // parse in order to produce the right diagnostic. + return true; + case KNRTypeListContext: case MemberContext: - case ConditionContext: case PrototypeContext: case ObjCParameterContext: case ObjCResultContext: Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=151137&r1=151136&r2=151137&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Feb 22 00:49:09 2012 @@ -1271,6 +1271,8 @@ /// condition: /// expression /// type-specifier-seq declarator '=' assignment-expression +/// [C++11] type-specifier-seq declarator '=' initializer-clause +/// [C++11] type-specifier-seq declarator braced-init-list /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] /// '=' assignment-expression /// @@ -1342,17 +1344,34 @@ // '=' assignment-expression // If a '==' or '+=' is found, suggest a fixit to '='. - if (isTokenEqualOrEqualTypo()) { + bool CopyInitialization = isTokenEqualOrEqualTypo(); + if (CopyInitialization) ConsumeToken(); - ExprResult AssignExpr(ParseAssignmentExpression()); - if (!AssignExpr.isInvalid()) - Actions.AddInitializerToDecl(DeclOut, AssignExpr.take(), false, - DS.getTypeSpecType() == DeclSpec::TST_auto); + + ExprResult InitExpr = ExprError(); + if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { + Diag(Tok.getLocation(), + diag::warn_cxx98_compat_generalized_initializer_lists); + InitExpr = ParseBraceInitializer(); + } else if (CopyInitialization) { + InitExpr = ParseAssignmentExpression(); + } else if (Tok.is(tok::l_paren)) { + // This was probably an attempt to initialize the variable. + SourceLocation LParen = ConsumeParen(), RParen = LParen; + if (SkipUntil(tok::r_paren, true, /*DontConsume=*/true)) + RParen = ConsumeParen(); + Diag(DeclOut ? DeclOut->getLocation() : LParen, + diag::err_expected_init_in_condition_lparen) + << SourceRange(LParen, RParen); } else { - // FIXME: C++0x allows a braced-init-list - Diag(Tok, diag::err_expected_equal_after_declarator); + Diag(DeclOut ? DeclOut->getLocation() : Tok.getLocation(), + diag::err_expected_init_in_condition); } - + + if (!InitExpr.isInvalid()) + Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization, + DS.getTypeSpecType() == DeclSpec::TST_auto); + // FIXME: Build a reference to this declaration? Convert it to bool? // (This is currently handled by Sema). Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp?rev=151137&r1=151136&r2=151137&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp Wed Feb 22 00:49:09 2012 @@ -13,9 +13,9 @@ auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}} - if (auto b) {} // expected-error {{expected '='}} - for (;auto b;) {} // expected-error {{expected '='}} - while (auto b) {} // expected-error {{expected '='}} + if (auto b) {} // expected-error {{must have an initializer}} + for (;auto b;) {} // expected-error {{must have an initializer}} + while (auto b) {} // expected-error {{must have an initializer}} if (auto b = true) { (void)b; } } Modified: cfe/trunk/test/Parser/cxx-condition.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-condition.cpp?rev=151137&r1=151136&r2=151137&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx-condition.cpp (original) +++ cfe/trunk/test/Parser/cxx-condition.cpp Wed Feb 22 00:49:09 2012 @@ -1,11 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +struct S { S(int); operator bool(); }; + void f() { int a; while (a) ; - while (int x) ; // expected-error {{expected '=' after declarator}} + while (int x) ; // expected-error {{variable declaration in condition must have an initializer}} while (float x = 0) ; if (const int x = a) ; // expected-warning{{empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} switch (int x = a+10) {} for (; int x = ++a; ) ; + + if (S a(42)) {} // expected-error {{variable declaration in condition cannot have a parenthesized initializer}} } Added: cfe/trunk/test/Parser/cxx0x-condition.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-condition.cpp?rev=151137&view=auto ============================================================================== --- cfe/trunk/test/Parser/cxx0x-condition.cpp (added) +++ cfe/trunk/test/Parser/cxx0x-condition.cpp Wed Feb 22 00:49:09 2012 @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { S(int); operator bool(); }; + +void f() { + int a; + typedef int n; + + while (a) ; + while (int x) ; // expected-error {{variable declaration in condition must have an initializer}} + while (float x = 0) ; + if (const int x = a) ; // expected-warning{{empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + switch (int x = a+10) {} + for (; int x = ++a; ) ; + + if (S(a)) {} // ok + if (S(a) = 0) {} // ok + if (S(a) == 0) {} // ok + + if (S(n)) {} // expected-error {{unexpected type name 'n': expected expression}} + if (S(n) = 0) {} // ok + if (S(n) == 0) {} // expected-error {{unexpected type name 'n': expected expression}} + + if (S b(a)) {} // expected-error {{variable declaration in condition cannot have a parenthesized initializer}} + + if (S b(n)) {} // expected-error {{a function type is not allowed here}} expected-error {{must have an initializer}} + if (S b(n) = 0) {} // expected-error {{a function type is not allowed here}} + if (S b(n) == 0) {} // expected-error {{a function type is not allowed here}} expected-error {{did you mean '='?}} + + // FIXME: this is legal, and incorrectly rejected, because tentative parsing + // does not yet know about braced function-style casts. + if (S{a}) {} // unexpected-error{{unqualified-id}} + + if (S a{a}) {} // ok + if (S a = {a}) {} // ok + if (S a == {a}) {} // expected-error {{did you mean '='?}} +} Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp?rev=151137&r1=151136&r2=151137&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Wed Feb 22 00:49:09 2012 @@ -15,6 +15,8 @@ // FIXME: Redundant warnings. { const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} { const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} + { if (const int a{1}) static_assert(a == 1, ""); } + { if (const int a = {1}) static_assert(a == 1, ""); } } int direct_usage() { From rjmccall at apple.com Tue Feb 21 22:52:23 2012 From: rjmccall at apple.com (John McCall) Date: Tue, 21 Feb 2012 22:52:23 -0800 Subject: [cfe-commits] r151122 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/thiscall-struct-return.cpp In-Reply-To: References: <20120222030413.B97902A6C12F@llvm.org> Message-ID: <4F68169D-6D7F-4473-B70C-26A2C0D083B3@apple.com> On Feb 21, 2012, at 7:37 PM, Aaron Ballman wrote: > Hmm, I may have heard wrong then. If that's the case, I'll take care > of it. Confirmation? If it's not already set on all the source files in the project, you can assume you shouldn't set it somewhere new. John. From rjmccall at apple.com Tue Feb 21 22:54:17 2012 From: rjmccall at apple.com (John McCall) Date: Tue, 21 Feb 2012 22:54:17 -0800 Subject: [cfe-commits] r151131 - in /cfe/trunk: include/clang/AST/ lib/AST/ lib/CodeGen/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/CXX/expr/expr.prim/expr.prim.lambda/ test/PCH/ In-Reply-To: <20120222050249.3AC012A6C12F@llvm.org> References: <20120222050249.3AC012A6C12F@llvm.org> Message-ID: On Feb 21, 2012, at 9:02 PM, Douglas Gregor wrote: > Author: dgregor > Date: Tue Feb 21 23:02:47 2012 > New Revision: 151131 > > URL: http://llvm.org/viewvc/llvm-project?rev=151131&view=rev > Log: > Generate an AST for the conversion from a lambda closure type to a > block pointer that returns a block literal which captures (by copy) > the lambda closure itself. Some aspects of the block literal are left > unspecified, namely the capture variable (which doesn't actually > exist) and the body (which will be filled in by IRgen because it can't > be written as an AST). > > Because we're switching to this model, this patch also eliminates > tracking the copy-initialization expression for the block capture of > the conversion function, since that information is now embedded in the > synthesized block literal. -1 side tables FTW. This definitely seems like the better model. John. From chandlerc at google.com Tue Feb 21 23:14:01 2012 From: chandlerc at google.com (Chandler Carruth) Date: Tue, 21 Feb 2012 23:14:01 -0800 Subject: [cfe-commits] r151122 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/thiscall-struct-return.cpp In-Reply-To: <4F68169D-6D7F-4473-B70C-26A2C0D083B3@apple.com> References: <20120222030413.B97902A6C12F@llvm.org> <4F68169D-6D7F-4473-B70C-26A2C0D083B3@apple.com> Message-ID: On Tue, Feb 21, 2012 at 10:52 PM, John McCall wrote: > On Feb 21, 2012, at 7:37 PM, Aaron Ballman wrote: > > Hmm, I may have heard wrong then. If that's the case, I'll take care > > of it. Confirmation? > > If it's not already set on all the source files in the project, you can > assume > you shouldn't set it somewhere new. The desired state is to configure the SVN client to default to 'native' eol handling. Not all do this correctly, and so some have set it manually on a few files they were modifying. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pichet2000 at gmail.com Wed Feb 22 00:25:53 2012 From: pichet2000 at gmail.com (Francois Pichet) Date: Wed, 22 Feb 2012 08:25:53 -0000 Subject: [cfe-commits] r151140 - in /cfe/trunk: lib/Parse/ParseTemplate.cpp test/Parser/DelayedTemplateParsing.cpp Message-ID: <20120222082554.0191A2A6C12F@llvm.org> Author: fpichet Date: Wed Feb 22 02:25:53 2012 New Revision: 151140 URL: http://llvm.org/viewvc/llvm-project?rev=151140&view=rev Log: In -fdelayed-template-parsing mode, reenter every scope when late parsing a templated function; (Not just the template parameter scope as previously). Also enter the scope stack in the correct order. Otherwise this breaks some invariant during name lookup especially when dealing with shadowed declaration Fix PR11931. Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp cfe/trunk/test/Parser/DelayedTemplateParsing.cpp Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=151140&r1=151139&r2=151140&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original) +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Feb 22 02:25:53 2012 @@ -1157,109 +1157,113 @@ llvm_unreachable("Late templated function without associated lexed tokens"); } - -/// \brief Late parse a C++ function template in Microsoft mode. -void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { - if(!LMT.D) - return; - - // If this is a member template, introduce the template parameter scope. - ParseScope TemplateScope(this, Scope::TemplateParamScope); - - // Get the FunctionDecl. - FunctionDecl *FD = 0; - if (FunctionTemplateDecl *FunTmpl = dyn_cast(LMT.D)) - FD = FunTmpl->getTemplatedDecl(); - else - FD = cast(LMT.D); - - // Reinject the template parameters. - SmallVector TemplateParamScopeStack; - DeclaratorDecl* Declarator = dyn_cast(FD); - if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { - Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); - Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); - } else { - Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); - - // Get the list of DeclContext to reenter. - SmallVector DeclContextToReenter; - DeclContext *DD = FD->getLexicalParent(); - while (DD && DD->isRecord()) { - DeclContextToReenter.push_back(DD); - DD = DD->getLexicalParent(); - } - - // Reenter template scopes from outmost to innermost. - SmallVector::reverse_iterator II = - DeclContextToReenter.rbegin(); - for (; II != DeclContextToReenter.rend(); ++II) { - if (ClassTemplatePartialSpecializationDecl* MD = - dyn_cast_or_null(*II)) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope)); - Actions.ActOnReenterTemplateScope(getCurScope(), MD); - } else if (CXXRecordDecl* MD = dyn_cast_or_null(*II)) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope, - MD->getDescribedClassTemplate() != 0 )); - Actions.ActOnReenterTemplateScope(getCurScope(), - MD->getDescribedClassTemplate()); - } - } - } - assert(!LMT.Toks.empty() && "Empty body!"); - - // Append the current token at the end of the new token stream so that it - // doesn't get lost. - LMT.Toks.push_back(Tok); - PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false); - - // Consume the previously pushed token. - ConsumeAnyToken(); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) - && "Inline method not starting with '{', ':' or 'try'"); - - // Parse the method body. Function body parsing code is similar enough - // to be re-used for method bodies as well. - ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); - - // Recreate the DeclContext. - Sema::ContextRAII SavedContext(Actions, Actions.getContainingDC(FD)); - - if (FunctionTemplateDecl *FunctionTemplate - = dyn_cast_or_null(LMT.D)) - Actions.ActOnStartOfFunctionDef(getCurScope(), - FunctionTemplate->getTemplatedDecl()); - if (FunctionDecl *Function = dyn_cast_or_null(LMT.D)) - Actions.ActOnStartOfFunctionDef(getCurScope(), Function); - - - if (Tok.is(tok::kw_try)) { - ParseFunctionTryBlock(LMT.D, FnScope); - } else { - if (Tok.is(tok::colon)) - ParseConstructorInitializer(LMT.D); - else - Actions.ActOnDefaultCtorInitializers(LMT.D); - - if (Tok.is(tok::l_brace)) { - ParseFunctionStatementBody(LMT.D, FnScope); - Actions.MarkAsLateParsedTemplate(FD, false); - } else - Actions.ActOnFinishFunctionBody(LMT.D, 0); - } - - // Exit scopes. + +/// \brief Late parse a C++ function template in Microsoft mode. +void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { + if(!LMT.D) + return; + + // Get the FunctionDecl. + FunctionDecl *FD = 0; + if (FunctionTemplateDecl *FunTmpl = dyn_cast(LMT.D)) + FD = FunTmpl->getTemplatedDecl(); + else + FD = cast(LMT.D); + + // To restore the context after late parsing. + Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext); + + SmallVector TemplateParamScopeStack; + DeclaratorDecl* Declarator = dyn_cast(FD); + if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { + TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope)); + Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); + Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); + } else { + // Get the list of DeclContext to reenter. + SmallVector DeclContextToReenter; + DeclContext *DD = FD->getLexicalParent(); + while (DD && !DD->isTranslationUnit()) { + DeclContextToReenter.push_back(DD); + DD = DD->getLexicalParent(); + } + + // Reenter template scopes from outmost to innermost. + SmallVector::reverse_iterator II = + DeclContextToReenter.rbegin(); + for (; II != DeclContextToReenter.rend(); ++II) { + if (ClassTemplatePartialSpecializationDecl* MD = + dyn_cast_or_null(*II)) { + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope)); + Actions.ActOnReenterTemplateScope(getCurScope(), MD); + } else if (CXXRecordDecl* MD = dyn_cast_or_null(*II)) { + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope, + MD->getDescribedClassTemplate() != 0 )); + Actions.ActOnReenterTemplateScope(getCurScope(), + MD->getDescribedClassTemplate()); + } + TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); + Actions.PushDeclContext(Actions.getCurScope(), *II); + } + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope)); + Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); + } + + assert(!LMT.Toks.empty() && "Empty body!"); + + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + LMT.Toks.push_back(Tok); + PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false); + + // Consume the previously pushed token. + ConsumeAnyToken(); + assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) + && "Inline method not starting with '{', ':' or 'try'"); + + // Parse the method body. Function body parsing code is similar enough + // to be re-used for method bodies as well. + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); + + // Recreate the containing function DeclContext. + Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD)); + + if (FunctionTemplateDecl *FunctionTemplate + = dyn_cast_or_null(LMT.D)) + Actions.ActOnStartOfFunctionDef(getCurScope(), + FunctionTemplate->getTemplatedDecl()); + if (FunctionDecl *Function = dyn_cast_or_null(LMT.D)) + Actions.ActOnStartOfFunctionDef(getCurScope(), Function); + + + if (Tok.is(tok::kw_try)) { + ParseFunctionTryBlock(LMT.D, FnScope); + } else { + if (Tok.is(tok::colon)) + ParseConstructorInitializer(LMT.D); + else + Actions.ActOnDefaultCtorInitializers(LMT.D); + + if (Tok.is(tok::l_brace)) { + ParseFunctionStatementBody(LMT.D, FnScope); + Actions.MarkAsLateParsedTemplate(FD, false); + } else + Actions.ActOnFinishFunctionBody(LMT.D, 0); + } + + // Exit scopes. FnScope.Exit(); - SmallVector::reverse_iterator I = - TemplateParamScopeStack.rbegin(); - for (; I != TemplateParamScopeStack.rend(); ++I) - delete *I; - - DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D); - if (grp) - Actions.getASTConsumer().HandleTopLevelDecl(grp.get()); + SmallVector::reverse_iterator I = + TemplateParamScopeStack.rbegin(); + for (; I != TemplateParamScopeStack.rend(); ++I) + delete *I; + + DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D); + if (grp) + Actions.getASTConsumer().HandleTopLevelDecl(grp.get()); } /// \brief Lex a delayed template function for late parsing. Modified: cfe/trunk/test/Parser/DelayedTemplateParsing.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/DelayedTemplateParsing.cpp?rev=151140&r1=151139&r2=151140&view=diff ============================================================================== --- cfe/trunk/test/Parser/DelayedTemplateParsing.cpp (original) +++ cfe/trunk/test/Parser/DelayedTemplateParsing.cpp Wed Feb 22 02:25:53 2012 @@ -63,3 +63,30 @@ } + +namespace PR11931 { + +template +struct BindState; + + template<> +struct BindState { + static void Run() { } +}; + +class Callback { +public: + typedef void RunType(); + + template + Callback(BindState bind_state) { + BindState::Run(); + } +}; + + +Callback Bind() { + return Callback(BindState()); +} + +} From sebastian.redl at getdesigned.at Wed Feb 22 01:07:22 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Wed, 22 Feb 2012 09:07:22 -0000 Subject: [cfe-commits] r151146 - in /cfe/trunk: lib/Sema/SemaExprCXX.cpp test/SemaCXX/new-delete.cpp Message-ID: <20120222090722.1B0682A6C12F@llvm.org> Author: cornedbee Date: Wed Feb 22 03:07:21 2012 New Revision: 151146 URL: http://llvm.org/viewvc/llvm-project?rev=151146&view=rev Log: Throw away stray CXXDefaultArgExprs. Fixes PR12061. I think there's a deeper problem here in the way TransformCXXConstructExpr works, but I won't tackle it now. Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/SemaCXX/new-delete.cpp Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=151146&r1=151145&r2=151146&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 22 03:07:21 2012 @@ -1018,6 +1018,13 @@ } else if (Initializer && isa(Initializer)) initStyle = CXXNewExpr::ListInit; else { + // In template instantiation, the initializer could be a CXXDefaultArgExpr + // unwrapped from a CXXConstructExpr that was implicitly built. There is no + // particularly sane way we can handle this (especially since it can even + // occur for array new), so we throw the initializer away and have it be + // rebuilt. + if (Initializer && isa(Initializer)) + Initializer = 0; assert((!Initializer || isa(Initializer) || isa(Initializer)) && "Initializer expression that cannot have been implicitly created."); Modified: cfe/trunk/test/SemaCXX/new-delete.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=151146&r1=151145&r2=151146&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/new-delete.cpp (original) +++ cfe/trunk/test/SemaCXX/new-delete.cpp Wed Feb 22 03:07:21 2012 @@ -460,3 +460,43 @@ return 0; } } + +namespace PR12061 { + template struct scoped_array { + scoped_array(C* p = __null); + }; + template struct Foo { + Foo() : a_(new scoped_array[5]) { } + scoped_array< scoped_array > a_; + }; + class Bar {}; + Foo x; + + template struct scoped_array2 { + scoped_array2(C* p = __null, C* q = __null); + }; + template struct Foo2 { + Foo2() : a_(new scoped_array2[5]) { } + scoped_array2< scoped_array2 > a_; + }; + class Bar2 {}; + Foo2 x2; + + class MessageLoop { + public: + explicit MessageLoop(int type = 0); + }; + template + class CookieStoreTest { + protected: + CookieStoreTest() { + new MessageLoop; + } + }; + struct CookieMonsterTestTraits { + }; + class DeferredCookieTaskTest : public CookieStoreTest + { + DeferredCookieTaskTest() {} + }; +} From isanbard at gmail.com Wed Feb 22 01:30:12 2012 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 22 Feb 2012 09:30:12 -0000 Subject: [cfe-commits] r151150 - in /cfe/trunk/lib/CodeGen: CGBuiltin.cpp CGObjCGNU.cpp CGObjCMac.cpp CodeGenFunction.h Message-ID: <20120222093012.33C112A6C12F@llvm.org> Author: void Date: Wed Feb 22 03:30:11 2012 New Revision: 151150 URL: http://llvm.org/viewvc/llvm-project?rev=151150&view=rev Log: Use an ArrayRef when we can instead of passing in a SmallVectorImpl reference. Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp cfe/trunk/lib/CodeGen/CGObjCGNU.cpp cfe/trunk/lib/CodeGen/CGObjCMac.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.h Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=151150&r1=151149&r2=151150&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Wed Feb 22 03:30:11 2012 @@ -2019,7 +2019,7 @@ } llvm::Value *CodeGenFunction:: -BuildVector(const SmallVectorImpl &Ops) { +BuildVector(ArrayRef Ops) { assert((Ops.size() & (Ops.size() - 1)) == 0 && "Not a power-of-two sized vector!"); bool AllConstants = true; Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=151150&r1=151149&r2=151150&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Wed Feb 22 03:30:11 2012 @@ -337,10 +337,9 @@ /// containing a size and an array of structures containing instance variable /// metadata. This is used purely for introspection in the fragile ABI. In /// the non-fragile ABI, it's used for instance variable fixup. - llvm::Constant *GenerateIvarList( - const SmallVectorImpl &IvarNames, - const SmallVectorImpl &IvarTypes, - const SmallVectorImpl &IvarOffsets); + llvm::Constant *GenerateIvarList(ArrayRef IvarNames, + ArrayRef IvarTypes, + ArrayRef IvarOffsets); /// Generates a method list structure. This is a structure containing a size /// and an array of structures containing method metadata. /// @@ -348,8 +347,8 @@ /// pointer allowing them to be chained together in a linked list. llvm::Constant *GenerateMethodList(const StringRef &ClassName, const StringRef &CategoryName, - const SmallVectorImpl &MethodSels, - const SmallVectorImpl &MethodTypes, + ArrayRef MethodSels, + ArrayRef MethodTypes, bool isClassMethodList); /// Emits an empty protocol. This is used for @protocol() where no protocol /// is found. The runtime will (hopefully) fix up the pointer to refer to the @@ -362,8 +361,7 @@ SmallVectorImpl &InstanceMethodTypes); /// Generates a list of referenced protocols. Classes, categories, and /// protocols all use this structure. - llvm::Constant *GenerateProtocolList( - const SmallVectorImpl &Protocols); + llvm::Constant *GenerateProtocolList(ArrayRef Protocols); /// To ensure that all protocols are seen by the runtime, we add a category on /// a class defined in the runtime, declaring no methods, but adopting the /// protocols. This is a horribly ugly hack, but it allows us to collect all @@ -388,8 +386,8 @@ /// Generates a method list. This is used by protocols to define the required /// and optional methods. llvm::Constant *GenerateProtocolMethodList( - const SmallVectorImpl &MethodNames, - const SmallVectorImpl &MethodTypes); + ArrayRef MethodNames, + ArrayRef MethodTypes); /// Returns a selector with the specified type encoding. An empty string is /// used to return an untyped selector (with the types field set to NULL). llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, @@ -428,7 +426,7 @@ /// significant bit being assumed to come first in the bitfield. Therefore, /// a bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, /// while a bitfield / with the 63rd bit set will be 1<<64. - llvm::Constant *MakeBitField(llvm::SmallVectorImpl &bits); + llvm::Constant *MakeBitField(ArrayRef bits); public: CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, unsigned protocolClassVersion); @@ -1257,11 +1255,12 @@ /// Generates a MethodList. Used in construction of a objc_class and /// objc_category structures. -llvm::Constant *CGObjCGNU::GenerateMethodList(const StringRef &ClassName, - const StringRef &CategoryName, - const SmallVectorImpl &MethodSels, - const SmallVectorImpl &MethodTypes, - bool isClassMethodList) { +llvm::Constant *CGObjCGNU:: +GenerateMethodList(const StringRef &ClassName, + const StringRef &CategoryName, + ArrayRef MethodSels, + ArrayRef MethodTypes, + bool isClassMethodList) { if (MethodSels.empty()) return NULLPtr; // Get the method structure type. @@ -1314,10 +1313,10 @@ } /// Generates an IvarList. Used in construction of a objc_class. -llvm::Constant *CGObjCGNU::GenerateIvarList( - const SmallVectorImpl &IvarNames, - const SmallVectorImpl &IvarTypes, - const SmallVectorImpl &IvarOffsets) { +llvm::Constant *CGObjCGNU:: +GenerateIvarList(ArrayRef IvarNames, + ArrayRef IvarTypes, + ArrayRef IvarOffsets) { if (IvarNames.size() == 0) return NULLPtr; // Get the method structure type. @@ -1444,9 +1443,9 @@ return Class; } -llvm::Constant *CGObjCGNU::GenerateProtocolMethodList( - const SmallVectorImpl &MethodNames, - const SmallVectorImpl &MethodTypes) { +llvm::Constant *CGObjCGNU:: +GenerateProtocolMethodList(ArrayRef MethodNames, + ArrayRef MethodTypes) { // Get the method structure type. llvm::StructType *ObjCMethodDescTy = llvm::StructType::get( PtrToInt8Ty, // Really a selector, but the runtime does the casting for us. @@ -1473,8 +1472,7 @@ } // Create the protocol list structure used in classes, categories and so on -llvm::Constant *CGObjCGNU::GenerateProtocolList( - const SmallVectorImpl &Protocols) { +llvm::Constant *CGObjCGNU::GenerateProtocolList(ArrayRefProtocols){ llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty, Protocols.size()); llvm::StructType *ProtocolListTy = llvm::StructType::get( @@ -1771,7 +1769,7 @@ /// significant bit being assumed to come first in the bitfield. Therefore, a /// bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, while a /// bitfield / with the 63rd bit set will be 1<<64. -llvm::Constant *CGObjCGNU::MakeBitField(llvm::SmallVectorImpl &bits) { +llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef bits) { int bitCount = bits.size(); int ptrBits = (TheModule.getPointerSize() == llvm::Module::Pointer32) ? 32 : 64; Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=151150&r1=151149&r2=151150&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Wed Feb 22 03:30:11 2012 @@ -831,7 +831,7 @@ void BuildAggrIvarLayout(const ObjCImplementationDecl *OI, const llvm::StructLayout *Layout, const RecordDecl *RD, - const SmallVectorImpl &RecFields, + ArrayRef RecFields, unsigned int BytePos, bool ForStrongLayout, bool &HasUnion); @@ -2561,14 +2561,14 @@ /* struct objc_ivar { - char *ivar_name; - char *ivar_type; - int ivar_offset; + char *ivar_name; + char *ivar_type; + int ivar_offset; }; struct objc_ivar_list { - int ivar_count; - struct objc_ivar list[count]; + int ivar_count; + struct objc_ivar list[count]; }; */ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, @@ -3768,7 +3768,7 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, const llvm::StructLayout *Layout, const RecordDecl *RD, - const SmallVectorImpl &RecFields, + ArrayRef RecFields, unsigned int BytePos, bool ForStrongLayout, bool &HasUnion) { bool IsUnion = (RD && RD->isUnion()); Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=151150&r1=151149&r2=151150&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Feb 22 03:30:11 2012 @@ -2226,7 +2226,7 @@ llvm::Value *EmitNeonShiftVector(llvm::Value *V, llvm::Type *Ty, bool negateForRightShift); - llvm::Value *BuildVector(const SmallVectorImpl &Ops); + llvm::Value *BuildVector(ArrayRef Ops); llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); From sebastian.redl at getdesigned.at Wed Feb 22 00:18:44 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Wed, 22 Feb 2012 09:18:44 +0100 Subject: [cfe-commits] r151137 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Sema/DeclSpec.h lib/Parse/ParseExprCXX.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp test/Parser/cxx-condition.cpp test/Parser/cxx0x-condition.cpp test/SemaCXX/cxx0x-initializer-scalars.cpp In-Reply-To: <20120222064910.27F452A6C12F@llvm.org> References: <20120222064910.27F452A6C12F@llvm.org> Message-ID: On 22.02.2012, at 07:49, Richard Smith wrote: > Author: rsmith > Date: Wed Feb 22 00:49:09 2012 > New Revision: 151137 > > URL: http://llvm.org/viewvc/llvm-project?rev=151137&view=rev > Log: > Accept braced-init-lists in conditions, and, in passing, dramatically improve > the diagnostic for using a parenthesized direct-initializer in a condition. Thank you. It's amazing (and worrying) how many places in the parser need to be changed for this. Sebastian From isanbard at gmail.com Wed Feb 22 01:38:11 2012 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 22 Feb 2012 09:38:11 -0000 Subject: [cfe-commits] r151151 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/JumpDiagnostics.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateVariadic.cpp Message-ID: <20120222093811.A28F32A6C12F@llvm.org> Author: void Date: Wed Feb 22 03:38:11 2012 New Revision: 151151 URL: http://llvm.org/viewvc/llvm-project?rev=151151&view=rev Log: ArrayRef-icize the function arguments. Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/JumpDiagnostics.cpp cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151151&r1=151150&r2=151151&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 22 03:38:11 2012 @@ -4496,7 +4496,7 @@ /// \param Unexpanded the set of unexpanded parameter packs. void DiagnoseUnexpandedParameterPacks(SourceLocation Loc, UnexpandedParameterPackContext UPPC, - const SmallVectorImpl &Unexpanded); + ArrayRef Unexpanded); /// \brief If the given type contains an unexpanded parameter pack, /// diagnose the error. Modified: cfe/trunk/lib/Sema/JumpDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/JumpDiagnostics.cpp?rev=151151&r1=151150&r2=151151&view=diff ============================================================================== --- cfe/trunk/lib/Sema/JumpDiagnostics.cpp (original) +++ cfe/trunk/lib/Sema/JumpDiagnostics.cpp Wed Feb 22 03:38:11 2012 @@ -74,7 +74,7 @@ void VerifyJumps(); void VerifyIndirectJumps(); - void NoteJumpIntoScopes(const SmallVectorImpl &ToScopes); + void NoteJumpIntoScopes(ArrayRef ToScopes); void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope, LabelDecl *Target, unsigned TargetScope); void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, @@ -669,8 +669,7 @@ } /// Produce note diagnostics for a jump into a protected scope. -void JumpScopeChecker::NoteJumpIntoScopes( - const SmallVectorImpl &ToScopes) { +void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef ToScopes) { assert(!ToScopes.empty()); for (unsigned I = 0, E = ToScopes.size(); I != E; ++I) if (Scopes[ToScopes[I]].InDiag) Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=151151&r1=151150&r2=151151&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Feb 22 03:38:11 2012 @@ -548,7 +548,7 @@ /// arguments in a set of argument packs. static void PrepareArgumentPackDeduction(Sema &S, SmallVectorImpl &Deduced, - const SmallVectorImpl &PackIndices, + ArrayRef PackIndices, SmallVectorImpl &SavedPacks, SmallVectorImpl< SmallVector > &NewlyDeducedPacks) { Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=151151&r1=151150&r2=151151&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Wed Feb 22 03:38:11 2012 @@ -158,7 +158,7 @@ void Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, UnexpandedParameterPackContext UPPC, - const SmallVectorImpl &Unexpanded) { + ArrayRef Unexpanded) { if (Unexpanded.empty()) return; From isanbard at gmail.com Wed Feb 22 01:51:33 2012 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 22 Feb 2012 09:51:33 -0000 Subject: [cfe-commits] r151152 - in /cfe/trunk: include/clang/AST/ASTDiagnostic.h include/clang/AST/DeclBase.h include/clang/Basic/Diagnostic.h lib/AST/ASTDiagnostic.cpp lib/AST/DeclBase.cpp lib/Basic/Diagnostic.cpp lib/Sema/SemaTemplateDeduction.cpp Message-ID: <20120222095133.DBA762A6C12F@llvm.org> Author: void Date: Wed Feb 22 03:51:33 2012 New Revision: 151152 URL: http://llvm.org/viewvc/llvm-project?rev=151152&view=rev Log: More ArrayRef-ification of methods. Modified: cfe/trunk/include/clang/AST/ASTDiagnostic.h cfe/trunk/include/clang/AST/DeclBase.h cfe/trunk/include/clang/Basic/Diagnostic.h cfe/trunk/lib/AST/ASTDiagnostic.cpp cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/lib/Basic/Diagnostic.cpp cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Modified: cfe/trunk/include/clang/AST/ASTDiagnostic.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTDiagnostic.h?rev=151152&r1=151151&r2=151152&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTDiagnostic.h (original) +++ cfe/trunk/include/clang/AST/ASTDiagnostic.h Wed Feb 22 03:51:33 2012 @@ -44,7 +44,7 @@ unsigned NumPrevArgs, SmallVectorImpl &Output, void *Cookie, - SmallVectorImpl &QualTypeVals); + ArrayRef QualTypeVals); } // end namespace clang #endif Modified: cfe/trunk/include/clang/AST/DeclBase.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=151152&r1=151151&r2=151152&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclBase.h (original) +++ cfe/trunk/include/clang/AST/DeclBase.h Wed Feb 22 03:51:33 2012 @@ -961,7 +961,7 @@ /// /// \returns the first/last pair of declarations. static std::pair - BuildDeclChain(const SmallVectorImpl &Decls, bool FieldsAlreadyLoaded); + BuildDeclChain(ArrayRef Decls, bool FieldsAlreadyLoaded); DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), Modified: cfe/trunk/include/clang/Basic/Diagnostic.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=151152&r1=151151&r2=151152&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Diagnostic.h (original) +++ cfe/trunk/include/clang/Basic/Diagnostic.h Wed Feb 22 03:51:33 2012 @@ -289,7 +289,7 @@ unsigned NumPrevArgs, SmallVectorImpl &Output, void *Cookie, - SmallVectorImpl &QualTypeVals); + ArrayRef QualTypeVals); void *ArgToStringCookie; ArgToStringFnTy ArgToStringFn; Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=151152&r1=151151&r2=151152&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original) +++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Wed Feb 22 03:51:33 2012 @@ -154,17 +154,16 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, - SmallVectorImpl &QualTypeVals) { + ArrayRef QualTypeVals) { // FIXME: Playing with std::string is really slow. bool ForceAKA = false; QualType CanTy = Ty.getCanonicalType(); std::string S = Ty.getAsString(Context.getPrintingPolicy()); std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); - for (SmallVectorImpl::iterator I = QualTypeVals.begin(), - E = QualTypeVals.end(); I != E; ++I) { + for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { QualType CompareTy = - QualType::getFromOpaquePtr(reinterpret_cast(*I)); + QualType::getFromOpaquePtr(reinterpret_cast(QualTypeVals[I])); if (CompareTy == Ty) continue; // Same types QualType CompareCanTy = CompareTy.getCanonicalType(); @@ -235,7 +234,7 @@ unsigned NumPrevArgs, SmallVectorImpl &Output, void *Cookie, - SmallVectorImpl &QualTypeVals) { + ArrayRef QualTypeVals) { ASTContext &Context = *static_cast(Cookie); std::string S; Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=151152&r1=151151&r2=151152&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Wed Feb 22 03:51:33 2012 @@ -872,7 +872,7 @@ } std::pair -DeclContext::BuildDeclChain(const SmallVectorImpl &Decls, +DeclContext::BuildDeclChain(ArrayRef Decls, bool FieldsAlreadyLoaded) { // Build up a chain of declarations via the Decl::NextInContextAndBits field. Decl *FirstNewDecl = 0; Modified: cfe/trunk/lib/Basic/Diagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=151152&r1=151151&r2=151152&view=diff ============================================================================== --- cfe/trunk/lib/Basic/Diagnostic.cpp (original) +++ cfe/trunk/lib/Basic/Diagnostic.cpp Wed Feb 22 03:51:33 2012 @@ -27,7 +27,7 @@ unsigned NumPrevArgs, SmallVectorImpl &Output, void *Cookie, - SmallVectorImpl &QualTypeVals) { + ArrayRef QualTypeVals) { const char *Str = ""; Output.append(Str, Str+strlen(Str)); } Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=151152&r1=151151&r2=151152&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Feb 22 03:51:33 2012 @@ -583,7 +583,7 @@ TemplateParameterList *TemplateParams, bool HasAnyArguments, SmallVectorImpl &Deduced, - const SmallVectorImpl &PackIndices, + ArrayRef PackIndices, SmallVectorImpl &SavedPacks, SmallVectorImpl< SmallVector > &NewlyDeducedPacks, From hans at hanshq.net Wed Feb 22 02:17:02 2012 From: hans at hanshq.net (Hans Wennborg) Date: Wed, 22 Feb 2012 10:17:02 -0000 Subject: [cfe-commits] r151154 - in /cfe/trunk: include/clang/Analysis/Analyses/FormatString.h include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/Analysis/FormatString.cpp lib/Sema/SemaChecking.cpp test/Sema/format-strings-c90.c test/Sema/format-strings-non-standard.c test/Sema/format-strings.c test/SemaCXX/format-strings.cpp Message-ID: <20120222101702.588812A6C12F@llvm.org> Author: hans Date: Wed Feb 22 04:17:01 2012 New Revision: 151154 URL: http://llvm.org/viewvc/llvm-project?rev=151154&view=rev Log: Warn about non-standard format strings (pr12017) This adds the -Wformat-non-standard flag (off by default, enabled by -pedantic), which warns about non-standard things in format strings (such as the 'q' length modifier, the 'S' conversion specifier, etc.) Added: cfe/trunk/test/Sema/format-strings-non-standard.c Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h cfe/trunk/include/clang/Basic/DiagnosticGroups.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Analysis/FormatString.cpp cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/Sema/format-strings-c90.c cfe/trunk/test/Sema/format-strings.c cfe/trunk/test/SemaCXX/format-strings.cpp Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original) +++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Wed Feb 22 04:17:01 2012 @@ -348,6 +348,12 @@ bool usesPositionalArg() const { return UsesPositionalArg; } bool hasValidLengthModifier() const; + + bool hasStandardLengthModifier() const; + + bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; + + bool hasStandardLengthConversionCombination() const; }; } // end analyze_format_string namespace Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed Feb 22 04:17:01 2012 @@ -290,6 +290,7 @@ // Format settings. def FormatInvalidSpecifier : DiagGroup<"format-invalid-specifier">; def FormatSecurity : DiagGroup<"format-security">; +def FormatNonStandard : DiagGroup<"format-non-standard">; def FormatY2K : DiagGroup<"format-y2k">; def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull, Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 22 04:17:01 2012 @@ -4847,6 +4847,11 @@ def warn_format_nonsensical_length: Warning< "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">, InGroup; +def warn_format_non_standard: ExtWarn< + "'%0' is a non-standard %1">, InGroup, DefaultIgnore; +def warn_format_non_standard_conversion_spec: ExtWarn< + "using the length modifier '%0' with the conversion specifier '%1' is non-standard">, + InGroup, DefaultIgnore; def warn_printf_ignored_flag: Warning< "flag '%0' is ignored when flag '%1' is present">, InGroup; Modified: cfe/trunk/lib/Analysis/FormatString.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/FormatString.cpp (original) +++ cfe/trunk/lib/Analysis/FormatString.cpp Wed Feb 22 04:17:01 2012 @@ -602,3 +602,74 @@ } llvm_unreachable("Invalid LengthModifier Kind!"); } + +bool FormatSpecifier::hasStandardLengthModifier() const { + switch (LM.getKind()) { + case LengthModifier::None: + case LengthModifier::AsChar: + case LengthModifier::AsShort: + case LengthModifier::AsLong: + case LengthModifier::AsLongLong: + case LengthModifier::AsIntMax: + case LengthModifier::AsSizeT: + case LengthModifier::AsPtrDiff: + case LengthModifier::AsLongDouble: + return true; + case LengthModifier::AsAllocate: + case LengthModifier::AsMAllocate: + case LengthModifier::AsQuad: + return false; + } + llvm_unreachable("Invalid LengthModifier Kind!"); +} + +bool FormatSpecifier::hasStandardConversionSpecifier(const LangOptions &LangOpt) const { + switch (CS.getKind()) { + case ConversionSpecifier::cArg: + case ConversionSpecifier::dArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::fArg: + case ConversionSpecifier::FArg: + case ConversionSpecifier::eArg: + case ConversionSpecifier::EArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::pArg: + case ConversionSpecifier::nArg: + case ConversionSpecifier::ObjCObjArg: + case ConversionSpecifier::ScanListArg: + case ConversionSpecifier::PercentArg: + return true; + case ConversionSpecifier::CArg: + case ConversionSpecifier::SArg: + return LangOpt.ObjC1 || LangOpt.ObjC2; + case ConversionSpecifier::InvalidSpecifier: + case ConversionSpecifier::PrintErrno: + return false; + } + llvm_unreachable("Invalid ConversionSpecifier Kind!"); +} + +bool FormatSpecifier::hasStandardLengthConversionCombination() const { + if (LM.getKind() == LengthModifier::AsLongDouble) { + switch(CS.getKind()) { + case ConversionSpecifier::dArg: + case ConversionSpecifier::iArg: + case ConversionSpecifier::oArg: + case ConversionSpecifier::uArg: + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + return false; + default: + return true; + } + } + return true; +} Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Feb 22 04:17:01 2012 @@ -1663,7 +1663,20 @@ void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen); - + + void HandleNonStandardLengthModifier( + const analyze_format_string::LengthModifier &LM, + const char *startSpecifier, unsigned specifierLen); + + void HandleNonStandardConversionSpecifier( + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen); + + void HandleNonStandardConversionSpecification( + const analyze_format_string::LengthModifier &LM, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen); + virtual void HandleInvalidPosition(const char *startSpecifier, unsigned specifierLen, analyze_format_string::PositionContext p); @@ -1739,6 +1752,37 @@ getSpecifierRange(startSpecifier, specifierLen)); } +void CheckFormatHandler::HandleNonStandardLengthModifier( + const analyze_format_string::LengthModifier &LM, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << LM.toString() + << "length modifier", + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardConversionSpecifier( + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << CS.toString() + << "conversion specifier", + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardConversionSpecification( + const analyze_format_string::LengthModifier &LM, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_conversion_spec) + << LM.toString() << CS.toString(), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + void CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen, analyze_format_string::PositionContext p) { @@ -2157,6 +2201,13 @@ FixItHint::CreateRemoval( getSpecifierRange(LM.getStart(), LM.getLength()))); + if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); + if (!FS.hasStandardConversionSpecifier(S.getLangOptions())) + HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); + if (!FS.hasStandardLengthConversionCombination()) + HandleNonStandardConversionSpecification(LM, CS, startSpecifier, + specifierLen); // Are we using '%n'? if (CS.getKind() == ConversionSpecifier::nArg) { @@ -2343,6 +2394,14 @@ FixItHint::CreateRemoval(R)); } + if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); + if (!FS.hasStandardConversionSpecifier(S.getLangOptions())) + HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); + if (!FS.hasStandardLengthConversionCombination()) + HandleNonStandardConversionSpecification(LM, CS, startSpecifier, + specifierLen); + // The remaining checks depend on the data arguments. if (HasVAListArg) return true; @@ -4971,4 +5030,3 @@ Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line); } } - Modified: cfe/trunk/test/Sema/format-strings-c90.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-c90.c?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/test/Sema/format-strings-c90.c (original) +++ cfe/trunk/test/Sema/format-strings-c90.c Wed Feb 22 04:17:01 2012 @@ -5,9 +5,8 @@ int printf(const char *restrict, ...); void foo(char **sp, float *fp, int *ip) { - /* TODO: Warn that the 'a' length modifier is an extension. */ - scanf("%as", sp); - scanf("%a[abc]", sp); + scanf("%as", sp); /* expected-warning{{'a' is a non-standard length modifier}} */ + scanf("%a[abc]", sp); /* expected-warning{{'a' is a non-standard length modifier}} */ /* TODO: Warn that the 'a' conversion specifier is a C99 feature. */ scanf("%a", fp); @@ -21,7 +20,11 @@ scanf("%da", ip); /* Test argument type check for the 'a' length modifier. */ - scanf("%as", fp); /* expected-warning{{format specifies type 'char **' but the argument has type 'float *'}} */ - scanf("%aS", fp); /* expected-warning{{format specifies type 'wchar_t **' (aka 'int **') but the argument has type 'float *'}} */ - scanf("%a[abc]", fp); /* expected-warning{{format specifies type 'char **' but the argument has type 'float *'}} */ + scanf("%as", fp); /* expected-warning{{format specifies type 'char **' but the argument has type 'float *'}} + expected-warning{{'a' is a non-standard length modifier}} */ + scanf("%aS", fp); /* expected-warning{{format specifies type 'wchar_t **' (aka 'int **') but the argument has type 'float *'}} + expected-warning{{'a' is a non-standard length modifier}} + expected-warning{{'S' is a non-standard conversion specifier}} */ + scanf("%a[abc]", fp); /* expected-warning{{format specifies type 'char **' but the argument has type 'float *'}} + expected-warning{{'a' is a non-standard length modifier}} */ } Added: cfe/trunk/test/Sema/format-strings-non-standard.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-non-standard.c?rev=151154&view=auto ============================================================================== --- cfe/trunk/test/Sema/format-strings-non-standard.c (added) +++ cfe/trunk/test/Sema/format-strings-non-standard.c Wed Feb 22 04:17:01 2012 @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c99 -pedantic %s + +int printf(const char *restrict, ...); +int scanf(const char * restrict, ...); + +void f(void) { + char *cp; + + // The 'q' length modifier. + printf("%qd", (long long)42); // expected-warning{{'q' is a non-standard length modifier}} + scanf("%qd", (long long *)0); // expected-warning{{'q' is a non-standard length modifier}} + + // The 'm' length modifier. + scanf("%ms", &cp); // expected-warning{{'m' is a non-standard length modifier}} + + // The 'S' and 'C' conversion specifiers. + printf("%S", L"foo"); // expected-warning{{'S' is a non-standard conversion specifier}} + printf("%C", L'x'); // expected-warning{{'C' is a non-standard conversion specifier}} + + // Combining 'L' with an integer conversion specifier. + printf("%Li", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'i' is non-standard}} + printf("%Lo", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'o' is non-standard}} + printf("%Lu", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'u' is non-standard}} + printf("%Lx", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'x' is non-standard}} + printf("%LX", (long long)42); // expected-warning{{using the length modifier 'L' with the conversion specifier 'X' is non-standard}} +} Modified: cfe/trunk/test/Sema/format-strings.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings.c?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/test/Sema/format-strings.c (original) +++ cfe/trunk/test/Sema/format-strings.c Wed Feb 22 04:17:01 2012 @@ -268,7 +268,6 @@ // FIXME: This test reports inconsistent results. On Windows, '%C' expects // 'unsigned short'. // printf("%C", 10); - // FIXME: we report the expected type as 'int*' instead of 'wchar_t*' printf("%S", "hello"); // expected-warning{{but the argument has type 'char *'}} } Modified: cfe/trunk/test/SemaCXX/format-strings.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/format-strings.cpp?rev=151154&r1=151153&r2=151154&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/format-strings.cpp (original) +++ cfe/trunk/test/SemaCXX/format-strings.cpp Wed Feb 22 04:17:01 2012 @@ -9,8 +9,7 @@ } void f(char **sp, float *fp) { - // TODO: Warn that the 'a' length modifier is an extension. - scanf("%as", sp); + scanf("%as", sp); // expected-warning{{'a' is a non-standard length modifier}} // TODO: Warn that the 'a' conversion specifier is a C++11 feature. printf("%a", 1.0); From hans at chromium.org Wed Feb 22 02:43:06 2012 From: hans at chromium.org (Hans Wennborg) Date: Wed, 22 Feb 2012 10:43:06 +0000 Subject: [cfe-commits] [Patch] Warn about non-standard format strings (PR12017) In-Reply-To: References: <83D625C8-B3E1-4B0D-8E08-4262DF9BB177@apple.com> Message-ID: On Tue, Feb 21, 2012 at 20:15, Ted Kremenek wrote: > On Feb 21, 2012, at 3:39 AM, Hans Wennborg wrote: > > On Mon, Feb 20, 2012 at 19:37, Ted Kremenek wrote: > > On Feb 20, 2012, at 11:25 AM, Hans Wennborg wrote: > > Keeping -Wformat-nonstandard out of -Wformat and having it in > -pedantic sounds perfectly fine to me. I expect that lines up with > what gcc does too. > > > Ok, I think that approach is worth experimenting with. > > > Cool. I think getting this warning in under -pedantic is a good step > in the right direction. > > > Me too. > > > I've looked at the patch, and other than the default configuration of the > warnings, it looks okay to me. > > > I've updated the patch to make the warning DefaultIgnore and ExtWarn. > > I've also changed it to not make a difference between -std=c99 and > -std=gnu99. If the user specifies -pedantic, I think we should warn > for '%ms' even if the user has selected -std=gnu99. This matches gcc > behavior too, and it's extra important because if the user doesn't > specify the -std flag, then gnu99 seems the be the default c mode. > > > Sounds great. > > > One nit on wording in the diagnostic: "non-standard" or "non-portable"?  The > former is more technically accurate, but the latter is the implication the > user cares about.  What do you think? > > > I'd prefer "non-standard", but I don't feel strongly about it. > > > I don't either.  I'm fine with staying with non-standard. > > > I noticed that this sparks new failures in > "clang-tests/gcc-4_2-testsuite" (excess warning), so I'm attaching a > patch for that too. Please take a look. > > > I did.  The change looks reasonable. > > > Please commit! > Committed r151153 and r151154. Thanks, Hans From sebastian.redl at getdesigned.at Wed Feb 22 02:50:08 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Wed, 22 Feb 2012 10:50:08 -0000 Subject: [cfe-commits] r151155 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseStmt.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaStmt.cpp test/SemaCXX/cxx0x-initializer-constructor.cpp test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp test/SemaCXX/cxx0x-return-init-list.cpp Message-ID: <20120222105009.15FD02A6C12F@llvm.org> Author: cornedbee Date: Wed Feb 22 04:50:08 2012 New Revision: 151155 URL: http://llvm.org/viewvc/llvm-project?rev=151155&view=rev Log: Fix parsing and processing initializer lists in return statements and as direct member initializers. Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaStmt.cpp cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Feb 22 04:50:08 2012 @@ -223,10 +223,8 @@ def warn_cxx98_compat_inline_namespace : Warning< "inline namespaces are incompatible with C++98">, InGroup, DefaultIgnore; -def err_generalized_initializer_lists : Error< - "generalized initializer lists are a C++11 extension unsupported in Clang">; def ext_generalized_initializer_lists : ExtWarn< - "generalized initializer lists are a C++11 extension unsupported in Clang">, + "generalized initializer lists are a C++11 extension">, InGroup; def warn_cxx98_compat_generalized_initializer_lists : Warning< "generalized initializer lists are incompatible with C++98">, Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 22 04:50:08 2012 @@ -5057,6 +5057,9 @@ DefaultError, InGroup; def ext_return_has_void_expr : Extension< "void %select{function|method}1 %0 should not return void expression">; +def err_return_init_list : Error< + "%select{void function|void method|constructor|destructor}1 %0 " + "must not return a value">; def warn_noreturn_function_has_return_expr : Warning< "function %0 declared 'noreturn' should not return">, InGroup>; Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Feb 22 04:50:08 2012 @@ -2012,7 +2012,7 @@ if (Init.isInvalid()) SkipUntil(tok::comma, true, true); else if (ThisDecl) - Actions.AddInitializerToDecl(ThisDecl, Init.get(), false, + Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(), DS.getTypeSpecType() == DeclSpec::TST_auto); } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) { // No initializer. @@ -2087,15 +2087,15 @@ /// /// pure-specifier: /// '= 0' -/// +/// /// brace-or-equal-initializer: /// '=' initializer-expression -/// braced-init-list [TODO] -/// +/// braced-init-list +/// /// initializer-clause: /// assignment-expression -/// braced-init-list [TODO] -/// +/// braced-init-list +/// /// defaulted/deleted function-definition: /// '=' 'default' /// '=' 'delete' @@ -2137,9 +2137,8 @@ return ExprResult(); } - return ParseInitializer(); - } else - return ExprError(Diag(Tok, diag::err_generalized_initializer_lists)); + } + return ParseInitializer(); } /// ParseCXXMemberSpecification - Parse the class definition. Modified: cfe/trunk/lib/Parse/ParseStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmt.cpp Wed Feb 22 04:50:08 2012 @@ -1597,9 +1597,6 @@ return StmtError(); } - // FIXME: This is a hack to allow something like C++0x's generalized - // initializer lists, but only enough of this feature to allow Clang to - // parse libstdc++ 4.5's headers. if (Tok.is(tok::l_brace) && getLang().CPlusPlus) { R = ParseInitializer(); if (R.isUsable()) Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb 22 04:50:08 2012 @@ -1640,12 +1640,17 @@ ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { if (isa(InitExpr) && isStdInitializerList(FD->getType(), 0)) { - Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) + Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) << /*at end of ctor*/1 << InitExpr->getSourceRange(); } - // FIXME: if there is no EqualLoc, this is list-initialization. - Init = PerformCopyInitialization( - InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr); + Expr **Inits = &InitExpr; + unsigned NumInits = 1; + InitializedEntity Entity = InitializedEntity::InitializeMember(FD); + InitializationKind Kind = EqualLoc.isInvalid() + ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) + : InitializationKind::CreateCopy(InitExpr->getLocStart(), EqualLoc); + InitializationSequence Seq(*this, Entity, Kind, Inits, NumInits); + Init = Seq.Perform(*this, Entity, Kind, MultiExprArg(Inits, NumInits)); if (Init.isInvalid()) { FD->setInvalidDecl(); return; Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Feb 22 04:50:08 2012 @@ -1961,7 +1961,26 @@ ReturnStmt *Result = 0; if (FnRetType->isVoidType()) { if (RetValExp) { - if (!RetValExp->isTypeDependent()) { + if (isa(RetValExp)) { + // We simply never allow init lists as the return value of void + // functions. This is compatible because this was never allowed before, + // so there's no legacy code to deal with. + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + int FunctionKind = 0; + if (isa(CurDecl)) + FunctionKind = 1; + else if (isa(CurDecl)) + FunctionKind = 2; + else if (isa(CurDecl)) + FunctionKind = 3; + + Diag(ReturnLoc, diag::err_return_init_list) + << CurDecl->getDeclName() << FunctionKind + << RetValExp->getSourceRange(); + + // Drop the expression. + RetValExp = 0; + } else if (!RetValExp->isTypeDependent()) { // C99 6.8.6.4p1 (ext_ since GCC warns) unsigned D = diag::ext_return_has_expr; if (RetValExp->getType()->isVoidType()) @@ -1995,8 +2014,10 @@ } } - CheckImplicitConversions(RetValExp, ReturnLoc); - RetValExp = MaybeCreateExprWithCleanups(RetValExp); + if (RetValExp) { + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } } Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0); Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Wed Feb 22 04:50:08 2012 @@ -153,9 +153,9 @@ G(std::initializer_list, T ...); // expected-note 3 {{not viable}} }; - struct H { // expected-note 6 {{not viable}} + struct H { // expected-note 8 {{not viable}} explicit H(int, int); // expected-note 3 {{not viable}} - H(int, void*); // expected-note 3 {{not viable}} + H(int, void*); // expected-note 4 {{not viable}} }; void edge_cases() { @@ -186,4 +186,11 @@ (void) new H{1, 2}; (void) H{1, 2}; } + + struct memberinit { + H h1{1, nullptr}; + H h2 = {1, nullptr}; + H h3{1, 1}; + H h4 = {1, 1}; // expected-error {{no matching constructor}} + }; } Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Wed Feb 22 04:50:08 2012 @@ -130,6 +130,7 @@ struct haslist1 { std::initializer_list il = {1, 2, 3}; // expected-warning{{at the end of the constructor}} + std::initializer_list jl{1, 2, 3}; // expected-warning{{at the end of the constructor}} haslist1(); }; Modified: cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp?rev=151155&r1=151154&r2=151155&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp Wed Feb 22 04:50:08 2012 @@ -1,17 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// This test checks for a teeny tiny subset of the functionality in -// the C++11 generalized initializer lists feature, which happens to -// be used in libstdc++ 4.5. We accept only this syntax so that Clang -// can handle the libstdc++ 4.5 headers. +// Test that a very basic variation of generalized initializer returns (that +// required for libstdc++ 4.5) is supposed in C++98. int test0(int i) { - return { i }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}} + return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}} } template T test1(U u) { - return { u }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}} + return { u }; // expected-warning{{generalized initializer lists are a C++11 extension}} } template int test1(char); From aaron at aaronballman.com Wed Feb 22 05:08:02 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Wed, 22 Feb 2012 07:08:02 -0600 Subject: [cfe-commits] r151122 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/thiscall-struct-return.cpp In-Reply-To: References: <20120222030413.B97902A6C12F@llvm.org> <4F68169D-6D7F-4473-B70C-26A2C0D083B3@apple.com> Message-ID: On Wed, Feb 22, 2012 at 1:14 AM, Chandler Carruth wrote: > On Tue, Feb 21, 2012 at 10:52 PM, John McCall wrote: >> >> On Feb 21, 2012, at 7:37 PM, Aaron Ballman wrote: >> > Hmm, I may have heard wrong then.  If that's the case, I'll take care >> > of it.  Confirmation? >> >> If it's not already set on all the source files in the project, you can >> assume >> you shouldn't set it somewhere new. > > > The desired state is to configure the SVN client to default to 'native' eol > handling. Not all do this correctly, and so some have set it manually on a > few files they were modifying. That was what I had heard -- so I set my autoprops to svn:eol-style=native. Is that incorrect? ~Aaron From jediknil at belkadan.com Wed Feb 22 07:07:39 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 22 Feb 2012 22:07:39 +0700 Subject: [cfe-commits] r150306 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp lib/StaticAnalyzer/Checkers/CMakeLists.txt lib/StaticAnalyzer/Checkers/Checkers.td test/Analysis/bool-assignment.cpp test/Analysis/bool-assignment2.c In-Reply-To: References: <20120211163209.A2DBE1BE003@llvm.org> <3164C109-A5D2-434C-BEB6-76DBA6E7F967@belkadan.com> Message-ID: <9E554E48-4FE0-4595-890B-EA2C7011CC09@belkadan.com> On Feb 20, 2012, at 16:44, Ryan Govostes wrote: > On Feb 17, 2012, at 1:11 AM, Jordy Rose wrote: > >> Nice idea for a checker. The one thing I'm wondering is why you decided to use this less than / greater than approach...it might not matter here, but in general statements about equality and inequality are a bit easier for the analyzer to reason about than less than and greater than. It requires the same number of checks, too: > > Hi Jordy, > > Thanks. This is my first checker and the patch I submitted is the result of a few iterations with Ted. Indeed I originally wrote it using equality and inequality as you suggested, but Ted recommended the approach used now: > >> [...] I can say that you are definitely going into territory where the current solver isn't going to handle this well. It currently doesn't reason about arbitrary disjunctions. We currently accomplish that feat in the static analyzer by bifurcating states. > > So, we settled on (x <= 1) && (x >= 0) as you see in the patch. Ah, I see...my strategy results in two valid states: stZero*, stNotZero stOne*, stNotZeroOrOne ...while yours only has one: stLTZero, stGEZero stGTOne, stZeroOrOne* Okay, thanks for the explanation! Jordy From jediknil at belkadan.com Wed Feb 22 07:59:46 2012 From: jediknil at belkadan.com (Jordy Rose) Date: Wed, 22 Feb 2012 22:59:46 +0700 Subject: [cfe-commits] r151124 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c In-Reply-To: <20120222031420.A64182A6C130@llvm.org> References: <20120222031420.A64182A6C130@llvm.org> Message-ID: <30DC14ED-C1D7-4375-831A-07145C98EE58@belkadan.com> Minor complaint: why is the size of a strdup allocation Undef and not Unknown? I see we can skip the extent-setting step, but really we might as well just do that anyway if it's Unknown. Jordy On Feb 22, 2012, at 10:14, Anna Zaks wrote: > Author: zaks > Date: Tue Feb 21 21:14:20 2012 > New Revision: 151124 > > URL: http://llvm.org/viewvc/llvm-project?rev=151124&view=rev > Log: > [analyzer] Malloc checker: mark 'strdup' and 'strndup' as allocators. > > Modified: > cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp > cfe/trunk/test/Analysis/malloc.c > > Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=151124&r1=151123&r2=151124&view=diff > ============================================================================== > --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) > +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Tue Feb 21 21:14:20 2012 > @@ -26,6 +26,8 @@ > #include "llvm/ADT/ImmutableMap.h" > #include "llvm/ADT/SmallString.h" > #include "llvm/ADT/STLExtras.h" > +#include > + > using namespace clang; > using namespace ento; > > @@ -97,11 +99,13 @@ > mutable OwningPtr BT_UseFree; > mutable OwningPtr BT_BadFree; > mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc, > - *II_valloc, *II_reallocf; > + *II_valloc, *II_reallocf, *II_strndup, *II_strdup; > + > + static const unsigned InvalidArgIndex = UINT_MAX; > > public: > MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0), > - II_valloc(0), II_reallocf(0) {} > + II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0) {} > > /// In pessimistic mode, the checker assumes that it does not know which > /// functions might free the memory. > @@ -140,7 +144,8 @@ > /// pointed to by one of its arguments. > bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const; > > - static void MallocMem(CheckerContext &C, const CallExpr *CE); > + static void MallocMem(CheckerContext &C, const CallExpr *CE, > + unsigned SizeIdx); > static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, > const OwnershipAttr* Att); > static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, > @@ -283,6 +288,10 @@ > II_calloc = &Ctx.Idents.get("calloc"); > if (!II_valloc) > II_valloc = &Ctx.Idents.get("valloc"); > + if (!II_strdup) > + II_strdup = &Ctx.Idents.get("strdup"); > + if (!II_strndup) > + II_strndup = &Ctx.Idents.get("strndup"); > } > > bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const { > @@ -294,9 +303,9 @@ > > initIdentifierInfo(C); > > - // TODO: Add more here : ex: reallocf! > if (FunI == II_malloc || FunI == II_free || FunI == II_realloc || > - FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc) > + FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc || > + FunI == II_strdup || FunI == II_strndup) > return true; > > if (Filter.CMallocOptimistic && FD->hasAttrs() && > @@ -319,7 +328,7 @@ > return; > > if (FunI == II_malloc || FunI == II_valloc) { > - MallocMem(C, CE); > + MallocMem(C, CE, 0); > return; > } else if (FunI == II_realloc) { > ReallocMem(C, CE, false); > @@ -330,9 +339,15 @@ > } else if (FunI == II_calloc) { > CallocMem(C, CE); > return; > - }else if (FunI == II_free) { > + } else if (FunI == II_free) { > FreeMem(C, CE); > return; > + } else if (FunI == II_strdup) { > + MallocMem(C, CE, InvalidArgIndex); > + return; > + } else if (FunI == II_strndup) { > + MallocMem(C, CE, 1); > + return; > } > > if (Filter.CMallocOptimistic) > @@ -358,10 +373,16 @@ > } > } > > -void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) { > - ProgramStateRef state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), > - C.getState()); > - C.addTransition(state); > +void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE, > + unsigned SizeIdx) { > + SVal Undef = UndefinedVal(); > + ProgramStateRef State; > + if (SizeIdx != InvalidArgIndex) > + State = MallocMemAux(C, CE, CE->getArg(SizeIdx), Undef, C.getState()); > + else > + State = MallocMemAux(C, CE, Undef, Undef, C.getState()); > + > + C.addTransition(State); > } > > void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, > @@ -400,16 +421,17 @@ > // Set the region's extent equal to the Size parameter. > const SymbolicRegion *R = > dyn_cast_or_null(retVal.getAsRegion()); > - if (!R || !isa(Size)) > + if (!R) > return 0; > + if (isa(Size)) { > + DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); > + DefinedOrUnknownSVal DefinedSize = cast(Size); > + DefinedOrUnknownSVal extentMatchesSize = > + svalBuilder.evalEQ(state, Extent, DefinedSize); > > - DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); > - DefinedOrUnknownSVal DefinedSize = cast(Size); > - DefinedOrUnknownSVal extentMatchesSize = > - svalBuilder.evalEQ(state, Extent, DefinedSize); > - > - state = state->assume(extentMatchesSize, true); > - assert(state); > + state = state->assume(extentMatchesSize, true); > + assert(state); > + } > > SymbolRef Sym = retVal.getAsLocSymbol(); > assert(Sym); > > Modified: cfe/trunk/test/Analysis/malloc.c > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=151124&r1=151123&r2=151124&view=diff > ============================================================================== > --- cfe/trunk/test/Analysis/malloc.c (original) > +++ cfe/trunk/test/Analysis/malloc.c Tue Feb 21 21:14:20 2012 > @@ -652,6 +652,25 @@ > return &(px->g); > } > > +// Test various allocation/deallocation functions. > + > +char *strdup(const char *s); > +char *strndup(const char *s, size_t n); > + > +void testStrdup(const char *s, unsigned validIndex) { > + char *s2 = strdup(s); > + s2[validIndex + 1] = 'b';// expected-warning {{Memory is never released; potential memory leak}} > +} > + > +int testStrndup(const char *s, unsigned validIndex, unsigned size) { > + char *s2 = strndup(s, size); > + s2 [validIndex + 1] = 'b'; > + if (s2[validIndex] != 'a') > + return 0;// expected-warning {{Memory is never released; potential memory leak}} > + else > + return 1;// expected-warning {{Memory is never released; potential memory leak}} > +} > + > // Below are the known false positives. > > // TODO: There should be no warning here. This one might be difficult to get rid of. > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From delesley at google.com Wed Feb 22 08:14:18 2012 From: delesley at google.com (Delesley Hutchins) Date: Wed, 22 Feb 2012 08:14:18 -0800 Subject: [cfe-commits] [PATCH] Thread-safety analysis: handle CFG blocks which call functions marked as noreturn. Message-ID: This is a quick fix to remove bogus errors that occur when calling functions marked as noreturn. http://codereview.appspot.com/5689070/ -- DeLesley Hutchins | Software Engineer | delesley at google.com | 505-206-0315 -------------- next part -------------- A non-text attachment was scrubbed... Name: clang-noreturn.patch Type: text/x-patch Size: 1209 bytes Desc: not available URL: From dgregor at apple.com Wed Feb 22 08:16:37 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 22 Feb 2012 08:16:37 -0800 Subject: [cfe-commits] r151155 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseStmt.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaStmt.cpp test/SemaCXX/cxx0x-initializer-constructor.cpp test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp test/SemaCXX/cxx0x-return-init-list.cpp In-Reply-To: <20120222105009.15FD02A6C12F@llvm.org> References: <20120222105009.15FD02A6C12F@llvm.org> Message-ID: On Feb 22, 2012, at 2:50 AM, Sebastian Redl wrote: > Author: cornedbee > Date: Wed Feb 22 04:50:08 2012 > New Revision: 151155 > > URL: http://llvm.org/viewvc/llvm-project?rev=151155&view=rev > Log: > Fix parsing and processing initializer lists in return statements and as direct member initializers. Thanks! > Modified: > cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/lib/Parse/ParseDeclCXX.cpp > cfe/trunk/lib/Parse/ParseStmt.cpp > cfe/trunk/lib/Sema/SemaDeclCXX.cpp > cfe/trunk/lib/Sema/SemaStmt.cpp > cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp > cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp > cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp > > Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151155&r1=151154&r2=151155&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Feb 22 04:50:08 2012 > @@ -223,10 +223,8 @@ > def warn_cxx98_compat_inline_namespace : Warning< > "inline namespaces are incompatible with C++98">, > InGroup, DefaultIgnore; > -def err_generalized_initializer_lists : Error< > - "generalized initializer lists are a C++11 extension unsupported in Clang">; > def ext_generalized_initializer_lists : ExtWarn< > - "generalized initializer lists are a C++11 extension unsupported in Clang">, > + "generalized initializer lists are a C++11 extension">, > InGroup; > def warn_cxx98_compat_generalized_initializer_lists : Warning< > "generalized initializer lists are incompatible with C++98">, > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=151155&r1=151154&r2=151155&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 22 04:50:08 2012 > @@ -5057,6 +5057,9 @@ > DefaultError, InGroup; > def ext_return_has_void_expr : Extension< > "void %select{function|method}1 %0 should not return void expression">; > +def err_return_init_list : Error< > + "%select{void function|void method|constructor|destructor}1 %0 " > + "must not return a value">; > def warn_noreturn_function_has_return_expr : Warning< > "function %0 declared 'noreturn' should not return">, > InGroup>; > > Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=151155&r1=151154&r2=151155&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) > +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Feb 22 04:50:08 2012 > @@ -2012,7 +2012,7 @@ > if (Init.isInvalid()) > SkipUntil(tok::comma, true, true); > else if (ThisDecl) > - Actions.AddInitializerToDecl(ThisDecl, Init.get(), false, > + Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(), > DS.getTypeSpecType() == DeclSpec::TST_auto); > } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) { > // No initializer. > @@ -2087,15 +2087,15 @@ > /// > /// pure-specifier: > /// '= 0' > -/// > +/// > /// brace-or-equal-initializer: > /// '=' initializer-expression > -/// braced-init-list [TODO] > -/// > +/// braced-init-list > +/// > /// initializer-clause: > /// assignment-expression > -/// braced-init-list [TODO] > -/// > +/// braced-init-list > +/// > /// defaulted/deleted function-definition: > /// '=' 'default' > /// '=' 'delete' > @@ -2137,9 +2137,8 @@ > return ExprResult(); > } > > - return ParseInitializer(); > - } else > - return ExprError(Diag(Tok, diag::err_generalized_initializer_lists)); > + } > + return ParseInitializer(); > } > > /// ParseCXXMemberSpecification - Parse the class definition. > > Modified: cfe/trunk/lib/Parse/ParseStmt.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=151155&r1=151154&r2=151155&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) > +++ cfe/trunk/lib/Parse/ParseStmt.cpp Wed Feb 22 04:50:08 2012 > @@ -1597,9 +1597,6 @@ > return StmtError(); > } > > - // FIXME: This is a hack to allow something like C++0x's generalized > - // initializer lists, but only enough of this feature to allow Clang to > - // parse libstdc++ 4.5's headers. > if (Tok.is(tok::l_brace) && getLang().CPlusPlus) { > R = ParseInitializer(); > if (R.isUsable()) > > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=151155&r1=151154&r2=151155&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb 22 04:50:08 2012 > @@ -1640,12 +1640,17 @@ > ExprResult Init = InitExpr; > if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { > if (isa(InitExpr) && isStdInitializerList(FD->getType(), 0)) { > - Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) > + Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) > << /*at end of ctor*/1 << InitExpr->getSourceRange(); > } > - // FIXME: if there is no EqualLoc, this is list-initialization. > - Init = PerformCopyInitialization( > - InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr); > + Expr **Inits = &InitExpr; > + unsigned NumInits = 1; > + InitializedEntity Entity = InitializedEntity::InitializeMember(FD); > + InitializationKind Kind = EqualLoc.isInvalid() > + ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) > + : InitializationKind::CreateCopy(InitExpr->getLocStart(), EqualLoc); > + InitializationSequence Seq(*this, Entity, Kind, Inits, NumInits); > + Init = Seq.Perform(*this, Entity, Kind, MultiExprArg(Inits, NumInits)); > if (Init.isInvalid()) { > FD->setInvalidDecl(); > return; > > Modified: cfe/trunk/lib/Sema/SemaStmt.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=151155&r1=151154&r2=151155&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) > +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Feb 22 04:50:08 2012 > @@ -1961,7 +1961,26 @@ > ReturnStmt *Result = 0; > if (FnRetType->isVoidType()) { > if (RetValExp) { > - if (!RetValExp->isTypeDependent()) { > + if (isa(RetValExp)) { > + // We simply never allow init lists as the return value of void > + // functions. This is compatible because this was never allowed before, > + // so there's no legacy code to deal with. > + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); > + int FunctionKind = 0; > + if (isa(CurDecl)) > + FunctionKind = 1; > + else if (isa(CurDecl)) > + FunctionKind = 2; > + else if (isa(CurDecl)) > + FunctionKind = 3; > + > + Diag(ReturnLoc, diag::err_return_init_list) > + << CurDecl->getDeclName() << FunctionKind > + << RetValExp->getSourceRange(); > + > + // Drop the expression. > + RetValExp = 0; I presume that you also want to drop the expression up in ActOnCapScopeReturnStmt (for blocks and lambdas), where we also have an InitListExpr check? > Modified: cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp?rev=151155&r1=151154&r2=151155&view=diff > ============================================================================== > --- cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp (original) > +++ cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp Wed Feb 22 04:50:08 2012 > @@ -1,17 +1,15 @@ > // RUN: %clang_cc1 -fsyntax-only -verify %s > > -// This test checks for a teeny tiny subset of the functionality in > -// the C++11 generalized initializer lists feature, which happens to > -// be used in libstdc++ 4.5. We accept only this syntax so that Clang > -// can handle the libstdc++ 4.5 headers. > +// Test that a very basic variation of generalized initializer returns (that > +// required for libstdc++ 4.5) is supposed in C++98. s/supposed/supported. - Doug From dgregor at apple.com Wed Feb 22 09:32:19 2012 From: dgregor at apple.com (Douglas Gregor) Date: Wed, 22 Feb 2012 17:32:19 -0000 Subject: [cfe-commits] r151170 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Message-ID: <20120222173219.9C5FB2A6C12F@llvm.org> Author: dgregor Date: Wed Feb 22 11:32:19 2012 New Revision: 151170 URL: http://llvm.org/viewvc/llvm-project?rev=151170&view=rev Log: Teach overload resolution to prefer user-defined conversion via a lambda closure type's function pointer conversion over user-defined conversion via a lambda closure type's block pointer conversion, always. This is a preference for more-standard code (since blocks are an extension) and a nod to efficiency, since function pointers don't require any memory management. Fixes PR12063. Modified: cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=151170&r1=151169&r2=151170&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb 22 11:32:19 2012 @@ -3065,6 +3065,41 @@ return true; } +/// \brief Compare the user-defined conversion functions or constructors +/// of two user-defined conversion sequences to determine whether any ordering +/// is possible. +static ImplicitConversionSequence::CompareKind +compareConversionFunctions(Sema &S, + FunctionDecl *Function1, + FunctionDecl *Function2) { + if (!S.getLangOptions().ObjC1 || !S.getLangOptions().CPlusPlus0x) + return ImplicitConversionSequence::Indistinguishable; + + // Objective-C++: + // If both conversion functions are implicitly-declared conversions from + // a lambda closure type to a function pointer and a block pointer, + // respectively, always prefer the conversion to a function pointer, + // because the function pointer is more lightweight and is more likely + // to keep code working. + CXXConversionDecl *Conv1 = dyn_cast(Function1); + if (!Conv1) + return ImplicitConversionSequence::Indistinguishable; + + CXXConversionDecl *Conv2 = dyn_cast(Function2); + if (!Conv2) + return ImplicitConversionSequence::Indistinguishable; + + if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) { + bool Block1 = Conv1->getConversionType()->isBlockPointerType(); + bool Block2 = Conv2->getConversionType()->isBlockPointerType(); + if (Block1 != Block2) + return Block1? ImplicitConversionSequence::Worse + : ImplicitConversionSequence::Better; + } + + return ImplicitConversionSequence::Indistinguishable; +} + /// CompareImplicitConversionSequences - Compare two implicit /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2). @@ -3118,6 +3153,10 @@ Result = CompareStandardConversionSequences(S, ICS1.UserDefined.After, ICS2.UserDefined.After); + else + Result = compareConversionFunctions(S, + ICS1.UserDefined.ConversionFunction, + ICS2.UserDefined.ConversionFunction); } // List-initialization sequence L1 is a better conversion sequence than @@ -7538,6 +7577,15 @@ if (UserDefinedConversion && Cand1.Function && Cand2.Function && isa(Cand1.Function) && isa(Cand2.Function)) { + // First check whether we prefer one of the conversion functions over the + // other. This only distinguishes the results in non-standard, extension + // cases such as the conversion from a lambda closure type to a function + // pointer or block. + ImplicitConversionSequence::CompareKind FuncResult + = compareConversionFunctions(S, Cand1.Function, Cand2.Function); + if (FuncResult != ImplicitConversionSequence::Indistinguishable) + return FuncResult; + switch (CompareStandardConversionSequences(S, Cand1.FinalConversion, Cand2.FinalConversion)) { 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=151170&r1=151169&r2=151170&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 Feb 22 11:32:19 2012 @@ -55,3 +55,34 @@ }(); }(); } + +namespace overloading { + void bool_conversion() { + if ([](){}) { + } + + bool b = []{}; + b = (bool)[]{}; + } + + void conversions() { + int (*fp)(int) = [](int x) { return x + 1; }; + fp = [](int x) { return x + 1; }; + + typedef int (*func_ptr)(int); + fp = (func_ptr)[](int x) { return x + 1; }; + + int (^bp)(int) = [](int x) { return x + 1; }; + bp = [](int x) { return x + 1; }; + + typedef int (^block_ptr)(int); + bp = (block_ptr)[](int x) { return x + 1; }; + } + + int &accept_lambda_conv(int (*fp)(int)); + float &accept_lambda_conv(int (^bp)(int)); + + void call_with_lambda() { + int &ir = accept_lambda_conv([](int x) { return x + 1; }); + } +} From ganna at apple.com Wed Feb 22 09:36:06 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 22 Feb 2012 09:36:06 -0800 Subject: [cfe-commits] r150846 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/CStringChecker.cpp lib/StaticAnalyzer/Checkers/InterCheckerAPI.h lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c In-Reply-To: <7D103CC0-FA0C-4CF7-9EF3-F3D8E7E6A268@belkadan.com> References: <20120217223531.EFA962A6C12F@llvm.org> <7D103CC0-FA0C-4CF7-9EF3-F3D8E7E6A268@belkadan.com> Message-ID: <9BE10BE8-461B-4EAF-9751-8F4ED3CBEEDD@apple.com> On Feb 18, 2012, at 5:34 AM, Jordy Rose wrote: > Does MallocChecker really "need" to know this? I mean, I doubt CStringCheckerBasic is a huge performance hit, but it seems like someone who wants the analyzer to model C library string functions should enable CStringChecker themselves. Malloc Checker directly depends on the evaluation of the CString functions. In particular, it needs to know that when strcpy is evaluated, the return value is equal to the input parameter. You can see the malloc false positive fixed by this commit at the very end of the diff. > > (I see that someone on Radar thought the answer was "yes", but...) > > Also, separately...is this the way we're going to do inter-checker dependencies? I like how simple it is! And since all the checker registration is done with vectors, it even handles ordering. I don't think this handles ordering.. The ordering still depends on the order in which the checkers are defined in the Checker.td file. That's something which needs to be fixed. > But I don't know how it will scale, and it does sort of compel us to expose a registration function for /every/ checker. (Just like warning flags, if we decide it's okay not to have a registration function for some checker, we'll end up in a situation where we need it.) > We do not have the dependency mechanism set in stone. We can revisit this later on. I view this approach as something that we can use to define dependencies in special cases. Currently, this is the only dependency we have, though it might quickly change.. Anna. > Jordy > > > On Feb 18, 2012, at 5:35, Anna Zaks wrote: > >> Author: zaks >> Date: Fri Feb 17 16:35:31 2012 >> New Revision: 150846 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=150846&view=rev >> Log: >> [analyzer] Fix another false positive in the Malloc Checker, by making >> it aware of CString APIs that return the input parameter. >> >> Malloc Checker needs to know how the 'strcpy' function is >> evaluated. Introduce the dependency on CStringChecker for that. >> CStringChecker knows all about these APIs. >> >> Addresses radar://10864450 >> >> Added: >> cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h >> Modified: >> cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp >> cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp >> cfe/trunk/test/Analysis/malloc.c >> >> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=150846&r1=150845&r2=150846&view=diff >> ============================================================================== >> --- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original) >> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Fri Feb 17 16:35:31 2012 >> @@ -13,6 +13,7 @@ >> //===----------------------------------------------------------------------===// >> >> #include "ClangSACheckers.h" >> +#include "InterCheckerAPI.h" >> #include "clang/StaticAnalyzer/Core/Checker.h" >> #include "clang/StaticAnalyzer/Core/CheckerManager.h" >> #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" >> @@ -1924,3 +1925,7 @@ >> REGISTER_CHECKER(CStringOutOfBounds) >> REGISTER_CHECKER(CStringBufferOverlap) >> REGISTER_CHECKER(CStringNotNullTerm) >> + >> +void ento::registerCStringCheckerBasic(CheckerManager &Mgr) { >> + registerCStringNullArg(Mgr); >> +} >> >> Added: cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h?rev=150846&view=auto >> ============================================================================== >> --- cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h (added) >> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/InterCheckerAPI.h Fri Feb 17 16:35:31 2012 >> @@ -0,0 +1,22 @@ >> +//==--- InterCheckerAPI.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 allows introduction of checker dependencies. It contains APIs for >> +// inter-checker communications. >> +//===----------------------------------------------------------------------===// >> + >> +#ifndef INTERCHECKERAPI_H_ >> +#define INTERCHECKERAPI_H_ >> +namespace clang { >> +namespace ento { >> + >> +/// Register the checker which evaluates CString API calls. >> +void registerCStringCheckerBasic(CheckerManager &Mgr); >> + >> +}} >> +#endif /* INTERCHECKERAPI_H_ */ >> >> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=150846&r1=150845&r2=150846&view=diff >> ============================================================================== >> --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) >> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Fri Feb 17 16:35:31 2012 >> @@ -13,6 +13,7 @@ >> //===----------------------------------------------------------------------===// >> >> #include "ClangSACheckers.h" >> +#include "InterCheckerAPI.h" >> #include "clang/StaticAnalyzer/Core/Checker.h" >> #include "clang/StaticAnalyzer/Core/CheckerManager.h" >> #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" >> @@ -1130,6 +1131,7 @@ >> >> #define REGISTER_CHECKER(name) \ >> void ento::register##name(CheckerManager &mgr) {\ >> + registerCStringCheckerBasic(mgr); \ >> mgr.registerChecker()->Filter.C##name = true;\ >> } >> >> >> Modified: cfe/trunk/test/Analysis/malloc.c >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=150846&r1=150845&r2=150846&view=diff >> ============================================================================== >> --- cfe/trunk/test/Analysis/malloc.c (original) >> +++ cfe/trunk/test/Analysis/malloc.c Fri Feb 17 16:35:31 2012 >> @@ -594,6 +594,26 @@ >> strcpy(p, s); // expected-warning {{leak}} >> } >> >> +// Rely on the CString checker evaluation of the strcpy API to convey that the result of strcpy is equal to p. >> +void symbolLostWithStrcpy(char *s) { >> + char *p = malloc(12); >> + p = strcpy(p, s); >> + free(p); >> +} >> + >> + >> +// The same test as the one above, but with what is actually generated on a mac. >> +static __inline char * >> +__inline_strcpy_chk (char *restrict __dest, const char *restrict __src) >> +{ >> + return __builtin___strcpy_chk (__dest, __src, __builtin_object_size (__dest, 2 > 1)); >> +} >> + >> +void symbolLostWithStrcpy_InlineStrcpyVersion(char *s) { >> + char *p = malloc(12); >> + p = ((__builtin_object_size (p, 0) != (size_t) -1) ? __builtin___strcpy_chk (p, s, __builtin_object_size (p, 2 > 1)) : __inline_strcpy_chk (p, s)); >> + free(p); >> +} >> // Below are the known false positives. >> >> // TODO: There should be no warning here. This one might be difficult to get rid of. >> @@ -627,13 +647,6 @@ >> return p;// expected-warning {{Memory is never released; potential memory leak}} >> } >> >> -// TODO: This is a false positve that should be fixed by making CString checker smarter. >> -void symbolLostWithStrcpy(char *s) { >> - char *p = malloc(12); >> - p = strcpy(p, s); >> - free(p);// expected-warning {{leak}} >> -} >> - >> // False negatives. >> >> // TODO: This requires tracking symbols stored inside the structs/arrays. >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > From sebastian.redl at getdesigned.at Wed Feb 22 09:37:52 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Wed, 22 Feb 2012 17:37:52 -0000 Subject: [cfe-commits] r151171 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/new-array-init.cpp Message-ID: <20120222173753.0F64E2A6C12F@llvm.org> Author: cornedbee Date: Wed Feb 22 11:37:52 2012 New Revision: 151171 URL: http://llvm.org/viewvc/llvm-project?rev=151171&view=rev Log: CodeGen for array new list initializers. Doesn't correctly clean up in the face of exceptions yet. Added: cfe/trunk/test/CodeGenCXX/new-array-init.cpp Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=151171&r1=151170&r2=151171&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Feb 22 11:37:52 2012 @@ -508,6 +508,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, const CXXNewExpr *e, + unsigned minElements, llvm::Value *&numElements, llvm::Value *&sizeWithoutCookie) { QualType type = e->getAllocatedType(); @@ -581,6 +582,11 @@ // Okay, compute a count at the right width. llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth); + // If there is a brace-initializer, we cannot allocate fewer elements than + // there are initializers. If we do, that's treated like an overflow. + if (adjustedCount.ult(minElements)) + hasAnyOverflow = true; + // Scale numElements by that. This might overflow, but we don't // care because it only overflows if allocationSize does, too, and // if that overflows then we shouldn't use this. @@ -612,14 +618,16 @@ // Otherwise, we might need to use the overflow intrinsics. } else { - // There are up to four conditions we need to test for: + // There are up to five conditions we need to test for: // 1) if isSigned, we need to check whether numElements is negative; // 2) if numElementsWidth > sizeWidth, we need to check whether // numElements is larger than something representable in size_t; - // 3) we need to compute + // 3) if minElements > 0, we need to check whether numElements is smaller + // than that. + // 4) we need to compute // sizeWithoutCookie := numElements * typeSizeMultiplier // and check whether it overflows; and - // 4) if we need a cookie, we need to compute + // 5) if we need a cookie, we need to compute // size := sizeWithoutCookie + cookieSize // and check whether it overflows. @@ -646,10 +654,11 @@ // If there's a non-1 type size multiplier, then we can do the // signedness check at the same time as we do the multiply // because a negative number times anything will cause an - // unsigned overflow. Otherwise, we have to do it here. + // unsigned overflow. Otherwise, we have to do it here. But at least + // in this case, we can subsume the >= minElements check. if (typeSizeMultiplier == 1) hasOverflow = CGF.Builder.CreateICmpSLT(numElements, - llvm::ConstantInt::get(CGF.SizeTy, 0)); + llvm::ConstantInt::get(CGF.SizeTy, minElements)); // Otherwise, zext up to size_t if necessary. } else if (numElementsWidth < sizeWidth) { @@ -658,6 +667,21 @@ assert(numElements->getType() == CGF.SizeTy); + if (minElements) { + // Don't allow allocation of fewer elements than we have initializers. + if (!hasOverflow) { + hasOverflow = CGF.Builder.CreateICmpULT(numElements, + llvm::ConstantInt::get(CGF.SizeTy, minElements)); + } else if (numElementsWidth > sizeWidth) { + // The other existing overflow subsumes this check. + // We do an unsigned comparison, since any signed value < -1 is + // taken care of either above or below. + hasOverflow = CGF.Builder.CreateOr(hasOverflow, + CGF.Builder.CreateICmpULT(numElements, + llvm::ConstantInt::get(CGF.SizeTy, minElements))); + } + } + size = numElements; // Multiply by the type size if necessary. This multiplier @@ -741,11 +765,8 @@ return size; } -static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E, - llvm::Value *NewPtr) { - - const Expr *Init = E->getInitializer(); - QualType AllocType = E->getAllocatedType(); +static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init, + QualType AllocType, llvm::Value *NewPtr) { CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType); if (!CGF.hasAggregateLLVMType(AllocType)) @@ -775,26 +796,39 @@ if (!E->hasInitializer()) return; // We have a POD type. - // Check if the number of elements is constant. - bool checkZero = true; - if (llvm::ConstantInt *constNum = dyn_cast(numElements)) { - // If it's constant zero, skip the whole loop. - if (constNum->isZero()) return; - - checkZero = false; - } - + llvm::Value *explicitPtr = beginPtr; // Find the end of the array, hoisted out of the loop. llvm::Value *endPtr = Builder.CreateInBoundsGEP(beginPtr, numElements, "array.end"); + unsigned initializerElements = 0; + + const Expr *Init = E->getInitializer(); + // If the initializer is an initializer list, first do the explicit elements. + if (const InitListExpr *ILE = dyn_cast(Init)) { + initializerElements = ILE->getNumInits(); + QualType elementType = E->getAllocatedType(); + // FIXME: exception-safety for the explicit initializers + for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) { + StoreAnyExprIntoOneUnit(*this, ILE->getInit(i), elementType, explicitPtr); + explicitPtr =Builder.CreateConstGEP1_32(explicitPtr, 1, "array.exp.next"); + } + + // The remaining elements are filled with the array filler expression. + Init = ILE->getArrayFiller(); + } + // Create the continuation block. llvm::BasicBlock *contBB = createBasicBlock("new.loop.end"); - // If we need to check for zero, do so now. - if (checkZero) { + // If the number of elements isn't constant, we have to now check if there is + // anything left to initialize. + if (llvm::ConstantInt *constNum = dyn_cast(numElements)) { + // If all elements have already been initialized, skip the whole loop. + if (constNum->getZExtValue() <= initializerElements) return; + } else { llvm::BasicBlock *nonEmptyBB = createBasicBlock("new.loop.nonempty"); - llvm::Value *isEmpty = Builder.CreateICmpEQ(beginPtr, endPtr, + llvm::Value *isEmpty = Builder.CreateICmpEQ(explicitPtr, endPtr, "array.isempty"); Builder.CreateCondBr(isEmpty, contBB, nonEmptyBB); EmitBlock(nonEmptyBB); @@ -808,8 +842,8 @@ // Set up the current-element phi. llvm::PHINode *curPtr = - Builder.CreatePHI(beginPtr->getType(), 2, "array.cur"); - curPtr->addIncoming(beginPtr, entryBB); + Builder.CreatePHI(explicitPtr->getType(), 2, "array.cur"); + curPtr->addIncoming(explicitPtr, entryBB); // Enter a partial-destruction cleanup if necessary. QualType::DestructionKind dtorKind = elementType.isDestructedType(); @@ -823,7 +857,7 @@ } // Emit the initializer into this element. - StoreAnyExprIntoOneUnit(*this, E, curPtr); + StoreAnyExprIntoOneUnit(*this, Init, E->getAllocatedType(), curPtr); // Leave the cleanup if we entered one. if (cleanupDominator) { @@ -895,7 +929,7 @@ if (!Init) return; - StoreAnyExprIntoOneUnit(CGF, E, NewPtr); + StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr); } namespace { @@ -1069,10 +1103,18 @@ // The allocation size is the first argument. QualType sizeType = getContext().getSizeType(); + // If there is a brace-initializer, cannot allocate fewer elements than inits. + unsigned minElements = 0; + if (E->isArray() && E->hasInitializer()) { + if (const InitListExpr *ILE = dyn_cast(E->getInitializer())) + minElements = ILE->getNumInits(); + } + llvm::Value *numElements = 0; llvm::Value *allocSizeWithoutCookie = 0; llvm::Value *allocSize = - EmitCXXNewAllocSize(*this, E, numElements, allocSizeWithoutCookie); + EmitCXXNewAllocSize(*this, E, minElements, numElements, + allocSizeWithoutCookie); allocatorArgs.add(RValue::get(allocSize), sizeType); Added: cfe/trunk/test/CodeGenCXX/new-array-init.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new-array-init.cpp?rev=151171&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/new-array-init.cpp (added) +++ cfe/trunk/test/CodeGenCXX/new-array-init.cpp Wed Feb 22 11:37:52 2012 @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s + +// CHECK: define void @_Z2fni +void fn(int n) { + // CHECK: icmp ult i{{32|64}} %{{[^ ]+}}, 3 + // CHECK: store i32 1 + // CHECK: store i32 2 + // CHECK: store i32 3 + // CHECK: icmp eq i32* + // CHECK-NEXT: br i1 + new int[n] { 1, 2, 3 }; +} + +// CHECK: define void @_Z15const_underflowv +void const_underflow() { + // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3 + // CHECK: call noalias i8* @_Zna{{.}}(i{{32|64}} -1) + new int[2] { 1, 2, 3 }; +} + +// CHECK: define void @_Z11const_exactv +void const_exact() { + // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3 + // CHECK-NOT: icmp eq i32* + new int[3] { 1, 2, 3 }; +} + +// CHECK: define void @_Z16const_sufficientv +void const_sufficient() { + // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3 + new int[4] { 1, 2, 3 }; + // CHECK: ret void +} From sebastian.redl at getdesigned.at Wed Feb 22 09:38:04 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Wed, 22 Feb 2012 17:38:04 -0000 Subject: [cfe-commits] r151173 - in /cfe/trunk: lib/Sema/SemaStmt.cpp test/SemaCXX/cxx0x-return-init-list.cpp Message-ID: <20120222173804.BE4782A6C12F@llvm.org> Author: cornedbee Date: Wed Feb 22 11:38:04 2012 New Revision: 151173 URL: http://llvm.org/viewvc/llvm-project?rev=151173&view=rev Log: Doug's review comments. Modified: cfe/trunk/lib/Sema/SemaStmt.cpp cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=151173&r1=151172&r2=151173&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Feb 22 11:38:04 2012 @@ -1878,7 +1878,7 @@ // Delay processing for now. TODO: there are lots of dependent // types we can conclusively prove aren't void. } else if (FnRetType->isVoidType()) { - if (RetValExp && + if (RetValExp && !isa(RetValExp) && !(getLangOptions().CPlusPlus && (RetValExp->isTypeDependent() || RetValExp->getType()->isVoidType()))) { Modified: cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp?rev=151173&r1=151172&r2=151173&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp Wed Feb 22 11:38:04 2012 @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // Test that a very basic variation of generalized initializer returns (that -// required for libstdc++ 4.5) is supposed in C++98. +// required for libstdc++ 4.5) is supported in C++98. int test0(int i) { return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}} From sebastian.redl at getdesigned.at Wed Feb 22 09:37:59 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Wed, 22 Feb 2012 17:37:59 -0000 Subject: [cfe-commits] r151172 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/new-array-init-exceptions.cpp Message-ID: <20120222173759.8CE752A6C130@llvm.org> Author: cornedbee Date: Wed Feb 22 11:37:59 2012 New Revision: 151172 URL: http://llvm.org/viewvc/llvm-project?rev=151172&view=rev Log: Unwind path cleanup for array new list initializers. Added: cfe/trunk/test/CodeGenCXX/new-array-init-exceptions.cpp Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=151172&r1=151171&r2=151172&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Feb 22 11:37:59 2012 @@ -804,12 +804,32 @@ unsigned initializerElements = 0; const Expr *Init = E->getInitializer(); + llvm::AllocaInst *endOfInit = 0; + QualType::DestructionKind dtorKind = elementType.isDestructedType(); + EHScopeStack::stable_iterator cleanup; + llvm::Instruction *cleanupDominator = 0; // If the initializer is an initializer list, first do the explicit elements. if (const InitListExpr *ILE = dyn_cast(Init)) { initializerElements = ILE->getNumInits(); - QualType elementType = E->getAllocatedType(); - // FIXME: exception-safety for the explicit initializers + + // Enter a partial-destruction cleanup if necessary. + if (needsEHCleanup(dtorKind)) { + // In principle we could tell the cleanup where we are more + // directly, but the control flow can get so varied here that it + // would actually be quite complex. Therefore we go through an + // alloca. + endOfInit = CreateTempAlloca(beginPtr->getType(), "array.endOfInit"); + cleanupDominator = Builder.CreateStore(beginPtr, endOfInit); + pushIrregularPartialArrayCleanup(beginPtr, endOfInit, elementType, + getDestroyer(dtorKind)); + cleanup = EHStack.stable_begin(); + } + for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) { + // Tell the cleanup that it needs to destroy up to this + // element. TODO: some of these stores can be trivially + // observed to be unnecessary. + if (endOfInit) Builder.CreateStore(explicitPtr, endOfInit); StoreAnyExprIntoOneUnit(*this, ILE->getInit(i), elementType, explicitPtr); explicitPtr =Builder.CreateConstGEP1_32(explicitPtr, 1, "array.exp.next"); } @@ -825,7 +845,12 @@ // anything left to initialize. if (llvm::ConstantInt *constNum = dyn_cast(numElements)) { // If all elements have already been initialized, skip the whole loop. - if (constNum->getZExtValue() <= initializerElements) return; + if (constNum->getZExtValue() <= initializerElements) { + // If there was a cleanup, deactivate it. + if (cleanupDominator) + DeactivateCleanupBlock(cleanup, cleanupDominator);; + return; + } } else { llvm::BasicBlock *nonEmptyBB = createBasicBlock("new.loop.nonempty"); llvm::Value *isEmpty = Builder.CreateICmpEQ(explicitPtr, endPtr, @@ -845,11 +870,11 @@ Builder.CreatePHI(explicitPtr->getType(), 2, "array.cur"); curPtr->addIncoming(explicitPtr, entryBB); + // Store the new cleanup position for irregular cleanups. + if (endOfInit) Builder.CreateStore(curPtr, endOfInit); + // Enter a partial-destruction cleanup if necessary. - QualType::DestructionKind dtorKind = elementType.isDestructedType(); - EHScopeStack::stable_iterator cleanup; - llvm::Instruction *cleanupDominator = 0; - if (needsEHCleanup(dtorKind)) { + if (!cleanupDominator && needsEHCleanup(dtorKind)) { pushRegularPartialArrayCleanup(beginPtr, curPtr, elementType, getDestroyer(dtorKind)); cleanup = EHStack.stable_begin(); Added: cfe/trunk/test/CodeGenCXX/new-array-init-exceptions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new-array-init-exceptions.cpp?rev=151172&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/new-array-init-exceptions.cpp (added) +++ cfe/trunk/test/CodeGenCXX/new-array-init-exceptions.cpp Wed Feb 22 11:37:59 2012 @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown -fexceptions -fcxx-exceptions %s -emit-llvm -o - | FileCheck %s + +struct Throws { + Throws(int); + Throws(); + ~Throws(); +}; + +// CHECK: define void @_Z7cleanupi +void cleanup(int n) { + // CHECK: invoke void @_ZN6ThrowsC1Ei + // CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD:[^ ]+]] + // CHECK: invoke void @_ZN6ThrowsC1Ei + // CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD]] + // CHECK: invoke void @_ZN6ThrowsC1Ei + // CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD]] + // CHECK: invoke void @_ZN6ThrowsC1Ev + // CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD]] + new Throws[n] { 1, 2, 3 }; + // CHECK: [[LPAD]]: + // CHECK-NEXT: landingpad + // CHECK: call void @_ZN6ThrowsD1Ev + // CHECK: call void @_ZdaPv +} + + +// CHECK: define void @_Z7cleanupv +void cleanup() { + // CHECK: invoke void @_ZN6ThrowsC1Ei + // CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD2:[^ ]+]] + // CHECK: invoke void @_ZN6ThrowsC1Ei + // CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD2]] + // CHECK: invoke void @_ZN6ThrowsC1Ei + // CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD2]] + new Throws[3] { 1, 2, 3 }; + // CHECK: [[LPAD2]]: + // CHECK-NEXT: landingpad + // CHECK: call void @_ZN6ThrowsD1Ev + // CHECK: call void @_ZdaPv +} From kremenek at apple.com Wed Feb 22 09:58:46 2012 From: kremenek at apple.com (Ted Kremenek) Date: Wed, 22 Feb 2012 09:58:46 -0800 Subject: [cfe-commits] r150846 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/CStringChecker.cpp lib/StaticAnalyzer/Checkers/InterCheckerAPI.h lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c In-Reply-To: <9BE10BE8-461B-4EAF-9751-8F4ED3CBEEDD@apple.com> References: <20120217223531.EFA962A6C12F@llvm.org> <7D103CC0-FA0C-4CF7-9EF3-F3D8E7E6A268@belkadan.com> <9BE10BE8-461B-4EAF-9751-8F4ED3CBEEDD@apple.com> Message-ID: <457F74FA-EED7-4CAA-8F33-4C45A5E6CC98@apple.com> On Feb 22, 2012, at 9:36 AM, Anna Zaks wrote: >> (I see that someone on Radar thought the answer was "yes", but...) >> >> Also, separately...is this the way we're going to do inter-checker dependencies? I like how simple it is! And since all the checker registration is done with vectors, it even handles ordering. > > I don't think this handles ordering.. The ordering still depends on the order in which the checkers are defined in the Checker.td file. That's something which needs to be fixed. > >> But I don't know how it will scale, and it does sort of compel us to expose a registration function for /every/ checker. (Just like warning flags, if we decide it's okay not to have a registration function for some checker, we'll end up in a situation where we need it.) >> > > We do not have the dependency mechanism set in stone. We can revisit this later on. I view this approach as something that we can use to define dependencies in special cases. Currently, this is the only dependency we have, though it might quickly change.. Jordy, To add what Anna said, this solution is what we can work with, and it allows us to explore the kind of behavioral dependencies we would want between checkers. Doing it this way has serious limitations; for example, if one explicitly disables a checker from the command line, how does it interplay with such dependencies? What we have is progress towards figuring out what kind of behavioral patterns we need to support as part of expressing checker dependencies, and what that means for the end user. Ted -------------- next part -------------- An HTML attachment was scrubbed... URL: From mcrosier at apple.com Wed Feb 22 09:55:22 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 22 Feb 2012 17:55:22 -0000 Subject: [cfe-commits] r151174 - in /cfe/trunk: include/clang/Basic/DiagnosticDriverKinds.td lib/Driver/Driver.cpp Message-ID: <20120222175522.60AB92A6C12F@llvm.org> Author: mcrosier Date: Wed Feb 22 11:55:22 2012 New Revision: 151174 URL: http://llvm.org/viewvc/llvm-project?rev=151174&view=rev Log: [driver] Add a warning for when -mcpu= is specified without an argument. There are likely many other OPT_xxxx_EQ options that could/should be added here. rdar://10704648 Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td cfe/trunk/lib/Driver/Driver.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=151174&r1=151173&r2=151174&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Wed Feb 22 11:55:22 2012 @@ -105,6 +105,8 @@ def warn_drv_unused_argument : Warning< "argument unused during compilation: '%0'">, InGroup>; +def warn_drv_empty_joined_argument : Warning< + "joined argument expects addition arg: '%0'">; def warn_drv_not_using_clang_cpp : Warning< "not using the clang preprocessor due to user override">; def warn_drv_not_using_clang_cxx : Warning< Modified: cfe/trunk/lib/Driver/Driver.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=151174&r1=151173&r2=151174&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Driver.cpp (original) +++ cfe/trunk/lib/Driver/Driver.cpp Wed Feb 22 11:55:22 2012 @@ -113,6 +113,12 @@ Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; } + + // Warn about -mcpu= without an argument. + if (A->getOption().matches(options::OPT_mcpu_EQ) && + A->containsValue("")) { + Diag(clang::diag::warn_drv_empty_joined_argument) << A->getAsString(*Args); + } } return Args; From thakis at chromium.org Wed Feb 22 10:15:58 2012 From: thakis at chromium.org (Nico Weber) Date: Wed, 22 Feb 2012 10:15:58 -0800 Subject: [cfe-commits] [patch][pr12001] Avoid increasing visibility in some cases In-Reply-To: References: <4F41B060.9020500@gmail.com> <4F41B9E8.4020407@gmail.com> Message-ID: Doh, I think I found an issue with this patch :-/ I'm building a reduced test case now, I'll post it here in a few hours. Nico On Tue, Feb 21, 2012 at 5:57 PM, Eric Christopher wrote: > > On Feb 19, 2012, at 7:11 PM, Rafael Ávila de Espíndola wrote: > >> Nico noticed that the patch included an infinite loop from when I >> renamed merge2 to mergeWithMin. >> >> An updated patch is attached. > > I think this is ok. Some more comments on the visibility that should be happening in the various testcases and where you use mergeWithMin would be helpful next time I need to review something through there. > > -eric From fjahanian at apple.com Wed Feb 22 10:13:25 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Wed, 22 Feb 2012 18:13:25 -0000 Subject: [cfe-commits] r151176 - in /cfe/trunk: lib/Rewrite/RewriteModernObjC.cpp test/Rewriter/rewrite-modern-class.mm test/Rewriter/rewrite-nested-ivar.mm Message-ID: <20120222181325.C2AF02A6C12F@llvm.org> Author: fjahanian Date: Wed Feb 22 12:13:25 2012 New Revision: 151176 URL: http://llvm.org/viewvc/llvm-project?rev=151176&view=rev Log: modern objc translator. more writing of modern ivar access abi. Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp cfe/trunk/test/Rewriter/rewrite-modern-class.mm cfe/trunk/test/Rewriter/rewrite-nested-ivar.mm Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp?rev=151176&r1=151175&r2=151176&view=diff ============================================================================== --- cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp (original) +++ cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Wed Feb 22 12:13:25 2012 @@ -133,7 +133,9 @@ llvm::SmallPtrSet ImportedLocalExternalDecls; llvm::DenseMap RewrittenBlockExprs; - + llvm::DenseMap > ReferencedIvars; + // This maps an original source AST to it's rewritten form. This allows // us to avoid rewriting the same node twice (which is very uncommon). // This is needed to support some of the exotic property rewriting. @@ -331,6 +333,9 @@ void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, std::string &Result); + void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, + std::string &Result); + virtual void Initialize(ASTContext &context); // Misc. AST transformation routines. Somtimes they end up calling @@ -1231,6 +1236,9 @@ ResultStr += "typedef struct objc_object "; ResultStr += ClassDecl->getNameAsString(); ResultStr += ";\n#endif\n"; + + RewriteIvarOffsetSymbols(ClassDecl, ResultStr); + RewriteObjCInternalStruct(ClassDecl, ResultStr); // Mark this typedef as having been written into its c++ equivalent. ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl()); @@ -3221,6 +3229,24 @@ llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct"); } +/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which +/// have been referenced in an ivar access expression. +void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, + std::string &Result) { + // write out ivar offset symbols which have been referenced in an ivar + // access expression. + llvm::SmallPtrSet Ivars = ReferencedIvars[CDecl]; + if (Ivars.empty()) + return; + for (llvm::SmallPtrSet::iterator i = Ivars.begin(), + e = Ivars.end(); i != e; i++) { + ObjCIvarDecl *IvarDecl = (*i); + Result += "\nextern unsigned long OBJC_IVAR_$_"; + Result += CDecl->getName(); Result += "_"; + Result += IvarDecl->getName(); Result += ";"; + } +} + //===----------------------------------------------------------------------===// // Meta Data Emission //===----------------------------------------------------------------------===// @@ -5020,7 +5046,7 @@ // private ivars. RewriteInterfaceDecl(CDecl); } - + if (ClassImplementation.size() || CategoryImplementation.size()) RewriteImplementations(); @@ -6423,6 +6449,8 @@ IvarOffsetName += clsDeclared->getIdentifier()->getName(); IvarOffsetName += "_"; IvarOffsetName += D->getName(); + ReferencedIvars[clsDeclared].insert(D); + // cast offset to "char *". CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(Context->CharTy), Modified: cfe/trunk/test/Rewriter/rewrite-modern-class.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-class.mm?rev=151176&r1=151175&r2=151176&view=diff ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-class.mm (original) +++ cfe/trunk/test/Rewriter/rewrite-modern-class.mm Wed Feb 22 12:13:25 2012 @@ -56,8 +56,7 @@ @implementation INTF - (SUPER *) Meth : (SUPER *)arg { -// NYI - return arg->p_super; - return (SUPER *)0; + return arg->p_super; } @end Modified: cfe/trunk/test/Rewriter/rewrite-nested-ivar.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-nested-ivar.mm?rev=151176&r1=151175&r2=151176&view=diff ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-nested-ivar.mm (original) +++ cfe/trunk/test/Rewriter/rewrite-nested-ivar.mm Wed Feb 22 12:13:25 2012 @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-fragile-abi %s -o %t-rw.cpp // RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw-modern.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw-modern.cpp // radar 7583971 From delesley at google.com Wed Feb 22 10:21:11 2012 From: delesley at google.com (Delesley Hutchins) Date: Wed, 22 Feb 2012 10:21:11 -0800 Subject: [cfe-commits] [PATCH] Bugfix: bogus error message "invalid use of non-static data member" Message-ID: This fixes a bug where clang erroneously reports "invalid use of non-static data member" if a class is forward declared, and the reference to data member in question occurs outside of a member function (e.g. in an attribute). See patch for example. Patch: http://codereview.appspot.com/5684064/ -- DeLesley Hutchins | Software Engineer | delesley at google.com | 505-206-0315 -------------- next part -------------- A non-text attachment was scrubbed... Name: clang-invalid-nonstatic.patch Type: text/x-patch Size: 1265 bytes Desc: not available URL: From mcrosier at apple.com Wed Feb 22 10:18:48 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 22 Feb 2012 18:18:48 -0000 Subject: [cfe-commits] r151177 - /cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Message-ID: <20120222181848.C1FB62A6C12F@llvm.org> Author: mcrosier Date: Wed Feb 22 12:18:48 2012 New Revision: 151177 URL: http://llvm.org/viewvc/llvm-project?rev=151177&view=rev Log: Add new driver warning from r151174 to a warning group. Please let me know if this isn't the appropriate grouping. Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=151177&r1=151176&r2=151177&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Wed Feb 22 12:18:48 2012 @@ -106,7 +106,8 @@ "argument unused during compilation: '%0'">, InGroup>; def warn_drv_empty_joined_argument : Warning< - "joined argument expects addition arg: '%0'">; + "joined argument expects addition arg: '%0'">, + InGroup>; def warn_drv_not_using_clang_cpp : Warning< "not using the clang preprocessor due to user override">; def warn_drv_not_using_clang_cxx : Warning< From echristo at apple.com Wed Feb 22 10:26:43 2012 From: echristo at apple.com (Eric Christopher) Date: Wed, 22 Feb 2012 10:26:43 -0800 Subject: [cfe-commits] [patch][pr12001] Avoid increasing visibility in some cases In-Reply-To: References: <4F41B060.9020500@gmail.com> <4F41B9E8.4020407@gmail.com> Message-ID: <5CBC5288-6B29-4050-A830-C12D7EE299BD@apple.com> Yeah, this is why I wanted the comments :) -eric On Feb 22, 2012, at 10:15 AM, Nico Weber wrote: > Doh, I think I found an issue with this patch :-/ I'm building a > reduced test case now, I'll post it here in a few hours. > > Nico > > On Tue, Feb 21, 2012 at 5:57 PM, Eric Christopher wrote: >> >> On Feb 19, 2012, at 7:11 PM, Rafael Ávila de Espíndola wrote: >> >>> Nico noticed that the patch included an infinite loop from when I >>> renamed merge2 to mergeWithMin. >>> >>> An updated patch is attached. >> >> I think this is ok. Some more comments on the visibility that should be happening in the various testcases and where you use mergeWithMin would be helpful next time I need to review something through there. >> >> -eric From kremenek at apple.com Wed Feb 22 10:44:35 2012 From: kremenek at apple.com (Ted Kremenek) Date: Wed, 22 Feb 2012 18:44:35 -0000 Subject: [cfe-commits] r151179 - /cfe/trunk/tools/scan-build/set-xcode-analyzer Message-ID: <20120222184435.794132A6C12F@llvm.org> Author: kremenek Date: Wed Feb 22 12:44:35 2012 New Revision: 151179 URL: http://llvm.org/viewvc/llvm-project?rev=151179&view=rev Log: Update set-xcode-analyzer to work with Xcode repackaging in Xcode 4.3 Modified: cfe/trunk/tools/scan-build/set-xcode-analyzer Modified: cfe/trunk/tools/scan-build/set-xcode-analyzer URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/set-xcode-analyzer?rev=151179&r1=151178&r2=151179&view=diff ============================================================================== --- cfe/trunk/tools/scan-build/set-xcode-analyzer (original) +++ cfe/trunk/tools/scan-build/set-xcode-analyzer Wed Feb 22 12:44:35 2012 @@ -5,6 +5,7 @@ # This one has the scripting bridge enabled. import os +import subprocess import sys import re import tempfile @@ -13,6 +14,7 @@ from AppKit import * def FindClangSpecs(path): + print "(+) Searching for xcspec file in: ", path for root, dirs, files in os.walk(path): for f in files: if f.endswith(".xcspec") and f.startswith("Clang LLVM"): @@ -73,7 +75,13 @@ print "(+) Using the Clang bundled with Xcode" path = options.default - for x in FindClangSpecs('/Developer'): + xcode_path = subprocess.check_output(["xcode-select", "-print-path"]) + if (re.search("Xcode.app", xcode_path)): + # Cut off the 'Developer' dir, as the xcspec lies in another part + # of the Xcode.app subtree. + xcode_path = os.path.dirname(xcode_path) + + for x in FindClangSpecs(xcode_path): ModifySpec(x, path) if __name__ == '__main__': From mcrosier at apple.com Wed Feb 22 11:14:46 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 22 Feb 2012 19:14:46 -0000 Subject: [cfe-commits] r151184 - /cfe/trunk/docs/UsersManual.html Message-ID: <20120222191446.9EFCD2A6C12F@llvm.org> Author: mcrosier Date: Wed Feb 22 13:14:46 2012 New Revision: 151184 URL: http://llvm.org/viewvc/llvm-project?rev=151184&view=rev Log: Add clang crash diagnostic info and associated flags to Clang user manual. Modified: cfe/trunk/docs/UsersManual.html Modified: cfe/trunk/docs/UsersManual.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.html?rev=151184&r1=151183&r2=151184&view=diff ============================================================================== --- cfe/trunk/docs/UsersManual.html (original) +++ cfe/trunk/docs/UsersManual.html Wed Feb 22 13:14:46 2012 @@ -30,6 +30,8 @@

  • Language and Target-Independent Features @@ -196,6 +198,26 @@

    -ftemplate-backtrace-limit=123: Only emit up to 123 template instantiation notes within the template instantiation backtrace for a single warning or error. The default is 10, and the limit can be disabled with -ftemplate-backtrace-limit=0.

    + +

    Options to Control Clang Crash Diagnostics

    + + +

    As unbelievable as it may sound, Clang does crash from time to time. +Generally, this only occurs to those living on the +bleeding edge. Clang +goes to great lengths to assist you in filing a bug report. Specifically, Clang +generates preprocessed source file(s) and associated run script(s) upon a +crash. These files should be attached to a bug report to ease reproducibility +of the failure. Below are the command line options to control the crash +diagnostics. +

    + +

    -fno-crash-diagnostics: Disable auto-generation of preprocessed +source files during a clang crash.

    + +

    The -fno-crash-diagnostics flag can be helpful for speeding the process of +generating a delta reduced test case.

    +

    Formatting of Diagnostics

    From joerg at bec.de Wed Feb 22 11:15:16 2012 From: joerg at bec.de (Joerg Sonnenberger) Date: Wed, 22 Feb 2012 19:15:16 -0000 Subject: [cfe-commits] r151185 - in /cfe/trunk: lib/Driver/Driver.cpp test/Driver/Inputs/prefixed_tools_tree/ test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-as test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-ld test/Driver/prefixed-tools.c Message-ID: <20120222191516.BF5202A6C12F@llvm.org> Author: joerg Date: Wed Feb 22 13:15:16 2012 New Revision: 151185 URL: http://llvm.org/viewvc/llvm-project?rev=151185&view=rev Log: Revert part of r148839 and keep DefaultTargetTriple in the form adjusted by -target and similar options. As discussed in PR 12026, the change broke support for target-prefixed tools, i.e. calling x86_64--linux-ld when compiling for x86_64--linux. Improve the test cases added originally in r149083 to not require execution, just executable files. Document the hack with appropiate FIXME comments. Added: cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/ cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-as (with props) cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-ld (with props) cfe/trunk/test/Driver/prefixed-tools.c Modified: cfe/trunk/lib/Driver/Driver.cpp Modified: cfe/trunk/lib/Driver/Driver.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=151185&r1=151184&r2=151185&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Driver.cpp (original) +++ cfe/trunk/lib/Driver/Driver.cpp Wed Feb 22 13:15:16 2012 @@ -310,6 +310,10 @@ Cur = Split.second; } } + // FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld + // and getToolChain is const. + if (const Arg *A = Args->getLastArg(options::OPT_target)) + DefaultTargetTriple = A->getValue(*Args); if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir)) Dir = InstalledDir = A->getValue(*Args); for (arg_iterator it = Args->filtered_begin(options::OPT_B), @@ -1513,6 +1517,7 @@ std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC, bool WantFile) const { + // FIXME: Needs a better variable than DefaultTargetTriple std::string TargetSpecificExecutable(DefaultTargetTriple + "-" + Name); // Respect a limited subset of the '-Bprefix' functionality in GCC by // attempting to use this prefix when lokup up program paths. @@ -1583,6 +1588,7 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, const ArgList &Args, StringRef DarwinArchName) { + // FIXME: Already done in Compilation *Driver::BuildCompilation if (const Arg *A = Args.getLastArg(options::OPT_target)) DefaultTargetTriple = A->getValue(Args); Added: cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-as URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-as?rev=151185&view=auto ============================================================================== --- cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-as (added) +++ cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-as Wed Feb 22 13:15:16 2012 @@ -0,0 +1,2 @@ +#!/bin/sh +# This file must be executable to be picked up by GetProgramPath Propchange: cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-as ------------------------------------------------------------------------------ svn:executable = * Added: cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-ld URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-ld?rev=151185&view=auto ============================================================================== --- cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-ld (added) +++ cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-ld Wed Feb 22 13:15:16 2012 @@ -0,0 +1,2 @@ +#!/bin/sh +# This file must be executable to be picked up by GetProgramPath Propchange: cfe/trunk/test/Driver/Inputs/prefixed_tools_tree/x86_64--linux-ld ------------------------------------------------------------------------------ svn:executable = * Added: cfe/trunk/test/Driver/prefixed-tools.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/prefixed-tools.c?rev=151185&view=auto ============================================================================== --- cfe/trunk/test/Driver/prefixed-tools.c (added) +++ cfe/trunk/test/Driver/prefixed-tools.c Wed Feb 22 13:15:16 2012 @@ -0,0 +1,12 @@ +// RUN: %clang -### -B%S/Inputs/prefixed_tools_tree -o %t.o -no-integrated-as \ +// RUN: -target x86_64--linux %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-M64 %s + +// RUN: %clang -### -B%S/Inputs/prefixed_tools_tree -o %t.o -no-integrated-as \ +// RUN: -m32 -target x86_64--linux %s 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-M32 %s + +// CHECK-M64: "{{.*}}{{[/\\]}}prefixed_tools_tree{{[/\\]}}x86_64--linux-as" +// CHECK-M64: "{{.*}}{{[/\\]}}prefixed_tools_tree{{[/\\]}}x86_64--linux-ld" +// CHECK-M32: "{{.*}}{{[/\\]}}prefixed_tools_tree{{[/\\]}}x86_64--linux-as" +// CHECK-M32: "{{.*}}{{[/\\]}}prefixed_tools_tree{{[/\\]}}x86_64--linux-ld" From mcrosier at apple.com Wed Feb 22 11:22:42 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 22 Feb 2012 11:22:42 -0800 Subject: [cfe-commits] r151109 - in /cfe/trunk: include/clang/Driver/Options.td lib/Driver/Driver.cpp In-Reply-To: <9AC1F911-8484-444E-B862-1F293EAF8EE5@apple.com> References: <20120222003039.C2FCD2A6C12F@llvm.org> <9AC1F911-8484-444E-B862-1F293EAF8EE5@apple.com> Message-ID: On Feb 21, 2012, at 8:08 PM, Chris Lattner wrote: > > On Feb 21, 2012, at 4:30 PM, Chad Rosier wrote: > >> Author: mcrosier >> Date: Tue Feb 21 18:30:39 2012 >> New Revision: 151109 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=151109&view=rev >> Log: >> Provide a way to disable auto-generation of preprocessed files during clang >> crash. This can speedup the process of generating a delta reduced test case. >> rdar://10905465 > > Hi Chad, > > Please document this in the Clang user's manual. Done so in r151184. Chad > -Chris > >> >> Modified: >> cfe/trunk/include/clang/Driver/Options.td >> cfe/trunk/lib/Driver/Driver.cpp >> >> Modified: cfe/trunk/include/clang/Driver/Options.td >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=151109&r1=151108&r2=151109&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/Driver/Options.td (original) >> +++ cfe/trunk/include/clang/Driver/Options.td Tue Feb 21 18:30:39 2012 >> @@ -292,6 +292,7 @@ >> def fconstexpr_depth_EQ : Joined<"-fconstexpr-depth=">, Group; >> def fconstexpr_backtrace_limit_EQ : Joined<"-fconstexpr-backtrace-limit=">, >> Group; >> +def fno_crash_diagnostics : Flag<"-fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>; >> def fcreate_profile : Flag<"-fcreate-profile">, Group; >> def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group; >> def fcxx_modules : Flag <"-fcxx-modules">, Group, Flags<[NoForward]>; >> >> Modified: cfe/trunk/lib/Driver/Driver.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=151109&r1=151108&r2=151109&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Driver/Driver.cpp (original) >> +++ cfe/trunk/lib/Driver/Driver.cpp Tue Feb 21 18:30:39 2012 >> @@ -363,6 +363,9 @@ >> // diagnostic information to a bug report. >> void Driver::generateCompilationDiagnostics(Compilation &C, >> const Command *FailingCommand) { >> + if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) >> + return; >> + >> Diag(clang::diag::note_drv_command_failed_diag_msg) >> << "Please submit a bug report to " BUG_REPORT_URL " and include command" >> " line arguments and all diagnostic information."; >> >> >> _______________________________________________ >> 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 Feb 22 11:24:52 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 22 Feb 2012 19:24:52 -0000 Subject: [cfe-commits] r151188 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c Message-ID: <20120222192452.C9C992A6C12F@llvm.org> Author: zaks Date: Wed Feb 22 13:24:52 2012 New Revision: 151188 URL: http://llvm.org/viewvc/llvm-project?rev=151188&view=rev Log: [analyzer] Malloc cleanup: - We should not evaluate strdup in the Malloc Checker, it's the job of CString checker, so just update the RefState to reflect allocated memory. - Refactor to reduce LOC: remove some wrapper auxiliary functions, make all functions return the state and add the transition in one place (instead of in each auxiliary function). Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/test/Analysis/malloc.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=151188&r1=151187&r2=151188&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Feb 22 13:24:52 2012 @@ -144,10 +144,9 @@ /// pointed to by one of its arguments. bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const; - static void MallocMem(CheckerContext &C, const CallExpr *CE, - unsigned SizeIdx); - static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att); + static ProgramStateRef MallocMemReturnsAttr(CheckerContext &C, + const CallExpr *CE, + const OwnershipAttr* Att); static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, const Expr *SizeEx, SVal Init, ProgramStateRef state) { @@ -155,20 +154,25 @@ state->getSVal(SizeEx, C.getLocationContext()), Init, state); } + static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, SVal SizeEx, SVal Init, ProgramStateRef state); - void FreeMem(CheckerContext &C, const CallExpr *CE) const; - void FreeMemAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att) const; + /// Update the RefState to reflect the new memory allocation. + static ProgramStateRef MallocUpdateRefState(CheckerContext &C, + const CallExpr *CE, + ProgramStateRef state); + + ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE, + const OwnershipAttr* Att) const; ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE, ProgramStateRef state, unsigned Num, bool Hold) const; - void ReallocMem(CheckerContext &C, const CallExpr *CE, - bool FreesMemOnFailure) const; - static void CallocMem(CheckerContext &C, const CallExpr *CE); + ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE, + bool FreesMemOnFailure) const; + static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE); bool checkEscape(SymbolRef Sym, const Stmt *S, CheckerContext &C) const; bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, @@ -327,87 +331,60 @@ if (!FunI) return; + ProgramStateRef State = C.getState(); if (FunI == II_malloc || FunI == II_valloc) { - MallocMem(C, CE, 0); - return; + State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); } else if (FunI == II_realloc) { - ReallocMem(C, CE, false); - return; + State = ReallocMem(C, CE, false); } else if (FunI == II_reallocf) { - ReallocMem(C, CE, true); - return; + State = ReallocMem(C, CE, true); } else if (FunI == II_calloc) { - CallocMem(C, CE); - return; + State = CallocMem(C, CE); } else if (FunI == II_free) { - FreeMem(C, CE); - return; + State = FreeMemAux(C, CE, C.getState(), 0, false); } else if (FunI == II_strdup) { - MallocMem(C, CE, InvalidArgIndex); - return; + State = MallocUpdateRefState(C, CE, State); } else if (FunI == II_strndup) { - MallocMem(C, CE, 1); - return; - } - - if (Filter.CMallocOptimistic) - // Check all the attributes, if there are any. - // There can be multiple of these attributes. - if (FD->hasAttrs()) { - for (specific_attr_iterator - i = FD->specific_attr_begin(), - e = FD->specific_attr_end(); - i != e; ++i) { - switch ((*i)->getOwnKind()) { - case OwnershipAttr::Returns: { - MallocMemReturnsAttr(C, CE, *i); - return; - } - case OwnershipAttr::Takes: - case OwnershipAttr::Holds: { - FreeMemAttr(C, CE, *i); - return; + State = MallocUpdateRefState(C, CE, State); + } else if (Filter.CMallocOptimistic) { + // Check all the attributes, if there are any. + // There can be multiple of these attributes. + if (FD->hasAttrs()) + for (specific_attr_iterator + i = FD->specific_attr_begin(), + e = FD->specific_attr_end(); + i != e; ++i) { + switch ((*i)->getOwnKind()) { + case OwnershipAttr::Returns: + State = MallocMemReturnsAttr(C, CE, *i); + break; + case OwnershipAttr::Takes: + case OwnershipAttr::Holds: + State = FreeMemAttr(C, CE, *i); + break; + } } - } - } } -} - -void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE, - unsigned SizeIdx) { - SVal Undef = UndefinedVal(); - ProgramStateRef State; - if (SizeIdx != InvalidArgIndex) - State = MallocMemAux(C, CE, CE->getArg(SizeIdx), Undef, C.getState()); - else - State = MallocMemAux(C, CE, Undef, Undef, C.getState()); - C.addTransition(State); } -void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att) { +ProgramStateRef MallocChecker::MallocMemReturnsAttr(CheckerContext &C, + const CallExpr *CE, + const OwnershipAttr* Att) { if (Att->getModule() != "malloc") - return; + return 0; OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); if (I != E) { - ProgramStateRef state = - MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState()); - C.addTransition(state); - return; + return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState()); } - ProgramStateRef state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), - C.getState()); - C.addTransition(state); + return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState()); } ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, const CallExpr *CE, SVal Size, SVal Init, ProgramStateRef state) { - SValBuilder &svalBuilder = C.getSValBuilder(); - // Get the return value. SVal retVal = state->getSVal(CE, C.getLocationContext()); @@ -424,6 +401,7 @@ if (!R) return 0; if (isa(Size)) { + SValBuilder &svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); DefinedOrUnknownSVal DefinedSize = cast(Size); DefinedOrUnknownSVal extentMatchesSize = @@ -433,33 +411,39 @@ assert(state); } + return MallocUpdateRefState(C, CE, state); +} + +ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C, + const CallExpr *CE, + ProgramStateRef state) { + // Get the return value. + SVal retVal = state->getSVal(CE, C.getLocationContext()); + + // We expect the malloc functions to return a pointer. + if (!isa(retVal)) + return 0; + SymbolRef Sym = retVal.getAsLocSymbol(); assert(Sym); // Set the symbol's state to Allocated. return state->set(Sym, RefState::getAllocateUnchecked(CE)); -} -void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) const { - ProgramStateRef state = FreeMemAux(C, CE, C.getState(), 0, false); - - if (state) - C.addTransition(state); } -void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att) const { +ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C, + const CallExpr *CE, + const OwnershipAttr* Att) const { if (Att->getModule() != "malloc") - return; + return 0; for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); I != E; ++I) { - ProgramStateRef state = - FreeMemAux(C, CE, C.getState(), *I, - Att->getOwnKind() == OwnershipAttr::Holds); - if (state) - C.addTransition(state); + return FreeMemAux(C, CE, C.getState(), *I, + Att->getOwnKind() == OwnershipAttr::Holds); } + return 0; } ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, @@ -682,14 +666,15 @@ } } -void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE, - bool FreesOnFail) const { +ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C, + const CallExpr *CE, + bool FreesOnFail) const { ProgramStateRef state = C.getState(); const Expr *arg0Expr = CE->getArg(0); const LocationContext *LCtx = C.getLocationContext(); SVal Arg0Val = state->getSVal(arg0Expr, LCtx); if (!isa(Arg0Val)) - return; + return 0; DefinedOrUnknownSVal arg0Val = cast(Arg0Val); SValBuilder &svalBuilder = C.getSValBuilder(); @@ -700,12 +685,12 @@ // Get the size argument. If there is no size arg then give up. const Expr *Arg1 = CE->getArg(1); if (!Arg1) - return; + return 0; // Get the value of the size argument. SVal Arg1ValG = state->getSVal(Arg1, LCtx); if (!isa(Arg1ValG)) - return; + return 0; DefinedOrUnknownSVal Arg1Val = cast(Arg1ValG); // Compare the size argument to 0. @@ -725,14 +710,13 @@ // If the ptr is NULL and the size is not 0, the call is equivalent to // malloc(size). if ( PrtIsNull && !SizeIsZero) { - ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1), + ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1), UndefinedVal(), StatePtrIsNull); - C.addTransition(stateMalloc); - return; + return stateMalloc; } if (PrtIsNull && SizeIsZero) - return; + return 0; // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size). assert(!PrtIsNull); @@ -740,7 +724,7 @@ SVal RetVal = state->getSVal(CE, LCtx); SymbolRef ToPtr = RetVal.getAsSymbol(); if (!FromPtr || !ToPtr) - return; + return 0; // If the size is 0, free the memory. if (SizeIsZero) @@ -751,8 +735,7 @@ stateFree = stateFree->set(ToPtr, ReallocPair(FromPtr, FreesOnFail)); C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr); - C.addTransition(stateFree); - return; + return stateFree; } // Default behavior. @@ -761,16 +744,16 @@ ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1), UnknownVal(), stateFree); if (!stateRealloc) - return; + return 0; stateRealloc = stateRealloc->set(ToPtr, ReallocPair(FromPtr, FreesOnFail)); C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr); - C.addTransition(stateRealloc); - return; + return stateRealloc; } + return 0; } -void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) { +ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){ ProgramStateRef state = C.getState(); SValBuilder &svalBuilder = C.getSValBuilder(); const LocationContext *LCtx = C.getLocationContext(); @@ -780,7 +763,7 @@ svalBuilder.getContext().getSizeType()); SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); - C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state)); + return MallocMemAux(C, CE, TotalSize, zeroVal, state); } void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=151188&r1=151187&r2=151188&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Wed Feb 22 13:24:52 2012 @@ -671,6 +671,12 @@ return 1;// expected-warning {{Memory is never released; potential memory leak}} } +void testStrdupContentIsDefined(const char *s, unsigned validIndex) { + char *s2 = strdup(s); + char result = s2[1];// no warning + free(s2); +} + // Below are the known false positives. // TODO: There should be no warning here. This one might be difficult to get rid of. From ganna at apple.com Wed Feb 22 11:41:19 2012 From: ganna at apple.com (Anna Zaks) Date: Wed, 22 Feb 2012 11:41:19 -0800 Subject: [cfe-commits] r151124 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c In-Reply-To: <30DC14ED-C1D7-4375-831A-07145C98EE58@belkadan.com> References: <20120222031420.A64182A6C130@llvm.org> <30DC14ED-C1D7-4375-831A-07145C98EE58@belkadan.com> Message-ID: Jordy, You are right, it should be Unknown. However, as I was looking at this, I've realized that the Malloc Checker should not try to evaluate strdup - it's the job of the CString checker; addressed in r151188. Thanks, Anna. On Feb 22, 2012, at 7:59 AM, Jordy Rose wrote: > Minor complaint: why is the size of a strdup allocation Undef and not Unknown? I see we can skip the extent-setting step, but really we might as well just do that anyway if it's Unknown. > > Jordy > > > On Feb 22, 2012, at 10:14, Anna Zaks wrote: > >> Author: zaks >> Date: Tue Feb 21 21:14:20 2012 >> New Revision: 151124 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=151124&view=rev >> Log: >> [analyzer] Malloc checker: mark 'strdup' and 'strndup' as allocators. >> >> Modified: >> cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp >> cfe/trunk/test/Analysis/malloc.c >> >> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=151124&r1=151123&r2=151124&view=diff >> ============================================================================== >> --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) >> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Tue Feb 21 21:14:20 2012 >> @@ -26,6 +26,8 @@ >> #include "llvm/ADT/ImmutableMap.h" >> #include "llvm/ADT/SmallString.h" >> #include "llvm/ADT/STLExtras.h" >> +#include >> + >> using namespace clang; >> using namespace ento; >> >> @@ -97,11 +99,13 @@ >> mutable OwningPtr BT_UseFree; >> mutable OwningPtr BT_BadFree; >> mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc, >> - *II_valloc, *II_reallocf; >> + *II_valloc, *II_reallocf, *II_strndup, *II_strdup; >> + >> + static const unsigned InvalidArgIndex = UINT_MAX; >> >> public: >> MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0), >> - II_valloc(0), II_reallocf(0) {} >> + II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0) {} >> >> /// In pessimistic mode, the checker assumes that it does not know which >> /// functions might free the memory. >> @@ -140,7 +144,8 @@ >> /// pointed to by one of its arguments. >> bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const; >> >> - static void MallocMem(CheckerContext &C, const CallExpr *CE); >> + static void MallocMem(CheckerContext &C, const CallExpr *CE, >> + unsigned SizeIdx); >> static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, >> const OwnershipAttr* Att); >> static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, >> @@ -283,6 +288,10 @@ >> II_calloc = &Ctx.Idents.get("calloc"); >> if (!II_valloc) >> II_valloc = &Ctx.Idents.get("valloc"); >> + if (!II_strdup) >> + II_strdup = &Ctx.Idents.get("strdup"); >> + if (!II_strndup) >> + II_strndup = &Ctx.Idents.get("strndup"); >> } >> >> bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const { >> @@ -294,9 +303,9 @@ >> >> initIdentifierInfo(C); >> >> - // TODO: Add more here : ex: reallocf! >> if (FunI == II_malloc || FunI == II_free || FunI == II_realloc || >> - FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc) >> + FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc || >> + FunI == II_strdup || FunI == II_strndup) >> return true; >> >> if (Filter.CMallocOptimistic && FD->hasAttrs() && >> @@ -319,7 +328,7 @@ >> return; >> >> if (FunI == II_malloc || FunI == II_valloc) { >> - MallocMem(C, CE); >> + MallocMem(C, CE, 0); >> return; >> } else if (FunI == II_realloc) { >> ReallocMem(C, CE, false); >> @@ -330,9 +339,15 @@ >> } else if (FunI == II_calloc) { >> CallocMem(C, CE); >> return; >> - }else if (FunI == II_free) { >> + } else if (FunI == II_free) { >> FreeMem(C, CE); >> return; >> + } else if (FunI == II_strdup) { >> + MallocMem(C, CE, InvalidArgIndex); >> + return; >> + } else if (FunI == II_strndup) { >> + MallocMem(C, CE, 1); >> + return; >> } >> >> if (Filter.CMallocOptimistic) >> @@ -358,10 +373,16 @@ >> } >> } >> >> -void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) { >> - ProgramStateRef state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), >> - C.getState()); >> - C.addTransition(state); >> +void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE, >> + unsigned SizeIdx) { >> + SVal Undef = UndefinedVal(); >> + ProgramStateRef State; >> + if (SizeIdx != InvalidArgIndex) >> + State = MallocMemAux(C, CE, CE->getArg(SizeIdx), Undef, C.getState()); >> + else >> + State = MallocMemAux(C, CE, Undef, Undef, C.getState()); >> + >> + C.addTransition(State); >> } >> >> void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, >> @@ -400,16 +421,17 @@ >> // Set the region's extent equal to the Size parameter. >> const SymbolicRegion *R = >> dyn_cast_or_null(retVal.getAsRegion()); >> - if (!R || !isa(Size)) >> + if (!R) >> return 0; >> + if (isa(Size)) { >> + DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); >> + DefinedOrUnknownSVal DefinedSize = cast(Size); >> + DefinedOrUnknownSVal extentMatchesSize = >> + svalBuilder.evalEQ(state, Extent, DefinedSize); >> >> - DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); >> - DefinedOrUnknownSVal DefinedSize = cast(Size); >> - DefinedOrUnknownSVal extentMatchesSize = >> - svalBuilder.evalEQ(state, Extent, DefinedSize); >> - >> - state = state->assume(extentMatchesSize, true); >> - assert(state); >> + state = state->assume(extentMatchesSize, true); >> + assert(state); >> + } >> >> SymbolRef Sym = retVal.getAsLocSymbol(); >> assert(Sym); >> >> Modified: cfe/trunk/test/Analysis/malloc.c >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=151124&r1=151123&r2=151124&view=diff >> ============================================================================== >> --- cfe/trunk/test/Analysis/malloc.c (original) >> +++ cfe/trunk/test/Analysis/malloc.c Tue Feb 21 21:14:20 2012 >> @@ -652,6 +652,25 @@ >> return &(px->g); >> } >> >> +// Test various allocation/deallocation functions. >> + >> +char *strdup(const char *s); >> +char *strndup(const char *s, size_t n); >> + >> +void testStrdup(const char *s, unsigned validIndex) { >> + char *s2 = strdup(s); >> + s2[validIndex + 1] = 'b';// expected-warning {{Memory is never released; potential memory leak}} >> +} >> + >> +int testStrndup(const char *s, unsigned validIndex, unsigned size) { >> + char *s2 = strndup(s, size); >> + s2 [validIndex + 1] = 'b'; >> + if (s2[validIndex] != 'a') >> + return 0;// expected-warning {{Memory is never released; potential memory leak}} >> + else >> + return 1;// expected-warning {{Memory is never released; potential memory leak}} >> +} >> + >> // Below are the known false positives. >> >> // TODO: There should be no warning here. This one might be difficult to get rid of. >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > From rtrieu at google.com Wed Feb 22 11:43:35 2012 From: rtrieu at google.com (Richard Trieu) Date: Wed, 22 Feb 2012 11:43:35 -0800 Subject: [cfe-commits] [Patch] Add a warning for for loops with conditions that do not change In-Reply-To: References: Message-ID: On Tue, Feb 14, 2012 at 6:37 PM, Richard Trieu wrote: > On Tue, Feb 14, 2012 at 3:42 PM, Richard Trieu wrote: > >> On Tue, Feb 7, 2012 at 10:38 AM, Douglas Gregor wrote: >> >>> >>> On Feb 6, 2012, at 1:00 PM, Eli Friedman wrote: >>> >>> > On Mon, Feb 6, 2012 at 2:50 PM, Richard Trieu >>> wrote: >>> >> On Mon, Feb 6, 2012 at 2:02 PM, Eli Friedman >>> wrote: >>> >>> >>> >>> On Mon, Feb 6, 2012 at 1:55 PM, Richard Trieu >>> wrote: >>> >>>> The motivation of this path is to catch code like this: >>> >>>> >>> >>>> for (int i = 0; i < 10; ++i) >>> >>>> for (int j = 0; j < 10; ++i) >>> >>>> { } >>> >>>> >>> >>>> The second for loop increments i instead of j causing an infinite >>> loop. >>> >>>> The >>> >>>> warning also checks the body of the for loop so it will trigger on: >>> >>>> >>> >>>> for (int i; i <10; ) { } >>> >>>> >>> >>>> But not trigger on: >>> >>>> >>> >>>> for (int i; i< 10; ) { ++i; } >>> >>>> >>> >>>> I'm still fine-tuning the trigger conditions, but would like some >>> >>>> feedback >>> >>>> on this patch. >>> >>> >>> >>> Adding an additional recursive traversal of the body of every parsed >>> >>> for loop is very expensive. >>> >>> >>> >>> -Eli >>> >> >>> >> >>> >> Is it that expensive? I would think that once the AST was >>> constructed, the >>> >> visitor would be pretty fast, especially if no action is taken on >>> most of >>> >> the nodes. I also made the warning default ignore and put in an early >>> >> return to prevent the visitors from running in the default case. >>> >> >>> >> Do you have any suggestions on removing the recursive traversal? >>> > >>> > Okay, thinking about it a bit more, maybe it's not that expensive, but >>> > you should at least measure to make sure. >>> >>> I'm still very nervous about adding such an AST traversal. Presumably, >>> it's not going to be a concern in practice because most of the time, the >>> increment statement of the 'for' loop will mention one of the variables in >>> the condition, and therefore we'll short-circuit the expensive walk of the >>> loop body. It would be helpful to know that's the case. >>> >>> > I don't have any good suggestion for an alternative. >>> >>> >>> Nor do I. >>> >>> A couple more comments: >>> >>> + ValueDecl *VD = E->getDecl(); >>> + for (SmallVectorImpl::iterator I = Decls.begin(), >>> + E = Decls.end(); >>> + I != E; ++I) >>> + if (*I == VD) { >>> + FoundDecl = true; >>> + return; >>> + } >>> >>> This is linear; please use a SmallPtrSet instead. >>> >> Done. >> >>> >>> Plus, I think you want to narrow this check to only consider VarDecls. >>> Functions and enumerators are not interesting. >>> >> Done. >> >>> >>> + S.Diag(Second->getLocStart(), >>> diag::warn_variables_not_in_loop_body) >>> + << Second->getSourceRange(); >>> >>> This warning needs to specify which variables were not used or point to >>> them in the source. >>> >> The diagnostic now underlines all the variables in the condition. >> >>> >>> Do we want to actually look for modification, e.g., any use of the >>> variable that isn't immediately consumed by an lvalue-to-rvalue conversion? >>> >> Yes, that is exactly what we are checking for. The VisitCastExpr checks >> for LvalueToRvalue casts and skips any DeclRefExpr's that are direct >> sub-expressions. >> >>> >>> - Doug >>> >> >> I also did a comparison between runs with and without -Wloop-analysis. >> Even with the heavily nested loop, the extra recursive checks don't take >> too much extra time to run. >> >> clang loop.cc -fsyntax-only >> .460 - .480s >> >> clang loop.cc -fsyntax-only -Wloop-analysis >> .520 - .540s >> >> Code with increments removed to trigger 2044 for loop warnings >> clang loop.cc -fsyntax-only >> .310 - .330s >> >> clang loop.cc -fsyntax-only -Wloop-analysis 2>/dev/null >> .740 - .780s >> >> clang loop.cc -fsyntax-only -Wloop-analysis >> 1.430 - 1.550s >> >> // Test loop code. >> #define M(A) A A >> #define L1 for(int a1 = 0; a1 < 10;){M(L2) } >> #define L2 for(int a2 = 0; a2 < 10;){M(L3) a1++; } >> #define L3 for(int a3 = 0; a3 < 10;){M(L4) a2++; } >> #define L4 for(int a4 = 0; a4 < 10;){M(L5) a3++; } >> #define L5 for(int a5 = 0; a5 < 10;){M(L6) a4++; } >> #define L6 for(int a6 = 0; a6 < 10;){M(L7) a5++; } >> #define L7 for(int a7 = 0; a7 < 10;){M(L8) a6++; } >> #define L8 for(int a8 = 0; a8 < 10;){M(L9) a7++; } >> #define L9 for(int a9 = 0; a9 < 10;){M(L) a8++; } >> #define L a9++; >> >> void foo() { >> L1 >> L1 >> L1 >> L1 >> } >> > > Some data from real code. Took Clang source and preprocessed it into 300k > lines of code (if that seems high, I accidentally copied the files twice). > Ran the patched Clang across the files with either -Wloop-analysis set or > omitted. -fsyntax-only was also used. > > Without -Wloop-analysis, > Min time = 24.99s > Max time = 25.63s > Average = 25.218s > > With -Wloop-analysis, > Min time = 25s > Max time = 25.5s > Average = 25.214s > > > Ping. -------------- next part -------------- An HTML attachment was scrubbed... URL: From rtrieu at google.com Wed Feb 22 11:44:46 2012 From: rtrieu at google.com (Richard Trieu) Date: Wed, 22 Feb 2012 11:44:46 -0800 Subject: [cfe-commits] [Patch] Add highlighting and type eliding when two templates are used in a diagnostics. Also, template tree printing. In-Reply-To: References: Message-ID: On Mon, Feb 13, 2012 at 1:52 PM, Richard Trieu wrote: > On Mon, Jan 30, 2012 at 10:41 AM, Richard Trieu wrote: > >> On Wed, Jan 18, 2012 at 12:01 PM, Richard Trieu wrote: >> >>> On Wed, Jan 11, 2012 at 6:22 PM, Richard Trieu wrote: >>> >>>> On Tue, Dec 13, 2011 at 2:32 PM, Chandler Carruth >>> > wrote: >>>> >>>>> I've left detailed comments on the codereview. Some of them might be >>>>> addressed by some of my high-level comments: >>>>> >>>>> How the various pieces of this interact are not clear from an initial >>>>> reading. I think we need lots of comments to clearly document how the >>>>> QualType's move into the ASTDiagnostics layer, and what the expect result >>>>> is when we are rendering strings in that layer, and how those results are >>>>> re-composed into the final diagnostic. Without that context at each layer, >>>>> it's hard to understand how this works. >>>>> >>>>> I lot of that has been cleaned up. Comments have been added to >>>> document how the types are loaded. Magic values have been moved to shared >>>> headers. >>>> >>>>> >>>>> The implementation of the new text is also quite hard to understand >>>>> for me. I have a theory as to why: There are really two orthogonal things >>>>> going on: one is computing the different (pruned) tree to print, and the >>>>> second is rendering the various parts of that tree to text. I think it >>>>> would help te separate these two as much as possible. What I'm envisioning >>>>> is first building an object which represents (in some tree-like >>>>> data-structure with a reasonable set of APIs) the "interesting" pieces of >>>>> the type(s). Then, methods on the object which (recursively) build a >>>>> textual representation out of it. Among other readability advantages this >>>>> would especially help by potentially factoring the two different styles of >>>>> formatting (tree vs. elision) more firmly -- they could be a largely >>>>> distinct collection of methods. >>>>> >>>>> The diffing has been separated into two phases. The first phase walks >>>> the type and builds up a diff tree. The second phase takes this diff tree >>>> and converts it into the output string. >>>> >>>> >>>>> As part of this (and as I mention in my detailed comments) it would be >>>>> good to move to a stream-based rendering system to make the composition of >>>>> the text easier to read as well as much more efficient. >>>>> >>>>> Moved from strings to a steam-based system. >>>> >>>>> >>>>> Finally, I think you'll need Doug to look at the actual logic of >>>>> computing the "interesting" set of nodes. I think that's going to be one of >>>>> the more tricky parts of this to get right. >>>>> >>>> >>>> Major changes from the last patch is the separation of the building of >>>> the diff information tree and the eventual construction of the output >>>> string. Elision is handled a bit more consistently. Also fixed a place >>>> where the two types get switched. >>>> >>> >>> Ping. >>> >> Ping. > > Ping. Ping. -------------- next part -------------- An HTML attachment was scrubbed... URL: From chandlerc at google.com Wed Feb 22 11:51:28 2012 From: chandlerc at google.com (Chandler Carruth) Date: Wed, 22 Feb 2012 11:51:28 -0800 Subject: [cfe-commits] [Patch] Add highlighting and type eliding when two templates are used in a diagnostics. Also, template tree printing. In-Reply-To: References: Message-ID: On Wed, Feb 22, 2012 at 11:44 AM, Richard Trieu wrote: > On Mon, Feb 13, 2012 at 1:52 PM, Richard Trieu wrote: > >> On Mon, Jan 30, 2012 at 10:41 AM, Richard Trieu wrote: >> >>> On Wed, Jan 18, 2012 at 12:01 PM, Richard Trieu wrote: >>> >>>> On Wed, Jan 11, 2012 at 6:22 PM, Richard Trieu wrote: >>>> >>>>> On Tue, Dec 13, 2011 at 2:32 PM, Chandler Carruth < >>>>> chandlerc at google.com> wrote: >>>>> >>>>>> I've left detailed comments on the codereview. Some of them might be >>>>>> addressed by some of my high-level comments: >>>>>> >>>>>> How the various pieces of this interact are not clear from an initial >>>>>> reading. I think we need lots of comments to clearly document how the >>>>>> QualType's move into the ASTDiagnostics layer, and what the expect result >>>>>> is when we are rendering strings in that layer, and how those results are >>>>>> re-composed into the final diagnostic. Without that context at each layer, >>>>>> it's hard to understand how this works. >>>>>> >>>>>> I lot of that has been cleaned up. Comments have been added to >>>>> document how the types are loaded. Magic values have been moved to shared >>>>> headers. >>>>> >>>>>> >>>>>> The implementation of the new text is also quite hard to understand >>>>>> for me. I have a theory as to why: There are really two orthogonal things >>>>>> going on: one is computing the different (pruned) tree to print, and the >>>>>> second is rendering the various parts of that tree to text. I think it >>>>>> would help te separate these two as much as possible. What I'm envisioning >>>>>> is first building an object which represents (in some tree-like >>>>>> data-structure with a reasonable set of APIs) the "interesting" pieces of >>>>>> the type(s). Then, methods on the object which (recursively) build a >>>>>> textual representation out of it. Among other readability advantages this >>>>>> would especially help by potentially factoring the two different styles of >>>>>> formatting (tree vs. elision) more firmly -- they could be a largely >>>>>> distinct collection of methods. >>>>>> >>>>>> The diffing has been separated into two phases. The first phase >>>>> walks the type and builds up a diff tree. The second phase takes this diff >>>>> tree and converts it into the output string. >>>>> >>>>> >>>>>> As part of this (and as I mention in my detailed comments) it would >>>>>> be good to move to a stream-based rendering system to make the composition >>>>>> of the text easier to read as well as much more efficient. >>>>>> >>>>>> Moved from strings to a steam-based system. >>>>> >>>>>> >>>>>> Finally, I think you'll need Doug to look at the actual logic of >>>>>> computing the "interesting" set of nodes. I think that's going to be one of >>>>>> the more tricky parts of this to get right. >>>>>> >>>>> >>>>> Major changes from the last patch is the separation of the building of >>>>> the diff information tree and the eventual construction of the output >>>>> string. Elision is handled a bit more consistently. Also fixed a place >>>>> where the two types get switched. >>>>> >>>> >>>> Ping. >>>> >>> Ping. >> >> Ping. > > Ping. :: hangs head in shame :: 4 pings in a row... bumping this up toward the top. -------------- next part -------------- An HTML attachment was scrubbed... URL: From matthieu.monrocq at gmail.com Wed Feb 22 11:51:40 2012 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Wed, 22 Feb 2012 20:51:40 +0100 Subject: [cfe-commits] r151177 - /cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td In-Reply-To: <20120222181848.C1FB62A6C12F@llvm.org> References: <20120222181848.C1FB62A6C12F@llvm.org> Message-ID: Le 22 février 2012 19:18, Chad Rosier a écrit : > Author: mcrosier > Date: Wed Feb 22 12:18:48 2012 > New Revision: 151177 > > URL: http://llvm.org/viewvc/llvm-project?rev=151177&view=rev > Log: > Add new driver warning from r151174 to a warning group. Please let me > know if this isn't the appropriate grouping. > > Modified: > cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td > > Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=151177&r1=151176&r2=151177&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Wed Feb 22 > 12:18:48 2012 > @@ -106,7 +106,8 @@ > "argument unused during compilation: '%0'">, > InGroup>; > def warn_drv_empty_joined_argument : Warning< > - "joined argument expects addition arg: '%0'">; > + "joined argument expects addition arg: '%0'">, > + InGroup>; > def warn_drv_not_using_clang_cpp : Warning< > "not using the clang preprocessor due to user override">; > def warn_drv_not_using_clang_cxx : Warning< > > > In the spirit of "avoid magic values", it might be worth creating a named DiagGroup for "unused-command-line-argument". -- Matthieu -------------- next part -------------- An HTML attachment was scrubbed... URL: From thakis at chromium.org Wed Feb 22 12:00:57 2012 From: thakis at chromium.org (Nico Weber) Date: Wed, 22 Feb 2012 12:00:57 -0800 Subject: [cfe-commits] [patch][pr12001] Avoid increasing visibility in some cases In-Reply-To: References: <4F41B060.9020500@gmail.com> <4F41B9E8.4020407@gmail.com> Message-ID: Consider this program: $ cat repro.ii template class DeviceDataProviderImplBase { }; template class DeviceDataProvider { __attribute__((visibility("default"))) static DeviceDataProviderImplBase* DefaultFactoryFunction(); }; struct __attribute__((visibility("default"))) RadioData { }; typedef DeviceDataProviderImplBase RadioDataProviderImplBase; typedef DeviceDataProvider RadioDataProvider; template<> RadioDataProviderImplBase* RadioDataProvider::DefaultFactoryFunction() { } With gcc, and with clang before your patch, DefaultFactorFunction() is a non-hidden symbol: $ gcc -c repro.ii -w -fvisibility=hidden 2> /dev/null && objdump --syms repro.o | grep '_ZN18DeviceDataProviderI9RadioDataE22DefaultFactoryFunctionEv' 0000000000000000 g F .text 0000000000000006 _ZN18DeviceDataProviderI9RadioDataE22DefaultFactoryFunctionEv With clang with your patch, it becomes hidden: $ chrome/src/third_party/llvm-build/Release+Asserts/bin/clang -c repro.ii -w -fvisibility=hidden 2> /dev/null && objdump --syms repro.o | grep '_ZN18DeviceDataProviderI9RadioDataE22DefaultFactoryFunctionEv' 0000000000000000 g F .text 0000000000000006 .hidden _ZN18DeviceDataProviderI9RadioDataE22DefaultFactoryFunctionEv This breaks building some unit test binary in chromium land (the browser itself builds fine either way). Nico On Wed, Feb 22, 2012 at 10:15 AM, Nico Weber wrote: > Doh, I think I found an issue with this patch :-/ I'm building a > reduced test case now, I'll post it here in a few hours. > > Nico > > On Tue, Feb 21, 2012 at 5:57 PM, Eric Christopher wrote: >> >> On Feb 19, 2012, at 7:11 PM, Rafael Ávila de Espíndola wrote: >> >>> Nico noticed that the patch included an infinite loop from when I >>> renamed merge2 to mergeWithMin. >>> >>> An updated patch is attached. >> >> I think this is ok. Some more comments on the visibility that should be happening in the various testcases and where you use mergeWithMin would be helpful next time I need to review something through there. >> >> -eric From mcrosier at apple.com Wed Feb 22 12:26:10 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 22 Feb 2012 20:26:10 -0000 Subject: [cfe-commits] r151192 - /cfe/trunk/docs/UsersManual.html Message-ID: <20120222202610.C3C832A6C12F@llvm.org> Author: mcrosier Date: Wed Feb 22 14:26:10 2012 New Revision: 151192 URL: http://llvm.org/viewvc/llvm-project?rev=151192&view=rev Log: Improve placement of clang crash diagnostics section. Modified: cfe/trunk/docs/UsersManual.html Modified: cfe/trunk/docs/UsersManual.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.html?rev=151192&r1=151191&r2=151192&view=diff ============================================================================== --- cfe/trunk/docs/UsersManual.html (original) +++ cfe/trunk/docs/UsersManual.html Wed Feb 22 14:26:10 2012 @@ -198,26 +198,6 @@

    -ftemplate-backtrace-limit=123: Only emit up to 123 template instantiation notes within the template instantiation backtrace for a single warning or error. The default is 10, and the limit can be disabled with -ftemplate-backtrace-limit=0.

    - -

    Options to Control Clang Crash Diagnostics

    - - -

    As unbelievable as it may sound, Clang does crash from time to time. -Generally, this only occurs to those living on the -bleeding edge. Clang -goes to great lengths to assist you in filing a bug report. Specifically, Clang -generates preprocessed source file(s) and associated run script(s) upon a -crash. These files should be attached to a bug report to ease reproducibility -of the failure. Below are the command line options to control the crash -diagnostics. -

    - -

    -fno-crash-diagnostics: Disable auto-generation of preprocessed -source files during a clang crash.

    - -

    The -fno-crash-diagnostics flag can be helpful for speeding the process of -generating a delta reduced test case.

    -

    Formatting of Diagnostics

    @@ -437,7 +417,6 @@ - @@ -531,6 +510,27 @@ + +

    Options to Control Clang Crash Diagnostics

    + + +

    As unbelievable as it may sound, Clang does crash from time to time. +Generally, this only occurs to those living on the +bleeding edge. Clang +goes to great lengths to assist you in filing a bug report. Specifically, Clang +generates preprocessed source file(s) and associated run script(s) upon a +crash. These files should be attached to a bug report to ease reproducibility +of the failure. Below are the command line options to control the crash +diagnostics. +

    + +

    -fno-crash-diagnostics: Disable auto-generation of preprocessed +source files during a clang crash.

    + +

    The -fno-crash-diagnostics flag can be helpful for speeding the process of +generating a delta reduced test case.

    + +

    Language and Target-Independent Features

    From mcrosier at apple.com Wed Feb 22 12:46:25 2012 From: mcrosier at apple.com (Chad Rosier) Date: Wed, 22 Feb 2012 12:46:25 -0800 Subject: [cfe-commits] r151172 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/new-array-init-exceptions.cpp In-Reply-To: <20120222173759.8CE752A6C130@llvm.org> References: <20120222173759.8CE752A6C130@llvm.org> Message-ID: <718EBC33-FE3A-48AB-93D6-1490922F704C@apple.com> Hi Sebastian, The test you added here is failing on one of our internal buildbots. Here's the exact errors: ******************** TEST 'Clang :: CodeGenCXX/new-array-init-exceptions.cpp' FAILED ********************Script: -- /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang-build/Release/bin/clang -cc1 -internal-isystem /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang-build/Release/bin/../lib/clang/3.1/include -std=c++11 -triple i386-unknown-unknown -fexceptions -fcxx-exceptions /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp -emit-llvm -o - | FileCheck /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp -- Exit Code: 1 Command Output (stderr): -- /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp:20:12: error: expected string not found in input // CHECK: [[LPAD]]: ^ :56:1: note: scanning from here ;
  • Contains a new experimental malloc/free checker.
  • Better support for projects using ARC.
  • set-xcode-analyzer now supports self-contained Xcode.app (Xcode 4.3 and later). -
  • Misc. bug fixes and performance work. +
  • Misc. bug fixes and performance work.
  • +
  • Contains a newer version of the analyzer than Xcode 4.3.
  • checker-260

    From mimomorin at gmail.com Wed Feb 22 16:54:35 2012 From: mimomorin at gmail.com (Michel Morin) Date: Thu, 23 Feb 2012 09:54:35 +0900 Subject: [cfe-commits] [Patch] Adding __has_feature(cxx_decltype_incomplete_return_type) for querying N3276 decltype Message-ID: I think N3276 (Decltype and Call Expressions) is implemented in r151117. Boost.Config needs a config macro to determine the support of this feature, but clang does not have such a macro. This patch adds a new config macro __has_feature(cxx_decltype_incomplete_return_type) and updates doc and test. (I'm willing to change the macro name to better one.) Regards, Michel -------------- next part -------------- A non-text attachment was scrubbed... Name: cxx_decltype_incomplete_return_type.patch Type: application/octet-stream Size: 2810 bytes Desc: not available URL: From aaron at aaronballman.com Wed Feb 22 16:56:40 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Wed, 22 Feb 2012 18:56:40 -0600 Subject: [cfe-commits] [PATCH] Enabling support for __declspec(deprecated) Message-ID: You can attach __declspec(deprecated) with an optional message to any type or variable declaration in MS compatibility mode. This patch enables support for such functionality. All of the work was already done for this -- I'm just enabling it for __declspec and adding some test cases. http://msdn.microsoft.com/en-us/library/044swk7y.aspx ~Aaron -------------- next part -------------- A non-text attachment was scrubbed... Name: DeclspecDeprecated.patch Type: application/octet-stream Size: 1533 bytes Desc: not available URL: From ganna at apple.com Wed Feb 22 17:05:27 2012 From: ganna at apple.com (Anna Zaks) Date: Thu, 23 Feb 2012 01:05:27 -0000 Subject: [cfe-commits] r151220 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp test/Analysis/malloc.c test/Analysis/system-header-simulator.h Message-ID: <20120223010528.165EF2A6C12F@llvm.org> Author: zaks Date: Wed Feb 22 19:05:27 2012 New Revision: 151220 URL: http://llvm.org/viewvc/llvm-project?rev=151220&view=rev Log: [analyzer] Invalidate the region passed to pthread_setspecific() call. Make this call an exception in ExprEngine::invalidateArguments: 'int pthread_setspecific(ptheread_key k, const void *)' stores a value into thread local storage. The value can later be retrieved with 'void *ptheread_getspecific(pthread_key)'. So even thought the parameter is 'const void *', the region escapes through the call. (Here we just blacklist the call in the ExprEngine's default logic. Another option would be to add a checker which evaluates the call and triggers the call to invalidate regions.) Teach the Malloc Checker, which treats all system calls as safe about the API. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp cfe/trunk/test/Analysis/malloc.c cfe/trunk/test/Analysis/system-header-simulator.h Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=151220&r1=151219&r2=151220&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Feb 22 19:05:27 2012 @@ -1033,9 +1033,19 @@ return false; } - // If it's a system call, we know it does not free the memory. + // Most system calls, do not free the memory. SourceManager &SM = ASTC.getSourceManager(); if (SM.isInSystemHeader(FD->getLocation())) { + const IdentifierInfo *II = FD->getIdentifier(); + + // White list the system functions whose arguments escape. + if (II) { + StringRef FName = II->getName(); + if (FName.equals("pthread_setspecific")) + return true; + } + + // Otherwise, assume that the function does not free memory. return false; } @@ -1052,7 +1062,7 @@ ArrayRef ExplicitRegions, ArrayRef Regions, const CallOrObjCMessage *Call) const { - if (!invalidated) + if (!invalidated || invalidated->empty()) return State; llvm::SmallPtrSet WhitelistedSymbols; Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=151220&r1=151219&r2=151220&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Wed Feb 22 19:05:27 2012 @@ -187,6 +187,20 @@ return; if (const FunctionDecl *FDecl = dyn_cast(CallDecl)) { + const IdentifierInfo *II = FDecl->getIdentifier(); + + // List the cases, where the region should be invalidated even if the + // argument is const. + if (II) { + StringRef FName = II->getName(); + // 'int pthread_setspecific(ptheread_key k, const void *)' stores a value + // into thread local storage. The value can later be retrieved with + // 'void *ptheread_getspecific(pthread_key)'. So even thought the + // parameter is 'const void *', the region escapes through the call. + if (FName.equals("pthread_setspecific")) + return; + } + for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) { if (FDecl && Idx < FDecl->getNumParams()) { if (isPointerToConst(FDecl->getParamDecl(Idx))) Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=151220&r1=151219&r2=151220&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Wed Feb 22 19:05:27 2012 @@ -677,6 +677,16 @@ free(s2); } +// Test the system library functions to which the pointer can escape. + +// For now, we assume memory passed to pthread_specific escapes. +// TODO: We could check that if a new pthread binding is set, the existing +// binding must be freed; otherwise, a memory leak can occur. +void testPthereadSpecificEscape(pthread_key_t key) { + void *buf = malloc(12); + pthread_setspecific(key, buf); // no warning +} + // Below are the known false positives. // TODO: There should be no warning here. This one might be difficult to get rid of. Modified: cfe/trunk/test/Analysis/system-header-simulator.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/system-header-simulator.h?rev=151220&r1=151219&r2=151220&view=diff ============================================================================== --- cfe/trunk/test/Analysis/system-header-simulator.h (original) +++ cfe/trunk/test/Analysis/system-header-simulator.h Wed Feb 22 19:05:27 2012 @@ -11,3 +11,7 @@ char *strcpy(char *restrict s1, const char *restrict s2); +typedef unsigned long __darwin_pthread_key_t; +typedef __darwin_pthread_key_t pthread_key_t; +int pthread_setspecific(pthread_key_t , + const void *); From eli.friedman at gmail.com Wed Feb 22 17:11:33 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 22 Feb 2012 17:11:33 -0800 Subject: [cfe-commits] [PATCH] Enabling support for __declspec(deprecated) In-Reply-To: References: Message-ID: On Wed, Feb 22, 2012 at 4:56 PM, Aaron Ballman wrote: > You can attach __declspec(deprecated) with an optional message to any > type or variable declaration in MS compatibility mode.  This patch > enables support for such functionality. > > All of the work was already done for this -- I'm just enabling it for > __declspec and adding some test cases. > > http://msdn.microsoft.com/en-us/library/044swk7y.aspx Looks fine. -Eli From aaron at aaronballman.com Wed Feb 22 17:19:31 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Thu, 23 Feb 2012 01:19:31 -0000 Subject: [cfe-commits] r151225 - in /cfe/trunk: lib/Sema/SemaDeclAttr.cpp test/Sema/MicrosoftExtensions.c Message-ID: <20120223011931.F37E52A6C12F@llvm.org> Author: aaronballman Date: Wed Feb 22 19:19:31 2012 New Revision: 151225 URL: http://llvm.org/viewvc/llvm-project?rev=151225&view=rev Log: Turned on support for __declspec(deprecated) in MS compatibility mode. Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/test/Sema/MicrosoftExtensions.c Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=151225&r1=151224&r2=151225&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Feb 22 19:19:31 2012 @@ -3465,7 +3465,8 @@ static bool isKnownDeclSpecAttr(const AttributeList &Attr) { return Attr.getKind() == AttributeList::AT_dllimport || Attr.getKind() == AttributeList::AT_dllexport || - Attr.getKind() == AttributeList::AT_uuid; + Attr.getKind() == AttributeList::AT_uuid || + Attr.getKind() == AttributeList::AT_deprecated; } //===----------------------------------------------------------------------===// Modified: cfe/trunk/test/Sema/MicrosoftExtensions.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/MicrosoftExtensions.c?rev=151225&r1=151224&r2=151225&view=diff ============================================================================== --- cfe/trunk/test/Sema/MicrosoftExtensions.c (original) +++ cfe/trunk/test/Sema/MicrosoftExtensions.c Wed Feb 22 19:19:31 2012 @@ -86,3 +86,17 @@ typedef struct { AA; // expected-warning {{anonymous structs are a Microsoft extension}} } BB; + +__declspec(deprecated("This is deprecated")) enum DE1 { one, two } e1; +struct __declspec(deprecated) DS1 { int i; float f; }; + +#define MY_TEXT "This is also deprecated" +__declspec(deprecated(MY_TEXT)) void Dfunc1( void ) {} + +void test( void ) { + e1 = one; // expected-warning {{'e1' is deprecated: This is deprecated}} + struct DS1 s = { 0 }; // expected-warning {{'DS1' is deprecated}} + Dfunc1(); // expected-warning {{'Dfunc1' is deprecated: This is also deprecated}} + + enum DE1 no; // no warning because E1 is not deprecated +} From richard-llvm at metafoo.co.uk Wed Feb 22 17:36:13 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Thu, 23 Feb 2012 01:36:13 -0000 Subject: [cfe-commits] r151227 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseTentative.cpp test/Parser/cxx0x-ambig.cpp test/Parser/cxx0x-condition.cpp Message-ID: <20120223013613.438D42A6C12F@llvm.org> Author: rsmith Date: Wed Feb 22 19:36:12 2012 New Revision: 151227 URL: http://llvm.org/viewvc/llvm-project?rev=151227&view=rev Log: Update parser's disambiguation to cope with braced function-style casts in C++11, and with braced-init-list initializers in conditions. This exposed an ambiguity with enum underlying types versus bitfields, which we resolve by treating 'enum E : T {' as always defining an enumeration (even if it would only successfully parse as a bitfield). This appears to be g++ compatible. Added: cfe/trunk/test/Parser/cxx0x-ambig.cpp Modified: cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/lib/Parse/ParseTentative.cpp cfe/trunk/test/Parser/cxx0x-condition.cpp Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=151227&r1=151226&r2=151227&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed Feb 22 19:36:12 2012 @@ -1828,9 +1828,11 @@ /// declaration specifier, TPResult::False() if it is not, /// TPResult::Ambiguous() if it could be either a decl-specifier or a /// function-style cast, and TPResult::Error() if a parsing error was - /// encountered. + /// encountered. If it could be a braced C++11 function-style cast, returns + /// BracedCastResult. /// Doesn't consume tokens. - TPResult isCXXDeclarationSpecifier(); + TPResult + isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False()); // "Tentative parsing" functions, used for disambiguation. If a parsing error // is encountered they will return TPResult::Error(). Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=151227&r1=151226&r2=151227&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Feb 22 19:36:12 2012 @@ -3000,9 +3000,15 @@ // Consume the ':'. ConsumeToken(); - - if ((getLang().CPlusPlus && - isCXXDeclarationSpecifier() != TPResult::True()) || + + // If we see a type specifier followed by an open-brace, we have an + // ambiguity between an underlying type and a C++11 braced + // function-style cast. Resolve this by always treating it as an + // underlying type. + // FIXME: The standard is not entirely clear on how to disambiguate in + // this case. + if ((getLang().CPlusPlus && + isCXXDeclarationSpecifier(TPResult::True()) != TPResult::True()) || (!getLang().CPlusPlus && !isDeclarationSpecifier(true))) { // We'll parse this as a bitfield later. PossibleBitfield = true; Modified: cfe/trunk/lib/Parse/ParseTentative.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=151227&r1=151226&r2=151227&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTentative.cpp (original) +++ cfe/trunk/lib/Parse/ParseTentative.cpp Wed Feb 22 19:36:12 2012 @@ -233,6 +233,8 @@ /// condition: /// expression /// type-specifier-seq declarator '=' assignment-expression +/// [C++11] type-specifier-seq declarator '=' initializer-clause +/// [C++11] type-specifier-seq declarator braced-init-list /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] /// '=' assignment-expression /// @@ -274,6 +276,8 @@ if (Tok.is(tok::equal) || Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) TPR = TPResult::True(); + else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) + TPR = TPResult::True(); else TPR = TPResult::False(); } @@ -834,7 +838,8 @@ /// 'volatile' /// [GNU] restrict /// -Parser::TPResult Parser::isCXXDeclarationSpecifier() { +Parser::TPResult +Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult) { switch (Tok.getKind()) { case tok::identifier: // foo::bar // Check for need to substitute AltiVec __vector keyword @@ -849,7 +854,7 @@ return TPResult::Error(); if (Tok.is(tok::identifier)) return TPResult::False(); - return isCXXDeclarationSpecifier(); + return isCXXDeclarationSpecifier(BracedCastResult); case tok::coloncolon: { // ::foo::bar const Token &Next = NextToken(); @@ -863,7 +868,7 @@ // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) return TPResult::Error(); - return isCXXDeclarationSpecifier(); + return isCXXDeclarationSpecifier(BracedCastResult); // decl-specifier: // storage-class-specifier @@ -965,7 +970,7 @@ bool isIdentifier = Tok.is(tok::identifier); TPResult TPR = TPResult::False(); if (!isIdentifier) - TPR = isCXXDeclarationSpecifier(); + TPR = isCXXDeclarationSpecifier(BracedCastResult); PA.Revert(); if (isIdentifier || @@ -1005,6 +1010,7 @@ TPResult TPR = TryParseProtocolQualifiers(); bool isFollowedByParen = Tok.is(tok::l_paren); + bool isFollowedByBrace = Tok.is(tok::l_brace); PA.Revert(); @@ -1013,6 +1019,9 @@ if (isFollowedByParen) return TPResult::Ambiguous(); + + if (getLang().CPlusPlus0x && isFollowedByBrace) + return BracedCastResult; return TPResult::True(); } @@ -1036,6 +1045,15 @@ if (NextToken().is(tok::l_paren)) return TPResult::Ambiguous(); + // This is a function-style cast in all cases we disambiguate other than + // one: + // struct S { + // enum E : int { a = 4 }; // enum + // enum E : int { 4 }; // bit-field + // }; + if (getLang().CPlusPlus0x && NextToken().is(tok::l_brace)) + return BracedCastResult; + if (isStartOfObjCClassMessageMissingOpenBracket()) return TPResult::False(); @@ -1050,6 +1068,7 @@ TPResult TPR = TryParseTypeofSpecifier(); bool isFollowedByParen = Tok.is(tok::l_paren); + bool isFollowedByBrace = Tok.is(tok::l_brace); PA.Revert(); @@ -1059,6 +1078,9 @@ if (isFollowedByParen) return TPResult::Ambiguous(); + if (getLang().CPlusPlus0x && isFollowedByBrace) + return BracedCastResult; + return TPResult::True(); } @@ -1219,6 +1241,8 @@ MaybeParseMicrosoftAttributes(attrs); // 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(); if (TPR != TPResult::Ambiguous()) return TPR; Added: cfe/trunk/test/Parser/cxx0x-ambig.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-ambig.cpp?rev=151227&view=auto ============================================================================== --- cfe/trunk/test/Parser/cxx0x-ambig.cpp (added) +++ cfe/trunk/test/Parser/cxx0x-ambig.cpp Wed Feb 22 19:36:12 2012 @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// New exciting ambiguities in C++11 + +// final 'context sensitive' mess. +namespace final { + struct S { int n; }; + namespace N { + int n; + // This defines a class, not a variable, even though it would successfully + // parse as a variable but not as a class. DR1318's wording suggests that + // this disambiguation is only performed on an ambiguity, but that was not + // the intent. + struct S final { + int(n) // expected-error {{expected ';'}} + }; + } +} + +// enum versus bitfield mess. +namespace bitfield { + enum E {}; + + struct T { + constexpr T() {} + constexpr T(int) {} + constexpr T(T, T, T, T) {} + constexpr T operator=(T) { return *this; } + constexpr operator int() { return 4; } + }; + constexpr T a, b, c, d; + + struct S1 { + enum E : T ( a = 1, b = 2, c = 3, 4 ); // ok, declares a bitfield + }; + // This could be a bit-field. + struct S2 { + enum E : T { a = 1, b = 2, c = 3, 4 }; // expected-error {{non-integral type}} expected-error {{expected '}'}} expected-note {{to match}} + }; + struct S3 { + enum E : int { a = 1, b = 2, c = 3, d }; // ok, defines an enum + }; + // Ambiguous. + struct S4 { + enum E : int { a = 1 }; // ok, defines an enum + }; + // This could be a bit-field, but would be ill-formed due to the anonymous + // member being initialized. + struct S5 { + enum E : int { a = 1 } { b = 2 }; // expected-error {{expected member name}} + }; + // This could be a bit-field. + struct S6 { + enum E : int { 1 }; // expected-error {{expected '}'}} expected-note {{to match}} + }; + + struct U { + constexpr operator T() { return T(); } // expected-note 2{{candidate}} + }; + // This could be a bit-field. + struct S7 { + enum E : int { a = U() }; // expected-error {{no viable conversion}} + }; + // This could be a bit-field, and does not conform to the grammar of an + // enum definition, because 'id(U())' is not a constant-expression. + constexpr const U &id(const U &u) { return u; } + struct S8 { + enum E : int { a = id(U()) }; // expected-error {{no viable conversion}} + }; +} + +namespace trailing_return { + typedef int n; + int a; + + struct S { + S(int); + S *operator()() const; + int n; + }; + + namespace N { + void f() { + // This parses as a function declaration, but DR1223 makes the presence of + // 'auto' be used for disambiguation. + S(a)()->n; // ok, expression; expected-warning{{expression result unused}} + auto(a)()->n; // ok, function declaration + using T = decltype(a); + using T = auto() -> n; + } + } +} Modified: cfe/trunk/test/Parser/cxx0x-condition.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-condition.cpp?rev=151227&r1=151226&r2=151227&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx0x-condition.cpp (original) +++ cfe/trunk/test/Parser/cxx0x-condition.cpp Wed Feb 22 19:36:12 2012 @@ -27,11 +27,11 @@ if (S b(n) = 0) {} // expected-error {{a function type is not allowed here}} if (S b(n) == 0) {} // expected-error {{a function type is not allowed here}} expected-error {{did you mean '='?}} - // FIXME: this is legal, and incorrectly rejected, because tentative parsing - // does not yet know about braced function-style casts. - if (S{a}) {} // unexpected-error{{unqualified-id}} - + if (S{a}) {} // ok if (S a{a}) {} // ok if (S a = {a}) {} // ok if (S a == {a}) {} // expected-error {{did you mean '='?}} + + if (S(b){a}) {} // ok + if (S(b) = {a}) {} // ok } From aaron at aaronballman.com Wed Feb 22 17:41:44 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Wed, 22 Feb 2012 19:41:44 -0600 Subject: [cfe-commits] [PATCH] Support for __declspec(noreturn) Message-ID: Similar to the deprecated declspec, this is support for noreturn. Again, just enabling what was already there, and adding test cases. ~Aaron -------------- next part -------------- A non-text attachment was scrubbed... Name: DeclspecNoReturn.patch Type: application/octet-stream Size: 2316 bytes Desc: not available URL: From eli.friedman at gmail.com Wed Feb 22 18:25:10 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Thu, 23 Feb 2012 02:25:10 -0000 Subject: [cfe-commits] r151229 - in /cfe/trunk: lib/CodeGen/CGExprAgg.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaInit.cpp test/CodeGenObjC/arc-blocks.m Message-ID: <20120223022510.DEC1C2A6C12F@llvm.org> Author: efriedma Date: Wed Feb 22 20:25:10 2012 New Revision: 151229 URL: http://llvm.org/viewvc/llvm-project?rev=151229&view=rev Log: Try to handle qualifiers more consistently for array InitListExprs. Fixes , and makes the ASTs a bit more self-consistent. (I've chosen to keep the qualifiers, but it isn't a strong preference; if anyone prefers removing them, please yell.) Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/test/CodeGenObjC/arc-blocks.m Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=151229&r1=151228&r2=151229&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Wed Feb 22 20:25:10 2012 @@ -905,10 +905,8 @@ } } - QualType elementType = E->getType().getCanonicalType(); - elementType = CGF.getContext().getQualifiedType( - cast(elementType)->getElementType(), - elementType.getQualifiers() + Dest.getQualifiers()); + QualType elementType = + CGF.getContext().getAsArrayType(E->getType())->getElementType(); llvm::PointerType *APType = cast(DestPtr->getType()); Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=151229&r1=151228&r2=151229&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 22 20:25:10 2012 @@ -6226,10 +6226,8 @@ // completed by the initializer. For example: // int ary[] = { 1, 3, 5 }; // "ary" transitions from an IncompleteArrayType to a ConstantArrayType. - if (!VDecl->isInvalidDecl() && (DclT != SavT)) { + if (!VDecl->isInvalidDecl() && (DclT != SavT)) VDecl->setType(DclT); - Init->setType(DclT.getNonReferenceType()); - } // Check any implicit conversions within the expression. CheckImplicitConversions(Init, VDecl->getLocation()); Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=151229&r1=151228&r2=151229&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Feb 22 20:25:10 2012 @@ -604,7 +604,9 @@ CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, Index, StructuredList, StructuredIndex, TopLevelObject); if (!VerifyOnly) { - QualType ExprTy = T.getNonLValueExprType(SemaRef.Context); + QualType ExprTy = T; + if (!ExprTy->isArrayType()) + ExprTy = ExprTy.getNonLValueExprType(SemaRef.Context); IList->setType(ExprTy); StructuredList->setType(ExprTy); } @@ -2077,7 +2079,10 @@ InitRange.getBegin(), 0, 0, InitRange.getEnd()); - Result->setType(CurrentObjectType.getNonLValueExprType(SemaRef.Context)); + QualType ResultType = CurrentObjectType; + if (!ResultType->isArrayType()) + ResultType = ResultType.getNonLValueExprType(SemaRef.Context); + Result->setType(ResultType); // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; Modified: cfe/trunk/test/CodeGenObjC/arc-blocks.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-blocks.m?rev=151229&r1=151228&r2=151229&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/arc-blocks.m (original) +++ cfe/trunk/test/CodeGenObjC/arc-blocks.m Wed Feb 22 20:25:10 2012 @@ -510,3 +510,7 @@ // CHECK-NEXT: ret void } +// +void test14() { + void (^const x[1])(void) = { ^{} }; +} From eli.friedman at gmail.com Wed Feb 22 18:47:46 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 22 Feb 2012 18:47:46 -0800 Subject: [cfe-commits] r149014 - in /cfe/trunk: include/clang/Basic/TokenKinds.def include/clang/Parse/Parser.h lib/Parse/ParsePragma.cpp lib/Parse/Parser.cpp test/CodeGenCXX/pr11797.cpp test/CodeGenCXX/pragma-visibility.cpp In-Reply-To: <20120126020257.7DB4A2A6C12C@llvm.org> References: <20120126020257.7DB4A2A6C12C@llvm.org> Message-ID: On Wed, Jan 25, 2012 at 6:02 PM, Rafael Espindola wrote: > Author: rafael > Date: Wed Jan 25 20:02:57 2012 > New Revision: 149014 > > URL: http://llvm.org/viewvc/llvm-project?rev=149014&view=rev > Log: > Fix our handling of #pragma GCC visibility. > Now the lexer just produces a token and the parser is the one responsible for > activating it. > This fixes problem like the one pr11797 where the lexer and the parser were not > in sync. This also let us be more strict on where in the file we accept > these pragmas. I've run into a case () where #pragma GCC visibility is used inside of a class definition. Do you think this is something we should try to accept? -Eli From aaron at aaronballman.com Wed Feb 22 18:50:30 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Wed, 22 Feb 2012 20:50:30 -0600 Subject: [cfe-commits] [PATCH] A lot of MS declspecs being turned on Message-ID: Instead of doing single patches for all of these, I've put them into a single patch. In each case, all I've done is turn on the declspecs and added test cases to ensure they behave as expected. This patch supports four more low-hanging fruit declspecs. ~Aaron -------------- next part -------------- A non-text attachment was scrubbed... Name: Declspecs.patch Type: application/octet-stream Size: 4618 bytes Desc: not available URL: From dgregor at apple.com Wed Feb 22 19:02:32 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 03:02:32 -0000 Subject: [cfe-commits] r151231 - in /cfe/trunk: lib/Lex/PPMacroExpansion.cpp test/Lexer/has_feature_cxx0x.cpp www/cxx_status.html Message-ID: <20120223030233.0D0BD2A6C12F@llvm.org> Author: dgregor Date: Wed Feb 22 21:02:32 2012 New Revision: 151231 URL: http://llvm.org/viewvc/llvm-project?rev=151231&view=rev Log: Clang now supports lambda expressions. Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp cfe/trunk/test/Lexer/has_feature_cxx0x.cpp cfe/trunk/www/cxx_status.html Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=151231&r1=151230&r2=151231&view=diff ============================================================================== --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Feb 22 21:02:32 2012 @@ -649,7 +649,7 @@ .Case("cxx_implicit_moves", LangOpts.CPlusPlus0x) //.Case("cxx_inheriting_constructors", false) .Case("cxx_inline_namespaces", LangOpts.CPlusPlus0x) - //.Case("cxx_lambdas", false) + .Case("cxx_lambdas", LangOpts.CPlusPlus0x) .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus0x) .Case("cxx_noexcept", LangOpts.CPlusPlus0x) .Case("cxx_nullptr", LangOpts.CPlusPlus0x) Modified: cfe/trunk/test/Lexer/has_feature_cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/has_feature_cxx0x.cpp?rev=151231&r1=151230&r2=151231&view=diff ============================================================================== --- cfe/trunk/test/Lexer/has_feature_cxx0x.cpp (original) +++ cfe/trunk/test/Lexer/has_feature_cxx0x.cpp Wed Feb 22 21:02:32 2012 @@ -16,7 +16,7 @@ int no_lambdas(); #endif -// CHECK-0X: no_lambdas +// CHECK-0X: has_lambdas // CHECK-NO-0X: no_lambdas Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=151231&r1=151230&r2=151231&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Wed Feb 22 21:02:32 2012 @@ -107,9 +107,9 @@ Clang 2.9 - New wording for C++0x lambdas + Lambda expressions N2927 - No + SVN Declared type of an expression From dgregor at apple.com Wed Feb 22 19:10:25 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 03:10:25 -0000 Subject: [cfe-commits] r151232 - /cfe/trunk/www/cxx_status.html Message-ID: <20120223031025.244202A6C12F@llvm.org> Author: dgregor Date: Wed Feb 22 21:10:24 2012 New Revision: 151232 URL: http://llvm.org/viewvc/llvm-project?rev=151232&view=rev Log: Tweak C++ status table: - Apparently, SVN is yellow - Note that initializer lists are "in progress" Modified: cfe/trunk/www/cxx_status.html Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=151232&r1=151231&r2=151232&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Wed Feb 22 21:10:24 2012 @@ -79,7 +79,7 @@ Initializer lists N2672 - No + In progress Static assertions @@ -109,7 +109,7 @@ Lambda expressions N2927 - SVN + SVN Declared type of an expression From rafael.espindola at gmail.com Wed Feb 22 20:17:32 2012 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Thu, 23 Feb 2012 04:17:32 -0000 Subject: [cfe-commits] r151236 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCXX/visibility.cpp Message-ID: <20120223041732.848552A6C12F@llvm.org> Author: rafael Date: Wed Feb 22 22:17:32 2012 New Revision: 151236 URL: http://llvm.org/viewvc/llvm-project?rev=151236&view=rev Log: Two fixes to how we compute visibility: * Handle some situations where we should never make a decl more visible, even when merging in an explicit visibility. * Handle attributes in members of classes that are explicitly specialized. Thanks Nico for the report and testing, Eric for the initial review, and dgregor for the awesome test27 :-) Modified: cfe/trunk/include/clang/AST/Decl.h cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/CodeGenCXX/visibility.cpp Modified: cfe/trunk/include/clang/AST/Decl.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=151236&r1=151235&r2=151236&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Decl.h (original) +++ cfe/trunk/include/clang/AST/Decl.h Wed Feb 22 22:17:32 2012 @@ -251,6 +251,10 @@ mergeLinkage(Other.linkage()); } + // Merge the visibility V giving preference to explicit ones. + // This is used, for example, when merging the visibility of a class + // down to one of its members. If the member has no explicit visibility, + // the class visibility wins. void mergeVisibility(Visibility V, bool E = false) { // If one has explicit visibility and the other doesn't, keep the // explicit one. @@ -262,14 +266,35 @@ // If both are explicit or both are implicit, keep the minimum. setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E); } + // Merge the visibility V, keeping the most restrictive one. + // This is used for cases like merging the visibility of a template + // argument to an instantiation. If we already have a hidden class, + // no argument should give it default visibility. + void mergeVisibilityWithMin(Visibility V, bool E = false) { + // Never increase the visibility + if (visibility() < V) + return; + + // If this visibility is explicit, keep it. + if (visibilityExplicit() && !E) + return; + setVisibility(V, E); + } void mergeVisibility(LinkageInfo Other) { mergeVisibility(Other.visibility(), Other.visibilityExplicit()); } + void mergeVisibilityWithMin(LinkageInfo Other) { + mergeVisibilityWithMin(Other.visibility(), Other.visibilityExplicit()); + } void merge(LinkageInfo Other) { mergeLinkage(Other); mergeVisibility(Other); } + void mergeWithMin(LinkageInfo Other) { + mergeLinkage(Other); + mergeVisibilityWithMin(Other); + } friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) { L.merge(R); Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=151236&r1=151235&r2=151236&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Wed Feb 22 22:17:32 2012 @@ -176,9 +176,9 @@ break; case TemplateArgument::Pack: - LV.merge(getLVForTemplateArgumentList(Args[I].pack_begin(), - Args[I].pack_size(), - F)); + LV.mergeWithMin(getLVForTemplateArgumentList(Args[I].pack_begin(), + Args[I].pack_size(), + F)); break; } } @@ -279,6 +279,7 @@ // scope and no storage-class specifier, its linkage is // external. LinkageInfo LV; + LV.mergeVisibility(Context.getLangOptions().getVisibilityMode()); if (F.ConsiderVisibilityAttributes) { if (llvm::Optional Vis = D->getExplicitVisibility()) { @@ -413,7 +414,7 @@ LV.merge(getLVForDecl(specInfo->getTemplate(), F.onlyTemplateVisibility())); const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; - LV.merge(getLVForTemplateArgumentList(templateArgs, F)); + LV.mergeWithMin(getLVForTemplateArgumentList(templateArgs, F)); } } @@ -439,7 +440,7 @@ // The arguments at which the template was instantiated. const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LV.merge(getLVForTemplateArgumentList(TemplateArgs, F)); + LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs, F)); } } @@ -482,11 +483,6 @@ if (LV.linkage() != ExternalLinkage) return LinkageInfo(LV.linkage(), DefaultVisibility, false); - // If we didn't end up with hidden visibility, consider attributes - // and -fvisibility. - if (F.ConsiderGlobalVisibility) - LV.mergeVisibility(Context.getLangOptions().getVisibilityMode()); - return LV; } @@ -503,6 +499,7 @@ return LinkageInfo::none(); LinkageInfo LV; + LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode()); // The flags we're going to use to compute the class's visibility. LVFlags ClassF = F; @@ -544,7 +541,8 @@ if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { if (shouldConsiderTemplateLV(MD, spec)) { - LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F)); + LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments, + F)); if (F.ConsiderTemplateParameterTypes) LV.merge(getLVForTemplateParameterList( spec->getTemplate()->getTemplateParameters())); @@ -583,7 +581,8 @@ if (shouldConsiderTemplateLV(spec)) { // Merge template argument/parameter information for member // class template specializations. - LV.merge(getLVForTemplateArgumentList(spec->getTemplateArgs(), F)); + LV.mergeWithMin(getLVForTemplateArgumentList(spec->getTemplateArgs(), + F)); if (F.ConsiderTemplateParameterTypes) LV.merge(getLVForTemplateParameterList( spec->getSpecializedTemplate()->getTemplateParameters())); @@ -601,13 +600,6 @@ LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit()); } - F.ConsiderGlobalVisibility &= !LV.visibilityExplicit(); - - // Apply -fvisibility if desired. - if (F.ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) { - LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode()); - } - return LV; } @@ -697,6 +689,12 @@ = fn->getTemplateSpecializationInfo()) return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl()); + // If the function is a member of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom); + return llvm::Optional(); } @@ -711,6 +709,14 @@ = dyn_cast(this)) return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl()); + // If this is a member class of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + if (const CXXRecordDecl *RD = dyn_cast(this)) { + CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom); + } + return llvm::Optional(); } Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=151236&r1=151235&r2=151236&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Feb 22 22:17:32 2012 @@ -5350,6 +5350,7 @@ /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { + // FIXME: "make check" is clean if the call to dropAttrs() is commented out. D->dropAttrs(); if (FunctionDecl *FD = dyn_cast(D)) { Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=151236&r1=151235&r2=151236&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/visibility.cpp (original) +++ cfe/trunk/test/CodeGenCXX/visibility.cpp Wed Feb 22 22:17:32 2012 @@ -5,6 +5,21 @@ #define PROTECTED __attribute__((visibility("protected"))) #define DEFAULT __attribute__((visibility("default"))) +namespace test25 { + template + struct X { + template + struct definition { + }; + }; + + class DEFAULT A { }; + + X::definition a; + // CHECK: @_ZN6test251aE = global + // CHECK-HIDDEN: @_ZN6test251aE = hidden global +} + // CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10 // CHECK: @_ZN5Test71aE = hidden global // CHECK: @_ZN5Test71bE = global @@ -22,6 +37,26 @@ // CHECK-HIDDEN: @_ZN6Test143varE = external global // CHECK: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8] // CHECK-HIDDEN: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8] + +namespace test27 { + template + class C { + class __attribute__((visibility("default"))) D { + void f(); + }; + }; + + template<> + class C::D { + virtual void g(); + }; + + void C::D::g() { + } + // CHECK: _ZTVN6test271CIiE1DE = unnamed_addr constant + // CHECK-HIDDEN: _ZTVN6test271CIiE1DE = unnamed_addr constant +} + // CHECK: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr global // CHECK: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr global i64 // CHECK-HIDDEN: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr hidden global @@ -500,3 +535,65 @@ // CHECK: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv // CHECK-HIDDEN: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv } + +namespace test23 { + // Having a template argument that is explicitly visible should not make + // the template instantiation visible. + template + struct X { + static void f() { + } + }; + + class DEFAULT A; + + void g() { + X y; + y.f(); + } + // CHECK: define linkonce_odr void @_ZN6test231XINS_1AEE1fEv + // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test231XINS_1AEE1fEv +} + +namespace PR12001 { + template + void Bind(const P1& p1) { + } + + class DEFAULT Version { }; + + void f() { + Bind(Version()); + } + // CHECK: define linkonce_odr void @_ZN7PR120014BindINS_7VersionEEEvRKT_ + // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN7PR120014BindINS_7VersionEEEvRKT_ +} + +namespace test24 { + class DEFAULT A { }; + + struct S { + template + void mem() {} + }; + + void test() { + S s; + s.mem(); + } + // CHECK: define linkonce_odr void @_ZN6test241S3memINS_1AEEEvv + // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test241S3memINS_1AEEEvv +} + +namespace test26 { + template + class C { + __attribute__((visibility("default"))) void f(); + }; + + template<> + void C::f() { } + + // CHECK: define void @_ZN6test261CIiE1fEv + // CHECK-HIDDEN: define void @_ZN6test261CIiE1fEv +} From rafael.espindola at gmail.com Wed Feb 22 21:38:01 2012 From: rafael.espindola at gmail.com (=?UTF-8?Q?Rafael_Esp=C3=ADndola?=) Date: Thu, 23 Feb 2012 00:38:01 -0500 Subject: [cfe-commits] r149014 - in /cfe/trunk: include/clang/Basic/TokenKinds.def include/clang/Parse/Parser.h lib/Parse/ParsePragma.cpp lib/Parse/Parser.cpp test/CodeGenCXX/pr11797.cpp test/CodeGenCXX/pragma-visibility.cpp In-Reply-To: References: <20120126020257.7DB4A2A6C12C@llvm.org> Message-ID: > I've run into a case () where #pragma GCC > visibility is used inside of a class definition.  Do you think this is > something we should try to accept? I guess it is OK if it is opened at the class level and closed at the class level. For example, it is probably OK to accept class foo { static int a; #pragma ... push ... static int b; #pragma ... pop }; but reject if the push or pop is missing or if they are inside a method for example. > -Eli Cheers, Rafael From dgregor at apple.com Wed Feb 22 21:44:09 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 05:44:09 -0000 Subject: [cfe-commits] r151239 - /cfe/trunk/docs/LanguageExtensions.html Message-ID: <20120223054409.EE3682A6C12F@llvm.org> Author: dgregor Date: Wed Feb 22 23:44:09 2012 New Revision: 151239 URL: http://llvm.org/viewvc/llvm-project?rev=151239&view=rev Log: Clang supports lambdas. Modified: cfe/trunk/docs/LanguageExtensions.html Modified: cfe/trunk/docs/LanguageExtensions.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.html?rev=151239&r1=151238&r2=151239&view=diff ============================================================================== --- cfe/trunk/docs/LanguageExtensions.html (original) +++ cfe/trunk/docs/LanguageExtensions.html Wed Feb 22 23:44:09 2012 @@ -728,7 +728,7 @@

    Use __has_feature(cxx_lambdas) or __has_extension(cxx_lambdas) to determine if support for lambdas -is enabled. Clang does not currently implement this feature.

    +is enabled.

    C++11 noexcept

    From dgregor at apple.com Wed Feb 22 23:33:15 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 07:33:15 -0000 Subject: [cfe-commits] r151240 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/Basic/TokenKinds.def include/clang/Basic/TypeTraits.h lib/AST/Expr.cpp lib/AST/StmtPrinter.cpp lib/Lex/PPMacroExpansion.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/ParseTentative.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/type-traits.cpp Message-ID: <20120223073316.22F8F2A6C12F@llvm.org> Author: dgregor Date: Thu Feb 23 01:33:15 2012 New Revision: 151240 URL: http://llvm.org/viewvc/llvm-project?rev=151240&view=rev Log: Provide the __is_trivially_assignable type trait, which provides compiler support for the std::is_trivially_assignable library type trait. Modified: cfe/trunk/include/clang/AST/Expr.h cfe/trunk/include/clang/Basic/TokenKinds.def cfe/trunk/include/clang/Basic/TypeTraits.h cfe/trunk/lib/AST/Expr.cpp cfe/trunk/lib/AST/StmtPrinter.cpp cfe/trunk/lib/Lex/PPMacroExpansion.cpp cfe/trunk/lib/Parse/ParseExpr.cpp cfe/trunk/lib/Parse/ParseExprCXX.cpp cfe/trunk/lib/Parse/ParseTentative.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/SemaCXX/type-traits.cpp Modified: cfe/trunk/include/clang/AST/Expr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Expr.h (original) +++ cfe/trunk/include/clang/AST/Expr.h Thu Feb 23 01:33:15 2012 @@ -512,6 +512,10 @@ /// variable read. bool HasSideEffects(const ASTContext &Ctx) const; + /// \brief Determine whether this expression involves a call to any function + /// that is not trivial. + bool hasNonTrivialCall(ASTContext &Ctx); + /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded /// integer. This must be called on an expression that constant folds to an /// integer. Modified: cfe/trunk/include/clang/Basic/TokenKinds.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) +++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Feb 23 01:33:15 2012 @@ -366,6 +366,7 @@ // Clang-only C++ Type Traits KEYWORD(__is_trivially_copyable , KEYCXX) +KEYWORD(__is_trivially_assignable , KEYCXX) KEYWORD(__underlying_type , KEYCXX) // Embarcadero Expression Traits Modified: cfe/trunk/include/clang/Basic/TypeTraits.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TypeTraits.h (original) +++ cfe/trunk/include/clang/Basic/TypeTraits.h Thu Feb 23 01:33:15 2012 @@ -68,7 +68,8 @@ BTT_IsConvertible, BTT_IsConvertibleTo, BTT_IsSame, - BTT_TypeCompatible + BTT_TypeCompatible, + BTT_IsTriviallyAssignable }; /// ArrayTypeTrait - Names for the array type traits. Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Thu Feb 23 01:33:15 2012 @@ -18,6 +18,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/LiteralSupport.h" @@ -2664,6 +2665,60 @@ return isEvaluatable(Ctx); } +namespace { + /// \brief Look for a call to a non-trivial function within an expression. + class NonTrivialCallFinder : public EvaluatedExprVisitor + { + typedef EvaluatedExprVisitor Inherited; + + bool NonTrivial; + + public: + explicit NonTrivialCallFinder(ASTContext &Context) + : EvaluatedExprVisitor(Context), NonTrivial(false) { } + + bool hasNonTrivialCall() const { return NonTrivial; } + + void VisitCallExpr(CallExpr *E) { + if (CXXMethodDecl *Method + = dyn_cast_or_null(E->getCalleeDecl())) { + if (Method->isTrivial()) { + // Recurse to children of the call. + Inherited::VisitStmt(E); + return; + } + } + + NonTrivial = true; + } + + void VisitCXXConstructExpr(CXXConstructExpr *E) { + if (E->getConstructor()->isTrivial()) { + // Recurse to children of the call. + Inherited::VisitStmt(E); + return; + } + + NonTrivial = true; + } + + void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + if (E->getTemporary()->getDestructor()->isTrivial()) { + Inherited::VisitStmt(E); + return; + } + + NonTrivial = true; + } + }; +} + +bool Expr::hasNonTrivialCall(ASTContext &Ctx) { + NonTrivialCallFinder Finder(Ctx); + Finder.Visit(this); + return Finder.hasNonTrivialCall(); +} + /// isNullPointerConstant - C99 6.3.2.3p3 - Return whether this is a null /// pointer constant or not, as well as the specific kind of constant detected. /// Null pointer constants can be integer constant expressions with the Modified: cfe/trunk/lib/AST/StmtPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtPrinter.cpp (original) +++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu Feb 23 01:33:15 2012 @@ -1545,11 +1545,12 @@ static const char *getTypeTraitName(BinaryTypeTrait BTT) { switch (BTT) { - case BTT_IsBaseOf: return "__is_base_of"; - case BTT_IsConvertible: return "__is_convertible"; - case BTT_IsSame: return "__is_same"; - case BTT_TypeCompatible: return "__builtin_types_compatible_p"; - case BTT_IsConvertibleTo: return "__is_convertible_to"; + case BTT_IsBaseOf: return "__is_base_of"; + case BTT_IsConvertible: return "__is_convertible"; + case BTT_IsSame: return "__is_same"; + case BTT_TypeCompatible: return "__builtin_types_compatible_p"; + case BTT_IsConvertibleTo: return "__is_convertible_to"; + case BTT_IsTriviallyAssignable: return "__is_trivially_assignable"; } llvm_unreachable("Binary type trait not covered by switch"); } Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Feb 23 01:33:15 2012 @@ -700,6 +700,7 @@ != tok::identifier) .Case("is_polymorphic", LangOpts.CPlusPlus) .Case("is_trivial", LangOpts.CPlusPlus) + .Case("is_trivially_assignable", LangOpts.CPlusPlus) .Case("is_trivially_copyable", LangOpts.CPlusPlus) .Case("is_union", LangOpts.CPlusPlus) .Case("modules", LangOpts.Modules) Modified: cfe/trunk/lib/Parse/ParseExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) +++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Feb 23 01:33:15 2012 @@ -1140,6 +1140,7 @@ case tok::kw___is_same: case tok::kw___is_convertible: case tok::kw___is_convertible_to: + case tok::kw___is_trivially_assignable: return ParseBinaryTypeTrait(); case tok::kw___array_rank: Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Feb 23 01:33:15 2012 @@ -2454,6 +2454,7 @@ case tok::kw___is_same: return BTT_IsSame; case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible; case tok::kw___is_convertible_to: return BTT_IsConvertibleTo; + case tok::kw___is_trivially_assignable: return BTT_IsTriviallyAssignable; } } Modified: cfe/trunk/lib/Parse/ParseTentative.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTentative.cpp (original) +++ cfe/trunk/lib/Parse/ParseTentative.cpp Thu Feb 23 01:33:15 2012 @@ -689,6 +689,7 @@ case tok::kw___is_pod: case tok::kw___is_polymorphic: case tok::kw___is_trivial: + case tok::kw___is_trivially_assignable: case tok::kw___is_trivially_copyable: case tok::kw___is_union: case tok::kw___uuidof: Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Feb 23 01:33:15 2012 @@ -3301,6 +3301,54 @@ ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); } + + case BTT_IsTriviallyAssignable: { + // C++11 [meta.unary.prop]p3: + // is_trivially_assignable is defined as: + // is_assignable::value is true and the assignment, as defined by + // is_assignable, is known to call no operation that is not trivial + // + // is_assignable is defined as: + // The expression declval() = declval() is well-formed when + // treated as an unevaluated operand (Clause 5). + // + // For both, T and U shall be complete types, (possibly cv-qualified) + // void, or arrays of unknown bound. + if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() && + Self.RequireCompleteType(KeyLoc, LhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() && + Self.RequireCompleteType(KeyLoc, RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + + // cv void is never assignable. + if (LhsT->isVoidType() || RhsT->isVoidType()) + return false; + + // Build expressions that emulate the effect of declval() and + // declval(). + if (LhsT->isObjectType() || LhsT->isFunctionType()) + LhsT = Self.Context.getRValueReferenceType(LhsT); + if (RhsT->isObjectType() || RhsT->isFunctionType()) + RhsT = Self.Context.getRValueReferenceType(RhsT); + OpaqueValueExpr Lhs(KeyLoc, LhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(LhsT)); + OpaqueValueExpr Rhs(KeyLoc, RhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(RhsT)); + + // Attempt the assignment in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated); + Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); + ExprResult Result = Self.BuildBinOp(/*S=*/0, KeyLoc, BO_Assign, &Lhs, &Rhs); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return false; + + return !Result.get()->hasNonTrivialCall(Self.Context); + } } llvm_unreachable("Unknown type trait or not implemented"); } @@ -3333,6 +3381,7 @@ case BTT_IsSame: ResultType = Context.BoolTy; break; case BTT_TypeCompatible: ResultType = Context.IntTy; break; case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break; + case BTT_IsTriviallyAssignable: ResultType = Context.BoolTy; } return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo, Modified: cfe/trunk/test/SemaCXX/type-traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=151240&r1=151239&r2=151240&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/type-traits.cpp (original) +++ cfe/trunk/test/SemaCXX/type-traits.cpp Thu Feb 23 01:33:15 2012 @@ -39,6 +39,14 @@ struct HasCons { HasCons(int); }; struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); }; struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; +struct HasDefaultTrivialCopyAssign { + HasDefaultTrivialCopyAssign &operator =(const HasDefaultTrivialCopyAssign&) + = default; +}; +struct TrivialMoveButNotCopy { + TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default; + TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&); +}; struct HasDest { ~HasDest(); }; class HasPriv { int priv; }; class HasProt { protected: int prot; }; @@ -1637,6 +1645,39 @@ { int arr[F(__is_trivially_copyable(DerivesHasVirt))]; } { int arr[F(__is_trivially_copyable(void))]; } { int arr[F(__is_trivially_copyable(cvoid))]; } + + { int arr[T((__is_trivially_assignable(int&, int)))]; } + { int arr[T((__is_trivially_assignable(int&, int&)))]; } + { int arr[T((__is_trivially_assignable(int&, int&&)))]; } + { int arr[T((__is_trivially_assignable(int&, const int&)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD&)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; } + { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; } + { int arr[T((__is_trivially_assignable(int*&, int*)))]; } + + { int arr[F((__is_trivially_assignable(int*&, float*)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, const HasCopyAssign&)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&&)))]; } + { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, + TrivialMoveButNotCopy&)))]; } + { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, + const TrivialMoveButNotCopy&)))]; } + + // FIXME: The following answers are wrong, because we don't properly + // mark user-declared constructors/assignment operators/destructors + // that are defaulted on their first declaration as trivial when we + // can. + { int arr[F((__is_trivially_assignable(HasDefaultTrivialCopyAssign&, + HasDefaultTrivialCopyAssign&)))]; } + { int arr[F((__is_trivially_assignable(HasDefaultTrivialCopyAssign&, + const HasDefaultTrivialCopyAssign&)))]; } + { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, + TrivialMoveButNotCopy)))]; } + { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, + TrivialMoveButNotCopy&&)))]; } } void array_rank() { From dgregor at apple.com Wed Feb 22 23:44:18 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 07:44:18 -0000 Subject: [cfe-commits] r151241 - /cfe/trunk/lib/AST/Expr.cpp Message-ID: <20120223074418.97E372A6C12F@llvm.org> Author: dgregor Date: Thu Feb 23 01:44:18 2012 New Revision: 151241 URL: http://llvm.org/viewvc/llvm-project?rev=151241&view=rev Log: Seriously, are injected-class-names that hard? Modified: cfe/trunk/lib/AST/Expr.cpp Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151241&r1=151240&r2=151241&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Thu Feb 23 01:44:18 2012 @@ -2675,7 +2675,7 @@ public: explicit NonTrivialCallFinder(ASTContext &Context) - : EvaluatedExprVisitor(Context), NonTrivial(false) { } + : Inherited(Context), NonTrivial(false) { } bool hasNonTrivialCall() const { return NonTrivial; } From richard-llvm at metafoo.co.uk Thu Feb 23 00:33:24 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Thu, 23 Feb 2012 08:33:24 -0000 Subject: [cfe-commits] r151245 - in /cfe/trunk: lib/CodeGen/CGExprConstant.cpp test/CodeGenCXX/const-init-cxx11.cpp Message-ID: <20120223083324.3F4752A6C130@llvm.org> Author: rsmith Date: Thu Feb 23 02:33:23 2012 New Revision: 151245 URL: http://llvm.org/viewvc/llvm-project?rev=151245&view=rev Log: PR12067: When emitting an evaluated constant structure in C++11 mode, don't forget the vptrs. Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=151245&r1=151244&r2=151245&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Feb 23 02:33:23 2012 @@ -53,9 +53,14 @@ NextFieldOffsetInChars(CharUnits::Zero()), LLVMStructAlignment(CharUnits::One()) { } + void AppendVTablePointer(BaseSubobject Base, llvm::Constant *VTable, + const CXXRecordDecl *VTableClass); + void AppendField(const FieldDecl *Field, uint64_t FieldOffset, llvm::Constant *InitExpr); + void AppendBytes(CharUnits FieldOffsetInChars, llvm::Constant *InitCst); + void AppendBitField(const FieldDecl *Field, uint64_t FieldOffset, llvm::ConstantInt *InitExpr); @@ -66,7 +71,9 @@ void ConvertStructToPacked(); bool Build(InitListExpr *ILE); - void Build(const APValue &Val, QualType ValTy); + void Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase, + llvm::Constant *VTable, const CXXRecordDecl *VTableClass, + CharUnits BaseOffset); llvm::Constant *Finalize(QualType Ty); CharUnits getAlignment(const llvm::Constant *C) const { @@ -81,14 +88,36 @@ } }; +void ConstStructBuilder::AppendVTablePointer(BaseSubobject Base, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass) { + // Find the appropriate vtable within the vtable group. + uint64_t AddressPoint = + CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base); + llvm::Value *Indices[] = { + llvm::ConstantInt::get(CGM.Int64Ty, 0), + llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint) + }; + llvm::Constant *VTableAddressPoint = + llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices); + + // Add the vtable at the start of the object. + AppendBytes(CharUnits::Zero(), VTableAddressPoint); +} + void ConstStructBuilder:: AppendField(const FieldDecl *Field, uint64_t FieldOffset, llvm::Constant *InitCst) { - const ASTContext &Context = CGM.getContext(); CharUnits FieldOffsetInChars = Context.toCharUnitsFromBits(FieldOffset); + AppendBytes(FieldOffsetInChars, InitCst); +} + +void ConstStructBuilder:: +AppendBytes(CharUnits FieldOffsetInChars, llvm::Constant *InitCst) { + assert(NextFieldOffsetInChars <= FieldOffsetInChars && "Field offset mismatch!"); @@ -399,23 +428,56 @@ return true; } -void ConstStructBuilder::Build(const APValue &Val, QualType ValTy) { - RecordDecl *RD = ValTy->getAs()->getDecl(); +namespace { +struct BaseInfo { + BaseInfo(const CXXRecordDecl *Decl, CharUnits Offset, unsigned Index) + : Decl(Decl), Offset(Offset), Index(Index) { + } + + const CXXRecordDecl *Decl; + CharUnits Offset; + unsigned Index; + + bool operator<(const BaseInfo &O) const { return Offset < O.Offset; } +}; +} + +void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, + bool IsPrimaryBase, llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + CharUnits Offset) { const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - if (CXXRecordDecl *CD = dyn_cast(RD)) { + if (const CXXRecordDecl *CD = dyn_cast(RD)) { + // Add a vtable pointer, if we need one and it hasn't already been added. + if (CD->isDynamicClass() && !IsPrimaryBase) + AppendVTablePointer(BaseSubobject(CD, Offset), VTable, VTableClass); + + // Accumulate and sort bases, in order to visit them in address order, which + // may not be the same as declaration order. + llvm::SmallVector Bases; + Bases.reserve(CD->getNumBases()); unsigned BaseNo = 0; - for (CXXRecordDecl::base_class_iterator Base = CD->bases_begin(), + for (CXXRecordDecl::base_class_const_iterator Base = CD->bases_begin(), BaseEnd = CD->bases_end(); Base != BaseEnd; ++Base, ++BaseNo) { - // Build the base class subobject at the appropriately-offset location - // within this object. + assert(!Base->isVirtual() && "should not have virtual bases here"); const CXXRecordDecl *BD = Base->getType()->getAsCXXRecordDecl(); CharUnits BaseOffset = Layout.getBaseClassOffset(BD); - NextFieldOffsetInChars -= BaseOffset; + Bases.push_back(BaseInfo(BD, BaseOffset, BaseNo)); + } + std::stable_sort(Bases.begin(), Bases.end()); - Build(Val.getStructBase(BaseNo), Base->getType()); + for (unsigned I = 0, N = Bases.size(); I != N; ++I) { + BaseInfo &Base = Bases[I]; + // Build the base class subobject at the appropriately-offset location + // within this object. + NextFieldOffsetInChars -= Base.Offset; + + bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl; + Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase, + VTable, VTableClass, Offset + Base.Offset); - NextFieldOffsetInChars += BaseOffset; + NextFieldOffsetInChars += Base.Offset; } } @@ -532,7 +594,15 @@ const APValue &Val, QualType ValTy) { ConstStructBuilder Builder(CGM, CGF); - Builder.Build(Val, ValTy); + + const RecordDecl *RD = ValTy->castAs()->getDecl(); + const CXXRecordDecl *CD = dyn_cast(RD); + llvm::Constant *VTable = 0; + if (CD && CD->isDynamicClass()) + VTable = CGM.getVTables().GetAddrOfVTable(CD); + + Builder.Build(Val, RD, false, VTable, CD, CharUnits::Zero()); + return Builder.Finalize(ValTy); } Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp?rev=151245&r1=151244&r2=151245&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp (original) +++ cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Thu Feb 23 02:33:23 2012 @@ -254,6 +254,42 @@ } } +// PR12067 +namespace VirtualMembers { + struct A { + constexpr A(double d) : d(d) {} + virtual void f(); + double d; + }; + struct B : A { + constexpr B() : A(2.0), c{'h', 'e', 'l', 'l', 'o'} {} + constexpr B(int n) : A(n), c{'w', 'o', 'r', 'l', 'd'} {} + virtual void g(); + char c[5]; + }; + struct C { + constexpr C() : n(64) {} + int n; + }; + struct D : C, A, B { + constexpr D() : A(1.0), B(), s(5) {} + short s; + }; + struct E : D, B { + constexpr E() : B(3), c{'b','y','e'} {} + char c[3]; + }; + + // CHECK: @_ZN14VirtualMembers1eE = global { i8**, double, i32, i8**, double, [5 x i8], i16, i8**, double, [5 x i8], [3 x i8] } { i8** getelementptr inbounds ([11 x i8*]* @_ZTVN14VirtualMembers1EE, i64 0, i64 2), double 1.000000e+00, i32 64, i8** getelementptr inbounds ([11 x i8*]* @_ZTVN14VirtualMembers1EE, i64 0, i64 5), double 2.000000e+00, [5 x i8] c"hello", i16 5, i8** getelementptr inbounds ([11 x i8*]* @_ZTVN14VirtualMembers1EE, i64 0, i64 9), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" } + E e; + + struct nsMemoryImpl { + virtual void f(); + }; + // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ([3 x i8*]* @_ZTVN14VirtualMembers12nsMemoryImplE, i64 0, i64 2) } + static nsMemoryImpl sGlobalMemory; +} + // Constant initialization tests go before this point, // dynamic initialization tests go after. From James.Molloy at arm.com Thu Feb 23 02:18:52 2012 From: James.Molloy at arm.com (James Molloy) Date: Thu, 23 Feb 2012 10:18:52 +0000 Subject: [cfe-commits] FW: [PATCH] Fix tag decls/enum constants in function prototypes In-Reply-To: References: <4f16ec2f.aab9ec0a.6aee.0e1aSMTPIN_ADDED@mx.google.com> <4f2132d1.8761b40a.4bc2.7a6dSMTPIN_ADDED@mx.google.com> , Message-ID: Hi all, This patch was reviewed by Chandler in January - I pinged him for a round 2 review but he hasn't done it in a month. Could I please ask someone else on the list to perform it? Cheers in advance, James ________________________________________ From: James Molloy [james.molloy at arm.com] Sent: 27 January 2012 17:31 To: Chandler Carruth Cc: cfe-commits at cs.uiuc.edu; juli at clockworksquid.com; ken.dyck at onsemi.com Subject: RE: [cfe-commits] [PATCH] Fix tag decls/enum constants in function prototypes Hi Chandler, > Interesting... Maybe we're already visiting them somewhere else, perhaps in the outer decl context? It'd be good to verify what's going on here. It's unclear to me whether this requires no change, strictly an additive change (visit these things), or moving the visit that exists to occur at the right point in the visitation sequence.... It was unclear to me too, so I have investigated it. All of the visitors/dumpers were already visiting these tags. This is because the issue is purely to do with scoping - the tag was still attached to the ParmVarDecl as its Type, so was already being visited. For example: "void f(enum {X} p)" - the ast printer prints "void f( p)". It would also however print the contents of the enum at the translation unit scope. This is due to a hack in the parser that hangs such tags on the translation unit because no proper declcontext is available at that point. I've modified my code so it catches this and unhooks them from the translation unit, so they don't get visited twice and the output is better. I have also modified the XML dumper to print these tags, which it wasn't currently doing (aside: is the XML dumper deprecated?) I think I've covered all your other points - I'm going to add a warning group -Wvisibility, which will cover the two warnings mentioned (warn_decl_in_param_list and the new warn_redefinition_in_param_list). Hopefully this should be OK now? Cheers, James From: Chandler Carruth [mailto:chandlerc at google.com] Sent: 26 January 2012 11:17 To: James Molloy Cc: cfe-commits at cs.uiuc.edu; juli at clockworksquid.com; ken.dyck at onsemi.com Subject: Re: [cfe-commits] [PATCH] Fix tag decls/enum constants in function prototypes On Thu, Jan 26, 2012 at 3:01 AM, James Molloy wrote: No problem. This is a convention in LLVM’s test dirs Just as an FYI, I think the convention is going away even in LLVM. Many new tests getting added don't have a date, and I'm hoping to see a continuing trend away from them. Separation of concerns is good. Yes, I’m adding a new warning that has no flag, but it’s essentially a clone of another warning with one verb different that currently has no flag. Do you suggest I add the flag to cover both the old and new warnings in the same patch? I can do it as a followup and I’d prefer that if possible. This is a tricky point. The thing is that this file is specifically designed to prevent the slow creep for the reasons you describe. The logic you use got us into a bad state where most warnings don't have flags. That said, I support separate commits, I would just invert the order. Add the flag to the existing warning, and remove it from the file, then proceed with this patch, using the newly available flag. That way the test policy is maintained and it never shrinks. It's a bit of a refactoring tax, but probably a healthy one considering how bad this got. - You need to add visiting logic for all of these decls to the various visitors I suspect. We have several, I'd have to go looking to enumerate all of them. Off the top of my head I would check: - RecursiveASTVisitor descends into these decls. - The various printing and dumping visitors catch them - The CFG builder handles them (not sure how much it really has to care) - Maybe update libclang? Not likely important for the first pass. Thanks for catching this – I didn’t think it would be required. I’ll ensure everything acts as it should, although I’m not sure how much effect this will have. The decls already existed previously, just were in the wrong scope. Interesting... Maybe we're already visiting them somewhere else, perhaps in the outer decl context? It'd be good to verify what's going on here. It's unclear to me whether this requires no change, strictly an additive change (visit these things), or moving the visit that exists to occur at the right point in the visitation sequence.... Looking at the output of AST dump with some obvious test cases will likely make it obvious what the right thing is to do here. It’s raw new’d for the reason you state. I didn’t use arrayref because the existing code for ParmVarDecl (see diff context) also doesn’t use ArrayRef. I copied its interface completely, assuming (for better or worse) that it was designed that way for a reason. Hmm, I fear this may not be a good assumption. ;] Technically, ArrayRef isn't as good of a fit for the Parm ones because we have external knowledge about how many of those there are. Using an arrayref would waste at least 4 bytes of storage. Since you need both the pointer and the size, might as well use ArrayRef. Here and below where the same issue arose, I would encourage you to use the simplest and most minimal interface that works for your use case. If the surrounding code has a more complex pattern that isn't actually needed, let's simplify that as well to get consistency. (Naturally, I would do that in a separate patch, it can even be another 'pre factoring' patch if you will). I don't want us to become complacent in the pursuit of consistency and miss opportunities to use better and/or simpler interfaces. -- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. -------------- next part -------------- A non-text attachment was scrubbed... Name: enum_patch_v2.diff Type: application/octet-stream Size: 16020 bytes Desc: enum_patch_v2.diff URL: From sebastian.redl at getdesigned.at Thu Feb 23 04:02:15 2012 From: sebastian.redl at getdesigned.at (Sebastian Redl) Date: Thu, 23 Feb 2012 13:02:15 +0100 Subject: [cfe-commits] r151172 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/new-array-init-exceptions.cpp In-Reply-To: <718EBC33-FE3A-48AB-93D6-1490922F704C@apple.com> References: <20120222173759.8CE752A6C130@llvm.org> <718EBC33-FE3A-48AB-93D6-1490922F704C@apple.com> Message-ID: <4F462AC7.1010309@getdesigned.at> On 22.02.2012 21:46, Chad Rosier wrote: > Hi Sebastian, > The test you added here is failing on one of our internal buildbots. > > Here's the exact errors: > ******************** TEST 'Clang :: CodeGenCXX/new-array-init-exceptions.cpp' FAILED ********************Script: > -- > /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang-build/Release/bin/clang -cc1 -internal-isystem /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang-build/Release/bin/../lib/clang/3.1/include -std=c++11 -triple i386-unknown-unknown -fexceptions -fcxx-exceptions /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp -emit-llvm -o - | FileCheck /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp > -- > Exit Code: 1 > Command Output (stderr): > -- > /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp:20:12: error: expected string not found in input > // CHECK: [[LPAD]]: > ^ > :56:1: note: scanning from here > ;
    N2927 > - No > + SVN > > > Declared type of an expression > > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From dgregor at apple.com Thu Feb 23 09:51:51 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 17:51:51 -0000 Subject: [cfe-commits] r151263 - /cfe/trunk/docs/ReleaseNotes.html Message-ID: <20120223175152.190EC2A6C12F@llvm.org> Author: dgregor Date: Thu Feb 23 11:51:51 2012 New Revision: 151263 URL: http://llvm.org/viewvc/llvm-project?rev=151263&view=rev Log: Note that lambda expressions are available in the release notes for 3.1 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=151263&r1=151262&r2=151263&view=diff ============================================================================== --- cfe/trunk/docs/ReleaseNotes.html (original) +++ cfe/trunk/docs/ReleaseNotes.html Thu Feb 23 11:51:51 2012 @@ -121,8 +121,8 @@ following are now considered to be of production quality:
    • Generalized constant expressions
    • +
    • Lambda expressions
    From dgregor at apple.com Thu Feb 23 09:57:11 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 09:57:11 -0800 Subject: [cfe-commits] r151231 - in /cfe/trunk: lib/Lex/PPMacroExpansion.cpp test/Lexer/has_feature_cxx0x.cpp www/cxx_status.html In-Reply-To: References: <20120223030233.0D0BD2A6C12F@llvm.org> Message-ID: On Feb 23, 2012, at 9:47 AM, Chris Lattner wrote: > > On Feb 22, 2012, at 7:02 PM, Douglas Gregor wrote: > >> Author: dgregor >> Date: Wed Feb 22 21:02:32 2012 >> New Revision: 151231 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=151231&view=rev >> Log: >> Clang now supports lambda expressions. > > Wewt! Release note? :) r151263. - Doug > -Chris > >> >> Modified: >> cfe/trunk/lib/Lex/PPMacroExpansion.cpp >> cfe/trunk/test/Lexer/has_feature_cxx0x.cpp >> cfe/trunk/www/cxx_status.html >> >> Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=151231&r1=151230&r2=151231&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) >> +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Feb 22 21:02:32 2012 >> @@ -649,7 +649,7 @@ >> .Case("cxx_implicit_moves", LangOpts.CPlusPlus0x) >> //.Case("cxx_inheriting_constructors", false) >> .Case("cxx_inline_namespaces", LangOpts.CPlusPlus0x) >> - //.Case("cxx_lambdas", false) >> + .Case("cxx_lambdas", LangOpts.CPlusPlus0x) >> .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus0x) >> .Case("cxx_noexcept", LangOpts.CPlusPlus0x) >> .Case("cxx_nullptr", LangOpts.CPlusPlus0x) >> >> Modified: cfe/trunk/test/Lexer/has_feature_cxx0x.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/has_feature_cxx0x.cpp?rev=151231&r1=151230&r2=151231&view=diff >> ============================================================================== >> --- cfe/trunk/test/Lexer/has_feature_cxx0x.cpp (original) >> +++ cfe/trunk/test/Lexer/has_feature_cxx0x.cpp Wed Feb 22 21:02:32 2012 >> @@ -16,7 +16,7 @@ >> int no_lambdas(); >> #endif >> >> -// CHECK-0X: no_lambdas >> +// CHECK-0X: has_lambdas >> // CHECK-NO-0X: no_lambdas >> >> >> >> Modified: cfe/trunk/www/cxx_status.html >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=151231&r1=151230&r2=151231&view=diff >> ============================================================================== >> --- cfe/trunk/www/cxx_status.html (original) >> +++ cfe/trunk/www/cxx_status.html Wed Feb 22 21:02:32 2012 >> @@ -107,9 +107,9 @@ >> Clang 2.9 >> >> >> - New wording for C++0x lambdas >> + Lambda expressions >> N2927 >> - No >> + SVN >> >> >> Declared type of an expression >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > From dgregor at apple.com Thu Feb 23 09:54:00 2012 From: dgregor at apple.com (Douglas Gregor) Date: Thu, 23 Feb 2012 17:54:00 -0000 Subject: [cfe-commits] r151264 - /cfe/trunk/docs/ReleaseNotes.html Message-ID: <20120223175400.5E5A52A6C12F@llvm.org> Author: dgregor Date: Thu Feb 23 11:54:00 2012 New Revision: 151264 URL: http://llvm.org/viewvc/llvm-project?rev=151264&view=rev Log: Fix indentation 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=151264&r1=151263&r2=151264&view=diff ============================================================================== --- cfe/trunk/docs/ReleaseNotes.html (original) +++ cfe/trunk/docs/ReleaseNotes.html Thu Feb 23 11:54:00 2012 @@ -121,7 +121,7 @@ following are now considered to be of production quality:
    • Generalized constant expressions
    • -
    • Lambda expressions
    • +
    • Lambda expressions
    • From eli.friedman at gmail.com Thu Feb 23 10:11:40 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Thu, 23 Feb 2012 10:11:40 -0800 Subject: [cfe-commits] r151255 - /cfe/trunk/lib/AST/CXXInheritance.cpp In-Reply-To: <20120223151831.4FDC82A6C12F@llvm.org> References: <20120223151831.4FDC82A6C12F@llvm.org> Message-ID: On Thu, Feb 23, 2012 at 7:18 AM, Benjamin Kramer wrote: > Author: d0k > Date: Thu Feb 23 09:18:31 2012 > New Revision: 151255 > > URL: http://llvm.org/viewvc/llvm-project?rev=151255&view=rev > Log: > Unique CXXBasePath decls with the SmallVector/pod_sort/std::unique idiom instead of employing a wasteful std::set. > > Modified: >    cfe/trunk/lib/AST/CXXInheritance.cpp > > Modified: cfe/trunk/lib/AST/CXXInheritance.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXInheritance.cpp?rev=151255&r1=151254&r2=151255&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/CXXInheritance.cpp (original) > +++ cfe/trunk/lib/AST/CXXInheritance.cpp Thu Feb 23 09:18:31 2012 > @@ -23,12 +23,15 @@ >  void CXXBasePaths::ComputeDeclsFound() { >   assert(NumDeclsFound == 0 && !DeclsFound && >          "Already computed the set of declarations"); > - > -  std::set Decls; > -  for (CXXBasePaths::paths_iterator Path = begin(), PathEnd = end(); > -       Path != PathEnd; ++Path) > -    Decls.insert(*Path->Decls.first); > - > + > +  SmallVector Decls; > +  for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) > +    Decls.push_back(*Path->Decls.first); > + > +  // Eliminate duplicated decls. > +  llvm::array_pod_sort(Decls.begin(), Decls.end()); > +  std::unique(Decls.begin(), Decls.end()); Does this usage of std::unique actually do the right thing? You never actually shrink the SmallVector. -Eli From fjahanian at apple.com Thu Feb 23 10:21:25 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Thu, 23 Feb 2012 18:21:25 -0000 Subject: [cfe-commits] r151268 - in /cfe/trunk: lib/Sema/SemaObjCProperty.cpp test/CodeGenObjC/auto-property-synthesize-protocol.m Message-ID: <20120223182125.66ABD2A6C12F@llvm.org> Author: fjahanian Date: Thu Feb 23 12:21:25 2012 New Revision: 151268 URL: http://llvm.org/viewvc/llvm-project?rev=151268&view=rev Log: objective-c default synthesis. classes which adopt protocol properties must still auto synthesize those propeties which have been redeclared in the class. // rdar://10907410 Added: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=151268&r1=151267&r2=151268&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original) +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Thu Feb 23 12:21:25 2012 @@ -1277,7 +1277,8 @@ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), E = PDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Prop = (*P); - PropMap[Prop->getIdentifier()] = Prop; + if (!PropMap.count(Prop->getIdentifier())) + PropMap[Prop->getIdentifier()] = Prop; } // scan through protocol's protocols. for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), Added: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m?rev=151268&view=auto ============================================================================== --- cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m (added) +++ cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Thu Feb 23 12:21:25 2012 @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fobjc-default-synthesize-properties -emit-llvm %s -o - | FileCheck %s +// rdar://10907410 + + at protocol P + at optional + at property int auto_opt_window; + at property int no_auto_opt_window; + + at required + at property int auto_req_window; + at property int no_auto_req_window; // expected-note {{property declared here}} + at end + + at interface I

      + at property int auto_opt_window; + at property int auto_req_window; + at end + + at implementation I // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}} + at end + +// CHECK: define internal i32 @"\01-[I auto_req_window]"( +// CHECK: define internal void @"\01-[I setAuto_req_window:]"( +// CHECK: define internal i32 @"\01-[I auto_opt_window]"( +// CHECK: define internal void @"\01-[I setAuto_opt_window:]"( + +// CHECK-NOT: define internal i32 @"\01-[I no_auto_opt_window]"( +// CHECK-NOT: define internal void @"\01-[I setNo_auto_opt_window:]"( +// CHECK-NOT: define internal i32 @"\01-[I no_auto_req_window]"( +// CHECK-NOT: define internal void @"\01-[I setNo_auto_req_window:]"( From fjahanian at apple.com Thu Feb 23 10:28:18 2012 From: fjahanian at apple.com (jahanian) Date: Thu, 23 Feb 2012 10:28:18 -0800 Subject: [cfe-commits] r151268 - in /cfe/trunk: lib/Sema/SemaObjCProperty.cpp test/CodeGenObjC/auto-property-synthesize-protocol.m In-Reply-To: <20120223182125.66ABD2A6C12F@llvm.org> References: <20120223182125.66ABD2A6C12F@llvm.org> Message-ID: <29AC8CBA-3AD2-42BC-A3F2-9C70164AF3FE@apple.com> On Feb 23, 2012, at 10:21 AM, Fariborz Jahanian wrote: > Author: fjahanian > Date: Thu Feb 23 12:21:25 2012 > New Revision: 151268 > > URL: http://llvm.org/viewvc/llvm-project?rev=151268&view=rev > Log: > objective-c default synthesis. classes which adopt protocol properties > must still auto synthesize those propeties which have been redeclared > in the class. // rdar://10907410 > > This should read // rdar://10891396 - Fariborz From kristof.beyls at arm.com Thu Feb 23 10:30:10 2012 From: kristof.beyls at arm.com (Kristof Beyls) Date: Thu, 23 Feb 2012 18:30:10 -0000 Subject: [cfe-commits] [PATCH] 2 fixes for tgmath.h Message-ID: <000901ccf259$2cdaa700$868ff500$@beyls@arm.com> The attached 2 patches each fix one issue in the lib/Headers/tgmath.h header file: * tgmath_logb.patch implements the missing logb function (see C99 standard 7.22, paragraph 5). * tgmath_fabs_complex.patch corrects the return types for the complex fabs functions. These must be non-complex float/double/long double (see C99 standard 7.22, paragraph 4 and 7.3.8.1) Could someone review and commit the patches if fine? Thanks, Kristof -------------- next part -------------- A non-text attachment was scrubbed... Name: tgmath_logb.patch Type: application/octet-stream Size: 625 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: tgmath_fabs_complex.patch Type: application/octet-stream Size: 621 bytes Desc: not available URL: From benny.kra at googlemail.com Thu Feb 23 10:35:56 2012 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Thu, 23 Feb 2012 18:35:56 -0000 Subject: [cfe-commits] r151270 - /cfe/trunk/lib/AST/CXXInheritance.cpp Message-ID: <20120223183556.A50562A6C12F@llvm.org> Author: d0k Date: Thu Feb 23 12:35:56 2012 New Revision: 151270 URL: http://llvm.org/viewvc/llvm-project?rev=151270&view=rev Log: Actually remove the duplicated elements from the vector. Modified: cfe/trunk/lib/AST/CXXInheritance.cpp Modified: cfe/trunk/lib/AST/CXXInheritance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXInheritance.cpp?rev=151270&r1=151269&r2=151270&view=diff ============================================================================== --- cfe/trunk/lib/AST/CXXInheritance.cpp (original) +++ cfe/trunk/lib/AST/CXXInheritance.cpp Thu Feb 23 12:35:56 2012 @@ -30,7 +30,7 @@ // Eliminate duplicated decls. llvm::array_pod_sort(Decls.begin(), Decls.end()); - std::unique(Decls.begin(), Decls.end()); + Decls.erase(std::unique(Decls.begin(), Decls.end()), Decls.end()); NumDeclsFound = Decls.size(); DeclsFound = new NamedDecl * [NumDeclsFound]; From benny.kra at googlemail.com Thu Feb 23 10:40:37 2012 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Thu, 23 Feb 2012 19:40:37 +0100 Subject: [cfe-commits] r151255 - /cfe/trunk/lib/AST/CXXInheritance.cpp In-Reply-To: References: <20120223151831.4FDC82A6C12F@llvm.org> Message-ID: <3151323B-B03D-40A0-A56A-929C6C0722E0@googlemail.com> On 23.02.2012, at 19:11, Eli Friedman wrote: > On Thu, Feb 23, 2012 at 7:18 AM, Benjamin Kramer > wrote: >> Author: d0k >> Date: Thu Feb 23 09:18:31 2012 >> New Revision: 151255 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=151255&view=rev >> Log: >> Unique CXXBasePath decls with the SmallVector/pod_sort/std::unique idiom instead of employing a wasteful std::set. >> >> Modified: >> cfe/trunk/lib/AST/CXXInheritance.cpp >> >> Modified: cfe/trunk/lib/AST/CXXInheritance.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXInheritance.cpp?rev=151255&r1=151254&r2=151255&view=diff >> ============================================================================== >> --- cfe/trunk/lib/AST/CXXInheritance.cpp (original) >> +++ cfe/trunk/lib/AST/CXXInheritance.cpp Thu Feb 23 09:18:31 2012 >> @@ -23,12 +23,15 @@ >> void CXXBasePaths::ComputeDeclsFound() { >> assert(NumDeclsFound == 0 && !DeclsFound && >> "Already computed the set of declarations"); >> - >> - std::set Decls; >> - for (CXXBasePaths::paths_iterator Path = begin(), PathEnd = end(); >> - Path != PathEnd; ++Path) >> - Decls.insert(*Path->Decls.first); >> - >> + >> + SmallVector Decls; >> + for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) >> + Decls.push_back(*Path->Decls.first); >> + >> + // Eliminate duplicated decls. >> + llvm::array_pod_sort(Decls.begin(), Decls.end()); >> + std::unique(Decls.begin(), Decls.end()); > > Does this usage of std::unique actually do the right thing? You never > actually shrink the SmallVector. No, looks like I forgot the actual idiom here :( Fixed in r151270. This brings up the question whether this code is actually used, all tests still pass (including the llvm test-suite) - Ben > -Eli From fjahanian at apple.com Thu Feb 23 10:57:03 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Thu, 23 Feb 2012 18:57:03 -0000 Subject: [cfe-commits] r151272 - /cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Message-ID: <20120223185704.08FC42A6C12F@llvm.org> Author: fjahanian Date: Thu Feb 23 12:57:03 2012 New Revision: 151272 URL: http://llvm.org/viewvc/llvm-project?rev=151272&view=rev Log: fix test for patch in r151268. Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m?rev=151272&r1=151271&r2=151272&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m (original) +++ cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Thu Feb 23 12:57:03 2012 @@ -19,10 +19,10 @@ @implementation I // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}} @end -// CHECK: define internal i32 @"\01-[I auto_req_window]"( -// CHECK: define internal void @"\01-[I setAuto_req_window:]"( // CHECK: define internal i32 @"\01-[I auto_opt_window]"( // CHECK: define internal void @"\01-[I setAuto_opt_window:]"( +// CHECK: define internal i32 @"\01-[I auto_req_window]"( +// CHECK: define internal void @"\01-[I setAuto_req_window:]"( // CHECK-NOT: define internal i32 @"\01-[I no_auto_opt_window]"( // CHECK-NOT: define internal void @"\01-[I setNo_auto_opt_window:]"( From fjahanian at apple.com Thu Feb 23 12:07:38 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Thu, 23 Feb 2012 20:07:38 -0000 Subject: [cfe-commits] r151275 - /cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Message-ID: <20120223200739.0DFD42A6C12F@llvm.org> Author: fjahanian Date: Thu Feb 23 14:07:38 2012 New Revision: 151275 URL: http://llvm.org/viewvc/llvm-project?rev=151275&view=rev Log: Change test again so it passes in build-bot until I can figure out what is going on. Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m?rev=151275&r1=151274&r2=151275&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m (original) +++ cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Thu Feb 23 14:07:38 2012 @@ -19,10 +19,10 @@ @implementation I // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}} @end -// CHECK: define internal i32 @"\01-[I auto_opt_window]"( -// CHECK: define internal void @"\01-[I setAuto_opt_window:]"( // CHECK: define internal i32 @"\01-[I auto_req_window]"( // CHECK: define internal void @"\01-[I setAuto_req_window:]"( +// CHECK: define internal i32 @"\01-[I auto_opt_window]"( +// CHECK: define internal void @"\01-[I setAuto_opt_window:]"( // CHECK-NOT: define internal i32 @"\01-[I no_auto_opt_window]"( // CHECK-NOT: define internal void @"\01-[I setNo_auto_opt_window:]"( From hhinnant at apple.com Thu Feb 23 12:22:10 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Thu, 23 Feb 2012 20:22:10 -0000 Subject: [cfe-commits] r151276 - /cfe/trunk/lib/Headers/tgmath.h Message-ID: <20120223202210.752CC2A6C12F@llvm.org> Author: hhinnant Date: Thu Feb 23 14:22:10 2012 New Revision: 151276 URL: http://llvm.org/viewvc/llvm-project?rev=151276&view=rev Log: * tgmath_logb.patch implements the missing logb function (see C99 standard 7.22, paragraph 5). * tgmath_fabs_complex.patch corrects the return types for the complex fabs functions. These must be non-complex float/double/long double (see C99 standard 7.22, paragraph 4 and 7.3.8.1). Patch contributed by Kristof Beyls. Modified: cfe/trunk/lib/Headers/tgmath.h Modified: cfe/trunk/lib/Headers/tgmath.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/tgmath.h?rev=151276&r1=151275&r2=151276&view=diff ============================================================================== --- cfe/trunk/lib/Headers/tgmath.h (original) +++ cfe/trunk/lib/Headers/tgmath.h Thu Feb 23 14:22:10 2012 @@ -540,15 +540,15 @@ _TG_ATTRS __tg_fabs(long double __x) {return fabsl(__x);} -static float _Complex +static float _TG_ATTRS __tg_fabs(float _Complex __x) {return cabsf(__x);} -static double _Complex +static double _TG_ATTRS __tg_fabs(double _Complex __x) {return cabs(__x);} -static long double _Complex +static long double _TG_ATTRS __tg_fabs(long double _Complex __x) {return cabsl(__x);} @@ -976,6 +976,23 @@ #undef log2 #define log2(__x) __tg_log2(__tg_promote1((__x))(__x)) +// logb + +static float + _TG_ATTRS + __tg_logb(float __x) {return logbf(__x);} + +static double + _TG_ATTRS + __tg_logb(double __x) {return logb(__x);} + +static long double + _TG_ATTRS + __tg_logb(long double __x) {return logbl(__x);} + +#undef logb +#define logb(__x) __tg_logb(__tg_promote1((__x))(__x)) + // lrint static long From fjahanian at apple.com Thu Feb 23 12:22:22 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Thu, 23 Feb 2012 20:22:22 -0000 Subject: [cfe-commits] r151277 - /cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Message-ID: <20120223202222.1D26A2A6C12F@llvm.org> Author: fjahanian Date: Thu Feb 23 14:22:21 2012 New Revision: 151277 URL: http://llvm.org/viewvc/llvm-project?rev=151277&view=rev Log: XFAIL test until I figure out how to make test pass on different platforms. Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m?rev=151277&r1=151276&r2=151277&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m (original) +++ cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Thu Feb 23 14:22:21 2012 @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -fobjc-default-synthesize-properties -emit-llvm %s -o - | FileCheck %s // rdar://10907410 +// XFAIL: * @protocol P @optional From hhinnant at apple.com Thu Feb 23 12:27:09 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Thu, 23 Feb 2012 15:27:09 -0500 Subject: [cfe-commits] [PATCH] 2 fixes for tgmath.h In-Reply-To: <000901ccf259$2cdaa700$868ff500$%beyls@arm.com> References: <000901ccf259$2cdaa700$868ff500$%beyls@arm.com> Message-ID: <9C7B20ED-7F51-4F64-AF68-3F0B7B5FF507@apple.com> Committed revision 151276. Thanks! Howard On Feb 23, 2012, at 1:30 PM, Kristof Beyls wrote: > The attached 2 patches each fix one issue in the lib/Headers/tgmath.h header > file: > > * tgmath_logb.patch implements the missing logb function (see C99 standard > 7.22, paragraph 5). > * tgmath_fabs_complex.patch corrects the return types for the complex fabs > functions. These must be non-complex float/double/long double (see C99 > standard 7.22, paragraph 4 and 7.3.8.1) > > Could someone review and commit the patches if fine? > > Thanks, > > Kristof_______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From fjahanian at apple.com Thu Feb 23 12:43:57 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Thu, 23 Feb 2012 20:43:57 -0000 Subject: [cfe-commits] r151280 - /cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Message-ID: <20120223204357.565572A6C12F@llvm.org> Author: fjahanian Date: Thu Feb 23 14:43:56 2012 New Revision: 151280 URL: http://llvm.org/viewvc/llvm-project?rev=151280&view=rev Log: Test is fixed. Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Modified: cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m?rev=151280&r1=151279&r2=151280&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m (original) +++ cfe/trunk/test/CodeGenObjC/auto-property-synthesize-protocol.m Thu Feb 23 14:43:56 2012 @@ -1,31 +1,37 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -fobjc-default-synthesize-properties -emit-llvm %s -o - | FileCheck %s // rdar://10907410 -// XFAIL: * @protocol P @optional @property int auto_opt_window; @property int no_auto_opt_window; + at end + + at interface I

      + at property int auto_opt_window; + at end - at required + at implementation I + at end + + at protocol P1 @property int auto_req_window; @property int no_auto_req_window; // expected-note {{property declared here}} @end - at interface I

      - at property int auto_opt_window; + at interface I1 @property int auto_req_window; @end - at implementation I // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}} + at implementation I1 // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}} @end -// CHECK: define internal i32 @"\01-[I auto_req_window]"( -// CHECK: define internal void @"\01-[I setAuto_req_window:]"( // CHECK: define internal i32 @"\01-[I auto_opt_window]"( // CHECK: define internal void @"\01-[I setAuto_opt_window:]"( +// CHECK: define internal i32 @"\01-[I1 auto_req_window]"( +// CHECK: define internal void @"\01-[I1 setAuto_req_window:]"( -// CHECK-NOT: define internal i32 @"\01-[I no_auto_opt_window]"( -// CHECK-NOT: define internal void @"\01-[I setNo_auto_opt_window:]"( +// CHECK-NOT: define internal i32 @"\01-[I1 no_auto_opt_window]"( +// CHECK-NOT: define internal void @"\01-[I1 setNo_auto_opt_window:]"( // CHECK-NOT: define internal i32 @"\01-[I no_auto_req_window]"( // CHECK-NOT: define internal void @"\01-[I setNo_auto_req_window:]"( From nicola.gigante at gmail.com Thu Feb 23 13:01:07 2012 From: nicola.gigante at gmail.com (Nicola Gigante) Date: Thu, 23 Feb 2012 22:01:07 +0100 Subject: [cfe-commits] [cfe-dev] [review request] Removing redundant implicit casts in the AST, take 2 In-Reply-To: <04408013-EC28-40D2-AF87-09A5FB940D8B@me.com> References: <38340.10.0.7.178.1324832340.squirrel@webmail.secure.aluminati.net> <47151.10.0.7.180.1324940787.squirrel@webmail.secure.aluminati.net> <8C608B16-0158-4770-B570-54E061D04149@me.com> <6C24E5FD-DE95-4056-882A-4F3F467F23C2@me.com> <04408013-EC28-40D2-AF87-09A5FB940D8B@me.com> Message-ID: Il giorno 16/feb/2012, alle ore 21:21, Nicola Gigante ha scritto: > > Il giorno 13/feb/2012, alle ore 15:42, Nicola Gigante ha scritto: > >> >> Il giorno 09/feb/2012, alle ore 13:36, Nicola Gigante ha scritto: >>> >>> Forget what I said on the last mail. I was wrong. >>> Now I've fixed the patch. It passes all the tests an applies to >>> the latest revision (r150076). >>> If it's ok, I'd commit it :) >> >> Ping? >> Can I commit the patch? > > Ping^2? > Is anybody reviewing my patch? Ping^3? I've attached an updated patch that applies to the current revision, just in case. Thanks, Nicola -------------- next part -------------- A non-text attachment was scrubbed... Name: ImplicitCastsRemoval-r151277.patch Type: application/octet-stream Size: 58145 bytes Desc: not available URL: From hhinnant at apple.com Thu Feb 23 13:09:29 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Thu, 23 Feb 2012 21:09:29 -0000 Subject: [cfe-commits] [libcxxabi] r151282 - in /libcxxabi/trunk/src: private_typeinfo.cpp private_typeinfo.h Message-ID: <20120223210930.0BE982A6C131@llvm.org> Author: hhinnant Date: Thu Feb 23 15:09:29 2012 New Revision: 151282 URL: http://llvm.org/viewvc/llvm-project?rev=151282&view=rev Log: Insert a couple of dummy virtual functions to ease low level binary compatibility with other low level tools. Modified: libcxxabi/trunk/src/private_typeinfo.cpp libcxxabi/trunk/src/private_typeinfo.h Modified: libcxxabi/trunk/src/private_typeinfo.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=151282&r1=151281&r2=151282&view=diff ============================================================================== --- libcxxabi/trunk/src/private_typeinfo.cpp (original) +++ libcxxabi/trunk/src/private_typeinfo.cpp Thu Feb 23 15:09:29 2012 @@ -20,6 +20,9 @@ { } +void __shim_type_info::noop1() const {} +void __shim_type_info::noop2() const {} + // __fundamental_type_info // This miraculously (compiler magic) emits the type_info's for: Modified: libcxxabi/trunk/src/private_typeinfo.h URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.h?rev=151282&r1=151281&r2=151282&view=diff ============================================================================== --- libcxxabi/trunk/src/private_typeinfo.h (original) +++ libcxxabi/trunk/src/private_typeinfo.h Thu Feb 23 15:09:29 2012 @@ -24,6 +24,8 @@ public: virtual ~__shim_type_info(); + virtual void noop1() const; + virtual void noop2() const; virtual bool can_catch(const __shim_type_info* thrown_type, void*& adjustedPtr) const = 0; }; From akyrtzi at gmail.com Thu Feb 23 13:11:21 2012 From: akyrtzi at gmail.com (Argyrios Kyrtzidis) Date: Thu, 23 Feb 2012 21:11:21 -0000 Subject: [cfe-commits] r151283 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/ParseObjc.cpp lib/Sema/SemaDeclObjC.cpp test/Index/get-cursor.m Message-ID: <20120223211121.3233E2A6C131@llvm.org> Author: akirtzidis Date: Thu Feb 23 15:11:20 2012 New Revision: 151283 URL: http://llvm.org/viewvc/llvm-project?rev=151283&view=rev Log: [libclang] Make sure that all top-level decls in a @implementation are marked as such. Previously we missed tag declarations; fixes rdar://10902015 Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseObjc.cpp cfe/trunk/lib/Sema/SemaDeclObjC.cpp cfe/trunk/test/Index/get-cursor.m Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151283&r1=151282&r2=151283&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb 23 15:11:20 2012 @@ -5477,6 +5477,9 @@ IdentifierInfo *CatName, SourceLocation CatLoc); + DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl, + ArrayRef Decls); + DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs, Modified: cfe/trunk/lib/Parse/ParseObjc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=151283&r1=151282&r2=151283&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseObjc.cpp (original) +++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Feb 23 15:11:20 2012 @@ -1532,9 +1532,7 @@ } } - DeclsInGroup.push_back(ObjCImpDecl); - return Actions.BuildDeclaratorGroup( - DeclsInGroup.data(), DeclsInGroup.size(), false); + return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup); } Parser::DeclGroupPtrTy Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=151283&r1=151282&r2=151283&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Thu Feb 23 15:11:20 2012 @@ -988,6 +988,25 @@ return ActOnObjCContainerStartDefinition(IMPDecl); } +Sema::DeclGroupPtrTy +Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef Decls) { + SmallVector DeclsInGroup; + DeclsInGroup.reserve(Decls.size() + 1); + + for (unsigned i = 0, e = Decls.size(); i != e; ++i) { + Decl *Dcl = Decls[i]; + if (!Dcl) + continue; + if (Dcl->getDeclContext()->isFileContext()) + Dcl->setTopLevelDeclInObjCContainer(); + DeclsInGroup.push_back(Dcl); + } + + DeclsInGroup.push_back(ObjCImpDecl); + + return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); +} + void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, ObjCIvarDecl **ivars, unsigned numIvars, SourceLocation RBrace) { Modified: cfe/trunk/test/Index/get-cursor.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/get-cursor.m?rev=151283&r1=151282&r2=151283&view=diff ============================================================================== --- cfe/trunk/test/Index/get-cursor.m (original) +++ cfe/trunk/test/Index/get-cursor.m Thu Feb 23 15:11:20 2012 @@ -26,6 +26,18 @@ @synthesize name = _name; @end + at interface rdar10902015 + at end + + at implementation rdar10902015 + +struct S {}; + +-(void)mm:(struct S*)s { + rdar10902015 *i = 0; +} + at end + // RUN: c-index-test -cursor-at=%s:4:28 -cursor-at=%s:5:28 %s | FileCheck -check-prefix=CHECK-PROP %s // CHECK-PROP: ObjCPropertyDecl=foo1:4:26 // CHECK-PROP: ObjCPropertyDecl=foo2:5:27 @@ -35,3 +47,6 @@ // RUN: c-index-test -cursor-at=%s:20:10 %s | FileCheck -check-prefix=CHECK-METHOD %s // CHECK-METHOD: ObjCInstanceMethodDecl=name:20:1 + +// RUN: c-index-test -cursor-at=%s:37:17 %s | FileCheck -check-prefix=CHECK-IN-IMPL %s +// CHECK-IN-IMPL: VarDecl=i:37:17 From eli.friedman at gmail.com Thu Feb 23 13:36:13 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Thu, 23 Feb 2012 13:36:13 -0800 Subject: [cfe-commits] [PATCH] Bugfix: bogus error message "invalid use of non-static data member" In-Reply-To: References: Message-ID: On Wed, Feb 22, 2012 at 10:21 AM, Delesley Hutchins wrote: > This fixes a bug where clang erroneously reports "invalid use of > non-static data member" if a class is forward declared, and the > reference to data member in question occurs outside of a member > function (e.g. in an attribute).  See patch for example. > > Patch: >  http://codereview.appspot.com/5684064/ Please also include the following C++11 testcase: class Foo; class Foo { int x; int y = x; }; Otherwise, looks fine. -Eli From eli.friedman at gmail.com Thu Feb 23 13:38:15 2012 From: eli.friedman at gmail.com (Eli Friedman) Date: Thu, 23 Feb 2012 13:38:15 -0800 Subject: [cfe-commits] [PATCH] A lot of MS declspecs being turned on In-Reply-To: References: Message-ID: On Wed, Feb 22, 2012 at 6:50 PM, Aaron Ballman wrote: > Instead of doing single patches for all of these, I've put them into a > single patch.  In each case, all I've done is turn on the declspecs > and added test cases to ensure they behave as expected.  This patch > supports four more low-hanging fruit declspecs. I would prefer that you don't turn on -fms-compatibility for a bunch of random tests; please put the relevant tests in their own file. Otherwise, looks fine. -Eli From ganna at apple.com Thu Feb 23 13:38:14 2012 From: ganna at apple.com (Anna Zaks) Date: Thu, 23 Feb 2012 21:38:14 -0000 Subject: [cfe-commits] r151286 - /cfe/trunk/www/analyzer/release_notes.html Message-ID: <20120223213814.960E92A6C131@llvm.org> Author: zaks Date: Thu Feb 23 15:38:14 2012 New Revision: 151286 URL: http://llvm.org/viewvc/llvm-project?rev=151286&view=rev Log: [analyzer] Add CString checks to the release notes. Modified: cfe/trunk/www/analyzer/release_notes.html Modified: cfe/trunk/www/analyzer/release_notes.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/release_notes.html?rev=151286&r1=151285&r2=151286&view=diff ============================================================================== --- cfe/trunk/www/analyzer/release_notes.html (original) +++ cfe/trunk/www/analyzer/release_notes.html Thu Feb 23 15:38:14 2012 @@ -24,9 +24,11 @@

      • Contains a new experimental malloc/free checker.
      • Better support for projects using ARC.
      • -
      • set-xcode-analyzer now supports self-contained Xcode.app (Xcode 4.3 and later). -
      • Misc. bug fixes and performance work.
      • +
      • Warns about null pointers passed as arguments to C string functions.
      • +
      • Warns about common anti-patterns in 'strncat' size argument, which can lead to buffer overflows.
      • +
      • set-xcode-analyzer now supports self-contained Xcode.app (Xcode 4.3 and later).
      • Contains a newer version of the analyzer than Xcode 4.3.
      • +
      • Misc. bug fixes and performance work.

      checker-260

      From ganna at apple.com Thu Feb 23 13:38:21 2012 From: ganna at apple.com (Anna Zaks) Date: Thu, 23 Feb 2012 21:38:21 -0000 Subject: [cfe-commits] r151287 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h lib/StaticAnalyzer/Checkers/MallocChecker.cpp lib/StaticAnalyzer/Core/BugReporter.cpp test/Analysis/malloc.c Message-ID: <20120223213821.F28942A6C131@llvm.org> Author: zaks Date: Thu Feb 23 15:38:21 2012 New Revision: 151287 URL: http://llvm.org/viewvc/llvm-project?rev=151287&view=rev Log: [analyzer] Malloc: unique leak reports by allocation site. When we find two leak reports with the same allocation site, report only one of them. Provide a helper method to BugReporter to facilitate this. Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp cfe/trunk/test/Analysis/malloc.c Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h?rev=151287&r1=151286&r2=151287&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h Thu Feb 23 15:38:21 2012 @@ -71,6 +71,7 @@ std::string ShortDescription; std::string Description; PathDiagnosticLocation Location; + PathDiagnosticLocation UniqueingLocation; const ExplodedNode *ErrorNode; SmallVector Ranges; ExtraTextList ExtraText; @@ -95,6 +96,18 @@ : BT(bt), Description(desc), Location(l), ErrorNode(0), Callbacks(F.getEmptyList()) {} + /// \brief Create a BugReport with a custom uniqueing location. + /// + /// The reports that have the same report location, description, bug type, and + /// ranges are uniqued - only one of the equivalent reports will be presented + /// to the user. This method allows to rest the location which should be used + /// for uniquing reports. For example, memory leaks checker, could set this to + /// the allocation site, rather then the location where the bug is reported. + BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, + PathDiagnosticLocation LocationToUnique) + : BT(bt), Description(desc), UniqueingLocation(LocationToUnique), + ErrorNode(errornode), Callbacks(F.getEmptyList()) {} + virtual ~BugReport(); const BugType& getBugType() const { return BT; } Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=151287&r1=151286&r2=151287&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Feb 23 15:38:21 2012 @@ -186,6 +186,11 @@ static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const; + /// Find the location of the allocation for Sym on the path leading to the + /// exploded node N. + const Stmt *getAllocationSite(const ExplodedNode *N, SymbolRef Sym, + CheckerContext &C) const; + void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const; /// The bug visitor which allows us to print extra diagnostics along the @@ -766,6 +771,24 @@ return MallocMemAux(C, CE, TotalSize, zeroVal, state); } +const Stmt * +MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym, + CheckerContext &C) const { + // Walk the ExplodedGraph backwards and find the first node that referred to + // the tracked symbol. + const ExplodedNode *AllocNode = N; + + while (N) { + if (!N->getState()->get(Sym)) + break; + AllocNode = N; + N = N->pred_empty() ? NULL : *(N->pred_begin()); + } + + ProgramPoint P = AllocNode->getLocation(); + return cast(P).getStmt(); +} + void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const { assert(N); @@ -779,8 +802,16 @@ BT_Leak->setSuppressOnSink(true); } + // Most bug reports are cached at the location where they occurred. + // With leaks, we want to unique them by the location where they were + // allocated, and only report a single path. + const Stmt *AllocStmt = getAllocationSite(N, Sym, C); + PathDiagnosticLocation LocUsedForUniqueing = + PathDiagnosticLocation::createBegin(AllocStmt, C.getSourceManager(), + N->getLocationContext()); + BugReport *R = new BugReport(*BT_Leak, - "Memory is never released; potential memory leak", N); + "Memory is never released; potential memory leak", N, LocUsedForUniqueing); R->addVisitor(new MallocBugVisitor(Sym)); C.EmitReport(R); } @@ -818,14 +849,17 @@ } } - ExplodedNode *N = C.addTransition(state->set(RS)); + // Generate leak node. + static SimpleProgramPointTag Tag("MallocChecker : DeadSymbolsLeak"); + ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag); - if (N && generateReport) { + if (generateReport) { for (llvm::SmallVector::iterator I = Errors.begin(), E = Errors.end(); I != E; ++I) { reportLeak(*I, N, C); } } + C.addTransition(state->set(RS), N); } void MallocChecker::checkEndPath(CheckerContext &C) const { Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=151287&r1=151286&r2=151287&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Thu Feb 23 15:38:21 2012 @@ -1270,7 +1270,9 @@ void BugReport::Profile(llvm::FoldingSetNodeID& hash) const { hash.AddPointer(&BT); hash.AddString(Description); - if (Location.isValid()) { + if (UniqueingLocation.isValid()) { + UniqueingLocation.Profile(hash); + } else if (Location.isValid()) { Location.Profile(hash); } else { assert(ErrorNode); Modified: cfe/trunk/test/Analysis/malloc.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=151287&r1=151286&r2=151287&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc.c (original) +++ cfe/trunk/test/Analysis/malloc.c Thu Feb 23 15:38:21 2012 @@ -379,7 +379,7 @@ void mallocMalloc() { int *p = malloc(12); - p = malloc(12); // expected-warning{{Memory is never released; potential memory leak}} + p = malloc(12); // expected-warning 2 {{Memory is never released; potential memory leak}} } void mallocFreeMalloc() { @@ -666,7 +666,7 @@ char *s2 = strndup(s, size); s2 [validIndex + 1] = 'b'; if (s2[validIndex] != 'a') - return 0;// expected-warning {{Memory is never released; potential memory leak}} + return 0; else return 1;// expected-warning {{Memory is never released; potential memory leak}} } From aaron at aaronballman.com Thu Feb 23 13:42:50 2012 From: aaron at aaronballman.com (Aaron Ballman) Date: Thu, 23 Feb 2012 15:42:50 -0600 Subject: [cfe-commits] [PATCH] A lot of MS declspecs being turned on In-Reply-To: References: Message-ID: On Thu, Feb 23, 2012 at 3:38 PM, Eli Friedman wrote: > On Wed, Feb 22, 2012 at 6:50 PM, Aaron Ballman wrote: >> Instead of doing single patches for all of these, I've put them into a >> single patch.  In each case, all I've done is turn on the declspecs >> and added test cases to ensure they behave as expected.  This patch >> supports four more low-hanging fruit declspecs. > > I would prefer that you don't turn on -fms-compatibility for a bunch > of random tests; please put the relevant tests in their own file. > > Otherwise, looks fine. Fair enough -- I was debating that too, but went the "keep the related tests together" route. But not an issue. Thanks! ~Aaron From tom.care at uqconnect.edu.au Thu Feb 23 13:50:24 2012 From: tom.care at uqconnect.edu.au (Tom Care) Date: Thu, 23 Feb 2012 22:50:24 +0100 Subject: [cfe-commits] [PATCH] Additional output for AnalyzerStatsChecker In-Reply-To: <9D425DD2-7FD6-4B13-858D-AB12562B8D93@apple.com> References: <2B6668A7-281A-4262-B797-376AE9E18116@apple.com> <9D425DD2-7FD6-4B13-858D-AB12562B8D93@apple.com> Message-ID: <5A166B8B-F425-49FC-883F-07689742A39D@uqconnect.edu.au> The reason I added a Stmt* was because the LocationContext of the node (which starts out as a PostStmt) can be overwritten to become a BlockEdge. The Stmt* pointer is lost in that case, and it becomes difficult to guess where the original Stmt was. Since we only add aborted blocks/nodes when a Stmt was unsupported, I thought that it was important to keep the original pointer to find out why we stopped. Example of the new output: /Users/tcare/Projects/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp:218:5: warning: The analyzer stopped at this point due to an unsupported statement of type CXXBindTemporaryExpr S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; ^ /Users/tcare/Projects/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp:308:28: warning: The analyzer stopped because this block was visited too many times for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { ^ /Users/tcare/Projects/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp:934:11: warning: The analyzer stoppedat this point due to visitation limits if (T->isAnyPointerType() || T->isBlockPointerType()) ^ (need to add a space in the last one) I'm testing over all of LLVM/Clang right now as I am collecting data. Tom On 23/02/2012, at 6:04 PM, Anna Zaks wrote: > On Feb 23, 2012, at 7:27 AM, Ted Kremenek wrote: > >> Looks good to me. Do you have an example of the new output? >> >> On Feb 23, 2012, at 7:08 AM, Tom Care wrote: >> >>> I made some changes to AnalyzerStatsChecker to make it a bit more useful. Changelog: >>> >>> Improved the information output by AnalyzerStatsChecker. In addition to the analysis stats for Decls, AnalyzerStatsChecker now also outputs: >>> - Exhausted blocks and sinks, including their approximate location >>> - Aborted blocks and their statement locations >>> - When and where the analyzer reaches the max block limit >>> Some supporting infrastructure changes: >>> - CoreEngine now stores Stmt* with the ExplodedNode* in the aborted block data, since the node can change between generation and VisitEndAnalysis > > My understanding is that, here, we add a bit of overhead on every analyzes run to make stats more precise. > Could you elaborate/investigate a bit more on why it is absolutely necessary in this case? Is the ExplodedNode you are storing here deleted by the time you reach VisitEndAnalysis? (How is the node changed?) > >>> - Exposed 'block limit exceeded' tag to allow AnalyzerStatsChecker to detect a sink caused by exceeding the max visits for a block >>> >>> Regarding test cases, any test case made for this checker would break quite frequently as the analyzer is changed. I can't think of a good way to solve this. >>> > > Would be great if you could (manually) test this with -analyzer-inline-call. > >>> Been a while since my last commit, so a review is much appreciated :) >>> >>> Tom >>> _______________________________________________ >>> 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 grosbach at apple.com Thu Feb 23 13:55:05 2012 From: grosbach at apple.com (Jim Grosbach) Date: Thu, 23 Feb 2012 21:55:05 -0000 Subject: [cfe-commits] r151288 - /cfe/trunk/lib/Driver/ToolChains.h Message-ID: <20120223215505.2E6FE2A6C131@llvm.org> Author: grosbach Date: Thu Feb 23 15:55:04 2012 New Revision: 151288 URL: http://llvm.org/viewvc/llvm-project?rev=151288&view=rev Log: ARM: enable the integrated assembler by default for Darwin. Modified: cfe/trunk/lib/Driver/ToolChains.h Modified: cfe/trunk/lib/Driver/ToolChains.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=151288&r1=151287&r2=151288&view=diff ============================================================================== --- cfe/trunk/lib/Driver/ToolChains.h (original) +++ cfe/trunk/lib/Driver/ToolChains.h Thu Feb 23 15:55:04 2012 @@ -329,9 +329,8 @@ #ifdef DISABLE_DEFAULT_INTEGRATED_ASSEMBLER return false; #else - // Default integrated assembler to on for x86. - return (getTriple().getArch() == llvm::Triple::x86 || - getTriple().getArch() == llvm::Triple::x86_64); + // Default integrated assembler to on for Darwin. + return true; #endif } virtual bool IsStrictAliasingDefault() const { From grosbach at apple.com Thu Feb 23 14:12:54 2012 From: grosbach at apple.com (Jim Grosbach) Date: Thu, 23 Feb 2012 22:12:54 -0000 Subject: [cfe-commits] r151290 - /cfe/trunk/test/Driver/darwin-as.c Message-ID: <20120223221254.31B3E2A6C12F@llvm.org> Author: grosbach Date: Thu Feb 23 16:12:53 2012 New Revision: 151290 URL: http://llvm.org/viewvc/llvm-project?rev=151290&view=rev Log: Update test for r151288 Modified: cfe/trunk/test/Driver/darwin-as.c Modified: cfe/trunk/test/Driver/darwin-as.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/darwin-as.c?rev=151290&r1=151289&r2=151290&view=diff ============================================================================== --- cfe/trunk/test/Driver/darwin-as.c (original) +++ cfe/trunk/test/Driver/darwin-as.c Thu Feb 23 16:12:53 2012 @@ -11,7 +11,7 @@ // CHECK-STATIC-64: as{{(.exe)?}}" "-arch" "x86_64" "-force_cpusubtype_ALL" "-o" // RUN: %clang -target x86_64-apple-darwin10 -### \ -// RUN: -arch armv6 -x assembler -c %s 2>%t +// RUN: -arch armv6 -no-integrated-as -x assembler -c %s 2>%t // RUN: FileCheck -check-prefix=ARMV6 --input-file %t %s // // CHECK-ARMV6: as{{(.exe)?}}" "-arch" "armv6" "-o" From mcrosier at apple.com Thu Feb 23 14:22:27 2012 From: mcrosier at apple.com (Chad Rosier) Date: Thu, 23 Feb 2012 14:22:27 -0800 Subject: [cfe-commits] r151172 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/new-array-init-exceptions.cpp In-Reply-To: <4F462AC7.1010309@getdesigned.at> References: <20120222173759.8CE752A6C130@llvm.org> <718EBC33-FE3A-48AB-93D6-1490922F704C@apple.com> <4F462AC7.1010309@getdesigned.at> Message-ID: On Feb 23, 2012, at 4:02 AM, Sebastian Redl wrote: > On 22.02.2012 21:46, Chad Rosier wrote: >> >> Hi Sebastian, >> The test you added here is failing on one of our internal buildbots. >> >> Here's the exact errors: >> ******************** TEST 'Clang :: CodeGenCXX/new-array-init-exceptions.cpp' FAILED ********************Script: >> -- >> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang-build/Release/bin/clang -cc1 -internal-isystem /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang-build/Release/bin/../lib/clang/3.1/include -std=c++11 -triple i386-unknown-unknown -fexceptions -fcxx-exceptions /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp -emit-llvm -o - | FileCheck /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp >> -- >> Exit Code: 1 >> Command Output (stderr): >> -- >> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-R/clang.src/test/CodeGenCXX/new-array-init-exceptions.cpp:20:12: error: expected string not found in input >> // CHECK: [[LPAD]]: >> ^ >> :56:1: note: scanning from here >> ;
    Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Fri Feb 24 01:38:34 2012 @@ -1926,6 +1926,102 @@ friend class ASTStmtReader; }; +/// \brief A type trait used in the implementation of various C++11 and +/// Library TR1 trait templates. +/// +/// \code +/// __is_trivially_constructible(vector, int*, int*) +/// \endcode +class TypeTraitExpr : public Expr { + /// \brief The location of the type trait keyword. + SourceLocation Loc; + + /// \brief The location of the closing parenthesis. + SourceLocation RParenLoc; + + // Note: The TypeSourceInfos for the arguments are allocated after the + // TypeTraitExpr. + + TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, + ArrayRef Args, + SourceLocation RParenLoc, + bool Value); + + TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { } + + /// \brief Retrieve the argument types. + TypeSourceInfo **getTypeSourceInfos() { + return reinterpret_cast(this+1); + } + + /// \brief Retrieve the argument types. + TypeSourceInfo * const *getTypeSourceInfos() const { + return reinterpret_cast(this+1); + } + +public: + /// \brief Create a new type trait expression. + static TypeTraitExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, + TypeTrait Kind, + ArrayRef Args, + SourceLocation RParenLoc, + bool Value); + + static TypeTraitExpr *CreateDeserialized(ASTContext &C, unsigned NumArgs); + + /// \brief Determine which type trait this expression uses. + TypeTrait getTrait() const { + return static_cast(TypeTraitExprBits.Kind); + } + + bool getValue() const { + assert(!isValueDependent()); + return TypeTraitExprBits.Value; + } + + /// \brief Determine the number of arguments to this type trait. + unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } + + /// \brief Retrieve the Ith argument. + TypeSourceInfo *getArg(unsigned I) const { + assert(I < getNumArgs() && "Argument out-of-range"); + return getArgs()[I]; + } + + /// \brief Retrieve the argument types. + ArrayRef getArgs() const { + return ArrayRef(getTypeSourceInfos(), getNumArgs()); + } + + typedef TypeSourceInfo **arg_iterator; + arg_iterator arg_begin() { + return getTypeSourceInfos(); + } + arg_iterator arg_end() { + return getTypeSourceInfos() + getNumArgs(); + } + + typedef TypeSourceInfo const * const *arg_const_iterator; + arg_const_iterator arg_begin() const { return getTypeSourceInfos(); } + arg_const_iterator arg_end() const { + return getTypeSourceInfos() + getNumArgs(); + } + + SourceRange getSourceRange() const { return SourceRange(Loc, RParenLoc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == TypeTraitExprClass; + } + static bool classof(const TypeTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; + +}; + /// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the /// implementation of __array_rank and __array_extent. /// Example: Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Feb 24 01:38:34 2012 @@ -1946,6 +1946,11 @@ TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(TypeTraitExpr, { + for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) + TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc())); +}) + DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); }) Modified: cfe/trunk/include/clang/AST/Stmt.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Stmt.h (original) +++ cfe/trunk/include/clang/AST/Stmt.h Fri Feb 24 01:38:34 2012 @@ -227,6 +227,24 @@ unsigned InitializesStdInitializerList : 1; }; + class TypeTraitExprBitfields { + friend class TypeTraitExpr; + friend class ASTStmtReader; + friend class ASTStmtWriter; + + unsigned : NumExprBits; + + /// \brief The kind of type trait, which is a value of a TypeTrait enumerator. + unsigned Kind : 8; + + /// \brief If this expression is not value-dependent, this indicates whether + /// the trait evaluated true or false. + unsigned Value : 1; + + /// \brief The number of arguments to this type trait. + unsigned NumArgs : 32 - 8 - 1 - NumExprBits; + }; + union { // FIXME: this is wasteful on 64-bit platforms. void *Aligner; @@ -241,9 +259,11 @@ PseudoObjectExprBitfields PseudoObjectExprBits; ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; InitListExprBitfields InitListExprBits; + TypeTraitExprBitfields TypeTraitExprBits; }; friend class ASTStmtReader; + friend class ASTStmtWriter; public: // Only allow allocation of Stmts using the allocator in ASTContext Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 24 01:38:34 2012 @@ -4438,6 +4438,10 @@ def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; +def err_type_trait_arity : Error< + "type trait requires %0%select{| or more}1 argument%select{|s}2; have " + "%3 argument%s3">; + def err_dimension_expr_not_constant_integer : Error< "dimension expression does not evaluate to a constant unsigned int">; def err_expected_ident_or_lparen : Error<"expected identifier or '('">; Modified: cfe/trunk/include/clang/Basic/StmtNodes.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/StmtNodes.td (original) +++ cfe/trunk/include/clang/Basic/StmtNodes.td Fri Feb 24 01:38:34 2012 @@ -107,6 +107,7 @@ def CXXNewExpr : DStmt; def CXXDeleteExpr : DStmt; def CXXPseudoDestructorExpr : DStmt; +def TypeTraitExpr : DStmt; def UnaryTypeTraitExpr : DStmt; def BinaryTypeTraitExpr : DStmt; def ArrayTypeTraitExpr : DStmt; Modified: cfe/trunk/include/clang/Basic/TokenKinds.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) +++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri Feb 24 01:38:34 2012 @@ -365,6 +365,7 @@ KEYWORD(__is_union , KEYCXX) // Clang-only C++ Type Traits +KEYWORD(__is_trivially_constructible, KEYCXX) KEYWORD(__is_trivially_copyable , KEYCXX) KEYWORD(__is_trivially_assignable , KEYCXX) KEYWORD(__underlying_type , KEYCXX) Modified: cfe/trunk/include/clang/Basic/TypeTraits.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TypeTraits.h (original) +++ cfe/trunk/include/clang/Basic/TypeTraits.h Fri Feb 24 01:38:34 2012 @@ -84,6 +84,12 @@ UETT_AlignOf, UETT_VecStep }; + + /// \brief Names for type traits that operate specifically on types. + enum TypeTrait { + TT_IsTriviallyConstructible + }; + } #endif Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Fri Feb 24 01:38:34 2012 @@ -2170,7 +2170,8 @@ // GNU G++: Type Traits [Type-Traits.html in the GCC manual] ExprResult ParseUnaryTypeTrait(); ExprResult ParseBinaryTypeTrait(); - + ExprResult ParseTypeTrait(); + //===--------------------------------------------------------------------===// // Embarcadero: Arary and Expression Traits ExprResult ParseArrayTypeTrait(); Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Fri Feb 24 01:38:34 2012 @@ -3317,6 +3317,14 @@ TypeSourceInfo *RhsT, SourceLocation RParen); + /// \brief Parsed one of the type trait support pseudo-functions. + ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc); + ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc); + /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support /// pseudo-functions. ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Feb 24 01:38:34 2012 @@ -1156,6 +1156,7 @@ EXPR_OPAQUE_VALUE, // OpaqueValueExpr EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr + EXPR_TYPE_TRAIT, // TypeTraitExpr EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr EXPR_PACK_EXPANSION, // PackExpansionExpr Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Fri Feb 24 01:38:34 2012 @@ -2169,6 +2169,7 @@ case AddrLabelExprClass: case ArrayTypeTraitExprClass: case BinaryTypeTraitExprClass: + case TypeTraitExprClass: case CXXBoolLiteralExprClass: case CXXNoexceptExprClass: case CXXNullPtrLiteralExprClass: Modified: cfe/trunk/lib/AST/ExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprCXX.cpp (original) +++ cfe/trunk/lib/AST/ExprCXX.cpp Fri Feb 24 01:38:34 2012 @@ -199,7 +199,6 @@ return SourceRange(Base->getLocStart(), End); } - // UnresolvedLookupExpr UnresolvedLookupExpr * UnresolvedLookupExpr::Create(ASTContext &C, @@ -1262,4 +1261,51 @@ return TemplateArgument(Arguments, NumArguments); } +TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, + ArrayRef Args, + SourceLocation RParenLoc, + bool Value) + : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, + /*ValueDependent=*/false, + /*InstantiationDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), + Loc(Loc), RParenLoc(RParenLoc) +{ + TypeTraitExprBits.Kind = Kind; + TypeTraitExprBits.Value = Value; + TypeTraitExprBits.NumArgs = Args.size(); + + TypeSourceInfo **ToArgs = getTypeSourceInfos(); + + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isDependentType()) + setValueDependent(true); + if (Args[I]->getType()->isInstantiationDependentType()) + setInstantiationDependent(true); + if (Args[I]->getType()->containsUnexpandedParameterPack()) + setContainsUnexpandedParameterPack(true); + + ToArgs[I] = Args[I]; + } +} + +TypeTraitExpr *TypeTraitExpr::Create(ASTContext &C, QualType T, + SourceLocation Loc, + TypeTrait Kind, + ArrayRef Args, + SourceLocation RParenLoc, + bool Value) { + unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * Args.size(); + void *Mem = C.Allocate(Size); + return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value); +} + +TypeTraitExpr *TypeTraitExpr::CreateDeserialized(ASTContext &C, + unsigned NumArgs) { + unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * NumArgs; + void *Mem = C.Allocate(Size); + return new (Mem) TypeTraitExpr(EmptyShell()); +} + void ArrayTypeTraitExpr::anchor() { } Modified: cfe/trunk/lib/AST/ExprClassification.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprClassification.cpp (original) +++ cfe/trunk/lib/AST/ExprClassification.cpp Fri Feb 24 01:38:34 2012 @@ -151,6 +151,7 @@ case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::ObjCSelectorExprClass: Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Feb 24 01:38:34 2012 @@ -4119,6 +4119,10 @@ return Success(E->getValue(), E); } + bool VisitTypeTraitExpr(const TypeTraitExpr *E) { + return Success(E->getValue(), E); + } + bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { return Success(E->getValue(), E); } @@ -6360,6 +6364,7 @@ case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::CXXNoexceptExprClass: Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Fri Feb 24 01:38:34 2012 @@ -2383,6 +2383,7 @@ case Expr::StmtExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: Modified: cfe/trunk/lib/AST/StmtPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtPrinter.cpp (original) +++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Feb 24 01:38:34 2012 @@ -1555,6 +1555,13 @@ llvm_unreachable("Binary type trait not covered by switch"); } +static const char *getTypeTraitName(TypeTrait TT) { + switch (TT) { + case clang::TT_IsTriviallyConstructible:return "__is_trivially_constructible"; + } + llvm_unreachable("Type trait not covered by switch"); +} + static const char *getTypeTraitName(ArrayTypeTrait ATT) { switch (ATT) { case ATT_ArrayRank: return "__array_rank"; @@ -1582,6 +1589,16 @@ << E->getRhsType().getAsString(Policy) << ")"; } +void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) { + OS << getTypeTraitName(E->getTrait()) << "("; + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { + if (I > 0) + OS << ", "; + OS << E->getArg(I)->getType().getAsString(Policy); + } + OS << ")"; +} + void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { OS << getTypeTraitName(E->getTrait()) << "(" << E->getQueriedType().getAsString(Policy) << ")"; Modified: cfe/trunk/lib/AST/StmtProfile.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtProfile.cpp (original) +++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Feb 24 01:38:34 2012 @@ -868,6 +868,14 @@ VisitType(S->getRhsType()); } +void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) { + VisitExpr(S); + ID.AddInteger(S->getTrait()); + ID.AddInteger(S->getNumArgs()); + for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) + VisitType(S->getArg(I)->getType()); +} + void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) { VisitExpr(S); ID.AddInteger(S->getTrait()); Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Fri Feb 24 01:38:34 2012 @@ -701,6 +701,7 @@ .Case("is_polymorphic", LangOpts.CPlusPlus) .Case("is_trivial", LangOpts.CPlusPlus) .Case("is_trivially_assignable", LangOpts.CPlusPlus) + .Case("is_trivially_constructible", LangOpts.CPlusPlus) .Case("is_trivially_copyable", LangOpts.CPlusPlus) .Case("is_union", LangOpts.CPlusPlus) .Case("modules", LangOpts.Modules) Modified: cfe/trunk/lib/Parse/ParseExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) +++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Feb 24 01:38:34 2012 @@ -1143,6 +1143,9 @@ case tok::kw___is_trivially_assignable: return ParseBinaryTypeTrait(); + case tok::kw___is_trivially_constructible: + return ParseTypeTrait(); + case tok::kw___array_rank: case tok::kw___array_extent: return ParseArrayTypeTrait(); Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Feb 24 01:38:34 2012 @@ -2458,6 +2458,14 @@ } } +static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) { + switch (kind) { + default: llvm_unreachable("Not a known type trait"); + case tok::kw___is_trivially_constructible: + return TT_IsTriviallyConstructible; + } +} + static ArrayTypeTrait ArrayTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { default: llvm_unreachable("Not a known binary type trait"); @@ -2540,6 +2548,58 @@ T.getCloseLocation()); } +/// \brief Parse the built-in type-trait pseudo-functions that allow +/// implementation of the TR1/C++11 type traits templates. +/// +/// primary-expression: +/// type-trait '(' type-id-seq ')' +/// +/// type-id-seq: +/// type-id ...[opt] type-id-seq[opt] +/// +ExprResult Parser::ParseTypeTrait() { + TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind()); + SourceLocation Loc = ConsumeToken(); + + BalancedDelimiterTracker Parens(*this, tok::l_paren); + if (Parens.expectAndConsume(diag::err_expected_lparen)) + return ExprError(); + + llvm::SmallVector Args; + do { + // Parse the next type. + TypeResult Ty = ParseTypeName(); + if (Ty.isInvalid()) { + Parens.skipToEnd(); + return ExprError(); + } + + // Parse the ellipsis, if present. + if (Tok.is(tok::ellipsis)) { + Ty = Actions.ActOnPackExpansion(Ty.get(), ConsumeToken()); + if (Ty.isInvalid()) { + Parens.skipToEnd(); + return ExprError(); + } + } + + // Add this type to the list of arguments. + Args.push_back(Ty.get()); + + if (Tok.is(tok::comma)) { + ConsumeToken(); + continue; + } + + break; + } while (true); + + if (Parens.consumeClose()) + return ExprError(); + + return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation()); +} + /// ParseArrayTypeTrait - Parse the built-in array type-trait /// pseudo-functions. /// Modified: cfe/trunk/lib/Parse/ParseTentative.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTentative.cpp (original) +++ cfe/trunk/lib/Parse/ParseTentative.cpp Fri Feb 24 01:38:34 2012 @@ -690,6 +690,7 @@ case tok::kw___is_polymorphic: case tok::kw___is_trivial: case tok::kw___is_trivially_assignable: + case tok::kw___is_trivially_constructible: case tok::kw___is_trivially_copyable: case tok::kw___is_union: case tok::kw___uuidof: Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Feb 24 01:38:34 2012 @@ -3212,6 +3212,127 @@ return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen); } +static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc) { + switch (Kind) { + case clang::TT_IsTriviallyConstructible: { + // C++11 [meta.unary.prop]: + // is_trivially_constructor is defined as: + // + // is_constructible::value is true and the variable + // + /// definition for is_constructible, as defined below, is known to call no + // operation that is not trivial. + // + // The predicate condition for a template specialization + // is_constructible shall be satisfied if and only if the + // following variable definition would be well-formed for some invented + // variable t: + // + // T t(create()...); + if (Args.empty()) { + S.Diag(KWLoc, diag::err_type_trait_arity) + << 1 << 1 << 1 << (int)Args.size(); + return false; + } + + bool SawVoid = false; + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isVoidType()) { + SawVoid = true; + continue; + } + + if (!Args[I]->getType()->isIncompleteType() && + S.RequireCompleteType(KWLoc, Args[I]->getType(), + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + } + + // If any argument was 'void', of course it won't type-check. + if (SawVoid) + return false; + + llvm::SmallVector OpaqueArgExprs; + llvm::SmallVector ArgExprs; + ArgExprs.reserve(Args.size() - 1); + for (unsigned I = 1, N = Args.size(); I != N; ++I) { + QualType T = Args[I]->getType(); + if (T->isObjectType() || T->isFunctionType()) + T = S.Context.getRValueReferenceType(T); + OpaqueArgExprs.push_back( + OpaqueValueExpr(Args[I]->getTypeLoc().getSourceRange().getBegin(), + T.getNonLValueExprType(S.Context), + Expr::getValueKindForType(T))); + ArgExprs.push_back(&OpaqueArgExprs.back()); + } + + // Perform the initialization in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); + Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); + InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0])); + InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc, + RParenLoc)); + InitializationSequence Init(S, To, InitKind, + ArgExprs.begin(), ArgExprs.size()); + if (Init.Failed()) + return false; + + ExprResult Result = Init.Perform(S, To, InitKind, + MultiExprArg(ArgExprs.data(), + ArgExprs.size())); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return false; + + // The initialization succeeded; not make sure there are no non-trivial + // calls. + return !Result.get()->hasNonTrivialCall(S.Context); + } + } + + return false; +} + +ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc) { + bool Dependent = false; + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isDependentType()) { + Dependent = true; + break; + } + } + + bool Value = false; + if (!Dependent) + Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc); + + return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind, + Args, RParenLoc, Value); +} + +ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc) { + llvm::SmallVector ConvertedArgs; + ConvertedArgs.reserve(Args.size()); + + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + TypeSourceInfo *TInfo; + QualType T = GetTypeFromParser(Args[I], &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc); + + ConvertedArgs.push_back(TInfo); + } + + return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc); +} + static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, QualType LhsT, QualType RhsT, SourceLocation KeyLoc) { Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Feb 24 01:38:34 2012 @@ -2022,6 +2022,17 @@ return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc); } + /// \brief Build a new type trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildTypeTrait(TypeTrait Trait, + SourceLocation StartLoc, + ArrayRef Args, + SourceLocation RParenLoc) { + return getSema().BuildTypeTrait(Trait, StartLoc, Args, RParenLoc); + } + /// \brief Build a new array type trait expression. /// /// By default, performs semantic analysis to build the new expression. @@ -7436,6 +7447,128 @@ template ExprResult +TreeTransform::TransformTypeTraitExpr(TypeTraitExpr *E) { + bool ArgChanged = false; + llvm::SmallVector Args; + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { + TypeSourceInfo *From = E->getArg(I); + TypeLoc FromTL = From->getTypeLoc(); + if (!isa(FromTL)) { + TypeLocBuilder TLB; + TLB.reserve(FromTL.getFullDataSize()); + QualType To = getDerived().TransformType(TLB, FromTL); + if (To.isNull()) + return ExprError(); + + if (To == From->getType()) + Args.push_back(From); + else { + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + ArgChanged = true; + } + continue; + } + + ArgChanged = true; + + // We have a pack expansion. Instantiate it. + PackExpansionTypeLoc ExpansionTL = cast(FromTL); + TypeLoc PatternTL = ExpansionTL.getPatternLoc(); + SmallVector Unexpanded; + SemaRef.collectUnexpandedParameterPacks(PatternTL, Unexpanded); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional OrigNumExpansions + = ExpansionTL.getTypePtr()->getNumExpansions(); + llvm::Optional NumExpansions = OrigNumExpansions; + if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), + PatternTL.getSourceRange(), + Unexpanded, + Expand, RetainExpansion, + NumExpansions)) + return ExprError(); + + if (!Expand) { + // The transform has determined that we should perform a simple + // transformation on the pack expansion, producing another pack + // expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + + TypeLocBuilder TLB; + TLB.reserve(From->getTypeLoc().getFullDataSize()); + + QualType To = getDerived().TransformType(TLB, PatternTL); + if (To.isNull()) + return ExprError(); + + To = getDerived().RebuildPackExpansionType(To, + PatternTL.getSourceRange(), + ExpansionTL.getEllipsisLoc(), + NumExpansions); + if (To.isNull()) + return ExprError(); + + PackExpansionTypeLoc ToExpansionTL + = TLB.push(To); + ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc()); + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + continue; + } + + // Expand the pack expansion by substituting for each argument in the + // pack(s). + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); + TypeLocBuilder TLB; + TLB.reserve(PatternTL.getFullDataSize()); + QualType To = getDerived().TransformType(TLB, PatternTL); + if (To.isNull()) + return ExprError(); + + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + } + + if (!RetainExpansion) + continue; + + // If we're supposed to retain a pack expansion, do so by temporarily + // forgetting the partially-substituted parameter pack. + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + + TypeLocBuilder TLB; + TLB.reserve(From->getTypeLoc().getFullDataSize()); + + QualType To = getDerived().TransformType(TLB, PatternTL); + if (To.isNull()) + return ExprError(); + + To = getDerived().RebuildPackExpansionType(To, + PatternTL.getSourceRange(), + ExpansionTL.getEllipsisLoc(), + NumExpansions); + if (To.isNull()) + return ExprError(); + + PackExpansionTypeLoc ToExpansionTL + = TLB.push(To); + ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc()); + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); + } + + if (!getDerived().AlwaysRebuild() && !ArgChanged) + return SemaRef.Owned(E); + + return getDerived().RebuildTypeTrait(E->getTrait(), + E->getLocStart(), + Args, + E->getLocEnd()); +} + +template +ExprResult TreeTransform::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); if (!T) Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri Feb 24 01:38:34 2012 @@ -1327,6 +1327,17 @@ E->RhsType = GetTypeSourceInfo(Record, Idx); } +void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { + VisitExpr(E); + E->TypeTraitExprBits.NumArgs = Record[Idx++]; + E->TypeTraitExprBits.Kind = Record[Idx++]; + E->TypeTraitExprBits.Value = Record[Idx++]; + + TypeSourceInfo **Args = E->getTypeSourceInfos(); + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) + Args[I] = GetTypeSourceInfo(Record, Idx); +} + void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { VisitExpr(E); E->ATT = (ArrayTypeTrait)Record[Idx++]; @@ -2046,6 +2057,11 @@ S = new (Context) BinaryTypeTraitExpr(Empty); break; + case EXPR_TYPE_TRAIT: + S = TypeTraitExpr::CreateDeserialized(Context, + Record[ASTStmtReader::NumExprFields]); + break; + case EXPR_ARRAY_TYPE_TRAIT: S = new (Context) ArrayTypeTraitExpr(Empty); break; Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri Feb 24 01:38:34 2012 @@ -1341,6 +1341,16 @@ Code = serialization::EXPR_BINARY_TYPE_TRAIT; } +void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { + VisitExpr(E); + Record.push_back(E->TypeTraitExprBits.NumArgs); + Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding + Record.push_back(E->TypeTraitExprBits.Value); + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) + Writer.AddTypeSourceInfo(E->getArg(I), Record); + Code = serialization::EXPR_TYPE_TRAIT; +} + void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { VisitExpr(E); Record.push_back(E->getTrait()); Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Feb 24 01:38:34 2012 @@ -478,6 +478,7 @@ case Stmt::DependentScopeDeclRefExprClass: case Stmt::UnaryTypeTraitExprClass: case Stmt::BinaryTypeTraitExprClass: + case Stmt::TypeTraitExprClass: case Stmt::ArrayTypeTraitExprClass: case Stmt::ExpressionTraitExprClass: case Stmt::UnresolvedLookupExprClass: Modified: cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp (original) +++ cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp Fri Feb 24 01:38:34 2012 @@ -6,6 +6,11 @@ void test() { int a; decltype(a) b; + + typedef int Integer; + typedef float Float; + typedef bool Bool; + bool b2 = __is_trivially_constructible(Integer, Float, Bool); } // RUN: c-index-test -test-annotate-tokens=%s:1:1:5:1 -fno-delayed-template-parsing -std=c++11 %s | FileCheck %s @@ -14,3 +19,9 @@ // RUN: c-index-test -test-annotate-tokens=%s:8:1:9:1 -std=c++11 %s | FileCheck -check-prefix=CHECK-DECLTYPE %s // CHECK-DECLTYPE: Identifier: "a" [8:12 - 8:13] DeclRefExpr=a:7:7 + +// RUN: c-index-test -test-annotate-tokens=%s:13:1:14:1 -std=c++11 %s | FileCheck -check-prefix=CHECK-TRAIT %s +// CHECK-TRAIT: Identifier: "Integer" [13:42 - 13:49] TypeRef=Integer:10:15 +// CHECK-TRAIT: Identifier: "Float" [13:51 - 13:56] TypeRef=Float:11:17 +// CHECK-TRAIT: Identifier: "Bool" [13:58 - 13:62] TypeRef=Bool:12:16 + Modified: cfe/trunk/test/PCH/cxx-traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/test/PCH/cxx-traits.cpp (original) +++ cfe/trunk/test/PCH/cxx-traits.cpp Fri Feb 24 01:38:34 2012 @@ -1,8 +1,11 @@ // Test this without pch. -// RUN: %clang_cc1 -include %S/cxx-traits.h -fsyntax-only -verify %s +// RUN: %clang_cc1 -include %S/cxx-traits.h -std=c++11 -fsyntax-only -verify %s -// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-traits.h -// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s +// RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -o %t %S/cxx-traits.h +// RUN: %clang_cc1 -std=c++11 -include-pch %t -fsyntax-only -verify %s bool _Is_pod_comparator = __is_pod::__value; bool _Is_empty_check = __is_empty::__value; + +bool default_construct_int = is_trivially_constructible::value; +bool copy_construct_int = is_trivially_constructible::value; Modified: cfe/trunk/test/PCH/cxx-traits.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.h?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/test/PCH/cxx-traits.h (original) +++ cfe/trunk/test/PCH/cxx-traits.h Fri Feb 24 01:38:34 2012 @@ -9,3 +9,8 @@ struct __is_empty { enum { __value }; }; + +template +struct is_trivially_constructible { + static const bool value = __is_trivially_constructible(T, Args...); +}; Modified: cfe/trunk/test/SemaCXX/type-traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/type-traits.cpp (original) +++ cfe/trunk/test/SemaCXX/type-traits.cpp Fri Feb 24 01:38:34 2012 @@ -47,6 +47,10 @@ TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default; TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&); }; +struct NonTrivialDefault { + NonTrivialDefault(); +}; + struct HasDest { ~HasDest(); }; class HasPriv { int priv; }; class HasProt { protected: int prot; }; @@ -104,6 +108,10 @@ ~AllPrivate() throw(); }; +struct ThreeArgCtor { + ThreeArgCtor(int*, char*, int); +}; + void is_pod() { { int arr[T(__is_pod(int))]; } @@ -1602,7 +1610,7 @@ { int arr[F(__is_trivial(cvoid))]; } } -void is_trivially_copyable() +void trivial_checks() { { int arr[T(__is_trivially_copyable(int))]; } { int arr[T(__is_trivially_copyable(Enum))]; } @@ -1646,6 +1654,25 @@ { int arr[F(__is_trivially_copyable(void))]; } { int arr[F(__is_trivially_copyable(cvoid))]; } + { int arr[T((__is_trivially_constructible(int)))]; } + { int arr[T((__is_trivially_constructible(int, int)))]; } + { int arr[T((__is_trivially_constructible(int, float)))]; } + { int arr[T((__is_trivially_constructible(int, int&)))]; } + { int arr[T((__is_trivially_constructible(int, const int&)))]; } + { int arr[T((__is_trivially_constructible(int, int)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign)))]; } + { int arr[T((__is_trivially_constructible(NonTrivialDefault, + const NonTrivialDefault&)))]; } + { int arr[T((__is_trivially_constructible(NonTrivialDefault, + NonTrivialDefault&&)))]; } + + { int arr[F((__is_trivially_constructible(int, int*)))]; } + { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; } + { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; } + { int arr[T((__is_trivially_assignable(int&, int)))]; } { int arr[T((__is_trivially_assignable(int&, int&)))]; } { int arr[T((__is_trivially_assignable(int&, int&&)))]; } @@ -1680,6 +1707,33 @@ TrivialMoveButNotCopy&&)))]; } } +// Instantiation of __is_trivially_constructible +template +struct is_trivially_constructible { + static const bool value = __is_trivially_constructible(T, Args...); +}; + +void is_trivially_constructible_test() { + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + { int arr[T((is_trivially_constructible::value))]; } + + { int arr[F((is_trivially_constructible::value))]; } + { int arr[F((is_trivially_constructible::value))]; } + { int arr[F((is_trivially_constructible::value))]; } +} + void array_rank() { int t01[T(__array_rank(IntAr) == 1)]; int t02[T(__array_rank(ConstIntArAr) == 2)]; Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Fri Feb 24 01:38:34 2012 @@ -1755,6 +1755,7 @@ void VisitWhileStmt(WhileStmt *W); void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); + void VisitTypeTraitExpr(TypeTraitExpr *E); void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); void VisitExpressionTraitExpr(ExpressionTraitExpr *E); void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U); @@ -2056,6 +2057,11 @@ AddTypeLoc(E->getLhsTypeSourceInfo()); } +void EnqueueVisitor::VisitTypeTraitExpr(TypeTraitExpr *E) { + for (unsigned I = E->getNumArgs(); I > 0; --I) + AddTypeLoc(E->getArg(I-1)); +} + void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { AddTypeLoc(E->getQueriedTypeSourceInfo()); } Modified: cfe/trunk/tools/libclang/CXCursor.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=151352&r1=151351&r2=151352&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CXCursor.cpp (original) +++ cfe/trunk/tools/libclang/CXCursor.cpp Fri Feb 24 01:38:34 2012 @@ -206,6 +206,7 @@ case Stmt::AtomicExprClass: case Stmt::BinaryConditionalOperatorClass: case Stmt::BinaryTypeTraitExprClass: + case Stmt::TypeTraitExprClass: case Stmt::CXXBindTemporaryExprClass: case Stmt::CXXDefaultArgExprClass: case Stmt::CXXScalarValueInitExprClass: From dgregor at apple.com Thu Feb 23 23:48:38 2012 From: dgregor at apple.com (Douglas Gregor) Date: Fri, 24 Feb 2012 07:48:38 -0000 Subject: [cfe-commits] r151353 - /cfe/trunk/lib/Sema/SemaInit.cpp Message-ID: <20120224074838.26D4C2A6C12F@llvm.org> Author: dgregor Date: Fri Feb 24 01:48:37 2012 New Revision: 151353 URL: http://llvm.org/viewvc/llvm-project?rev=151353&view=rev Log: Kill a spurious use of hasTrivialDefaultConstructor() Modified: cfe/trunk/lib/Sema/SemaInit.cpp Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=151353&r1=151352&r2=151353&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Feb 24 01:48:37 2012 @@ -4631,8 +4631,7 @@ CXXRecordDecl *ClassDecl = Constructor->getParent(); assert(ClassDecl && "No parent class for constructor."); if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && - ClassDecl->hasTrivialDefaultConstructor() && - !Constructor->isUsed(false)) + Constructor->isTrivial() && !Constructor->isUsed(false)) S.DefineImplicitDefaultConstructor(Loc, Constructor); } From dgregor at apple.com Thu Feb 23 23:55:51 2012 From: dgregor at apple.com (Douglas Gregor) Date: Fri, 24 Feb 2012 07:55:51 -0000 Subject: [cfe-commits] r151354 - /cfe/trunk/lib/AST/ExprConstant.cpp Message-ID: <20120224075551.C30832A6C12F@llvm.org> Author: dgregor Date: Fri Feb 24 01:55:51 2012 New Revision: 151354 URL: http://llvm.org/viewvc/llvm-project?rev=151354&view=rev Log: Remove some trivial uses of hasTrivialCopyConstructor() and hasTrivialMoveConstructor(). Modified: cfe/trunk/lib/AST/ExprConstant.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=151354&r1=151353&r2=151354&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Feb 24 01:55:51 2012 @@ -2225,8 +2225,8 @@ // essential for unions, where the operations performed by the constructor // cannot be represented by ctor-initializers. if (Definition->isDefaulted() && - ((Definition->isCopyConstructor() && RD->hasTrivialCopyConstructor()) || - (Definition->isMoveConstructor() && RD->hasTrivialMoveConstructor()))) { + ((Definition->isCopyConstructor() && Definition->isTrivial()) || + (Definition->isMoveConstructor() && Definition->isTrivial()))) { LValue RHS; RHS.setFrom(ArgValues[0]); CCValue Value; From matthewbg at google.com Fri Feb 24 00:38:01 2012 From: matthewbg at google.com (Matt Beaumont-Gay) Date: Fri, 24 Feb 2012 08:38:01 -0000 Subject: [cfe-commits] r151356 - /cfe/trunk/lib/Sema/SemaInit.cpp Message-ID: <20120224083801.7EC462A6C130@llvm.org> Author: matthewbg Date: Fri Feb 24 02:37:56 2012 New Revision: 151356 URL: http://llvm.org/viewvc/llvm-project?rev=151356&view=rev Log: Sink variable into assert Modified: cfe/trunk/lib/Sema/SemaInit.cpp Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=151356&r1=151355&r2=151356&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Feb 24 02:37:56 2012 @@ -4628,8 +4628,7 @@ // Force even a trivial, implicit default constructor to be // semantically checked. We do this explicitly because we don't build // the definition for completely trivial constructors. - CXXRecordDecl *ClassDecl = Constructor->getParent(); - assert(ClassDecl && "No parent class for constructor."); + assert(Constructor->getParent() && "No parent class for constructor."); if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && Constructor->isTrivial() && !Constructor->isUsed(false)) S.DefineImplicitDefaultConstructor(Loc, Constructor); From nicholas at mxc.ca Fri Feb 24 00:58:14 2012 From: nicholas at mxc.ca (Nick Lewycky) Date: Fri, 24 Feb 2012 08:58:14 -0000 Subject: [cfe-commits] r151357 - /cfe/trunk/lib/AST/Expr.cpp Message-ID: <20120224085814.CDA6A2A6C12F@llvm.org> Author: nicholas Date: Fri Feb 24 02:58:14 2012 New Revision: 151357 URL: http://llvm.org/viewvc/llvm-project?rev=151357&view=rev Log: Silence gcc warnings pointing out that CharByteWidth could be used uninitialized. While there, restyle this function! No functionality change. Modified: cfe/trunk/lib/AST/Expr.cpp Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151357&r1=151356&r2=151357&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Fri Feb 24 02:58:14 2012 @@ -499,25 +499,28 @@ return V.convertToDouble(); } -int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) { +int StringLiteral::mapCharByteWidth(TargetInfo const &Target, + StringKind Kind) { int CharByteWidth; - switch(k) { + switch(Kind) { case Ascii: case UTF8: - CharByteWidth = target.getCharWidth(); + CharByteWidth = Target.getCharWidth(); break; case Wide: - CharByteWidth = target.getWCharWidth(); + CharByteWidth = Target.getWCharWidth(); break; case UTF16: - CharByteWidth = target.getChar16Width(); + CharByteWidth = Target.getChar16Width(); break; case UTF32: - CharByteWidth = target.getChar32Width(); + CharByteWidth = Target.getChar32Width(); + default: + llvm_unreachable("Don't know byte width of this string kind!"); } assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple"); CharByteWidth /= 8; - assert((CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4) + assert((CharByteWidth == 1 || CharByteWidth == 2 || CharByteWidth == 4) && "character byte widths supported are 1, 2, and 4 only"); return CharByteWidth; } @@ -562,7 +565,7 @@ this->Kind = Kind; this->IsPascal = IsPascal; - CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind); + CharByteWidth = mapCharByteWidth(C.getTargetInfo(), Kind); assert((Str.size()%CharByteWidth == 0) && "size of data must be multiple of CharByteWidth"); Length = Str.size()/CharByteWidth; From nicholas at mxc.ca Fri Feb 24 01:07:53 2012 From: nicholas at mxc.ca (Nick Lewycky) Date: Fri, 24 Feb 2012 09:07:53 -0000 Subject: [cfe-commits] r151359 - /cfe/trunk/lib/AST/Expr.cpp Message-ID: <20120224090753.6C7322A6C12F@llvm.org> Author: nicholas Date: Fri Feb 24 03:07:53 2012 New Revision: 151359 URL: http://llvm.org/viewvc/llvm-project?rev=151359&view=rev Log: Revert r151357. That unreachable is reachable... Modified: cfe/trunk/lib/AST/Expr.cpp Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151359&r1=151358&r2=151359&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Fri Feb 24 03:07:53 2012 @@ -499,28 +499,25 @@ return V.convertToDouble(); } -int StringLiteral::mapCharByteWidth(TargetInfo const &Target, - StringKind Kind) { +int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) { int CharByteWidth; - switch(Kind) { + switch(k) { case Ascii: case UTF8: - CharByteWidth = Target.getCharWidth(); + CharByteWidth = target.getCharWidth(); break; case Wide: - CharByteWidth = Target.getWCharWidth(); + CharByteWidth = target.getWCharWidth(); break; case UTF16: - CharByteWidth = Target.getChar16Width(); + CharByteWidth = target.getChar16Width(); break; case UTF32: - CharByteWidth = Target.getChar32Width(); - default: - llvm_unreachable("Don't know byte width of this string kind!"); + CharByteWidth = target.getChar32Width(); } assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple"); CharByteWidth /= 8; - assert((CharByteWidth == 1 || CharByteWidth == 2 || CharByteWidth == 4) + assert((CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4) && "character byte widths supported are 1, 2, and 4 only"); return CharByteWidth; } @@ -565,7 +562,7 @@ this->Kind = Kind; this->IsPascal = IsPascal; - CharByteWidth = mapCharByteWidth(C.getTargetInfo(), Kind); + CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind); assert((Str.size()%CharByteWidth == 0) && "size of data must be multiple of CharByteWidth"); Length = Str.size()/CharByteWidth; From ahmedcharles at gmail.com Fri Feb 24 02:26:20 2012 From: ahmedcharles at gmail.com (Ahmed Charles) Date: Fri, 24 Feb 2012 02:26:20 -0800 Subject: [cfe-commits] [PATCH] ArrayRef'ize various functions in clang Message-ID: Fairly straight forward changes to allow ArrayRef rather than Expr** and int. -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-ArrayRef-ize-various-functions-in-the-AST-Parser-Sem.patch Type: application/octet-stream Size: 82735 bytes Desc: not available URL: From nicola.gigante at gmail.com Fri Feb 24 03:09:36 2012 From: nicola.gigante at gmail.com (Nicola Gigante) Date: Fri, 24 Feb 2012 12:09:36 +0100 Subject: [cfe-commits] [cfe-dev] [review request] Removing redundant implicit casts in the AST, take 2 In-Reply-To: References: <38340.10.0.7.178.1324832340.squirrel@webmail.secure.aluminati.net> <47151.10.0.7.180.1324940787.squirrel@webmail.secure.aluminati.net> <8C608B16-0158-4770-B570-54E061D04149@me.com> <6C24E5FD-DE95-4056-882A-4F3F467F23C2@me.com> <04408013-EC28-40D2-AF87-09A5FB940D8B@me.com> Message-ID: Il giorno 24/feb/2012, alle ore 03:28, Richard Smith ha scritto: > Hi, > Hello! > On to the patch. I think it's really very close now: > [..] I'm going to fix all those issues, off course. Just a couple of things: > -void CastOperation::CheckStaticCast() { > +void CastOperation::CheckStaticCast(bool &CastNodesCreated, > + Sema::CheckedConversionInfo CCI) { > > Rather than taking a bool argument by reference, it might be nicer to return a bool from here to indicate whether a CXXStaticCast node was created. > I've chosen to use a by-reference argument for clarity. A bool returned by a function named CheckStaticCast() can be very easily misinterpreted, in my opinion, to mean "checking done" vs "checking failed", even adding a comment that says otherwise. Don't you think so? I'll change it anyway, if you wish. > + CastNodesCreated = (SrcExpr.get() != SrcExprOrig && > + Kind != CK_ConstructorConversion); > > This approach makes me nervous: it seems too easy for us to accidentally change SrcExpr without building a cast node (checkNonOverloadPlaceholders could do this, for instance). Can we ensure that TryStaticCast returns TC_Success exactly when it's created a CXXStaticCast node, then use that to determine whether we need to build one? > You're right. I think we can be sure that TryStaticImplicitCast() has created the node if it returns TC_Success and Kind != CK_ConstructorConversion. But it depends on how InitializationSequence::Perform() behaves. Do you think this is the case? > In the ElType == ToType case, it looks like this could still produce a no-op static cast containing an implicit cast. You're right. Fixed it. I've also contextually fixed a warning that appears in addFixitForObjCARCConversion() that doesn't include the recently added CCK_StaticCast enum value in a switch statement. Attached is the patch to the last revision with all the issues fixed excepting the two questions I asked here. > > Thanks! > Richard Thanks, Nicola -------------- next part -------------- A non-text attachment was scrubbed... Name: ImplicitCastsRemoval-r151359.patch Type: application/octet-stream Size: 59567 bytes Desc: not available URL: From hhinnant at apple.com Fri Feb 24 06:09:53 2012 From: hhinnant at apple.com (Howard Hinnant) Date: Fri, 24 Feb 2012 09:09:53 -0500 Subject: [cfe-commits] r151352 - in /cfe/trunk: docs/ include/clang/AST/ include/clang/Basic/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/Lex/ lib/Parse/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/Index/ test/PCH/ test/SemaCXX/ tools/libclang/ In-Reply-To: <20120224073836.429A12A6C12F@llvm.org> References: <20120224073836.429A12A6C12F@llvm.org> Message-ID: Awesome, thanks! Howard On Feb 24, 2012, at 2:38 AM, Douglas Gregor wrote: > Author: dgregor > Date: Fri Feb 24 01:38:34 2012 > New Revision: 151352 > > URL: http://llvm.org/viewvc/llvm-project?rev=151352&view=rev > Log: > Implement a new type trait __is_trivially_constructible(T, Args...) > that provides the behavior of the C++11 library trait > std::is_trivially_constructible, which can't be > implemented purely as a library. > > Since __is_trivially_constructible can have zero or more arguments, I > needed to add Yet Another Type Trait Expression Class, this one > handling arbitrary arguments. The next step will be to migrate > UnaryTypeTrait and BinaryTypeTrait over to this new, more general > TypeTrait class. > > Fixes the Clang side of / PR12038. > > Modified: > cfe/trunk/docs/LanguageExtensions.html > cfe/trunk/include/clang/AST/ExprCXX.h > cfe/trunk/include/clang/AST/RecursiveASTVisitor.h > cfe/trunk/include/clang/AST/Stmt.h > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/include/clang/Basic/StmtNodes.td > cfe/trunk/include/clang/Basic/TokenKinds.def > cfe/trunk/include/clang/Basic/TypeTraits.h > cfe/trunk/include/clang/Parse/Parser.h > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/include/clang/Serialization/ASTBitCodes.h > cfe/trunk/lib/AST/Expr.cpp > cfe/trunk/lib/AST/ExprCXX.cpp > cfe/trunk/lib/AST/ExprClassification.cpp > cfe/trunk/lib/AST/ExprConstant.cpp > cfe/trunk/lib/AST/ItaniumMangle.cpp > cfe/trunk/lib/AST/StmtPrinter.cpp > cfe/trunk/lib/AST/StmtProfile.cpp > cfe/trunk/lib/Lex/PPMacroExpansion.cpp > cfe/trunk/lib/Parse/ParseExpr.cpp > cfe/trunk/lib/Parse/ParseExprCXX.cpp > cfe/trunk/lib/Parse/ParseTentative.cpp > cfe/trunk/lib/Sema/SemaExprCXX.cpp > cfe/trunk/lib/Sema/TreeTransform.h > cfe/trunk/lib/Serialization/ASTReaderStmt.cpp > cfe/trunk/lib/Serialization/ASTWriterStmt.cpp > cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp > cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp > cfe/trunk/test/PCH/cxx-traits.cpp > cfe/trunk/test/PCH/cxx-traits.h > cfe/trunk/test/SemaCXX/type-traits.cpp > cfe/trunk/tools/libclang/CIndex.cpp > cfe/trunk/tools/libclang/CXCursor.cpp > > Modified: cfe/trunk/docs/LanguageExtensions.html > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.html?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/docs/LanguageExtensions.html (original) > +++ cfe/trunk/docs/LanguageExtensions.html Fri Feb 24 01:38:34 2012 > @@ -889,6 +889,8 @@ >
  • __is_literal(type): Determines whether the given type is a literal type
  • >
  • __is_final: Determines whether the given type is declared with a final class-virt-specifier.
  • >
  • __underlying_type(type): Retrieves the underlying type for a given enum type. This trait is required to implement the C++11 standard library.
  • > +
  • __is_trivially_assignable(totype, fromtype): Determines whether a value of type totype can be assigned to from a value of type fromtype such that no non-trivial functions are called as part of that assignment. This trait is required to implement the C++11 standard library.
  • > +
  • __is_trivially_constructible(type, argtypes...): Determines whether a value of type type can be direct-initialized with arguments of types argtypes... such that no non-trivial functions are called as part of that initialization. This trait is required to implement the C++11 standard library.
  • > > > > > Modified: cfe/trunk/include/clang/AST/ExprCXX.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/ExprCXX.h (original) > +++ cfe/trunk/include/clang/AST/ExprCXX.h Fri Feb 24 01:38:34 2012 > @@ -1926,6 +1926,102 @@ > friend class ASTStmtReader; > }; > > +/// \brief A type trait used in the implementation of various C++11 and > +/// Library TR1 trait templates. > +/// > +/// \code > +/// __is_trivially_constructible(vector, int*, int*) > +/// \endcode > +class TypeTraitExpr : public Expr { > + /// \brief The location of the type trait keyword. > + SourceLocation Loc; > + > + /// \brief The location of the closing parenthesis. > + SourceLocation RParenLoc; > + > + // Note: The TypeSourceInfos for the arguments are allocated after the > + // TypeTraitExpr. > + > + TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, > + ArrayRef Args, > + SourceLocation RParenLoc, > + bool Value); > + > + TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { } > + > + /// \brief Retrieve the argument types. > + TypeSourceInfo **getTypeSourceInfos() { > + return reinterpret_cast(this+1); > + } > + > + /// \brief Retrieve the argument types. > + TypeSourceInfo * const *getTypeSourceInfos() const { > + return reinterpret_cast(this+1); > + } > + > +public: > + /// \brief Create a new type trait expression. > + static TypeTraitExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, > + TypeTrait Kind, > + ArrayRef Args, > + SourceLocation RParenLoc, > + bool Value); > + > + static TypeTraitExpr *CreateDeserialized(ASTContext &C, unsigned NumArgs); > + > + /// \brief Determine which type trait this expression uses. > + TypeTrait getTrait() const { > + return static_cast(TypeTraitExprBits.Kind); > + } > + > + bool getValue() const { > + assert(!isValueDependent()); > + return TypeTraitExprBits.Value; > + } > + > + /// \brief Determine the number of arguments to this type trait. > + unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } > + > + /// \brief Retrieve the Ith argument. > + TypeSourceInfo *getArg(unsigned I) const { > + assert(I < getNumArgs() && "Argument out-of-range"); > + return getArgs()[I]; > + } > + > + /// \brief Retrieve the argument types. > + ArrayRef getArgs() const { > + return ArrayRef(getTypeSourceInfos(), getNumArgs()); > + } > + > + typedef TypeSourceInfo **arg_iterator; > + arg_iterator arg_begin() { > + return getTypeSourceInfos(); > + } > + arg_iterator arg_end() { > + return getTypeSourceInfos() + getNumArgs(); > + } > + > + typedef TypeSourceInfo const * const *arg_const_iterator; > + arg_const_iterator arg_begin() const { return getTypeSourceInfos(); } > + arg_const_iterator arg_end() const { > + return getTypeSourceInfos() + getNumArgs(); > + } > + > + SourceRange getSourceRange() const { return SourceRange(Loc, RParenLoc); } > + > + static bool classof(const Stmt *T) { > + return T->getStmtClass() == TypeTraitExprClass; > + } > + static bool classof(const TypeTraitExpr *) { return true; } > + > + // Iterators > + child_range children() { return child_range(); } > + > + friend class ASTStmtReader; > + friend class ASTStmtWriter; > + > +}; > + > /// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the > /// implementation of __array_rank and __array_extent. > /// Example: > > Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) > +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Feb 24 01:38:34 2012 > @@ -1946,6 +1946,11 @@ > TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); > }) > > +DEF_TRAVERSE_STMT(TypeTraitExpr, { > + for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) > + TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc())); > +}) > + > DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { > TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); > }) > > Modified: cfe/trunk/include/clang/AST/Stmt.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/Stmt.h (original) > +++ cfe/trunk/include/clang/AST/Stmt.h Fri Feb 24 01:38:34 2012 > @@ -227,6 +227,24 @@ > unsigned InitializesStdInitializerList : 1; > }; > > + class TypeTraitExprBitfields { > + friend class TypeTraitExpr; > + friend class ASTStmtReader; > + friend class ASTStmtWriter; > + > + unsigned : NumExprBits; > + > + /// \brief The kind of type trait, which is a value of a TypeTrait enumerator. > + unsigned Kind : 8; > + > + /// \brief If this expression is not value-dependent, this indicates whether > + /// the trait evaluated true or false. > + unsigned Value : 1; > + > + /// \brief The number of arguments to this type trait. > + unsigned NumArgs : 32 - 8 - 1 - NumExprBits; > + }; > + > union { > // FIXME: this is wasteful on 64-bit platforms. > void *Aligner; > @@ -241,9 +259,11 @@ > PseudoObjectExprBitfields PseudoObjectExprBits; > ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; > InitListExprBitfields InitListExprBits; > + TypeTraitExprBitfields TypeTraitExprBits; > }; > > friend class ASTStmtReader; > + friend class ASTStmtWriter; > > public: > // Only allow allocation of Stmts using the allocator in ASTContext > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 24 01:38:34 2012 > @@ -4438,6 +4438,10 @@ > > def err_incomplete_type_used_in_type_trait_expr : Error< > "incomplete type %0 used in type trait expression">; > +def err_type_trait_arity : Error< > + "type trait requires %0%select{| or more}1 argument%select{|s}2; have " > + "%3 argument%s3">; > + > def err_dimension_expr_not_constant_integer : Error< > "dimension expression does not evaluate to a constant unsigned int">; > def err_expected_ident_or_lparen : Error<"expected identifier or '('">; > > Modified: cfe/trunk/include/clang/Basic/StmtNodes.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/StmtNodes.td (original) > +++ cfe/trunk/include/clang/Basic/StmtNodes.td Fri Feb 24 01:38:34 2012 > @@ -107,6 +107,7 @@ > def CXXNewExpr : DStmt; > def CXXDeleteExpr : DStmt; > def CXXPseudoDestructorExpr : DStmt; > +def TypeTraitExpr : DStmt; > def UnaryTypeTraitExpr : DStmt; > def BinaryTypeTraitExpr : DStmt; > def ArrayTypeTraitExpr : DStmt; > > Modified: cfe/trunk/include/clang/Basic/TokenKinds.def > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) > +++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri Feb 24 01:38:34 2012 > @@ -365,6 +365,7 @@ > KEYWORD(__is_union , KEYCXX) > > // Clang-only C++ Type Traits > +KEYWORD(__is_trivially_constructible, KEYCXX) > KEYWORD(__is_trivially_copyable , KEYCXX) > KEYWORD(__is_trivially_assignable , KEYCXX) > KEYWORD(__underlying_type , KEYCXX) > > Modified: cfe/trunk/include/clang/Basic/TypeTraits.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/TypeTraits.h (original) > +++ cfe/trunk/include/clang/Basic/TypeTraits.h Fri Feb 24 01:38:34 2012 > @@ -84,6 +84,12 @@ > UETT_AlignOf, > UETT_VecStep > }; > + > + /// \brief Names for type traits that operate specifically on types. > + enum TypeTrait { > + TT_IsTriviallyConstructible > + }; > + > } > > #endif > > Modified: cfe/trunk/include/clang/Parse/Parser.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Parse/Parser.h (original) > +++ cfe/trunk/include/clang/Parse/Parser.h Fri Feb 24 01:38:34 2012 > @@ -2170,7 +2170,8 @@ > // GNU G++: Type Traits [Type-Traits.html in the GCC manual] > ExprResult ParseUnaryTypeTrait(); > ExprResult ParseBinaryTypeTrait(); > - > + ExprResult ParseTypeTrait(); > + > //===--------------------------------------------------------------------===// > // Embarcadero: Arary and Expression Traits > ExprResult ParseArrayTypeTrait(); > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Fri Feb 24 01:38:34 2012 > @@ -3317,6 +3317,14 @@ > TypeSourceInfo *RhsT, > SourceLocation RParen); > > + /// \brief Parsed one of the type trait support pseudo-functions. > + ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, > + ArrayRef Args, > + SourceLocation RParenLoc); > + ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, > + ArrayRef Args, > + SourceLocation RParenLoc); > + > /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support > /// pseudo-functions. > ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, > > Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) > +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Feb 24 01:38:34 2012 > @@ -1156,6 +1156,7 @@ > EXPR_OPAQUE_VALUE, // OpaqueValueExpr > EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator > EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr > + EXPR_TYPE_TRAIT, // TypeTraitExpr > EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr > > EXPR_PACK_EXPANSION, // PackExpansionExpr > > Modified: cfe/trunk/lib/AST/Expr.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/Expr.cpp (original) > +++ cfe/trunk/lib/AST/Expr.cpp Fri Feb 24 01:38:34 2012 > @@ -2169,6 +2169,7 @@ > case AddrLabelExprClass: > case ArrayTypeTraitExprClass: > case BinaryTypeTraitExprClass: > + case TypeTraitExprClass: > case CXXBoolLiteralExprClass: > case CXXNoexceptExprClass: > case CXXNullPtrLiteralExprClass: > > Modified: cfe/trunk/lib/AST/ExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ExprCXX.cpp (original) > +++ cfe/trunk/lib/AST/ExprCXX.cpp Fri Feb 24 01:38:34 2012 > @@ -199,7 +199,6 @@ > return SourceRange(Base->getLocStart(), End); > } > > - > // UnresolvedLookupExpr > UnresolvedLookupExpr * > UnresolvedLookupExpr::Create(ASTContext &C, > @@ -1262,4 +1261,51 @@ > return TemplateArgument(Arguments, NumArguments); > } > > +TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, > + ArrayRef Args, > + SourceLocation RParenLoc, > + bool Value) > + : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary, > + /*TypeDependent=*/false, > + /*ValueDependent=*/false, > + /*InstantiationDependent=*/false, > + /*ContainsUnexpandedParameterPack=*/false), > + Loc(Loc), RParenLoc(RParenLoc) > +{ > + TypeTraitExprBits.Kind = Kind; > + TypeTraitExprBits.Value = Value; > + TypeTraitExprBits.NumArgs = Args.size(); > + > + TypeSourceInfo **ToArgs = getTypeSourceInfos(); > + > + for (unsigned I = 0, N = Args.size(); I != N; ++I) { > + if (Args[I]->getType()->isDependentType()) > + setValueDependent(true); > + if (Args[I]->getType()->isInstantiationDependentType()) > + setInstantiationDependent(true); > + if (Args[I]->getType()->containsUnexpandedParameterPack()) > + setContainsUnexpandedParameterPack(true); > + > + ToArgs[I] = Args[I]; > + } > +} > + > +TypeTraitExpr *TypeTraitExpr::Create(ASTContext &C, QualType T, > + SourceLocation Loc, > + TypeTrait Kind, > + ArrayRef Args, > + SourceLocation RParenLoc, > + bool Value) { > + unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * Args.size(); > + void *Mem = C.Allocate(Size); > + return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value); > +} > + > +TypeTraitExpr *TypeTraitExpr::CreateDeserialized(ASTContext &C, > + unsigned NumArgs) { > + unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * NumArgs; > + void *Mem = C.Allocate(Size); > + return new (Mem) TypeTraitExpr(EmptyShell()); > +} > + > void ArrayTypeTraitExpr::anchor() { } > > Modified: cfe/trunk/lib/AST/ExprClassification.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ExprClassification.cpp (original) > +++ cfe/trunk/lib/AST/ExprClassification.cpp Fri Feb 24 01:38:34 2012 > @@ -151,6 +151,7 @@ > case Expr::CXXScalarValueInitExprClass: > case Expr::UnaryTypeTraitExprClass: > case Expr::BinaryTypeTraitExprClass: > + case Expr::TypeTraitExprClass: > case Expr::ArrayTypeTraitExprClass: > case Expr::ExpressionTraitExprClass: > case Expr::ObjCSelectorExprClass: > > Modified: cfe/trunk/lib/AST/ExprConstant.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ExprConstant.cpp (original) > +++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Feb 24 01:38:34 2012 > @@ -4119,6 +4119,10 @@ > return Success(E->getValue(), E); > } > > + bool VisitTypeTraitExpr(const TypeTraitExpr *E) { > + return Success(E->getValue(), E); > + } > + > bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { > return Success(E->getValue(), E); > } > @@ -6360,6 +6364,7 @@ > case Expr::CXXScalarValueInitExprClass: > case Expr::UnaryTypeTraitExprClass: > case Expr::BinaryTypeTraitExprClass: > + case Expr::TypeTraitExprClass: > case Expr::ArrayTypeTraitExprClass: > case Expr::ExpressionTraitExprClass: > case Expr::CXXNoexceptExprClass: > > Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) > +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Fri Feb 24 01:38:34 2012 > @@ -2383,6 +2383,7 @@ > case Expr::StmtExprClass: > case Expr::UnaryTypeTraitExprClass: > case Expr::BinaryTypeTraitExprClass: > + case Expr::TypeTraitExprClass: > case Expr::ArrayTypeTraitExprClass: > case Expr::ExpressionTraitExprClass: > case Expr::VAArgExprClass: > > Modified: cfe/trunk/lib/AST/StmtPrinter.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/StmtPrinter.cpp (original) > +++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Feb 24 01:38:34 2012 > @@ -1555,6 +1555,13 @@ > llvm_unreachable("Binary type trait not covered by switch"); > } > > +static const char *getTypeTraitName(TypeTrait TT) { > + switch (TT) { > + case clang::TT_IsTriviallyConstructible:return "__is_trivially_constructible"; > + } > + llvm_unreachable("Type trait not covered by switch"); > +} > + > static const char *getTypeTraitName(ArrayTypeTrait ATT) { > switch (ATT) { > case ATT_ArrayRank: return "__array_rank"; > @@ -1582,6 +1589,16 @@ > << E->getRhsType().getAsString(Policy) << ")"; > } > > +void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) { > + OS << getTypeTraitName(E->getTrait()) << "("; > + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { > + if (I > 0) > + OS << ", "; > + OS << E->getArg(I)->getType().getAsString(Policy); > + } > + OS << ")"; > +} > + > void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { > OS << getTypeTraitName(E->getTrait()) << "(" > << E->getQueriedType().getAsString(Policy) << ")"; > > Modified: cfe/trunk/lib/AST/StmtProfile.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/StmtProfile.cpp (original) > +++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Feb 24 01:38:34 2012 > @@ -868,6 +868,14 @@ > VisitType(S->getRhsType()); > } > > +void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) { > + VisitExpr(S); > + ID.AddInteger(S->getTrait()); > + ID.AddInteger(S->getNumArgs()); > + for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) > + VisitType(S->getArg(I)->getType()); > +} > + > void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) { > VisitExpr(S); > ID.AddInteger(S->getTrait()); > > Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) > +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Fri Feb 24 01:38:34 2012 > @@ -701,6 +701,7 @@ > .Case("is_polymorphic", LangOpts.CPlusPlus) > .Case("is_trivial", LangOpts.CPlusPlus) > .Case("is_trivially_assignable", LangOpts.CPlusPlus) > + .Case("is_trivially_constructible", LangOpts.CPlusPlus) > .Case("is_trivially_copyable", LangOpts.CPlusPlus) > .Case("is_union", LangOpts.CPlusPlus) > .Case("modules", LangOpts.Modules) > > Modified: cfe/trunk/lib/Parse/ParseExpr.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) > +++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Feb 24 01:38:34 2012 > @@ -1143,6 +1143,9 @@ > case tok::kw___is_trivially_assignable: > return ParseBinaryTypeTrait(); > > + case tok::kw___is_trivially_constructible: > + return ParseTypeTrait(); > + > case tok::kw___array_rank: > case tok::kw___array_extent: > return ParseArrayTypeTrait(); > > Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) > +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Feb 24 01:38:34 2012 > @@ -2458,6 +2458,14 @@ > } > } > > +static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) { > + switch (kind) { > + default: llvm_unreachable("Not a known type trait"); > + case tok::kw___is_trivially_constructible: > + return TT_IsTriviallyConstructible; > + } > +} > + > static ArrayTypeTrait ArrayTypeTraitFromTokKind(tok::TokenKind kind) { > switch(kind) { > default: llvm_unreachable("Not a known binary type trait"); > @@ -2540,6 +2548,58 @@ > T.getCloseLocation()); > } > > +/// \brief Parse the built-in type-trait pseudo-functions that allow > +/// implementation of the TR1/C++11 type traits templates. > +/// > +/// primary-expression: > +/// type-trait '(' type-id-seq ')' > +/// > +/// type-id-seq: > +/// type-id ...[opt] type-id-seq[opt] > +/// > +ExprResult Parser::ParseTypeTrait() { > + TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind()); > + SourceLocation Loc = ConsumeToken(); > + > + BalancedDelimiterTracker Parens(*this, tok::l_paren); > + if (Parens.expectAndConsume(diag::err_expected_lparen)) > + return ExprError(); > + > + llvm::SmallVector Args; > + do { > + // Parse the next type. > + TypeResult Ty = ParseTypeName(); > + if (Ty.isInvalid()) { > + Parens.skipToEnd(); > + return ExprError(); > + } > + > + // Parse the ellipsis, if present. > + if (Tok.is(tok::ellipsis)) { > + Ty = Actions.ActOnPackExpansion(Ty.get(), ConsumeToken()); > + if (Ty.isInvalid()) { > + Parens.skipToEnd(); > + return ExprError(); > + } > + } > + > + // Add this type to the list of arguments. > + Args.push_back(Ty.get()); > + > + if (Tok.is(tok::comma)) { > + ConsumeToken(); > + continue; > + } > + > + break; > + } while (true); > + > + if (Parens.consumeClose()) > + return ExprError(); > + > + return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation()); > +} > + > /// ParseArrayTypeTrait - Parse the built-in array type-trait > /// pseudo-functions. > /// > > Modified: cfe/trunk/lib/Parse/ParseTentative.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseTentative.cpp (original) > +++ cfe/trunk/lib/Parse/ParseTentative.cpp Fri Feb 24 01:38:34 2012 > @@ -690,6 +690,7 @@ > case tok::kw___is_polymorphic: > case tok::kw___is_trivial: > case tok::kw___is_trivially_assignable: > + case tok::kw___is_trivially_constructible: > case tok::kw___is_trivially_copyable: > case tok::kw___is_union: > case tok::kw___uuidof: > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Feb 24 01:38:34 2012 > @@ -3212,6 +3212,127 @@ > return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen); > } > > +static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, > + ArrayRef Args, > + SourceLocation RParenLoc) { > + switch (Kind) { > + case clang::TT_IsTriviallyConstructible: { > + // C++11 [meta.unary.prop]: > + // is_trivially_constructor is defined as: > + // > + // is_constructible::value is true and the variable > + // > + /// definition for is_constructible, as defined below, is known to call no > + // operation that is not trivial. > + // > + // The predicate condition for a template specialization > + // is_constructible shall be satisfied if and only if the > + // following variable definition would be well-formed for some invented > + // variable t: > + // > + // T t(create()...); > + if (Args.empty()) { > + S.Diag(KWLoc, diag::err_type_trait_arity) > + << 1 << 1 << 1 << (int)Args.size(); > + return false; > + } > + > + bool SawVoid = false; > + for (unsigned I = 0, N = Args.size(); I != N; ++I) { > + if (Args[I]->getType()->isVoidType()) { > + SawVoid = true; > + continue; > + } > + > + if (!Args[I]->getType()->isIncompleteType() && > + S.RequireCompleteType(KWLoc, Args[I]->getType(), > + diag::err_incomplete_type_used_in_type_trait_expr)) > + return false; > + } > + > + // If any argument was 'void', of course it won't type-check. > + if (SawVoid) > + return false; > + > + llvm::SmallVector OpaqueArgExprs; > + llvm::SmallVector ArgExprs; > + ArgExprs.reserve(Args.size() - 1); > + for (unsigned I = 1, N = Args.size(); I != N; ++I) { > + QualType T = Args[I]->getType(); > + if (T->isObjectType() || T->isFunctionType()) > + T = S.Context.getRValueReferenceType(T); > + OpaqueArgExprs.push_back( > + OpaqueValueExpr(Args[I]->getTypeLoc().getSourceRange().getBegin(), > + T.getNonLValueExprType(S.Context), > + Expr::getValueKindForType(T))); > + ArgExprs.push_back(&OpaqueArgExprs.back()); > + } > + > + // Perform the initialization in an unevaluated context within a SFINAE > + // trap at translation unit scope. > + EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); > + Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true); > + Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); > + InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0])); > + InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc, > + RParenLoc)); > + InitializationSequence Init(S, To, InitKind, > + ArgExprs.begin(), ArgExprs.size()); > + if (Init.Failed()) > + return false; > + > + ExprResult Result = Init.Perform(S, To, InitKind, > + MultiExprArg(ArgExprs.data(), > + ArgExprs.size())); > + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) > + return false; > + > + // The initialization succeeded; not make sure there are no non-trivial > + // calls. > + return !Result.get()->hasNonTrivialCall(S.Context); > + } > + } > + > + return false; > +} > + > +ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, > + ArrayRef Args, > + SourceLocation RParenLoc) { > + bool Dependent = false; > + for (unsigned I = 0, N = Args.size(); I != N; ++I) { > + if (Args[I]->getType()->isDependentType()) { > + Dependent = true; > + break; > + } > + } > + > + bool Value = false; > + if (!Dependent) > + Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc); > + > + return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind, > + Args, RParenLoc, Value); > +} > + > +ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, > + ArrayRef Args, > + SourceLocation RParenLoc) { > + llvm::SmallVector ConvertedArgs; > + ConvertedArgs.reserve(Args.size()); > + > + for (unsigned I = 0, N = Args.size(); I != N; ++I) { > + TypeSourceInfo *TInfo; > + QualType T = GetTypeFromParser(Args[I], &TInfo); > + if (!TInfo) > + TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc); > + > + ConvertedArgs.push_back(TInfo); > + } > + > + return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc); > +} > + > static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, > QualType LhsT, QualType RhsT, > SourceLocation KeyLoc) { > > Modified: cfe/trunk/lib/Sema/TreeTransform.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/TreeTransform.h (original) > +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Feb 24 01:38:34 2012 > @@ -2022,6 +2022,17 @@ > return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc); > } > > + /// \brief Build a new type trait expression. > + /// > + /// By default, performs semantic analysis to build the new expression. > + /// Subclasses may override this routine to provide different behavior. > + ExprResult RebuildTypeTrait(TypeTrait Trait, > + SourceLocation StartLoc, > + ArrayRef Args, > + SourceLocation RParenLoc) { > + return getSema().BuildTypeTrait(Trait, StartLoc, Args, RParenLoc); > + } > + > /// \brief Build a new array type trait expression. > /// > /// By default, performs semantic analysis to build the new expression. > @@ -7436,6 +7447,128 @@ > > template > ExprResult > +TreeTransform::TransformTypeTraitExpr(TypeTraitExpr *E) { > + bool ArgChanged = false; > + llvm::SmallVector Args; > + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { > + TypeSourceInfo *From = E->getArg(I); > + TypeLoc FromTL = From->getTypeLoc(); > + if (!isa(FromTL)) { > + TypeLocBuilder TLB; > + TLB.reserve(FromTL.getFullDataSize()); > + QualType To = getDerived().TransformType(TLB, FromTL); > + if (To.isNull()) > + return ExprError(); > + > + if (To == From->getType()) > + Args.push_back(From); > + else { > + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); > + ArgChanged = true; > + } > + continue; > + } > + > + ArgChanged = true; > + > + // We have a pack expansion. Instantiate it. > + PackExpansionTypeLoc ExpansionTL = cast(FromTL); > + TypeLoc PatternTL = ExpansionTL.getPatternLoc(); > + SmallVector Unexpanded; > + SemaRef.collectUnexpandedParameterPacks(PatternTL, Unexpanded); > + > + // Determine whether the set of unexpanded parameter packs can and should > + // be expanded. > + bool Expand = true; > + bool RetainExpansion = false; > + llvm::Optional OrigNumExpansions > + = ExpansionTL.getTypePtr()->getNumExpansions(); > + llvm::Optional NumExpansions = OrigNumExpansions; > + if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), > + PatternTL.getSourceRange(), > + Unexpanded, > + Expand, RetainExpansion, > + NumExpansions)) > + return ExprError(); > + > + if (!Expand) { > + // The transform has determined that we should perform a simple > + // transformation on the pack expansion, producing another pack > + // expansion. > + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); > + > + TypeLocBuilder TLB; > + TLB.reserve(From->getTypeLoc().getFullDataSize()); > + > + QualType To = getDerived().TransformType(TLB, PatternTL); > + if (To.isNull()) > + return ExprError(); > + > + To = getDerived().RebuildPackExpansionType(To, > + PatternTL.getSourceRange(), > + ExpansionTL.getEllipsisLoc(), > + NumExpansions); > + if (To.isNull()) > + return ExprError(); > + > + PackExpansionTypeLoc ToExpansionTL > + = TLB.push(To); > + ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc()); > + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); > + continue; > + } > + > + // Expand the pack expansion by substituting for each argument in the > + // pack(s). > + for (unsigned I = 0; I != *NumExpansions; ++I) { > + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); > + TypeLocBuilder TLB; > + TLB.reserve(PatternTL.getFullDataSize()); > + QualType To = getDerived().TransformType(TLB, PatternTL); > + if (To.isNull()) > + return ExprError(); > + > + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); > + } > + > + if (!RetainExpansion) > + continue; > + > + // If we're supposed to retain a pack expansion, do so by temporarily > + // forgetting the partially-substituted parameter pack. > + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); > + > + TypeLocBuilder TLB; > + TLB.reserve(From->getTypeLoc().getFullDataSize()); > + > + QualType To = getDerived().TransformType(TLB, PatternTL); > + if (To.isNull()) > + return ExprError(); > + > + To = getDerived().RebuildPackExpansionType(To, > + PatternTL.getSourceRange(), > + ExpansionTL.getEllipsisLoc(), > + NumExpansions); > + if (To.isNull()) > + return ExprError(); > + > + PackExpansionTypeLoc ToExpansionTL > + = TLB.push(To); > + ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc()); > + Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To)); > + } > + > + if (!getDerived().AlwaysRebuild() && !ArgChanged) > + return SemaRef.Owned(E); > + > + return getDerived().RebuildTypeTrait(E->getTrait(), > + E->getLocStart(), > + Args, > + E->getLocEnd()); > +} > + > +template > +ExprResult > TreeTransform::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { > TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); > if (!T) > > Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri Feb 24 01:38:34 2012 > @@ -1327,6 +1327,17 @@ > E->RhsType = GetTypeSourceInfo(Record, Idx); > } > > +void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { > + VisitExpr(E); > + E->TypeTraitExprBits.NumArgs = Record[Idx++]; > + E->TypeTraitExprBits.Kind = Record[Idx++]; > + E->TypeTraitExprBits.Value = Record[Idx++]; > + > + TypeSourceInfo **Args = E->getTypeSourceInfos(); > + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) > + Args[I] = GetTypeSourceInfo(Record, Idx); > +} > + > void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { > VisitExpr(E); > E->ATT = (ArrayTypeTrait)Record[Idx++]; > @@ -2046,6 +2057,11 @@ > S = new (Context) BinaryTypeTraitExpr(Empty); > break; > > + case EXPR_TYPE_TRAIT: > + S = TypeTraitExpr::CreateDeserialized(Context, > + Record[ASTStmtReader::NumExprFields]); > + break; > + > case EXPR_ARRAY_TYPE_TRAIT: > S = new (Context) ArrayTypeTraitExpr(Empty); > break; > > Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri Feb 24 01:38:34 2012 > @@ -1341,6 +1341,16 @@ > Code = serialization::EXPR_BINARY_TYPE_TRAIT; > } > > +void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { > + VisitExpr(E); > + Record.push_back(E->TypeTraitExprBits.NumArgs); > + Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding > + Record.push_back(E->TypeTraitExprBits.Value); > + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) > + Writer.AddTypeSourceInfo(E->getArg(I), Record); > + Code = serialization::EXPR_TYPE_TRAIT; > +} > + > void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { > VisitExpr(E); > Record.push_back(E->getTrait()); > > Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) > +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Feb 24 01:38:34 2012 > @@ -478,6 +478,7 @@ > case Stmt::DependentScopeDeclRefExprClass: > case Stmt::UnaryTypeTraitExprClass: > case Stmt::BinaryTypeTraitExprClass: > + case Stmt::TypeTraitExprClass: > case Stmt::ArrayTypeTraitExprClass: > case Stmt::ExpressionTraitExprClass: > case Stmt::UnresolvedLookupExprClass: > > Modified: cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp (original) > +++ cfe/trunk/test/Index/annotate-tokens-cxx0x.cpp Fri Feb 24 01:38:34 2012 > @@ -6,6 +6,11 @@ > void test() { > int a; > decltype(a) b; > + > + typedef int Integer; > + typedef float Float; > + typedef bool Bool; > + bool b2 = __is_trivially_constructible(Integer, Float, Bool); > } > > // RUN: c-index-test -test-annotate-tokens=%s:1:1:5:1 -fno-delayed-template-parsing -std=c++11 %s | FileCheck %s > @@ -14,3 +19,9 @@ > > // RUN: c-index-test -test-annotate-tokens=%s:8:1:9:1 -std=c++11 %s | FileCheck -check-prefix=CHECK-DECLTYPE %s > // CHECK-DECLTYPE: Identifier: "a" [8:12 - 8:13] DeclRefExpr=a:7:7 > + > +// RUN: c-index-test -test-annotate-tokens=%s:13:1:14:1 -std=c++11 %s | FileCheck -check-prefix=CHECK-TRAIT %s > +// CHECK-TRAIT: Identifier: "Integer" [13:42 - 13:49] TypeRef=Integer:10:15 > +// CHECK-TRAIT: Identifier: "Float" [13:51 - 13:56] TypeRef=Float:11:17 > +// CHECK-TRAIT: Identifier: "Bool" [13:58 - 13:62] TypeRef=Bool:12:16 > + > > Modified: cfe/trunk/test/PCH/cxx-traits.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/test/PCH/cxx-traits.cpp (original) > +++ cfe/trunk/test/PCH/cxx-traits.cpp Fri Feb 24 01:38:34 2012 > @@ -1,8 +1,11 @@ > // Test this without pch. > -// RUN: %clang_cc1 -include %S/cxx-traits.h -fsyntax-only -verify %s > +// RUN: %clang_cc1 -include %S/cxx-traits.h -std=c++11 -fsyntax-only -verify %s > > -// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-traits.h > -// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s > +// RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -o %t %S/cxx-traits.h > +// RUN: %clang_cc1 -std=c++11 -include-pch %t -fsyntax-only -verify %s > > bool _Is_pod_comparator = __is_pod::__value; > bool _Is_empty_check = __is_empty::__value; > + > +bool default_construct_int = is_trivially_constructible::value; > +bool copy_construct_int = is_trivially_constructible::value; > > Modified: cfe/trunk/test/PCH/cxx-traits.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.h?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/test/PCH/cxx-traits.h (original) > +++ cfe/trunk/test/PCH/cxx-traits.h Fri Feb 24 01:38:34 2012 > @@ -9,3 +9,8 @@ > struct __is_empty { > enum { __value }; > }; > + > +template > +struct is_trivially_constructible { > + static const bool value = __is_trivially_constructible(T, Args...); > +}; > > Modified: cfe/trunk/test/SemaCXX/type-traits.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/test/SemaCXX/type-traits.cpp (original) > +++ cfe/trunk/test/SemaCXX/type-traits.cpp Fri Feb 24 01:38:34 2012 > @@ -47,6 +47,10 @@ > TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default; > TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&); > }; > +struct NonTrivialDefault { > + NonTrivialDefault(); > +}; > + > struct HasDest { ~HasDest(); }; > class HasPriv { int priv; }; > class HasProt { protected: int prot; }; > @@ -104,6 +108,10 @@ > ~AllPrivate() throw(); > }; > > +struct ThreeArgCtor { > + ThreeArgCtor(int*, char*, int); > +}; > + > void is_pod() > { > { int arr[T(__is_pod(int))]; } > @@ -1602,7 +1610,7 @@ > { int arr[F(__is_trivial(cvoid))]; } > } > > -void is_trivially_copyable() > +void trivial_checks() > { > { int arr[T(__is_trivially_copyable(int))]; } > { int arr[T(__is_trivially_copyable(Enum))]; } > @@ -1646,6 +1654,25 @@ > { int arr[F(__is_trivially_copyable(void))]; } > { int arr[F(__is_trivially_copyable(cvoid))]; } > > + { int arr[T((__is_trivially_constructible(int)))]; } > + { int arr[T((__is_trivially_constructible(int, int)))]; } > + { int arr[T((__is_trivially_constructible(int, float)))]; } > + { int arr[T((__is_trivially_constructible(int, int&)))]; } > + { int arr[T((__is_trivially_constructible(int, const int&)))]; } > + { int arr[T((__is_trivially_constructible(int, int)))]; } > + { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)))]; } > + { int arr[T((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)))]; } > + { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)))]; } > + { int arr[T((__is_trivially_constructible(HasCopyAssign)))]; } > + { int arr[T((__is_trivially_constructible(NonTrivialDefault, > + const NonTrivialDefault&)))]; } > + { int arr[T((__is_trivially_constructible(NonTrivialDefault, > + NonTrivialDefault&&)))]; } > + > + { int arr[F((__is_trivially_constructible(int, int*)))]; } > + { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; } > + { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; } > + > { int arr[T((__is_trivially_assignable(int&, int)))]; } > { int arr[T((__is_trivially_assignable(int&, int&)))]; } > { int arr[T((__is_trivially_assignable(int&, int&&)))]; } > @@ -1680,6 +1707,33 @@ > TrivialMoveButNotCopy&&)))]; } > } > > +// Instantiation of __is_trivially_constructible > +template > +struct is_trivially_constructible { > + static const bool value = __is_trivially_constructible(T, Args...); > +}; > + > +void is_trivially_constructible_test() { > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible::value))]; } > + { int arr[T((is_trivially_constructible + const NonTrivialDefault&>::value))]; } > + { int arr[T((is_trivially_constructible + NonTrivialDefault&&>::value))]; } > + > + { int arr[F((is_trivially_constructible::value))]; } > + { int arr[F((is_trivially_constructible::value))]; } > + { int arr[F((is_trivially_constructible::value))]; } > +} > + > void array_rank() { > int t01[T(__array_rank(IntAr) == 1)]; > int t02[T(__array_rank(ConstIntArAr) == 2)]; > > Modified: cfe/trunk/tools/libclang/CIndex.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/tools/libclang/CIndex.cpp (original) > +++ cfe/trunk/tools/libclang/CIndex.cpp Fri Feb 24 01:38:34 2012 > @@ -1755,6 +1755,7 @@ > void VisitWhileStmt(WhileStmt *W); > void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); > void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); > + void VisitTypeTraitExpr(TypeTraitExpr *E); > void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); > void VisitExpressionTraitExpr(ExpressionTraitExpr *E); > void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U); > @@ -2056,6 +2057,11 @@ > AddTypeLoc(E->getLhsTypeSourceInfo()); > } > > +void EnqueueVisitor::VisitTypeTraitExpr(TypeTraitExpr *E) { > + for (unsigned I = E->getNumArgs(); I > 0; --I) > + AddTypeLoc(E->getArg(I-1)); > +} > + > void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { > AddTypeLoc(E->getQueriedTypeSourceInfo()); > } > > Modified: cfe/trunk/tools/libclang/CXCursor.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=151352&r1=151351&r2=151352&view=diff > ============================================================================== > --- cfe/trunk/tools/libclang/CXCursor.cpp (original) > +++ cfe/trunk/tools/libclang/CXCursor.cpp Fri Feb 24 01:38:34 2012 > @@ -206,6 +206,7 @@ > case Stmt::AtomicExprClass: > case Stmt::BinaryConditionalOperatorClass: > case Stmt::BinaryTypeTraitExprClass: > + case Stmt::TypeTraitExprClass: > case Stmt::CXXBindTemporaryExprClass: > case Stmt::CXXDefaultArgExprClass: > case Stmt::CXXScalarValueInitExprClass: > > > _______________________________________________ > 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 Fri Feb 24 06:34:29 2012 From: rafael.espindola at gmail.com (=?UTF-8?Q?Rafael_Esp=C3=ADndola?=) Date: Fri, 24 Feb 2012 09:34:29 -0500 Subject: [cfe-commits] r151307 - in /cfe/trunk: include/clang/Basic/TokenKinds.def include/clang/Parse/Parser.h lib/Parse/ParseDeclCXX.cpp lib/Parse/ParsePragma.cpp lib/Parse/ParseStmt.cpp lib/Parse/Parser.cpp test/Sema/pragma-pack-2.c test/SemaCXX/pragma Message-ID: This doesn't work for C. For example, in struct A { #pragma GCC visibility push(protected) #pragma GCC visibility pop }; we produce home/espindola/llvm/test.c:2:15: error: type name requires a specifier or qualifier #pragma GCC visibility push(protected) and in c++, we don't produce an error on struct A { #pragma GCC visibility push(protected) }; Should we? Cheers, Rafael From clattner at apple.com Fri Feb 24 08:14:01 2012 From: clattner at apple.com (Chris Lattner) Date: Fri, 24 Feb 2012 08:14:01 -0800 Subject: [cfe-commits] [PATCH] ArrayRef'ize various functions in clang In-Reply-To: References: Message-ID: <3FB96456-4581-444A-83F3-3AE8FF56FBAC@apple.com> On Feb 24, 2012, at 2:26 AM, Ahmed Charles wrote: > Fairly straight forward changes to allow ArrayRef rather than > Expr** and int. Looks great, please commit! -Chris From rafael.espindola at gmail.com Fri Feb 24 08:22:39 2012 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Fri, 24 Feb 2012 16:22:39 -0000 Subject: [cfe-commits] r151367 - /cfe/trunk/runtime/compiler-rt/Makefile Message-ID: <20120224162239.8F1602A6C12F@llvm.org> Author: rafael Date: Fri Feb 24 10:22:39 2012 New Revision: 151367 URL: http://llvm.org/viewvc/llvm-project?rev=151367&view=rev Log: Use -no-integrated-as only on ARM. The X86 and X86-64 integrated as have been the default for clang for some time now and can handle compiler-rt. Modified: cfe/trunk/runtime/compiler-rt/Makefile Modified: cfe/trunk/runtime/compiler-rt/Makefile URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/runtime/compiler-rt/Makefile?rev=151367&r1=151366&r2=151367&view=diff ============================================================================== --- cfe/trunk/runtime/compiler-rt/Makefile (original) +++ cfe/trunk/runtime/compiler-rt/Makefile Fri Feb 24 10:22:39 2012 @@ -29,7 +29,10 @@ COMPILERRT_SRC_ROOT := $(LLVM_SRC_ROOT)/projects/compiler-rt # Additional flags to pass to Clang. -CLANG_CCFLAGS := -no-integrated-as +CLANG_CCFLAGS := +ifeq ($(ARCH), arm) +CLANG_CCFLAGS += -no-integrated-as +endif # We don't currently support building runtime libraries when we are # cross-compiling. The issue is that we really want to be set up so that the From ganna at apple.com Fri Feb 24 08:49:41 2012 From: ganna at apple.com (Anna Zaks) Date: Fri, 24 Feb 2012 16:49:41 -0000 Subject: [cfe-commits] r151368 - in /cfe/trunk: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp test/Analysis/malloc-interprocedural.c Message-ID: <20120224164941.716BE2A6C12F@llvm.org> Author: zaks Date: Fri Feb 24 10:49:41 2012 New Revision: 151368 URL: http://llvm.org/viewvc/llvm-project?rev=151368&view=rev Log: [analyzer] We were silently stopping exploring the path after visiting 'return;' statement! This most likely caused us to skip a bunch of code when analyzing with inlining. Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp cfe/trunk/test/Analysis/malloc-interprocedural.c Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=151368&r1=151367&r2=151368&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Fri Feb 24 10:49:41 2012 @@ -432,7 +432,4 @@ B.generateNode(RS, *it, (*it)->getState()); } } - else { - B.takeNodes(dstPreVisit); - } } Modified: cfe/trunk/test/Analysis/malloc-interprocedural.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-interprocedural.c?rev=151368&r1=151367&r2=151368&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc-interprocedural.c (original) +++ cfe/trunk/test/Analysis/malloc-interprocedural.c Fri Feb 24 10:49:41 2012 @@ -69,3 +69,19 @@ int *data; my_free1((int*)data); } + +// Test that we keep processing after 'return;' +void fooWithEmptyReturn(int x) { + if (x) + return; + x++; + return; +} + +int uafAndCallsFooWithEmptyReturn() { + int *x = (int*)malloc(12); + free(x); + fooWithEmptyReturn(12); + return *x; // expected-warning {{Use of memory after it is freed}} +} + From ganna at apple.com Fri Feb 24 08:49:46 2012 From: ganna at apple.com (Anna Zaks) Date: Fri, 24 Feb 2012 16:49:46 -0000 Subject: [cfe-commits] r151369 - in /cfe/trunk: lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/keychainAPI.m test/Analysis/malloc-interprocedural.c Message-ID: <20120224164946.5BDED2A6C12F@llvm.org> Author: zaks Date: Fri Feb 24 10:49:46 2012 New Revision: 151369 URL: http://llvm.org/viewvc/llvm-project?rev=151369&view=rev Log: [analyzer] Run remove dead bindings before each call. This ensures that we report the bugs associated with symbols going out of scope in the correct function context. Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/test/Analysis/keychainAPI.m cfe/trunk/test/Analysis/malloc-interprocedural.c Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=151369&r1=151368&r2=151369&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Feb 24 10:49:46 2012 @@ -230,7 +230,11 @@ // Is this on a non-expression? if (!isa(S.getStmt())) return true; - + + // Run before processing a call. + if (isa(S.getStmt())) + return true; + // Is this an expression that is consumed by another expression? If so, // postpone cleaning out the state. ParentMap &PM = LC->getAnalysisDeclContext()->getParentMap(); Modified: cfe/trunk/test/Analysis/keychainAPI.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/keychainAPI.m?rev=151369&r1=151368&r2=151369&view=diff ============================================================================== --- cfe/trunk/test/Analysis/keychainAPI.m (original) +++ cfe/trunk/test/Analysis/keychainAPI.m Fri Feb 24 10:49:46 2012 @@ -274,8 +274,8 @@ char * x; st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &bytes); if (st == noErr) { - CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorNull); // expected-warning{{Allocated data is not released}} - CFRelease(userStr); + CFStringRef userStr = CFStringCreateWithBytesNoCopy(alloc, bytes, length, 5, 0, kCFAllocatorNull); + CFRelease(userStr); // expected-warning{{Allocated data is not released}} } } Modified: cfe/trunk/test/Analysis/malloc-interprocedural.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-interprocedural.c?rev=151369&r1=151368&r2=151369&view=diff ============================================================================== --- cfe/trunk/test/Analysis/malloc-interprocedural.c (original) +++ cfe/trunk/test/Analysis/malloc-interprocedural.c Fri Feb 24 10:49:46 2012 @@ -70,6 +70,16 @@ my_free1((int*)data); } +static char *reshape(char *in) { + return 0; +} + +void testThatRemoveDeadBindingsRunBeforeEachCall() { + char *v = malloc(12); + v = reshape(v); + v = reshape(v);// expected-warning {{Memory is never released; potential memory leak}} +} + // Test that we keep processing after 'return;' void fooWithEmptyReturn(int x) { if (x) From fjahanian at apple.com Fri Feb 24 09:35:35 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Fri, 24 Feb 2012 17:35:35 -0000 Subject: [cfe-commits] r151371 - in /cfe/trunk: lib/Rewrite/RewriteModernObjC.cpp test/Rewriter/rewrite-modern-block-ivar-call.mm Message-ID: <20120224173535.BA6EE2A6C12F@llvm.org> Author: fjahanian Date: Fri Feb 24 11:35:35 2012 New Revision: 151371 URL: http://llvm.org/viewvc/llvm-project?rev=151371&view=rev Log: objc modern translator. Fixes writing of block pointer ivar access. Added: cfe/trunk/test/Rewriter/rewrite-modern-block-ivar-call.mm Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Modified: cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp?rev=151371&r1=151370&r2=151371&view=diff ============================================================================== --- cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp (original) +++ cfe/trunk/lib/Rewrite/RewriteModernObjC.cpp Fri Feb 24 11:35:35 2012 @@ -6469,8 +6469,10 @@ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), addExpr); + QualType IvarT = D->getType(); + convertBlockPointerToFunctionPointer(IvarT); + QualType castT = Context->getPointerType(IvarT); - QualType castT = Context->getPointerType(D->getType()); castExpr = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Added: cfe/trunk/test/Rewriter/rewrite-modern-block-ivar-call.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-block-ivar-call.mm?rev=151371&view=auto ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-block-ivar-call.mm (added) +++ cfe/trunk/test/Rewriter/rewrite-modern-block-ivar-call.mm Fri Feb 24 11:35:35 2012 @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -E %s -o %t.m +// RUN: %clang_cc1 -fblocks -rewrite-objc -fms-extensions %t.m -o %t-rw.cpp +// RUN: FileCheck --input-file=%t-rw.cpp %s +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + + at interface Foo { + void (^_block)(void); +} + at end + + at implementation Foo +- (void)bar { + _block(); +} + at end + +// CHECK: ((void (*)(struct __block_impl *))((struct __block_impl *)(*(void (**)(void))((char *)self + OBJC_IVAR_$_Foo__block)))->FuncPtr)((struct __block_impl *)(*(void (**)(void))((char *)self + OBJC_IVAR_$_Foo__block))); From dgregor at apple.com Fri Feb 24 09:41:39 2012 From: dgregor at apple.com (Douglas Gregor) Date: Fri, 24 Feb 2012 17:41:39 -0000 Subject: [cfe-commits] r151372 - in /cfe/trunk: include/clang/AST/Expr.h lib/Sema/TreeTransform.h test/CodeGenCXX/blocks.cpp Message-ID: <20120224174139.2635D2A6C130@llvm.org> Author: dgregor Date: Fri Feb 24 11:41:38 2012 New Revision: 151372 URL: http://llvm.org/viewvc/llvm-project?rev=151372&view=rev Log: Two minor, related fixes for template instantiation with blocks: - Make sure that the block expression is instantiation-dependent if the block is in a dependent context - Make sure that the C++ 'this' expression gets captured even if we don't rebuild the AST node during template instantiation. This would also have manifested as a bug for lambdas. Fixes . Modified: cfe/trunk/include/clang/AST/Expr.h cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/test/CodeGenCXX/blocks.cpp Modified: cfe/trunk/include/clang/AST/Expr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=151372&r1=151371&r2=151372&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Expr.h (original) +++ cfe/trunk/include/clang/AST/Expr.h Fri Feb 24 11:41:38 2012 @@ -4220,9 +4220,8 @@ public: BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, - ty->isDependentType(), false, - // FIXME: Check for instantiate-dependence in the statement? - ty->isInstantiationDependentType(), + ty->isDependentType(), ty->isDependentType(), + ty->isInstantiationDependentType() || BD->isDependentContext(), false), TheBlock(BD) {} Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=151372&r1=151371&r2=151372&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Feb 24 11:41:38 2012 @@ -7038,9 +7038,12 @@ T = getSema().Context.getPointerType( getSema().Context.getRecordType(cast(DC))); - if (!getDerived().AlwaysRebuild() && T == E->getType()) + if (!getDerived().AlwaysRebuild() && T == E->getType()) { + // Make sure that we capture 'this'. + getSema().CheckCXXThisCapture(E->getLocStart()); return SemaRef.Owned(E); - + } + return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit()); } @@ -8539,6 +8542,7 @@ oldCapture)); assert(blockScope->CaptureMap.count(newCapture)); } + assert(oldBlock->capturesCXXThis() == blockScope->isCXXThisCaptured()); } #endif Modified: cfe/trunk/test/CodeGenCXX/blocks.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/blocks.cpp?rev=151372&r1=151371&r2=151372&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/blocks.cpp (original) +++ cfe/trunk/test/CodeGenCXX/blocks.cpp Fri Feb 24 11:41:38 2012 @@ -211,3 +211,18 @@ return ^{ return *p; }(); } } + +namespace test8 { + // : failure to capture this after skipping rebuild + // of the 'this' pointer. + struct X { + int x; + + template + int foo() { + return ^ { return x; }(); + } + }; + + template int X::foo(); +} From richard at metafoo.co.uk Fri Feb 24 09:47:02 2012 From: richard at metafoo.co.uk (Richard Smith) Date: Fri, 24 Feb 2012 09:47:02 -0800 Subject: [cfe-commits] r151359 - /cfe/trunk/lib/AST/Expr.cpp In-Reply-To: <20120224090753.6C7322A6C12F@llvm.org> References: <20120224090753.6C7322A6C12F@llvm.org> Message-ID: On Fri, Feb 24, 2012 at 1:07 AM, Nick Lewycky wrote: > Author: nicholas > Date: Fri Feb 24 03:07:53 2012 > New Revision: 151359 > > URL: http://llvm.org/viewvc/llvm-project?rev=151359&view=rev > Log: > Revert r151357. That unreachable is reachable... > > Modified: > cfe/trunk/lib/AST/Expr.cpp > > Modified: cfe/trunk/lib/AST/Expr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=151359&r1=151358&r2=151359&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/Expr.cpp (original) > +++ cfe/trunk/lib/AST/Expr.cpp Fri Feb 24 03:07:53 2012 > @@ -499,28 +499,25 @@ > return V.convertToDouble(); > } > > -int StringLiteral::mapCharByteWidth(TargetInfo const &Target, > - StringKind Kind) { > +int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind > k) { > int CharByteWidth; > - switch(Kind) { > + switch(k) { > case Ascii: > case UTF8: > - CharByteWidth = Target.getCharWidth(); > + CharByteWidth = target.getCharWidth(); > break; > case Wide: > - CharByteWidth = Target.getWCharWidth(); > + CharByteWidth = target.getWCharWidth(); > break; > case UTF16: > - CharByteWidth = Target.getChar16Width(); > + CharByteWidth = target.getChar16Width(); > break; > case UTF32: > - CharByteWidth = Target.getChar32Width(); > - default: > - llvm_unreachable("Don't know byte width of this string kind!"); > + CharByteWidth = target.getChar32Width(); > This is why we need a warning on switch case fallthrough :-) -------------- next part -------------- An HTML attachment was scrubbed... URL: From fjahanian at apple.com Fri Feb 24 10:03:43 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Fri, 24 Feb 2012 18:03:43 -0000 Subject: [cfe-commits] r151376 - /cfe/trunk/test/Rewriter/rewrite-modern-nested-ivar.mm Message-ID: <20120224180343.0FE602A6C12F@llvm.org> Author: fjahanian Date: Fri Feb 24 12:03:42 2012 New Revision: 151376 URL: http://llvm.org/viewvc/llvm-project?rev=151376&view=rev Log: more objective-c modern translator ivar tests. Added: cfe/trunk/test/Rewriter/rewrite-modern-nested-ivar.mm Added: cfe/trunk/test/Rewriter/rewrite-modern-nested-ivar.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-nested-ivar.mm?rev=151376&view=auto ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-nested-ivar.mm (added) +++ cfe/trunk/test/Rewriter/rewrite-modern-nested-ivar.mm Fri Feb 24 12:03:42 2012 @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -E %s -o %t.m +// RUN: %clang_cc1 -fblocks -rewrite-objc -fms-extensions %t.m -o %t-rw.cpp +// RUN: FileCheck --input-file=%t-rw.cpp %s +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + + at interface NSURLResponse { + at public + NSURLResponse *InnerResponse; +} + at end + + at interface NSCachedURLResponseInternal +{ + @public + NSURLResponse *response; +} + at end + + at interface NSCachedURLResponse +{ + @private + NSCachedURLResponseInternal *_internal; +} +- (void) Meth; + at end + + at implementation NSCachedURLResponse +- (void) Meth { + _internal->response->InnerResponse = 0; + } + at end + +// CHECK: (*(NSURLResponse **)((char *)(*(NSURLResponse **)((char *)(*(NSCachedURLResponseInternal **)((char *)self + OBJC_IVAR_$_NSCachedURLResponse__internal)) + OBJC_IVAR_$_NSCachedURLResponseInternal_response)) + OBJC_IVAR_$_NSURLResponse_InnerResponse)) = 0; From richard-llvm at metafoo.co.uk Fri Feb 24 10:10:23 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Fri, 24 Feb 2012 18:10:23 -0000 Subject: [cfe-commits] r151377 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td lib/Parse/ParseDeclCXX.cpp lib/Sema/DeclSpec.cpp test/SemaCXX/cxx98-compat.cpp test/SemaCXX/decltype-98.cpp Message-ID: <20120224181023.AE4DE2A6C12F@llvm.org> Author: rsmith Date: Fri Feb 24 12:10:23 2012 New Revision: 151377 URL: http://llvm.org/viewvc/llvm-project?rev=151377&view=rev Log: __decltype is a GNU extension, not a C++11 extension. Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Sema/DeclSpec.cpp cfe/trunk/test/SemaCXX/cxx98-compat.cpp cfe/trunk/test/SemaCXX/decltype-98.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151377&r1=151376&r2=151377&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Feb 24 12:10:23 2012 @@ -254,6 +254,12 @@ "C requires a comma prior to the ellipsis in a variadic function type">; def err_unexpected_typedef_ident : Error< "unexpected type name %0: expected identifier">; +def ext_gnu_decltype : Extension< + "'__decltype' type specifier is a GNU extension">, + InGroup, DefaultIgnore; +def warn_cxx98_compat_decltype : Warning< + "'decltype' type specifier is incompatible with C++98">, + InGroup, DefaultIgnore; def err_unexpected_scope_on_base_decltype : Error< "unexpected namespace scope prior to decltype">; def err_expected_class_name : Error<"expected class name">; Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=151377&r1=151376&r2=151377&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 24 12:10:23 2012 @@ -1176,9 +1176,6 @@ InGroup, DefaultIgnore; // C++11 decltype -def warn_cxx98_compat_decltype : Warning< - "'decltype' type specifier is incompatible with C++98">, - InGroup, DefaultIgnore; def err_decltype_in_declarator : Error< "'decltype' cannot be used to name a declaration">; Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=151377&r1=151376&r2=151377&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Feb 24 12:10:23 2012 @@ -653,6 +653,9 @@ return EndLoc; } } else { + Diag(Tok, Tok.getIdentifierInfo()->isStr("decltype") + ? diag::warn_cxx98_compat_decltype : diag::ext_gnu_decltype); + ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); Modified: cfe/trunk/lib/Sema/DeclSpec.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=151377&r1=151376&r2=151377&view=diff ============================================================================== --- cfe/trunk/lib/Sema/DeclSpec.cpp (original) +++ cfe/trunk/lib/Sema/DeclSpec.cpp Fri Feb 24 12:10:23 2012 @@ -898,8 +898,6 @@ if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type) << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); - if (TypeSpecType == TST_decltype) - Diag(D, TSTLoc, diag::warn_cxx98_compat_decltype); if (Constexpr_specified) Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr); Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=151377&r1=151376&r2=151377&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Fri Feb 24 12:10:23 2012 @@ -99,6 +99,7 @@ char32_t c32 = 0; // expected-warning {{'char32_t' type specifier is incompatible with C++98}} constexpr int const_expr = 0; // expected-warning {{'constexpr' specifier is incompatible with C++98}} decltype(const_expr) decl_type = 0; // expected-warning {{'decltype' type specifier is incompatible with C++98}} +__decltype(const_expr) decl_type2 = 0; // ok void no_except() noexcept; // expected-warning {{noexcept specifications are incompatible with C++98}} bool no_except_expr = noexcept(1 + 1); // expected-warning {{noexcept expressions are incompatible with C++98}} void *null = nullptr; // expected-warning {{'nullptr' is incompatible with C++98}} Modified: cfe/trunk/test/SemaCXX/decltype-98.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decltype-98.cpp?rev=151377&r1=151376&r2=151377&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/decltype-98.cpp (original) +++ cfe/trunk/test/SemaCXX/decltype-98.cpp Fri Feb 24 12:10:23 2012 @@ -1,3 +1,3 @@ -// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s -Wgnu extern int x; -__decltype(1) x = 3; +__decltype(1) x = 3; // expected-warning {{is a GNU extension}} From fjahanian at apple.com Fri Feb 24 10:17:50 2012 From: fjahanian at apple.com (Fariborz Jahanian) Date: Fri, 24 Feb 2012 18:17:50 -0000 Subject: [cfe-commits] r151378 - /cfe/trunk/test/Rewriter/rewrite-modern-struct-ivar.mm Message-ID: <20120224181750.C16FC2A6C12F@llvm.org> Author: fjahanian Date: Fri Feb 24 12:17:50 2012 New Revision: 151378 URL: http://llvm.org/viewvc/llvm-project?rev=151378&view=rev Log: test for writing modern ivar of struct type. Added: cfe/trunk/test/Rewriter/rewrite-modern-struct-ivar.mm Added: cfe/trunk/test/Rewriter/rewrite-modern-struct-ivar.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-modern-struct-ivar.mm?rev=151378&view=auto ============================================================================== --- cfe/trunk/test/Rewriter/rewrite-modern-struct-ivar.mm (added) +++ cfe/trunk/test/Rewriter/rewrite-modern-struct-ivar.mm Fri Feb 24 12:17:50 2012 @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -E %s -o %t.mm +// RUN: %clang_cc1 -fblocks -rewrite-objc -fms-extensions %t.mm -o %t-rw.cpp +// RUN: FileCheck --input-file=%t-rw.cpp %s +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + +struct S { + int i1; + double d1; + void (^block1)(); +}; + + at interface I +{ + struct S struct_ivar; + + struct S *pstruct_ivar; +} + at end + + at implementation I +- (struct S) dMeth{ return struct_ivar; } + at end + +// CHECK: return (*(struct S *)((char *)self + OBJC_IVAR_$_I_struct_ivar)); From dgregor at apple.com Fri Feb 24 10:27:57 2012 From: dgregor at apple.com (Douglas Gregor) Date: Fri, 24 Feb 2012 10:27:57 -0800 Subject: [cfe-commits] r151330 - in /cfe/trunk: lib/Serialization/ASTWriter.cpp test/Index/targeted-cursor.m test/Index/targeted-cursor.m.h In-Reply-To: <20120224011238.CCC132A6C12F@llvm.org> References: <20120224011238.CCC132A6C12F@llvm.org> Message-ID: On Feb 23, 2012, at 5:12 PM, Argyrios Kyrtzidis wrote: > Author: akirtzidis > Date: Thu Feb 23 19:12:38 2012 > New Revision: 151330 > > URL: http://llvm.org/viewvc/llvm-project?rev=151330&view=rev > Log: > [PCH] When keeping track of top-level decls for "targeted deserialization" > make sure we don't mistake ParmVarDecls for top-level decls. > > Fixes rdar://10920009. > > Added: > cfe/trunk/test/Index/targeted-cursor.m > cfe/trunk/test/Index/targeted-cursor.m.h > Modified: > cfe/trunk/lib/Serialization/ASTWriter.cpp > > Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=151330&r1=151329&r2=151330&view=diff > ============================================================================== > --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Feb 23 19:12:38 2012 > @@ -3860,6 +3860,9 @@ > // We only keep track of the file-level declarations of each file. > if (!D->getLexicalDeclContext()->isFileContext()) > return; > + // FIXME: We should never have ParmVarDecls with TU as context. > + if (isa(D)) > + return; This FIXME isn't really true. ParmVarDecls that are part of a function type (but not a FunctionDecl) have translation unit context, e.g., typedef int func(int x, int y); - Doug From richard-llvm at metafoo.co.uk Fri Feb 24 10:37:14 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Fri, 24 Feb 2012 18:37:14 -0000 Subject: [cfe-commits] r151380 - /cfe/trunk/www/cxx_status.html Message-ID: <20120224183714.A65592A6C12F@llvm.org> Author: rsmith Date: Fri Feb 24 12:37:14 2012 New Revision: 151380 URL: http://llvm.org/viewvc/llvm-project?rev=151380&view=rev Log: cxx_status: extended sizeof has been essentially complete for some time. As agreed on IRC, any remaining issues are best dealt with as bugs. We have no __has_feature check for this; please shout if you'd like one. This feature seems too small to be worth its own release notes bullet (again, please shout if you disagree). Modified: cfe/trunk/www/cxx_status.html Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=151380&r1=151379&r2=151380&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Fri Feb 24 12:37:14 2012 @@ -153,9 +153,7 @@ Forward declarations for enums - - N2764 - + N2764 No @@ -237,8 +235,9 @@ Extending sizeof - N2253 - No + N2253 +
    DR850 + SVN Inline namespaces @@ -263,8 +262,8 @@ Explicit virtual overrides N2928 -
    N3206 -
    N3272 +
    N3206 +
    N3272 Clang 3.0 From ganna at apple.com Fri Feb 24 10:46:27 2012 From: ganna at apple.com (Anna Zaks) Date: Fri, 24 Feb 2012 10:46:27 -0800 Subject: [cfe-commits] [PATCH] Additional output for AnalyzerStatsChecker In-Reply-To: References: <2B6668A7-281A-4262-B797-376AE9E18116@apple.com> <9D425DD2-7FD6-4B13-858D-AB12562B8D93@apple.com> <5A166B8B-F425-49FC-883F-07689742A39D@uqconnect.edu.au> <0C14F9B3-2711-49C7-97C2-F55CF9A0D60D@uqconnect.edu.au> Message-ID: Tom, Addressing the question about testing, I think that we should definitely include the tests for the stats checker. The checker itself is the means for testing so it's only natural to use it for testing. I think it is absolutely acceptable for someone to need to change the test after adding support for a new expression or increasing the code coverage. (It would add a lot of benefit too. I spent hours yesterday tracking a code coverage issue (r151368), which could have been caught by the stats checker!) If you think that some of the diagnostics will change a lot, you can use FileCheck instead of '-verify' to grep for only some of the output. (However, keeping in mind that the analyzer should be deterministic, I am not sure when this happens.) A slightly outdated manual for FileCheck: http://llvm.org/cmds/FileCheck.html. Or take a look at some other tests using '// CHECK-NEXT:' and '// CHECK:': - ./test/Analysis/malloc-plist.c -./test/CodeGen/compound-literal.c Anna. On Feb 23, 2012, at 5:10 PM, Ted Kremenek wrote: > We probably should just add a general mechanism for holding onto ExplodedNodes, i.e., reference counts that say "this cannot be reclaimed". There are various clients that want to do this, e.g. the IdempotentOperationsChecker. In other words, this is a general problem we should just solve. Having a general solution will allows us to aggressively trim the graph further without breaking various clients that depend on nodes staying around. > > I wouldn't approach it by embedding a reference count in ExplodedNode, or if we did, just use a couple bits stolen from different fields. If the count exceeds some threshold, we can just store the count in a side table in ExplodedGraph. > > Note that in the common case the reference count we either be 0 or 1, depending on how we wanted to define the semantics (with "1" being for the ExplodedGraph is holding onto the node). > > On Feb 23, 2012, at 4:59 PM, Anna Zaks wrote: > >> Thanks. >> >> Looks like the node has been reclaimed and we are allocating a new one using the free memory. >> bool ExplodedGraph::shouldCollect(const ExplodedNode *node) { >> // Reclaimn all nodes that match *all* the following criteria: >> // >> // (1) 1 predecessor (that has one successor) >> // (2) 1 successor (that has one predecessor) >> // (3) The ProgramPoint is for a PostStmt. >> // (4) There is no 'tag' for the ProgramPoint. >> // (5) The 'store' is the same as the predecessor. >> // (6) The 'GDM' is the same as the predecessor. >> // (7) The LocationContext is the same as the predecessor. >> // (8) The PostStmt is for a non-consumed Stmt or Expr. >> >> How about tagging the node? Would that solve the problem? >> - const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState()); >> Engine.addAbortedBlock(node, currentBuilderContext->getBlock()); >> >> + static SimpleProgramPointTag Tag("Aborted: Unhandled symbol"); >> + const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState(), false, &Tag); >> Engine.addAbortedBlock(node, currentBuilderContext->getBlock()); >> >> I did not give this much thought, but maybe we could use tags instead of the abortedBlocks list. >> Anna. >> On Feb 23, 2012, at 4:29 PM, Tom Care wrote: >> >>> Sorry Anna yes I meant ProgramPoint. >>> >>> I managed to reproduce the situation I was talking about in gdb, and I used a file in the LLVM tree so hopefully you can reproduce it. >>> >>> I apologise for the wall of text! A brief run-through of what I did: >>> - added an assert to find when I cannot get a PostStmt from the ExplodedNode >>> - Tracked down an example to llvm/lib/Support/DeltaAlgorithm.cpp in function Search >>> - The third aborted block is the one that triggers my assertion. >>> >>> In the gdb run-through below, you can see that when the aborted block is added (node=0x1075499b8, stmt=0x10680d8e8) that everything is as expected. I added a watchpoint for the ProgramPoint::Kind of the node. After a number of reads triggering it, we can see a write that changes the Location to a BlockEdge. At this point I did a backtrace. When the VisitEndAnalysis happens, we see that the same node=0x1075499b8 now has a BlockEdge as its Location and the stmt=0x10680d8e8 has been lost. >>> >>> Let me know if you need any other information. >>> >>> Tom >>> >>> ------------ >>> >>> Starting program: /Users/tcare/Projects/llvm-debug/bin/clang++ -cc1 -triple x86_64-apple-macosx10.7.0 -analyze -disable-free -main-file-name DeltaAlgorithm.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=unix -analyzer-checker=osx -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-output plist -w -pic-level 1 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -resource-dir /Users/tcare/Projects/llvm-debug/bin/../lib/clang/3.1 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /Users/tcare/Projects/llvm-analysis/include -I /Users/tcare/Projects/llvm-analysis/lib/Support -I /Users/tcare/Projects/llvm/include -I /Users/tcare/Projects/llvm/lib/Support -fmodule-cache-path /var/folders/cz/fgrz7bdd7mn19gj5hl3w25rw0000gn/T/clang-module-cache -Wno-unused-parameter -fdeprecated-macro -fdebug-compilation-dir /Users/tcare/Projects/llvm-analysis/lib/Support -ferror-limit 19 -fmessage-length 0 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime-has-arc -fobjc-runtime-has-weak -fobjc-dispatch-method=mixed -fcxx-exceptions -fexceptions -fdiagnostics-show-option -analyzer-display-progress -analyzer-inline-call -analyzer-checker debug.Stats -analyzer-output=html -x c++ /Users/tcare/Projects/llvm/lib/Support/DeltaAlgorithm.cpp -analyze-function Search >>> ANALYZE: /Users/tcare/Projects/llvm/lib/Support/DeltaAlgorithm.cpp Search >>> >>> Breakpoint 2, clang::ento::CoreEngine::addAbortedBlock (this=0x7fff5fbfce08, block=0x10733e400, node=0x1073cf268, stmt=0x10680d8e8) at CoreEngine.h:149 >>> 149 blocksAborted.push_back(std::make_pair(block, std::make_pair(node, stmt))); >>> (gdb) c >>> Continuing. >>> >>> Breakpoint 2, clang::ento::CoreEngine::addAbortedBlock (this=0x7fff5fbfce08, block=0x10733f778, node=0x1075115a0, stmt=0x1072d0418) at CoreEngine.h:149 >>> 149 blocksAborted.push_back(std::make_pair(block, std::make_pair(node, stmt))); >>> (gdb) c >>> Continuing. >>> >>> Breakpoint 2, clang::ento::CoreEngine::addAbortedBlock (this=0x7fff5fbfce08, block=0x10733e400, node=0x1075499b8, stmt=0x10680d8e8) at CoreEngine.h:149 >>> 149 blocksAborted.push_back(std::make_pair(block, std::make_pair(node, stmt))); >>> (gdb) p stmt->dump() >>> (CXXBindTemporaryExpr 0x10680d8e8 'class DeltaAlgorithm::changeset_ty':'class std::set, class std::allocator >' (CXXTemporary 0x10680d8e0) >>> (CXXMemberCallExpr 0x10680d870 'class DeltaAlgorithm::changeset_ty':'class std::set, class std::allocator >' >>> (MemberExpr 0x10680d7e8 '' ->Delta 0x1072c80d0 >>> (CXXThisExpr 0x10680d7d0 'class llvm::DeltaAlgorithm *' this)) >>> (ImplicitCastExpr 0x10680d8a8 'const changeset_ty':'const class std::set, class std::allocator >' lvalue >>> (DeclRefExpr 0x10680d820 'changeset_ty':'class std::set, class std::allocator >' lvalue Var 0x1072d0700 'Complement' 'changeset_ty':'class std::set, class std::allocator >')) >>> (ImplicitCastExpr 0x10680d8c0 'const changesetlist_ty':'const class std::vector, class std::allocator >, class std::allocator, class std::allocator > > >' lvalue >>> (DeclRefExpr 0x10680d848 'changesetlist_ty':'class std::vector, class std::allocator >, class std::allocator, class std::allocator > > >' lvalue Var 0x1072d3020 'ComplementSets' 'changesetlist_ty':'class std::vector, class std::allocator >, class std::allocator, class std::allocator > > >')))) >>> $2 = void >>> (gdb) p *node >>> $3 = { >>> = { >>> NextInFoldingSetBucket = 0x107423da0 >>> }, >>> members of clang::ento::ExplodedNode: >>> Location = { >>> Data = { >>> first = 0x10680d8e8, >>> second = 0x0 >>> }, >>> K = clang::ProgramPoint::PostStmtKind, >>> L = 0x106580d30, >>> Tag = 0x0 >>> }, >>> State = { >>> Obj = 0x1075498f8 >>> }, >>> Preds = { >>> P = 4417952112 >>> }, >>> Succs = { >>> P = 0 >>> } >>> } >>> (gdb) p &node->Location->K >>> $4 = ('clang::ProgramPoint::Kind' *) 0x1075499d0 >>> (gdb) awatch *$4 >>> Hardware access (read/write) watchpoint 3: *$4 >>> (gdb) d 2 >>> (gdb) c >>> Continuing. >>> Hardware access (read/write) watchpoint 3: *$4 >>> >>> Value = clang::ProgramPoint::PostStmtKind >>> 0x00007fff92af4cde in memmove$VARIANT$sse42 () >>> (gdb) >>> Continuing. >>> ...several hits later... >>> Hardware access (read/write) watchpoint 3: *$4 >>> >>> Old value = clang::ProgramPoint::PostStmtKind >>> New value = clang::ProgramPoint::BlockEdgeKind >>> 0x00007fff92af4ce4 in memmove$VARIANT$sse42 () >>> (gdb) d 3 >>> (gdb) bt >>> #0 0x00007fff92af4ce4 in memmove$VARIANT$sse42 () >>> #1 0x0000000101090594 in clang::ento::ExplodedNode::ExplodedNode (this=0x1075499b8, loc=@0x7fff5fbfc4f8, state=@0x7fff5fbfc2f0, IsSink=false) at ExplodedGraph.h:122 >>> #2 0x000000010108d1cc in clang::ento::ExplodedNode::ExplodedNode (this=0x1075499b8, loc=@0x7fff5fbfc4f8, state=, IsSink=false) at ExplodedGraph.h:125 >>> #3 0x000000010108c160 in clang::ento::ExplodedGraph::getNode (this=0x10657eec0, L=@0x7fff5fbfc4f8, State=@0x7fff5fbfc438, IsSink=false, IsNew=0x7fff5fbfc44e) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp:257 >>> #4 0x0000000101081992 in clang::ento::NodeBuilder::generateNodeImpl (this=0x7fff5fbfc6c8, Loc=@0x7fff5fbfc4f8, State=@0x7fff5fbfc4c0, FromN=0x107549a48, MarkAsSink=false) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:535 >>> #5 0x0000000101081c96 in clang::ento::BranchNodeBuilder::generateNode (this=0x7fff5fbfc6c8, State=@0x7fff5fbfc5f0, branch=false, NodePred=0x107549a48) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:568 >>> #6 0x0000000101097044 in clang::ento::ExprEngine::processBranch (this=0x7fff5fbfcdf0, Condition=0x10730a140, Term=0x10730b180, BldCtx=@0x7fff5fbfc8f0, Pred=0x107549a48, Dst=@0x7fff5fbfc888, DstT=0x10738d610, DstF=0x10738c528) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:1125 >>> #7 0x00000001010812dd in clang::ento::CoreEngine::HandleBranch (this=0x7fff5fbfce08, Cond=0x10730a140, Term=0x10730b180, B=0x10738c770, Pred=0x107549a48) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:406 >>> #8 0x0000000101081021 in clang::ento::CoreEngine::HandleBlockExit (this=0x7fff5fbfce08, B=0x10738c770, Pred=0x107549a48) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:388 >>> #9 0x00000001010809e6 in clang::ento::CoreEngine::HandlePostStmt (this=0x7fff5fbfce08, B=0x10738c770, StmtIdx=1, Pred=0x107549a48) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:417 >>> #10 0x000000010108027a in clang::ento::CoreEngine::ExecuteWorkList (this=0x7fff5fbfce08, L=0x106580d30, Steps=146026, InitState=@0x7fff5fbfcda0) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:228 >>> #11 0x0000000100f3e0fd in clang::ento::ExprEngine::ExecuteWorkList (this=0x7fff5fbfcdf0, L=0x106580d30, Steps=150000) at ExprEngine.h:97 >>> #12 0x0000000100f3d2bc in ActionExprEngine (C=@0x1065063a0, mgr=@0x10650d280, D=0x1072ceac0, ObjCGCEnabled=false) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:325 >>> #13 0x0000000100f3d16f in RunPathSensitiveChecks (C=@0x1065063a0, mgr=@0x10650d280, D=0x1072ceac0) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:344 >>> #14 0x0000000100f3cfd7 in (anonymous namespace)::AnalysisConsumer::HandleCode (this=0x1065063a0, D=0x1072ceac0) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:300 >>> #15 0x0000000100f3c839 in (anonymous namespace)::AnalysisConsumer::HandleDeclContextDecl (this=0x1065063a0, C=@0x106829a00, D=0x1072ceac0) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:206 >>> #16 0x0000000100f3c574 in (anonymous namespace)::AnalysisConsumer::HandleDeclContext (this=0x1065063a0, C=@0x106829a00, dc=0x10682c4f0) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:177 >>> #17 0x0000000100f3c452 in (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit (this=0x1065063a0, C=@0x106829a00) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:244 >>> #18 0x0000000100634bb4 in clang::ParseAST (S=@0x106840200, PrintStats=false) at /Users/tcare/Projects/llvm/tools/clang/lib/Parse/ParseAST.cpp:106 >>> #19 0x0000000100589488 in clang::ASTFrontendAction::ExecuteAction (this=0x106503ea0) at /Users/tcare/Projects/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:414 >>> #20 0x00000001005890d7 in clang::FrontendAction::Execute (this=0x106503ea0) at /Users/tcare/Projects/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:334 >>> #21 0x00000001005557b5 in clang::CompilerInstance::ExecuteAction (this=0x1065029b0, Act=@0x106503ea0) at /Users/tcare/Projects/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:653 >>> #22 0x00000001000181cf in clang::ExecuteCompilerInvocation (Clang=0x1065029b0) at /Users/tcare/Projects/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:176 >>> #23 0x0000000100009749 in cc1_main (ArgBegin=0x7fff5fbfea40, ArgEnd=0x7fff5fbfecb8, Argv0=0x106500d08 "/Users/tcare/Projects/llvm-debug/bin/clang++", MainAddr=0x100001a40) at /Users/tcare/Projects/llvm/tools/clang/tools/driver/cc1_main.cpp:165 >>> #24 0x0000000100001c8d in main (argc_=81, argv_=0x7fff5fbff2b0) at /Users/tcare/Projects/llvm/tools/clang/tools/driver/driver.cpp:352 >>> (gdb) c >>> Continuing. >>> >>> Breakpoint 1, (anonymous namespace)::AnalyzerStatsChecker::emitAbortedStats (this=0x10650e050, Eng=@0x7fff5fbfcdf0, B=@0x7fff5fbfcfd8, SM=@0x106504c30) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp:170 >>> 170 const CoreEngine::AbortedStmtPair aborted = I->second; >>> (gdb) c >>> Continuing. >>> >>> Breakpoint 1, (anonymous namespace)::AnalyzerStatsChecker::emitAbortedStats (this=0x10650e050, Eng=@0x7fff5fbfcdf0, B=@0x7fff5fbfcfd8, SM=@0x106504c30) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp:170 >>> 170 const CoreEngine::AbortedStmtPair aborted = I->second; >>> (gdb) c >>> Continuing. >>> >>> Breakpoint 1, (anonymous namespace)::AnalyzerStatsChecker::emitAbortedStats (this=0x10650e050, Eng=@0x7fff5fbfcdf0, B=@0x7fff5fbfcfd8, SM=@0x106504c30) at /Users/tcare/Projects/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp:170 >>> 170 const CoreEngine::AbortedStmtPair aborted = I->second; >>> (gdb) n >>> 171 const LocationContext *LC = aborted.first->getLocationContext(); >>> (gdb) n >>> 173 const PostStmt *PS = aborted.first->getLocationAs(); >>> (gdb) n >>> 174 assert(PS); >>> (gdb) p PS >>> $5 = (const 'clang::PostStmt' *) 0x0 >>> (gdb) p aborted.first >>> $6 = (const 'clang::ento::ExplodedNode' *) 0x1075499b8 >>> (gdb) p *aborted.first >>> $7 = { >>> = { >>> NextInFoldingSetBucket = 0x1067326a9 >>> }, >>> members of clang::ento::ExplodedNode: >>> Location = { >>> Data = { >>> first = 0x10738c770, >>> second = 0x10738c528 >>> }, >>> K = clang::ProgramPoint::BlockEdgeKind, >>> L = 0x106584050, >>> Tag = 0x0 >>> }, >>> State = { >>> Obj = 0x10755da98 >>> }, >>> Preds = { >>> P = 4417952328 >>> }, >>> Succs = { >>> P = 4417950920 >>> } >>> } >>> (gdb) p aborted->second >>> $8 = (const 'clang::Stmt' *) 0x10680d8e8 >>> (gdb) p aborted->second->dump() >>> (CXXBindTemporaryExpr 0x10680d8e8 'class DeltaAlgorithm::changeset_ty':'class std::set, class std::allocator >' (CXXTemporary 0x10680d8e0) >>> (CXXMemberCallExpr 0x10680d870 'class DeltaAlgorithm::changeset_ty':'class std::set, class std::allocator >' >>> (MemberExpr 0x10680d7e8 '' ->Delta 0x1072c80d0 >>> (CXXThisExpr 0x10680d7d0 'class llvm::DeltaAlgorithm *' this)) >>> (ImplicitCastExpr 0x10680d8a8 'const changeset_ty':'const class std::set, class std::allocator >' lvalue >>> (DeclRefExpr 0x10680d820 'changeset_ty':'class std::set, class std::allocator >' lvalue Var 0x1072d0700 'Complement' 'changeset_ty':'class std::set, class std::allocator >')) >>> (ImplicitCastExpr 0x10680d8c0 'const changesetlist_ty':'const class std::vector, class std::allocator >, class std::allocator, class std::allocator > > >' lvalue >>> (DeclRefExpr 0x10680d848 'changesetlist_ty':'class std::vector, class std::allocator >, class std::allocator, class std::allocator > > >' lvalue Var 0x1072d3020 'ComplementSets' 'changesetlist_ty':'class std::vector, class std::allocator >, class std::allocator, class std::allocator > > >')))) >>> $9 = void >>> >>> >>> On 23/02/2012, at 11:26 PM, Anna Zaks wrote: >>> >>>> >>>> On Feb 23, 2012, at 1:50 PM, Tom Care wrote: >>>> >>>>> The reason I added a Stmt* was because the LocationContext of the node (which starts out as a PostStmt) can be overwritten to become a BlockEdge. The Stmt* pointer is lost in that case, and it becomes difficult to guess where the original Stmt was. Since we only add aborted blocks/nodes when a Stmt was unsupported, I thought that it was important to keep the original pointer to find out why we stopped. >>>>> >>>> >>>> Tom, you must be talking about ProgramPoint/Location, not LocationContext, correct? Can you investigate where it gets overwritten? As far as I understand, it should never change, in fact, it's declared as const. We are only adding predecessors and successors to the ExplodedNodes; they should stay unchanged otherwise. >>>> >>>> class ExplodedNode : public llvm::FoldingSetNode { >>>> .... >>>> /// Location - The program location (within a function body) associated >>>> /// with this node. >>>> const ProgramPoint Location; >>>> >>>>> Example of the new output: >>>>> >>>>> /Users/tcare/Projects/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp:218:5: warning: The analyzer stopped at this point due to an unsupported statement of type CXXBindTemporaryExpr >>>>> S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; >>>>> ^ >>>>> >>>>> /Users/tcare/Projects/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp:308:28: warning: The analyzer stopped because this block was visited too many times >>>>> for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { >>>>> ^ >>>>> >>>>> /Users/tcare/Projects/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp:934:11: warning: The analyzer stoppedat this point due to visitation limits >>>>> if (T->isAnyPointerType() || T->isBlockPointerType()) >>>>> ^ >>>>> >>>>> (need to add a space in the last one) >>>>> >>>>> I'm testing over all of LLVM/Clang right now as I am collecting data. >>>>> >>>>> Tom >>>>> >>>>> On 23/02/2012, at 6:04 PM, Anna Zaks wrote: >>>>> >>>>>> On Feb 23, 2012, at 7:27 AM, Ted Kremenek wrote: >>>>>> >>>>>>> Looks good to me. Do you have an example of the new output? >>>>>>> >>>>>>> On Feb 23, 2012, at 7:08 AM, Tom Care wrote: >>>>>>> >>>>>>>> I made some changes to AnalyzerStatsChecker to make it a bit more useful. Changelog: >>>>>>>> >>>>>>>> Improved the information output by AnalyzerStatsChecker. In addition to the analysis stats for Decls, AnalyzerStatsChecker now also outputs: >>>>>>>> - Exhausted blocks and sinks, including their approximate location >>>>>>>> - Aborted blocks and their statement locations >>>>>>>> - When and where the analyzer reaches the max block limit >>>>>>>> Some supporting infrastructure changes: >>>>>>>> - CoreEngine now stores Stmt* with the ExplodedNode* in the aborted block data, since the node can change between generation and VisitEndAnalysis >>>>>> >>>>>> My understanding is that, here, we add a bit of overhead on every analyzes run to make stats more precise. >>>>>> Could you elaborate/investigate a bit more on why it is absolutely necessary in this case? Is the ExplodedNode you are storing here deleted by the time you reach VisitEndAnalysis? (How is the node changed?) >>>>>> >>>>>>>> - Exposed 'block limit exceeded' tag to allow AnalyzerStatsChecker to detect a sink caused by exceeding the max visits for a block >>>>>>>> >>>>>>>> Regarding test cases, any test case made for this checker would break quite frequently as the analyzer is changed. I can't think of a good way to solve this. >>>>>>>> >>>>>> >>>>>> Would be great if you could (manually) test this with -analyzer-inline-call. >>>>>> >>>>>>>> Been a while since my last commit, so a review is much appreciated :) >>>>>>>> >>>>>>>> Tom >>>>>>>> _______________________________________________ >>>>>>>> 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: From richard-llvm at metafoo.co.uk Fri Feb 24 10:42:08 2012 From: richard-llvm at metafoo.co.uk (Richard Smith) Date: Fri, 24 Feb 2012 18:42:08 -0000 Subject: [cfe-commits] r151381 - /cfe/trunk/www/cxx_status.html Message-ID: <20120224184208.BFC132A6C12F@llvm.org> Author: rsmith Date: Fri Feb 24 12:42:08 2012 New Revision: 151381 URL: http://llvm.org/viewvc/llvm-project?rev=151381&view=rev Log: cxx_status: Consistently refer to C++11 as "C++11", not as "C++'11" nor as "C++0x". Use "C++98" to refer to C++98, not "C++". Add heading for C++98 support section. Modified: cfe/trunk/www/cxx_status.html Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=151381&r1=151380&r2=151381&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Fri Feb 24 12:42:08 2012 @@ -3,7 +3,7 @@ - Clang - C++ and C++'11 Status + Clang - C++98 and C++11 Status