From 13cc256e404620c1de0cbcc4e43ce1e2dbbc4898 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 2 Dec 2012 13:20:44 +0000 Subject: Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2): http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974 --- include/clang/ARCMigrate/ARCMT.h | 5 +- include/clang/AST/ASTConsumer.h | 15 +- include/clang/AST/ASTContext.h | 616 ++++---- include/clang/AST/ASTMutationListener.h | 2 + include/clang/AST/Attr.h | 5 - include/clang/AST/BuiltinTypes.def | 2 + include/clang/AST/CMakeLists.txt | 12 + include/clang/AST/CXXInheritance.h | 17 +- include/clang/AST/CanonicalType.h | 1 + include/clang/AST/CharUnits.h | 4 +- include/clang/AST/Comment.h | 189 +-- include/clang/AST/CommentBriefParser.h | 3 +- include/clang/AST/CommentCommandTraits.h | 186 ++- include/clang/AST/CommentCommands.td | 156 ++ include/clang/AST/CommentHTMLTags.td | 54 + include/clang/AST/CommentLexer.h | 116 +- include/clang/AST/CommentParser.h | 4 +- include/clang/AST/CommentSema.h | 48 +- include/clang/AST/Decl.h | 52 +- include/clang/AST/DeclBase.h | 27 +- include/clang/AST/DeclCXX.h | 46 +- include/clang/AST/DeclFriend.h | 12 +- include/clang/AST/DeclObjC.h | 106 +- include/clang/AST/DeclTemplate.h | 130 +- include/clang/AST/DeclarationName.h | 4 +- include/clang/AST/Expr.h | 249 +-- include/clang/AST/ExprCXX.h | 214 +-- include/clang/AST/ExprObjC.h | 33 +- include/clang/AST/ExternalASTSource.h | 2 +- include/clang/AST/Makefile | 19 +- include/clang/AST/NSAPI.h | 6 +- include/clang/AST/NestedNameSpecifier.h | 3 +- include/clang/AST/OperationKinds.h | 6 +- include/clang/AST/PrettyPrinter.h | 12 + include/clang/AST/RawCommentList.h | 6 +- include/clang/AST/RecordLayout.h | 4 +- include/clang/AST/RecursiveASTVisitor.h | 13 +- include/clang/AST/SelectorLocationsKind.h | 4 +- include/clang/AST/Stmt.h | 377 +++-- include/clang/AST/StmtCXX.h | 5 - include/clang/AST/StmtObjC.h | 7 - include/clang/AST/TemplateBase.h | 92 +- include/clang/AST/Type.h | 163 +- include/clang/AST/TypeLoc.h | 42 +- include/clang/AST/UnresolvedSet.h | 2 +- include/clang/AST/VTableBuilder.h | 5 +- include/clang/ASTMatchers/ASTMatchFinder.h | 29 +- include/clang/ASTMatchers/ASTMatchers.h | 1445 +++++++++++++---- include/clang/ASTMatchers/ASTMatchersInternal.h | 621 ++++++-- include/clang/ASTMatchers/ASTMatchersMacros.h | 65 + include/clang/ASTMatchers/ASTTypeTraits.h | 209 +++ include/clang/Analysis/Analyses/FormatString.h | 24 +- include/clang/Analysis/Analyses/ThreadSafety.h | 3 +- include/clang/Analysis/AnalysisContext.h | 35 +- include/clang/Analysis/CFG.h | 6 +- .../clang/Analysis/DomainSpecific/ObjCNoReturn.h | 46 + include/clang/Analysis/ProgramPoint.h | 7 +- include/clang/Basic/Attr.td | 16 +- include/clang/Basic/Builtins.def | 65 +- include/clang/Basic/BuiltinsMips.def | 63 + include/clang/Basic/BuiltinsNVPTX.def | 246 +++ include/clang/Basic/BuiltinsX86.def | 9 + include/clang/Basic/ConvertUTF.h | 12 +- include/clang/Basic/Diagnostic.h | 27 +- include/clang/Basic/DiagnosticASTKinds.td | 2 +- include/clang/Basic/DiagnosticCommentKinds.td | 16 + include/clang/Basic/DiagnosticCommonKinds.td | 5 +- include/clang/Basic/DiagnosticDriverKinds.td | 24 +- include/clang/Basic/DiagnosticFrontendKinds.td | 7 + include/clang/Basic/DiagnosticGroups.td | 83 +- include/clang/Basic/DiagnosticLexKinds.td | 35 +- include/clang/Basic/DiagnosticOptions.def | 93 ++ include/clang/Basic/DiagnosticOptions.h | 85 + include/clang/Basic/DiagnosticParseKinds.td | 50 +- include/clang/Basic/DiagnosticSemaKinds.td | 361 +++-- .../clang/Basic/DiagnosticSerializationKinds.td | 43 +- include/clang/Basic/FileManager.h | 4 + include/clang/Basic/IdentifierTable.h | 33 +- include/clang/Basic/LangOptions.def | 22 +- include/clang/Basic/Module.h | 30 +- include/clang/Basic/ObjCRuntime.h | 45 +- include/clang/Basic/OnDiskHashTable.h | 5 +- include/clang/Basic/Sanitizers.def | 69 + include/clang/Basic/SourceLocation.h | 2 + include/clang/Basic/SourceManager.h | 21 +- include/clang/Basic/Specifiers.h | 15 + include/clang/Basic/StmtNodes.td | 10 +- include/clang/Basic/TargetInfo.h | 59 +- include/clang/Basic/TargetOptions.h | 6 +- include/clang/Basic/TokenKinds.def | 41 +- include/clang/Basic/TokenKinds.h | 25 + include/clang/Basic/TypeTraits.h | 1 + include/clang/Basic/arm_neon.td | 8 +- include/clang/CodeGen/CodeGenAction.h | 2 +- include/clang/Driver/Action.h | 15 - include/clang/Driver/Arg.h | 26 +- include/clang/Driver/ArgList.h | 72 +- include/clang/Driver/CC1AsOptions.h | 4 +- include/clang/Driver/CC1AsOptions.td | 43 +- include/clang/Driver/CC1Options.td | 419 ++--- include/clang/Driver/Compilation.h | 11 +- include/clang/Driver/Driver.h | 43 +- include/clang/Driver/Job.h | 4 - include/clang/Driver/OptParser.td | 31 +- include/clang/Driver/OptTable.h | 61 +- include/clang/Driver/Option.h | 324 ++-- include/clang/Driver/Options.h | 4 +- include/clang/Driver/Options.td | 1645 ++++++++++---------- include/clang/Driver/Tool.h | 4 +- include/clang/Driver/ToolChain.h | 40 +- include/clang/Driver/Types.h | 4 - include/clang/Frontend/ASTUnit.h | 86 +- include/clang/Frontend/Analyses.def | 67 - include/clang/Frontend/AnalyzerOptions.h | 135 -- include/clang/Frontend/CodeGenOptions.def | 132 ++ include/clang/Frontend/CodeGenOptions.h | 182 +-- include/clang/Frontend/CompilerInstance.h | 44 +- include/clang/Frontend/CompilerInvocation.h | 79 +- include/clang/Frontend/DiagnosticOptions.h | 111 -- include/clang/Frontend/DiagnosticRenderer.h | 8 +- include/clang/Frontend/FrontendAction.h | 16 +- include/clang/Frontend/FrontendOptions.h | 34 +- include/clang/Frontend/HeaderSearchOptions.h | 146 -- include/clang/Frontend/LangStandard.h | 18 +- include/clang/Frontend/LangStandards.def | 58 +- include/clang/Frontend/LogDiagnosticPrinter.h | 4 +- include/clang/Frontend/MultiplexConsumer.h | 1 - include/clang/Frontend/PreprocessorOptions.h | 224 --- .../clang/Frontend/SerializedDiagnosticPrinter.h | 2 +- include/clang/Frontend/TextDiagnostic.h | 2 +- include/clang/Frontend/TextDiagnosticPrinter.h | 5 +- include/clang/Frontend/VerifyDiagnosticConsumer.h | 86 +- include/clang/Lex/ExternalPreprocessorSource.h | 3 - include/clang/Lex/HeaderMap.h | 5 +- include/clang/Lex/HeaderSearch.h | 25 +- include/clang/Lex/HeaderSearchOptions.h | 147 ++ include/clang/Lex/Lexer.h | 91 +- include/clang/Lex/LiteralSupport.h | 10 +- include/clang/Lex/MacroInfo.h | 60 +- include/clang/Lex/ModuleMap.h | 74 +- include/clang/Lex/PPCallbacks.h | 53 +- include/clang/Lex/PPMutationListener.h | 43 + include/clang/Lex/PTHLexer.h | 4 +- include/clang/Lex/PTHManager.h | 5 +- include/clang/Lex/PreprocessingRecord.h | 84 +- include/clang/Lex/Preprocessor.h | 128 +- include/clang/Lex/PreprocessorLexer.h | 4 +- include/clang/Lex/PreprocessorOptions.h | 221 +++ include/clang/Lex/Token.h | 18 +- include/clang/Lex/TokenLexer.h | 17 +- include/clang/Parse/Parser.h | 197 ++- include/clang/Rewrite/ASTConsumers.h | 48 - include/clang/Rewrite/Core/DeltaTree.h | 50 + include/clang/Rewrite/Core/HTMLRewrite.h | 81 + include/clang/Rewrite/Core/RewriteRope.h | 239 +++ include/clang/Rewrite/Core/Rewriter.h | 295 ++++ include/clang/Rewrite/Core/TokenRewriter.h | 79 + include/clang/Rewrite/DeltaTree.h | 48 - include/clang/Rewrite/FixItRewriter.h | 130 -- include/clang/Rewrite/Frontend/ASTConsumers.h | 48 + include/clang/Rewrite/Frontend/FixItRewriter.h | 130 ++ include/clang/Rewrite/Frontend/FrontendActions.h | 83 + include/clang/Rewrite/Frontend/Rewriters.h | 35 + include/clang/Rewrite/FrontendActions.h | 83 - include/clang/Rewrite/HTMLRewrite.h | 81 - include/clang/Rewrite/RewriteRope.h | 231 --- include/clang/Rewrite/Rewriter.h | 295 ---- include/clang/Rewrite/Rewriters.h | 35 - include/clang/Rewrite/TokenRewriter.h | 79 - include/clang/Sema/AttributeList.h | 8 +- include/clang/Sema/CodeCompleteConsumer.h | 20 +- include/clang/Sema/DeclSpec.h | 54 +- include/clang/Sema/DelayedDiagnostic.h | 11 +- include/clang/Sema/ExternalSemaSource.h | 1 - include/clang/Sema/Initialization.h | 4 +- include/clang/Sema/LocInfoType.h | 1 - include/clang/Sema/MultiplexExternalSemaSource.h | 367 +++++ include/clang/Sema/Overload.h | 12 +- include/clang/Sema/Ownership.h | 216 +-- include/clang/Sema/ParsedTemplate.h | 5 - include/clang/Sema/Scope.h | 8 +- include/clang/Sema/ScopeInfo.h | 226 ++- include/clang/Sema/Sema.h | 249 ++- include/clang/Sema/SemaConsumer.h | 1 - include/clang/Sema/Template.h | 5 +- include/clang/Sema/TemplateDeduction.h | 18 +- include/clang/Sema/TypoCorrection.h | 12 + include/clang/Serialization/ASTBitCodes.h | 234 +-- .../Serialization/ASTDeserializationListener.h | 6 +- include/clang/Serialization/ASTReader.h | 476 ++++-- include/clang/Serialization/ASTWriter.h | 72 +- include/clang/Serialization/ContinuousRangeMap.h | 4 +- include/clang/Serialization/Module.h | 66 +- include/clang/Serialization/ModuleManager.h | 9 +- .../StaticAnalyzer/Checkers/DereferenceChecker.h | 35 - include/clang/StaticAnalyzer/Core/Analyses.def | 67 + .../clang/StaticAnalyzer/Core/AnalyzerOptions.h | 308 ++++ .../StaticAnalyzer/Core/BugReporter/BugReporter.h | 89 +- .../Core/BugReporter/BugReporterVisitor.h | 58 +- .../Core/BugReporter/PathDiagnostic.h | 129 +- include/clang/StaticAnalyzer/Core/Checker.h | 17 - include/clang/StaticAnalyzer/Core/CheckerManager.h | 12 +- .../StaticAnalyzer/Core/PathSensitive/APSIntType.h | 4 + .../Core/PathSensitive/AnalysisManager.h | 80 +- .../Core/PathSensitive/BasicValueFactory.h | 5 +- .../StaticAnalyzer/Core/PathSensitive/CallEvent.h | 167 +- .../Core/PathSensitive/CheckerContext.h | 130 +- .../Core/PathSensitive/ConstraintManager.h | 111 +- .../StaticAnalyzer/Core/PathSensitive/CoreEngine.h | 70 +- .../Core/PathSensitive/DynamicTypeInfo.h | 52 + .../Core/PathSensitive/Environment.h | 11 +- .../Core/PathSensitive/ExplodedGraph.h | 74 +- .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 76 +- .../StaticAnalyzer/Core/PathSensitive/MemRegion.h | 43 +- .../Core/PathSensitive/ProgramState.h | 95 +- .../Core/PathSensitive/ProgramStateTrait.h | 31 + .../Core/PathSensitive/SValBuilder.h | 57 +- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 5 +- .../StaticAnalyzer/Core/PathSensitive/Store.h | 45 +- .../StaticAnalyzer/Core/PathSensitive/SubEngine.h | 6 +- .../Core/PathSensitive/SymbolManager.h | 52 +- .../Core/PathSensitive/TaintManager.h | 2 + include/clang/Tooling/CommandLineClangTool.h | 80 - include/clang/Tooling/CommonOptionsParser.h | 89 ++ include/clang/Tooling/CompilationDatabase.h | 95 +- .../Tooling/CompilationDatabasePluginRegistry.h | 27 + include/clang/Tooling/FileMatchTrie.h | 90 ++ include/clang/Tooling/JSONCompilationDatabase.h | 107 ++ include/clang/Tooling/Refactoring.h | 1 + include/clang/Tooling/Tooling.h | 48 +- 230 files changed, 12115 insertions(+), 6993 deletions(-) create mode 100644 include/clang/AST/CommentCommands.td create mode 100644 include/clang/AST/CommentHTMLTags.td create mode 100644 include/clang/ASTMatchers/ASTTypeTraits.h create mode 100644 include/clang/Analysis/DomainSpecific/ObjCNoReturn.h create mode 100644 include/clang/Basic/DiagnosticOptions.def create mode 100644 include/clang/Basic/DiagnosticOptions.h create mode 100644 include/clang/Basic/Sanitizers.def delete mode 100644 include/clang/Frontend/Analyses.def delete mode 100644 include/clang/Frontend/AnalyzerOptions.h create mode 100644 include/clang/Frontend/CodeGenOptions.def delete mode 100644 include/clang/Frontend/DiagnosticOptions.h delete mode 100644 include/clang/Frontend/HeaderSearchOptions.h delete mode 100644 include/clang/Frontend/PreprocessorOptions.h create mode 100644 include/clang/Lex/HeaderSearchOptions.h create mode 100644 include/clang/Lex/PPMutationListener.h create mode 100644 include/clang/Lex/PreprocessorOptions.h delete mode 100644 include/clang/Rewrite/ASTConsumers.h create mode 100644 include/clang/Rewrite/Core/DeltaTree.h create mode 100644 include/clang/Rewrite/Core/HTMLRewrite.h create mode 100644 include/clang/Rewrite/Core/RewriteRope.h create mode 100644 include/clang/Rewrite/Core/Rewriter.h create mode 100644 include/clang/Rewrite/Core/TokenRewriter.h delete mode 100644 include/clang/Rewrite/DeltaTree.h delete mode 100644 include/clang/Rewrite/FixItRewriter.h create mode 100644 include/clang/Rewrite/Frontend/ASTConsumers.h create mode 100644 include/clang/Rewrite/Frontend/FixItRewriter.h create mode 100644 include/clang/Rewrite/Frontend/FrontendActions.h create mode 100644 include/clang/Rewrite/Frontend/Rewriters.h delete mode 100644 include/clang/Rewrite/FrontendActions.h delete mode 100644 include/clang/Rewrite/HTMLRewrite.h delete mode 100644 include/clang/Rewrite/RewriteRope.h delete mode 100644 include/clang/Rewrite/Rewriter.h delete mode 100644 include/clang/Rewrite/Rewriters.h delete mode 100644 include/clang/Rewrite/TokenRewriter.h create mode 100644 include/clang/Sema/MultiplexExternalSemaSource.h delete mode 100644 include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h create mode 100644 include/clang/StaticAnalyzer/Core/Analyses.def create mode 100644 include/clang/StaticAnalyzer/Core/AnalyzerOptions.h create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h delete mode 100644 include/clang/Tooling/CommandLineClangTool.h create mode 100644 include/clang/Tooling/CommonOptionsParser.h create mode 100644 include/clang/Tooling/CompilationDatabasePluginRegistry.h create mode 100644 include/clang/Tooling/FileMatchTrie.h create mode 100644 include/clang/Tooling/JSONCompilationDatabase.h (limited to 'include/clang') diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index 86a6cbb22aae..cce866165210 100644 --- a/include/clang/ARCMigrate/ARCMT.h +++ b/include/clang/ARCMigrate/ARCMT.h @@ -12,6 +12,7 @@ #include "clang/ARCMigrate/FileRemapper.h" #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Basic/SourceLocation.h" namespace clang { class ASTContext; @@ -51,7 +52,7 @@ bool applyTransformations(CompilerInvocation &origCI, DiagnosticConsumer *DiagClient); /// \brief Applies automatic modifications and produces temporary files -/// and metadata into the \arg outputDir path. +/// and metadata into the \p outputDir path. /// /// \param emitPremigrationARCErrors if true all ARC errors will get emitted /// even if the migrator can fix them, but the function will still return false @@ -68,7 +69,7 @@ bool migrateWithTemporaryFiles(CompilerInvocation &origCI, bool emitPremigrationARCErrors, StringRef plistOut); -/// \brief Get the set of file remappings from the \arg outputDir path that +/// \brief Get the set of file remappings from the \p outputDir path that /// migrateWithTemporaryFiles produced. /// /// \returns false if no error is produced, true otherwise. diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 69a3866969d2..37b0740cb98b 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -19,12 +19,14 @@ namespace clang { class CXXRecordDecl; class DeclGroupRef; class HandleTagDeclDefinition; + class PPMutationListener; class ASTMutationListener; class ASTDeserializationListener; // layering violation because void* is ugly class SemaConsumer; // layering violation required for safe SemaConsumer class TagDecl; class VarDecl; class FunctionDecl; + class ImportDecl; /// ASTConsumer - This is an abstract interface that should be implemented by /// clients that read ASTs. This abstraction layer allows the client to be @@ -79,6 +81,11 @@ public: /// The default implementation ignored them. virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); + /// \brief Handle an ImportDecl that was implicitly created due to an + /// inclusion directive. + /// The default implementation passes it to HandleTopLevelDecl. + virtual void HandleImplicitImportDecl(ImportDecl *D); + /// CompleteTentativeDefinition - Callback invoked at the end of a translation /// unit to notify the consumer that the given tentative definition should be /// completed. @@ -105,6 +112,11 @@ public: /// it was actually used. virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} + /// \brief If the consumer is interested in preprocessor entities getting + /// modified after their initial creation, it should return a pointer to + /// a PPMutationListener here. + virtual PPMutationListener *GetPPMutationListener() { return 0; } + /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to /// an ASTMutationListener here. @@ -118,9 +130,6 @@ public: /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} - - // Support isa/cast/dyn_cast - static bool classof(const ASTConsumer *) { return true; } }; } // end namespace clang. diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index cad3ad2b5f9c..f0934b77961b 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the ASTContext interface. -// +/// +/// \file +/// \brief Defines the clang::ASTContext interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_ASTCONTEXT_H @@ -28,6 +29,7 @@ #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/RawCommentList.h" +#include "clang/AST/CommentCommandTraits.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -84,8 +86,8 @@ namespace clang { class FullComment; } -/// 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. +/// \brief 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 RefCountedBase { ASTContext &this_() { return *this; } @@ -144,19 +146,20 @@ class ASTContext : public RefCountedBase { mutable NestedNameSpecifier *GlobalNestedNameSpecifier; friend class NestedNameSpecifier; - /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts. - /// This is lazily created. This is intentionally not serialized. + /// \brief A cache mapping from RecordDecls to ASTRecordLayouts. + /// + /// This is lazily created. This is intentionally not serialized. mutable llvm::DenseMap ASTRecordLayouts; mutable llvm::DenseMap ObjCLayouts; - /// TypeInfoMap - A cache from types to size and alignment information. + /// \brief A cache from types to size and alignment information. typedef llvm::DenseMap > TypeInfoMap; mutable TypeInfoMap MemoizedTypeInfo; - /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions. + /// \brief A cache mapping from CXXRecordDecls to key functions. llvm::DenseMap KeyFunctions; /// \brief Mapping from ObjCContainers to their ObjCImplementations. @@ -170,7 +173,7 @@ class ASTContext : public RefCountedBase { llvm::DenseMap BlockVarCopyInits; /// \brief Mapping from class scope functions specialization to their - /// template patterns. + /// template patterns. llvm::DenseMap ClassScopeSpecializationPattern; @@ -206,17 +209,20 @@ class ASTContext : public RefCountedBase { /// __builtin_va_list type. mutable TypedefDecl *BuiltinVaListDecl; - /// \brief The typedef for the predefined 'id' type. + /// \brief The typedef for the predefined \c id type. mutable TypedefDecl *ObjCIdDecl; - /// \brief The typedef for the predefined 'SEL' type. + /// \brief The typedef for the predefined \c SEL type. mutable TypedefDecl *ObjCSelDecl; - /// \brief The typedef for the predefined 'Class' type. + /// \brief The typedef for the predefined \c Class type. mutable TypedefDecl *ObjCClassDecl; - /// \brief The typedef for the predefined 'Protocol' class in Objective-C. + /// \brief The typedef for the predefined \c Protocol class in Objective-C. mutable ObjCInterfaceDecl *ObjCProtocolClassDecl; + + /// \brief The typedef for the predefined 'BOOL' type. + mutable TypedefDecl *BOOLDecl; // Typedefs which may be provided defining the structure of Objective-C // pseudo-builtins @@ -296,9 +302,10 @@ class ASTContext : public RefCountedBase { InstantiatedFromStaticDataMember; /// \brief Keeps track of the declaration from which a UsingDecl was - /// created during instantiation. The source declaration is always - /// a UsingDecl, an UnresolvedUsingValueDecl, or an - /// UnresolvedUsingTypenameDecl. + /// created during instantiation. + /// + /// The source declaration is always a UsingDecl, an UnresolvedUsingValueDecl, + /// or an UnresolvedUsingTypenameDecl. /// /// For example: /// \code @@ -337,9 +344,8 @@ class ASTContext : public RefCountedBase { /// mangling context. llvm::DenseMap LambdaMangleContexts; - /// \brief Mapping that stores parameterIndex values for ParmVarDecls - /// when that value exceeds the bitfield size of - /// ParmVarDeclBits.ParameterIndex. + /// \brief Mapping that stores parameterIndex values for ParmVarDecls when + /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. typedef llvm::DenseMap ParameterIndexTable; ParameterIndexTable ParamIndices; @@ -348,10 +354,10 @@ class ASTContext : public RefCountedBase { TranslationUnitDecl *TUDecl; - /// SourceMgr - The associated SourceManager object. + /// \brief The associated SourceManager object.a SourceManager &SourceMgr; - /// LangOpts - The language options used to create the AST associated with + /// \brief The language options used to create the AST associated with /// this ASTContext object. LangOptions &LangOpts; @@ -387,9 +393,11 @@ public: OwningPtr ExternalSource; ASTMutationListener *Listener; - clang::PrintingPolicy getPrintingPolicy() const { return PrintingPolicy; } + const clang::PrintingPolicy &getPrintingPolicy() const { + return PrintingPolicy; + } - void setPrintingPolicy(clang::PrintingPolicy Policy) { + void setPrintingPolicy(const clang::PrintingPolicy &Policy) { PrintingPolicy = Policy; } @@ -508,6 +516,8 @@ public: } void addComment(const RawComment &RC) { + assert(LangOpts.RetainCommentsFromSystemHeaders || + !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin())); Comments.addComment(RC, BumpAlloc); } @@ -522,7 +532,22 @@ public: /// Return parsed documentation comment attached to a given declaration. /// Returns NULL if no comment is attached. - comments::FullComment *getCommentForDecl(const Decl *D) const; + /// + /// \param PP the Preprocessor used with this TU. Could be NULL if + /// preprocessor is not available. + comments::FullComment *getCommentForDecl(const Decl *D, + const Preprocessor *PP) const; + + comments::FullComment *cloneFullComment(comments::FullComment *FC, + const Decl *D) const; + +private: + mutable comments::CommandTraits CommentCommandTraits; + +public: + comments::CommandTraits &getCommentCommandTraits() const { + return CommentCommandTraits; + } /// \brief Retrieve the attributes for the given declaration. AttrVec& getDeclAttrs(const Decl *D); @@ -547,7 +572,7 @@ public: TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); - /// \brief If the given using decl is an instantiation of a + /// \brief If the given using decl \p Inst is an instantiation of a /// (possibly unresolved) using decl from a template instantiation, /// return it. NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst); @@ -564,28 +589,28 @@ public: void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); - /// ZeroBitfieldFollowsNonBitfield - return 'true" if 'FD' is a zero-length - /// bitfield which follows the non-bitfield 'LastFD'. + /// \brief Return \c true if \p FD is a zero-length bitfield which follows + /// the non-bitfield \p LastFD. bool ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const; - /// ZeroBitfieldFollowsBitfield - return 'true" if 'FD' is a zero-length - /// bitfield which follows the bitfield 'LastFD'. + /// \brief Return \c true if \p FD is a zero-length bitfield which follows + /// the bitfield \p LastFD. bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const; - /// BitfieldFollowsBitfield - return 'true" if 'FD' is a - /// bitfield which follows the bitfield 'LastFD'. + /// \brief Return \c true if \p FD is a bitfield which follows the bitfield + /// \p LastFD. bool BitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const; - /// NonBitfieldFollowsBitfield - return 'true" if 'FD' is not a - /// bitfield which follows the bitfield 'LastFD'. + /// \brief Return \c true if \p FD is not a bitfield which follows the + /// bitfield \p LastFD. bool NonBitfieldFollowsBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const; - /// BitfieldFollowsNonBitfield - return 'true" if 'FD' is a - /// bitfield which follows the none bitfield 'LastFD'. + /// \brief Return \c true if \p FD is a bitfield which follows the + /// non-bitfield \p LastFD. bool BitfieldFollowsNonBitfield(const FieldDecl *FD, const FieldDecl *LastFD) const; @@ -603,6 +628,17 @@ public: /// Overridden method. void addOverriddenMethod(const CXXMethodDecl *Method, const CXXMethodDecl *Overridden); + + /// \brief Return C++ or ObjC overridden methods for the given \p Method. + /// + /// An ObjC method is considered to override any method in the class's + /// base classes, its protocols, or its categories' protocols, that has + /// the same selector and is of the same kind (class or instance). + /// A method in an implementation is not considered as overriding the same + /// method in the interface or its categories. + void getOverriddenMethods( + const NamedDecl *Method, + SmallVectorImpl &Overridden) const; /// \brief Notify the AST context that a new import declaration has been /// parsed or implicitly created within this translation unit. @@ -673,6 +709,7 @@ public: CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType VoidPtrTy, NullPtrTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; + CanQualType BuiltinFnTy; CanQualType PseudoObjectTy, ARCUnbridgedCastTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; CanQualType ObjCBuiltinBoolTy; @@ -731,77 +768,85 @@ public: //===--------------------------------------------------------------------===// private: - /// getExtQualType - Return a type with extended qualifiers. + /// \brief Return a type with extended qualifiers. QualType getExtQualType(const Type *Base, Qualifiers Quals) const; QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const; public: - /// getAddSpaceQualType - Return the uniqued reference to the type for an - /// address space qualified type with the specified type and address space. + /// \brief Return the uniqued reference to the type for an address space + /// qualified type with the specified type and address space. + /// /// The resulting type has a union of the qualifiers from T and the address /// space. If T already has an address space specifier, it is silently /// replaced. QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const; - /// getObjCGCQualType - Returns the uniqued reference to the type for an - /// objc gc qualified type. The retulting type has a union of the qualifiers - /// from T and the gc attribute. + /// \brief Return the uniqued reference to the type for an Objective-C + /// gc-qualified type. + /// + /// The retulting type has a union of the qualifiers from T and the gc + /// attribute. QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const; - /// getRestrictType - Returns the uniqued reference to the type for a - /// 'restrict' qualified type. The resulting type has a union of the - /// qualifiers from T and 'restrict'. + /// \brief Return the uniqued reference to the type for a \c restrict + /// qualified type. + /// + /// The resulting type has a union of the qualifiers from \p T and + /// \c restrict. QualType getRestrictType(QualType T) const { return T.withFastQualifiers(Qualifiers::Restrict); } - /// getVolatileType - Returns the uniqued reference to the type for a - /// 'volatile' qualified type. The resulting type has a union of the - /// qualifiers from T and 'volatile'. + /// \brief Return the uniqued reference to the type for a \c volatile + /// qualified type. + /// + /// The resulting type has a union of the qualifiers from \p T and + /// \c volatile. QualType getVolatileType(QualType T) const { return T.withFastQualifiers(Qualifiers::Volatile); } - /// getConstType - Returns the uniqued reference to the type for a - /// 'const' qualified type. The resulting type has a union of the - /// qualifiers from T and 'const'. + /// \brief Return the uniqued reference to the type for a \c const + /// qualified type. /// - /// It can be reasonably expected that this will always be - /// equivalent to calling T.withConst(). + /// The resulting type has a union of the qualifiers from \p T and \c const. + /// + /// It can be reasonably expected that this will always be equivalent to + /// calling T.withConst(). QualType getConstType(QualType T) const { return T.withConst(); } - /// adjustFunctionType - Change the ExtInfo on a function type. + /// \brief Change the ExtInfo on a function type. const FunctionType *adjustFunctionType(const FunctionType *Fn, FunctionType::ExtInfo EInfo); - /// getComplexType - Return the uniqued reference to the type for a complex + /// \brief Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T) const; CanQualType getComplexType(CanQualType T) const { return CanQualType::CreateUnsafe(getComplexType((QualType) T)); } - /// getPointerType - Return the uniqued reference to the type for a pointer to + /// \brief Return the uniqued reference to the type for a pointer to /// the specified type. QualType getPointerType(QualType T) const; CanQualType getPointerType(CanQualType T) const { return CanQualType::CreateUnsafe(getPointerType((QualType) T)); } - /// getAtomicType - Return the uniqued reference to the atomic type for - /// the specified type. + /// \brief Return the uniqued reference to the atomic type for the specified + /// type. QualType getAtomicType(QualType T) const; - /// getBlockPointerType - Return the uniqued reference to the type for a block - /// of the specified type. + /// \brief Return the uniqued reference to the type for a block of the + /// specified type. QualType getBlockPointerType(QualType T) const; - /// This gets the struct used to keep track of the descriptor for pointer to + /// Gets the struct used to keep track of the descriptor for pointer to /// blocks. QualType getBlockDescriptorType() const; - /// This gets the struct used to keep track of the extended descriptor for + /// Gets the struct used to keep track of the extended descriptor for /// pointer to blocks. QualType getBlockDescriptorExtendedType() const; @@ -812,78 +857,82 @@ public: return cudaConfigureCallDecl; } - /// This builds the struct used for __block variables. + /// Builds the struct used for __block variables. QualType BuildByRefType(StringRef DeclName, QualType Ty) const; /// Returns true iff we need copy/dispose helpers for the given type. bool BlockRequiresCopying(QualType Ty) const; - /// getLValueReferenceType - Return the uniqued reference to the type for an - /// lvalue reference to the specified type. + /// \brief Return the uniqued reference to the type for an lvalue reference + /// to the specified type. QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true) const; - /// getRValueReferenceType - Return the uniqued reference to the type for an - /// rvalue reference to the specified type. + /// \brief Return the uniqued reference to the type for an rvalue reference + /// to the specified type. QualType getRValueReferenceType(QualType T) const; - /// getMemberPointerType - Return the uniqued reference to the type for a - /// member pointer to the specified type in the specified class. The class - /// is a Type because it could be a dependent name. + /// \brief Return the uniqued reference to the type for a member pointer to + /// the specified type in the specified class. + /// + /// The class \p Cls is a \c Type because it could be a dependent name. QualType getMemberPointerType(QualType T, const Type *Cls) const; - /// getVariableArrayType - Returns a non-unique reference to the type for a - /// variable array of the specified element type. + /// \brief Return a non-unique reference to the type for a variable array of + /// the specified element type. QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const; - /// getDependentSizedArrayType - Returns a non-unique reference to - /// the type for a dependently-sized array of the specified element - /// type. FIXME: We will need these to be uniqued, or at least - /// comparable, at some point. + /// \brief Return a non-unique reference to the type for a dependently-sized + /// array of the specified element type. + /// + /// FIXME: We will need these to be uniqued, or at least comparable, at some + /// point. QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const; - /// getIncompleteArrayType - Returns a unique reference to the type for a - /// incomplete array of the specified element type. + /// \brief Return a unique reference to the type for an incomplete array of + /// the specified element type. QualType getIncompleteArrayType(QualType EltTy, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; - /// getConstantArrayType - Return the unique reference to the type for a - /// constant array of the specified element type. + /// \brief Return the unique reference to the type for a constant array of + /// the specified element type. QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; - /// getVariableArrayDecayedType - Returns a vla type where known sizes - /// are replaced with [*]. + /// \brief Returns a vla type where known sizes are replaced with [*]. QualType getVariableArrayDecayedType(QualType Ty) const; - /// getVectorType - Return the unique reference to a vector type of - /// the specified element type and size. VectorType must be a built-in type. + /// \brief Return the unique reference to a vector type of the specified + /// element type and size. + /// + /// \pre \p VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, VectorType::VectorKind VecKind) const; - /// getExtVectorType - Return the unique reference to an extended vector type - /// of the specified element type and size. VectorType must be a built-in - /// type. + /// \brief Return the unique reference to an extended vector type + /// of the specified element type and size. + /// + /// \pre \p VectorType must be a built-in type. QualType getExtVectorType(QualType VectorType, unsigned NumElts) const; - /// getDependentSizedExtVectorType - Returns a non-unique reference to - /// the type for a dependently-sized vector of the specified element - /// type. FIXME: We will need these to be uniqued, or at least - /// comparable, at some point. + /// \pre Return a non-unique reference to the type for a dependently-sized + /// vector of the specified element type. + /// + /// FIXME: We will need these to be uniqued, or at least comparable, at some + /// point. QualType getDependentSizedExtVectorType(QualType VectorType, Expr *SizeExpr, SourceLocation AttrLoc) const; - /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. - /// + /// \brief Return a K&R style C function type like 'int()'. QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const; @@ -891,14 +940,13 @@ public: return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); } - /// getFunctionType - Return a normal function type with a typed - /// argument list. + /// \brief Return a normal function type with a typed argument list. QualType getFunctionType(QualType ResultTy, const QualType *Args, unsigned NumArgs, const FunctionProtoType::ExtProtoInfo &EPI) const; - /// getTypeDeclType - Return the unique reference to the type for - /// the specified type declaration. + /// \brief Return the unique reference to the type for the specified type + /// declaration. QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl = 0) const { assert(Decl && "Passed null for Decl param"); @@ -913,8 +961,8 @@ public: return getTypeDeclTypeSlow(Decl); } - /// getTypedefType - Return the unique reference to the type for the - /// specified typedef-name decl. + /// \brief Return the unique reference to the type for the specified + /// typedef-name decl. QualType getTypedefType(const TypedefNameDecl *Decl, QualType Canon = QualType()) const; @@ -986,69 +1034,75 @@ public: ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) const; - /// getObjCObjectPointerType - Return a ObjCObjectPointerType type - /// for the given ObjCObjectType. + /// \brief Return a ObjCObjectPointerType type for the given ObjCObjectType. QualType getObjCObjectPointerType(QualType OIT) const; - /// getTypeOfType - GCC extension. + /// \brief GCC extension. QualType getTypeOfExprType(Expr *e) const; QualType getTypeOfType(QualType t) const; - /// getDecltypeType - C++0x decltype. + /// \brief C++11 decltype. QualType getDecltypeType(Expr *e, QualType UnderlyingType) const; - /// getUnaryTransformType - unary type transforms + /// \brief Unary type transforms QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType, UnaryTransformType::UTTKind UKind) const; - /// getAutoType - C++0x deduced auto type. + /// \brief C++11 deduced auto type. QualType getAutoType(QualType DeducedType) const; - /// getAutoDeductType - C++0x deduction pattern for 'auto' type. + /// \brief C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; - /// getAutoRRefDeductType - C++0x deduction pattern for 'auto &&' type. + /// \brief C++11 deduction pattern for 'auto &&' type. QualType getAutoRRefDeductType() const; - /// getTagDeclType - Return the unique reference to the type for the - /// specified TagDecl (struct/union/class/enum) decl. + /// \brief Return the unique reference to the type for the specified TagDecl + /// (struct/union/class/enum) decl. QualType getTagDeclType(const TagDecl *Decl) const; - /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined - /// in . The sizeof operator requires this (C99 6.5.3.4p4). + /// \brief Return the unique type for "size_t" (C99 7.17), defined in + /// . + /// + /// The sizeof operator requires this (C99 6.5.3.4p4). CanQualType getSizeType() const; - /// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5), - /// defined in . + /// \brief Return the unique type for "intmax_t" (C99 7.18.1.5), defined in + /// . CanQualType getIntMaxType() const; - /// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5), - /// defined in . + /// \brief Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in + /// . CanQualType getUIntMaxType() const; - /// getWCharType - In C++, this returns the unique wchar_t type. In C99, this + /// \brief In C++, this returns the unique wchar_t type. In C99, this /// returns a type compatible with the type defined in as defined /// by the target. QualType getWCharType() const { return WCharTy; } - /// getSignedWCharType - Return the type of "signed wchar_t". + /// \brief Return the type of "signed wchar_t". + /// /// Used when in C++, as a GCC extension. QualType getSignedWCharType() const; - /// getUnsignedWCharType - Return the type of "unsigned wchar_t". + /// \brief Return the type of "unsigned wchar_t". + /// /// Used when in C++, as a GCC extension. QualType getUnsignedWCharType() const; - /// getWIntType - In C99, this returns a type compatible with the type + /// \brief In C99, this returns a type compatible with the type /// defined in as defined by the target. QualType getWIntType() const { return WIntTy; } - /// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) - /// defined in . Pointer - pointer requires this (C99 6.5.6p9). + /// \brief Return the unique type for "ptrdiff_t" (C99 7.17) defined in + /// . Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; - // getCFConstantStringType - Return the C structure type used to represent - // constant CFStrings. + /// \brief Return the unique type for "pid_t" defined in + /// . We need this to compute the correct type for vfork(). + QualType getProcessIDType() const; + + /// \brief Return the C structure type used to represent constant CFStrings. QualType getCFConstantStringType() const; /// Get the structure type used to representation CFStrings, or NULL @@ -1074,21 +1128,21 @@ public: ObjCNSStringType = T; } - /// \brief Retrieve the type that 'id' has been defined to, which may be - /// different from the built-in 'id' if 'id' has been typedef'd. + /// \brief Retrieve the type that \c id has been defined to, which may be + /// different from the built-in \c id if \c id has been typedef'd. QualType getObjCIdRedefinitionType() const { if (ObjCIdRedefinitionType.isNull()) return getObjCIdType(); return ObjCIdRedefinitionType; } - /// \brief Set the user-written type that redefines 'id'. + /// \brief Set the user-written type that redefines \c id. void setObjCIdRedefinitionType(QualType RedefType) { ObjCIdRedefinitionType = RedefType; } - /// \brief Retrieve the type that 'Class' has been defined to, which may be - /// different from the built-in 'Class' if 'Class' has been typedef'd. + /// \brief Retrieve the type that \c Class has been defined to, which may be + /// different from the built-in \c Class if \c Class has been typedef'd. QualType getObjCClassRedefinitionType() const { if (ObjCClassRedefinitionType.isNull()) return getObjCClassType(); @@ -1175,27 +1229,29 @@ public: return getLangOpts().CPlusPlus ? BoolTy : IntTy; } - /// getObjCEncodingForType - Emit the ObjC type encoding for the - /// given type into \arg S. If \arg NameFields is specified then - /// record field names are also encoded. - void getObjCEncodingForType(QualType t, std::string &S, + /// \brief Emit the Objective-CC type encoding for the given type \p T into + /// \p S. + /// + /// If \p Field is specified then record field names are also encoded. + void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=0) const; void getLegacyIntegralTypeEncoding(QualType &t) const; - // Put the string version of type qualifiers into S. + /// \brief Put the string version of the type qualifiers \p QT into \p S. void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, std::string &S) const; - /// getObjCEncodingForFunctionDecl - Returns the encoded type for this - /// function. This is in the same format as Objective-C method encodings. + /// \brief Emit the encoded type for the function \p Decl into \p S. + /// + /// This is in the same format as Objective-C method encodings. /// /// \returns true if an error occurred (e.g., because one of the parameter /// types is incomplete), false otherwise. bool getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S); - /// getObjCEncodingForMethodDecl - Return the encoded type for this method - /// declaration. + /// \brief Emit the encoded type for the method declaration \p Decl into + /// \p S. /// /// \returns true if an error occurred (e.g., because one of the parameter /// types is incomplete), false otherwise. @@ -1203,8 +1259,7 @@ public: bool Extended = false) const; - /// getObjCEncodingForBlock - Return the encoded type for this block - /// declaration. + /// \brief Return the encoded type for this block declaration. std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const; /// getObjCEncodingForPropertyDecl - Return the encoded type for @@ -1218,16 +1273,18 @@ public: bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, ObjCProtocolDecl *rProto) const; - /// getObjCEncodingTypeSize returns size of type for objective-c encoding - /// purpose in characters. - CharUnits getObjCEncodingTypeSize(QualType t) const; + /// \brief Return the size of type \p T for Objective-C encoding purpose, + /// in characters. + CharUnits getObjCEncodingTypeSize(QualType T) const; - /// \brief Retrieve the typedef corresponding to the predefined 'id' type + /// \brief Retrieve the typedef corresponding to the predefined \c id type /// in Objective-C. TypedefDecl *getObjCIdDecl() const; - /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by - /// Sema. id is always a (typedef for a) pointer type, a pointer to a struct. + /// \brief Represents the Objective-CC \c id type. + /// + /// This is set up lazily, by Sema. \c id is always a (typedef for a) + /// pointer type, a pointer to a struct. QualType getObjCIdType() const { return getTypeDeclType(getObjCIdDecl()); } @@ -1246,48 +1303,64 @@ public: /// Objective-C 'Class' type. TypedefDecl *getObjCClassDecl() const; - /// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by - /// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a - /// struct. + /// \brief Represents the Objective-C \c Class type. + /// + /// This is set up lazily, by Sema. \c Class is always a (typedef for a) + /// pointer type, a pointer to a struct. QualType getObjCClassType() const { return getTypeDeclType(getObjCClassDecl()); } /// \brief Retrieve the Objective-C class declaration corresponding to - /// the predefined 'Protocol' class. + /// the predefined \c Protocol class. ObjCInterfaceDecl *getObjCProtocolDecl() const; + + /// \brief Retrieve declaration of 'BOOL' typedef + TypedefDecl *getBOOLDecl() const { + return BOOLDecl; + } + + /// \brief Save declaration of 'BOOL' typedef + void setBOOLDecl(TypedefDecl *TD) { + BOOLDecl = TD; + } + + /// \brief type of 'BOOL' type. + QualType getBOOLType() const { + return getTypeDeclType(getBOOLDecl()); + } - /// \brief Retrieve the type of the Objective-C "Protocol" class. + /// \brief Retrieve the type of the Objective-C \c Protocol class. QualType getObjCProtoType() const { return getObjCInterfaceType(getObjCProtocolDecl()); } /// \brief Retrieve the C type declaration corresponding to the predefined - /// __builtin_va_list type. + /// \c __builtin_va_list type. TypedefDecl *getBuiltinVaListDecl() const; - /// \brief Retrieve the type of the __builtin_va_list type. + /// \brief Retrieve the type of the \c __builtin_va_list type. QualType getBuiltinVaListType() const { return getTypeDeclType(getBuiltinVaListDecl()); } /// \brief Retrieve the C type declaration corresponding to the predefined - /// __va_list_tag type used to help define the __builtin_va_list type for - /// some targets. + /// \c __va_list_tag type used to help define the \c __builtin_va_list type + /// for some targets. QualType getVaListTagType() const; - /// getCVRQualifiedType - Returns a type with additional const, - /// volatile, or restrict qualifiers. + /// \brief Return a type with additional \c const, \c volatile, or + /// \c restrict qualifiers. QualType getCVRQualifiedType(QualType T, unsigned CVR) const { return getQualifiedType(T, Qualifiers::fromCVRMask(CVR)); } - /// getQualifiedType - Un-split a SplitQualType. + /// \brief Un-split a SplitQualType. QualType getQualifiedType(SplitQualType split) const { return getQualifiedType(split.Ty, split.Quals); } - /// getQualifiedType - Returns a type with additional qualifiers. + /// \brief Return a type with additional qualifiers. QualType getQualifiedType(QualType T, Qualifiers Qs) const { if (!Qs.hasNonFastQualifiers()) return T.withFastQualifiers(Qs.getFastQualifiers()); @@ -1296,15 +1369,16 @@ public: return getExtQualType(Ptr, Qc); } - /// getQualifiedType - Returns a type with additional qualifiers. + /// \brief Return a type with additional qualifiers. QualType getQualifiedType(const Type *T, Qualifiers Qs) const { if (!Qs.hasNonFastQualifiers()) return QualType(T, Qs.getFastQualifiers()); return getExtQualType(T, Qs); } - /// getLifetimeQualifiedType - Returns a type with the given - /// lifetime qualifier. + /// \brief Return a type with the given lifetime qualifier. + /// + /// \pre Neither type.ObjCLifetime() nor \p lifetime may be \c OCL_None. QualType getLifetimeQualifiedType(QualType type, Qualifiers::ObjCLifetime lifetime) { assert(type.getObjCLifetime() == Qualifiers::OCL_None); @@ -1341,8 +1415,9 @@ public: GE_Missing_ucontext ///< Missing a type from }; - /// GetBuiltinType - Return the type for the specified builtin. If - /// IntegerConstantArgs is non-null, it is filled in with a bitmask of + /// \brief Return the type for the specified builtin. + /// + /// If \p IntegerConstantArgs is non-null, it is filled in with a bitmask of /// arguments to the builtin that are required to be integer constant /// expressions. QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, @@ -1357,19 +1432,19 @@ private: //===--------------------------------------------------------------------===// public: - /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's - /// garbage collection attribute. - /// + /// \brief Return one of the GCNone, Weak or Strong Objective-C garbage + /// collection attributes. Qualifiers::GC getObjCGCAttrKind(QualType Ty) const; - /// areCompatibleVectorTypes - Return true if the given vector types - /// are of the same unqualified type or if they are equivalent to the same - /// GCC vector type, ignoring whether they are target-specific (AltiVec or - /// Neon) types. + /// \brief Return true if the given vector types are of the same unqualified + /// type or if they are equivalent to the same GCC vector type. + /// + /// \note This ignores whether they are target-specific (AltiVec or Neon) + /// types. bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec); - /// isObjCNSObjectType - Return true if this is an NSObject object with - /// its NSObject attribute set. + /// \brief Return true if this is an \c NSObject object with its \c NSObject + /// attribute set. static bool isObjCNSObjectType(QualType Ty) { return Ty->isObjCNSObjectType(); } @@ -1378,19 +1453,17 @@ public: // Type Sizing and Analysis //===--------------------------------------------------------------------===// - /// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified - /// scalar floating point type. + /// \brief Return the APFloat 'semantics' for the specified scalar floating + /// point type. const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const; - /// getTypeInfo - Get the size and alignment of the specified complete type in - /// bits. + /// \brief Get the size and alignment of the specified complete type in bits. std::pair getTypeInfo(const Type *T) const; std::pair getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); } - /// getTypeSize - Return the size of the specified type, in bits. This method - /// does not work on incomplete types. + /// \brief Return the size of the specified (complete) type \p T, in bits. uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).first; } @@ -1398,24 +1471,24 @@ public: return getTypeInfo(T).first; } - /// getCharWidth - Return the size of the character type, in bits + /// \brief Return the size of the character type, in bits. uint64_t getCharWidth() const { return getTypeSize(CharTy); } - /// toCharUnitsFromBits - Convert a size in bits to a size in characters. + /// \brief Convert a size in bits to a size in characters. CharUnits toCharUnitsFromBits(int64_t BitSize) const; - /// toBits - Convert a size in characters to a size in bits. + /// \brief Convert a size in characters to a size in bits. int64_t toBits(CharUnits CharSize) const; - /// getTypeSizeInChars - Return the size of the specified type, in characters. - /// This method does not work on incomplete types. + /// \brief Return the size of the specified (complete) type \p T, in + /// characters. CharUnits getTypeSizeInChars(QualType T) const; CharUnits getTypeSizeInChars(const Type *T) const; - /// getTypeAlign - Return the ABI-specified alignment of a type, in bits. - /// This method does not work on incomplete types. + /// \brief Return the ABI-specified alignment of a (complete) type \p T, in + /// bits. unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).second; } @@ -1423,49 +1496,59 @@ public: return getTypeInfo(T).second; } - /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in - /// characters. This method does not work on incomplete types. + /// \brief Return the ABI-specified alignment of a (complete) type \p T, in + /// characters. CharUnits getTypeAlignInChars(QualType T) const; CharUnits getTypeAlignInChars(const Type *T) const; + + // getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the + // type is a record, its data size is returned. + std::pair getTypeInfoDataSizeInChars(QualType T) const; std::pair getTypeInfoInChars(const Type *T) const; std::pair getTypeInfoInChars(QualType T) const; - /// getPreferredTypeAlign - Return the "preferred" alignment of the specified - /// type for the current target in bits. This can be different than the ABI - /// alignment in cases where it is beneficial for performance to overalign - /// a data type. + /// \brief Return the "preferred" alignment of the specified type \p T for + /// the current target, in bits. + /// + /// This can be different than the ABI alignment in cases where it is + /// beneficial for performance to overalign a data type. unsigned getPreferredTypeAlign(const Type *T) const; - /// getDeclAlign - Return a conservative estimate of the alignment of - /// the specified decl. Note that bitfields do not have a valid alignment, so - /// this method will assert on them. - /// If @p RefAsPointee, references are treated like their underlying type + /// \brief Return a conservative estimate of the alignment of the specified + /// decl \p D. + /// + /// \pre \p D must not be a bitfield type, as bitfields do not have a valid + /// alignment. + /// + /// If \p RefAsPointee, references are treated like their underlying type /// (for alignof), else they're treated like pointers (for CodeGen). CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false) const; - /// getASTRecordLayout - Get or compute information about the layout of the - /// specified record (struct/union/class), which indicates its size and field + /// \brief Get or compute information about the layout of the specified + /// record (struct/union/class) \p D, which indicates its size and field /// position information. const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const; - /// getASTObjCInterfaceLayout - Get or compute information about the - /// layout of the specified Objective-C interface. + /// \brief Get or compute information about the layout of the specified + /// Objective-C interface. const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const; void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple = false) const; - /// getASTObjCImplementationLayout - Get or compute information about - /// the layout of the specified Objective-C implementation. This may - /// differ from the interface if synthesized ivars are present. + /// \brief Get or compute information about the layout of the specified + /// Objective-C implementation. + /// + /// This may differ from the interface if synthesized ivars are present. const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const; - /// getKeyFunction - Get the key function for the given record decl, or NULL - /// if there isn't one. The key function is, according to the Itanium C++ ABI - /// section 5.2.3: + /// \brief Get the key function for the given record decl, or NULL if there + /// isn't one. + /// + /// The key function is, according to the Itanium C++ ABI section 5.2.3: /// /// ...the first non-pure virtual function that is not inline at the point /// of class definition. @@ -1489,12 +1572,14 @@ public: // Type Operators //===--------------------------------------------------------------------===// - /// getCanonicalType - Return the canonical (structural) type corresponding to - /// the specified potentially non-canonical type. The non-canonical version - /// of a type may have many "decorated" versions of types. Decorators can - /// include typedefs, 'typeof' operators, etc. The returned type is guaranteed - /// to be free of any of these, allowing two canonical types to be compared - /// for exact equality with a simple pointer comparison. + /// \brief Return the canonical (structural) type corresponding to the + /// specified potentially non-canonical type \p T. + /// + /// The non-canonical version of a type may have many "decorated" versions of + /// types. Decorators can include typedefs, 'typeof' operators, etc. The + /// returned type is guaranteed to be free of any of these, allowing two + /// canonical types to be compared for exact equality with a simple pointer + /// comparison. CanQualType getCanonicalType(QualType T) const { return CanQualType::CreateUnsafe(T.getCanonicalType()); } @@ -1503,21 +1588,23 @@ public: return T->getCanonicalTypeInternal().getTypePtr(); } - /// getCanonicalParamType - Return the canonical parameter type - /// corresponding to the specific potentially non-canonical one. + /// \brief Return the canonical parameter type corresponding to the specific + /// potentially non-canonical one. + /// /// Qualifiers are stripped off, functions are turned into function /// pointers, and arrays decay one level into pointers. CanQualType getCanonicalParamType(QualType T) const; - /// \brief Determine whether the given types are equivalent. + /// \brief Determine whether the given types \p T1 and \p T2 are equivalent. bool hasSameType(QualType T1, QualType T2) const { return getCanonicalType(T1) == getCanonicalType(T2); } - /// \brief Returns this type as a completely-unqualified array type, - /// capturing the qualifiers in Quals. This will remove the minimal amount of - /// sugaring from the types, similar to the behavior of - /// QualType::getUnqualifiedType(). + /// \brief Return this type as a completely-unqualified array type, + /// capturing the qualifiers in \p Quals. + /// + /// This will remove the minimal amount of sugaring from the types, similar + /// to the behavior of QualType::getUnqualifiedType(). /// /// \param T is the qualified type, which may be an ArrayType /// @@ -1628,15 +1715,16 @@ public: return dyn_cast_or_null(getAsArrayType(T)); } - /// getBaseElementType - Returns the innermost element type of an array type. + /// \brief Return the innermost element type of an array type. + /// /// For example, will return "int" for int[m][n] QualType getBaseElementType(const ArrayType *VAT) const; - /// getBaseElementType - Returns the innermost element type of a type - /// (which needn't actually be an array type). + /// \brief Return the innermost element type of a type (which needn't + /// actually be an array type). QualType getBaseElementType(QualType QT) const; - /// getConstantArrayElementCount - Returns number of constant array elements. + /// \brief Return number of constant array elements. uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; /// \brief Perform adjustment on the parameter type of a function. @@ -1651,21 +1739,22 @@ public: /// cv-qualifiers. QualType getSignatureParameterType(QualType T) const; - /// getArrayDecayedType - Return the properly qualified result of decaying the - /// specified array type to a pointer. This operation is non-trivial when - /// handling typedefs etc. The canonical type of "T" must be an array type, - /// this returns a pointer to a properly qualified element of the array. + /// \brief Return the properly qualified result of decaying the specified + /// array type to a pointer. + /// + /// This operation is non-trivial when handling typedefs etc. The canonical + /// type of \p T must be an array type, this returns a pointer to a properly + /// qualified element of the array. /// /// See C99 6.7.5.3p7 and C99 6.3.2.1p3. QualType getArrayDecayedType(QualType T) const; - /// getPromotedIntegerType - Returns the type that Promotable will - /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable - /// integer type. + /// \brief Return the type that \p PromotableType will promote to: C99 + /// 6.3.1.1p2, assuming that \p PromotableType is a promotable integer type. QualType getPromotedIntegerType(QualType PromotableType) const; - /// \brief Recurses in pointer/array types until it finds an objc retainable - /// type and returns its ownership. + /// \brief Recurses in pointer/array types until it finds an Objective-C + /// retainable type and returns its ownership. Qualifiers::ObjCLifetime getInnerObjCOwnership(QualType T) const; /// \brief Whether this is a promotable bitfield reference according @@ -1675,21 +1764,24 @@ public: /// promotion occurs. QualType isPromotableBitField(Expr *E) const; - /// getIntegerTypeOrder - Returns the highest ranked integer type: - /// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If - /// LHS < RHS, return -1. + /// \brief Return the highest ranked integer type, see C99 6.3.1.8p1. + /// + /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If + /// \p LHS < \p RHS, return -1. int getIntegerTypeOrder(QualType LHS, QualType RHS) const; - /// getFloatingTypeOrder - Compare the rank of the two specified floating - /// point types, ignoring the domain of the type (i.e. 'double' == - /// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If - /// LHS < RHS, return -1. + /// \brief Compare the rank of the two specified floating point types, + /// ignoring the domain of the type (i.e. 'double' == '_Complex double'). + /// + /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If + /// \p LHS < \p RHS, return -1. int getFloatingTypeOrder(QualType LHS, QualType RHS) const; - /// getFloatingTypeOfSizeWithinDomain - Returns a real floating - /// point or a complex type (based on typeDomain/typeSize). - /// 'typeDomain' is a real floating point or complex type. - /// 'typeSize' is a real floating point or complex type. + /// \brief Return a real floating point or a complex type (based on + /// \p typeDomain/\p typeSize). + /// + /// \param typeDomain a real floating point or complex type. + /// \param typeSize a real floating point or complex type. QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, QualType typeDomain) const; @@ -1787,7 +1879,7 @@ public: // Per C99 6.2.5p6, for every signed integer type, there is a corresponding // unsigned integer type. This method takes a signed type, and returns the // corresponding unsigned integer type. - QualType getCorrespondingUnsignedType(QualType T); + QualType getCorrespondingUnsignedType(QualType T) const; //===--------------------------------------------------------------------===// // Type Iterators. @@ -1805,8 +1897,8 @@ public: // Integer Values //===--------------------------------------------------------------------===// - /// MakeIntValue - Make an APSInt of the appropriate width and - /// signedness for the given \arg Value and integer \arg Type. + /// \brief Make an APSInt of the appropriate width and signedness for the + /// given \p Value and integer \p Type. llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const { llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerOrEnumerationType()); @@ -1816,12 +1908,14 @@ public: bool isSentinelNullExpr(const Expr *E); - /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists. + /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or NULL if + /// none exists. ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D); - /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. + /// \brief Get the implementation of the ObjCCategoryDecl \p D, or NULL if + /// none exists. ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); - /// \brief returns true if there is at least one \@implementation in TU. + /// \brief Return true if there is at least one \@implementation in the TU. bool AnyObjCImplementation() { return !ObjCImpls.empty(); } @@ -1834,7 +1928,7 @@ public: ObjCCategoryImplDecl *ImplD); /// \brief Get the duplicate declaration of a ObjCMethod in the same - /// interface, or null if non exists. + /// interface, or null if none exists. const ObjCMethodDecl *getObjCMethodRedeclaration( const ObjCMethodDecl *MD) const { return ObjCMethodRedecls.lookup(MD); @@ -1846,16 +1940,16 @@ public: ObjCMethodRedecls[MD] = Redecl; } - /// \brief Returns the objc interface that \arg ND belongs to if it is a - /// objc method/property/ivar etc. that is part of an interface, + /// \brief Returns the Objective-C interface that \p ND belongs to if it is + /// an Objective-C method/property/ivar etc. that is part of an interface, /// otherwise returns null. ObjCInterfaceDecl *getObjContainingInterface(NamedDecl *ND) const; /// \brief Set the copy inialization expression of a block var decl. void setBlockVarCopyInits(VarDecl*VD, Expr* Init); - /// \brief Get the copy initialization expression of VarDecl,or NULL if - /// none exists. - Expr *getBlockVarCopyInits(const VarDecl*VD); + /// \brief Get the copy initialization expression of the VarDecl \p VD, or + /// NULL if none exists. + Expr *getBlockVarCopyInits(const VarDecl* VD); /// \brief Allocate an uninitialized TypeSourceInfo. /// @@ -1882,9 +1976,9 @@ public: /// \brief Add a deallocation callback that will be invoked when the /// ASTContext is destroyed. /// - /// \brief Callback A callback function that will be invoked on destruction. + /// \param Callback A callback function that will be invoked on destruction. /// - /// \brief Data Pointer data that will be provided to the callback function + /// \param Data Pointer data that will be provided to the callback function /// when it is called. void AddDeallocation(void (*Callback)(void*), void *Data); @@ -1957,8 +2051,8 @@ public: static unsigned NumImplicitDestructorsDeclared; private: - ASTContext(const ASTContext&); // DO NOT IMPLEMENT - void operator=(const ASTContext&); // DO NOT IMPLEMENT + ASTContext(const ASTContext &) LLVM_DELETED_FUNCTION; + void operator=(const ASTContext &) LLVM_DELETED_FUNCTION; public: /// \brief Initialize built-in types. @@ -1974,7 +2068,7 @@ public: private: void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); - // Return the ObjC type encoding for a given type. + // Return the Objective-C type encoding for a given type. void getObjCEncodingForTypeImpl(QualType t, std::string &S, bool ExpandPointedToStructures, bool ExpandStructures, @@ -2017,13 +2111,13 @@ private: void ReleaseDeclContextMaps(); }; -/// @brief Utility function for constructing a nullary selector. +/// \brief Utility function for constructing a nullary selector. static inline Selector GetNullarySelector(StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(0, &II); } -/// @brief Utility function for constructing an unary selector. +/// \brief Utility function for constructing an unary selector. static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(1, &II); diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index cb038a0a5826..56d15260a581 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -13,6 +13,8 @@ #ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H #define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H +#include "clang/Basic/SourceLocation.h" + namespace clang { class Decl; class DeclContext; diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index b17bd48b7d03..12a9855617c0 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -107,9 +107,6 @@ public: // Pretty print this attribute. virtual void printPretty(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const = 0; - - // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *) { return true; } }; class InheritableAttr : public Attr { @@ -125,7 +122,6 @@ public: static bool classof(const Attr *A) { return A->getKind() <= attr::LAST_INHERITABLE; } - static bool classof(const InheritableAttr *) { return true; } }; class InheritableParamAttr : public InheritableAttr { @@ -139,7 +135,6 @@ public: static bool classof(const Attr *A) { return A->getKind() <= attr::LAST_INHERITABLE_PARAM; } - static bool classof(const InheritableParamAttr *) { return true; } }; #include "clang/AST/Attrs.inc" diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index 34e6fc5cd826..ba322fb32655 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -206,6 +206,8 @@ PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy) // unknown type, most notably explicit casts. PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy) +PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy) + // The type of a cast which, in ARC, would normally require a // __bridge, but which might be okay depending on the immediate // context. diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index d7458aa7900e..4c4c0fb0a08b 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -20,3 +20,15 @@ clang_tablegen(CommentNodes.inc -gen-clang-comment-nodes SOURCE ../Basic/CommentNodes.td TARGET ClangCommentNodes) +clang_tablegen(CommentHTMLTags.inc -gen-clang-comment-html-tags + SOURCE CommentHTMLTags.td + TARGET ClangCommentHTMLTags) + +clang_tablegen(CommentHTMLTagsProperties.inc -gen-clang-comment-html-tags-properties + SOURCE CommentHTMLTags.td + TARGET ClangCommentHTMLTagsProperties) + +clang_tablegen(CommentCommandInfo.inc -gen-clang-comment-command-info + SOURCE CommentCommands.td + TARGET ClangCommentCommandInfo) + diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index ee6eba78e415..87bdbe04f3df 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -19,7 +19,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include @@ -271,15 +271,14 @@ struct UniqueVirtualMethod { /// pair is the virtual method that overrides it (including the /// subobject in which that virtual function occurs). class OverridingMethods { - llvm::DenseMap > - Overrides; + typedef SmallVector ValuesT; + typedef llvm::MapVector MapType; + MapType Overrides; public: // Iterate over the set of subobjects that have overriding methods. - typedef llvm::DenseMap > - ::iterator iterator; - typedef llvm::DenseMap > - ::const_iterator const_iterator; + typedef MapType::iterator iterator; + typedef MapType::const_iterator const_iterator; iterator begin() { return Overrides.begin(); } const_iterator begin() const { return Overrides.begin(); } iterator end() { return Overrides.end(); } @@ -357,8 +356,8 @@ public: /// 0 represents the virtua base class subobject of that type, while /// subobject numbers greater than 0 refer to non-virtual base class /// subobjects of that type. -class CXXFinalOverriderMap - : public llvm::DenseMap { }; +class CXXFinalOverriderMap + : public llvm::MapVector { }; /// \brief A set of all the primary bases for a class. class CXXIndirectPrimaryBaseSet diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 6cce88868db8..ea307bf307cb 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -276,6 +276,7 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 5be35826a964..12e74b32be8a 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -164,8 +164,8 @@ namespace clang { QuantityType getQuantity() const { return Quantity; } /// RoundUpToAlignment - Returns the next integer (mod 2**64) that is - /// greater than or equal to this quantity and is a multiple of \arg - /// Align. Align must be non-zero. + /// greater than or equal to this quantity and is a multiple of \p Align. + /// Align must be non-zero. CharUnits RoundUpToAlignment(const CharUnits &Align) { return CharUnits(llvm::RoundUpToAlignment(Quantity, Align.Quantity)); diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index 01aaac3f77ad..316a1801bd46 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -16,6 +16,8 @@ #include "clang/Basic/SourceLocation.h" #include "clang/AST/Type.h" +#include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/DeclObjC.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -25,7 +27,7 @@ class ParmVarDecl; class TemplateParameterList; namespace comments { - +class FullComment; /// Any part of the comment. /// Abstract class. class Comment { @@ -74,8 +76,9 @@ protected: unsigned : NumInlineContentCommentBits; unsigned RenderKind : 2; + unsigned CommandID : 8; }; - enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 1 }; + enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 }; class HTMLStartTagCommentBitfields { friend class HTMLStartTagComment; @@ -101,10 +104,19 @@ protected: }; enum { NumParagraphCommentBits = NumCommentBits + 2 }; + class BlockCommandCommentBitfields { + friend class BlockCommandComment; + + unsigned : NumCommentBits; + + unsigned CommandID : 8; + }; + enum { NumBlockCommandCommentBits = NumCommentBits + 8 }; + class ParamCommandCommentBitfields { friend class ParamCommandComment; - unsigned : NumCommentBits; + unsigned : NumBlockCommandCommentBits; /// Parameter passing direction, see ParamCommandComment::PassDirection. unsigned Direction : 2; @@ -112,7 +124,7 @@ protected: /// True if direction was specified explicitly in the comment. unsigned IsDirectionExplicit : 1; }; - enum { NumParamCommandCommentBits = 11 }; + enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 }; union { CommentBitfields CommentBits; @@ -121,6 +133,7 @@ protected: InlineCommandCommentBitfields InlineCommandCommentBits; HTMLStartTagCommentBitfields HTMLStartTagCommentBits; ParagraphCommentBitfields ParagraphCommentBits; + BlockCommandCommentBitfields BlockCommandCommentBits; ParamCommandCommentBitfields ParamCommandCommentBits; }; @@ -158,10 +171,9 @@ public: const char *getCommentKindName() const; LLVM_ATTRIBUTE_USED void dump() const; - LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; - void dump(llvm::raw_ostream &OS, SourceManager *SM) const; - - static bool classof(const Comment *) { return true; } + LLVM_ATTRIBUTE_USED void dump(const ASTContext &Context) const; + void dump(llvm::raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) const; SourceRange getSourceRange() const LLVM_READONLY { return Range; } @@ -204,8 +216,6 @@ public: C->getCommentKind() <= LastInlineContentCommentConstant; } - static bool classof(const InlineContentComment *) { return true; } - void addTrailingNewline() { InlineContentCommentBits.HasTrailingNewline = 1; } @@ -232,8 +242,6 @@ public: return C->getCommentKind() == TextCommentKind; } - static bool classof(const TextComment *) { return true; } - child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } @@ -273,35 +281,35 @@ public: }; protected: - /// Command name. - StringRef Name; - /// Command arguments. llvm::ArrayRef Args; public: InlineCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name, + unsigned CommandID, RenderKind RK, llvm::ArrayRef Args) : InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), - Name(Name), Args(Args) { + Args(Args) { InlineCommandCommentBits.RenderKind = RK; + InlineCommandCommentBits.CommandID = CommandID; } static bool classof(const Comment *C) { return C->getCommentKind() == InlineCommandCommentKind; } - static bool classof(const InlineCommandComment *) { return true; } - child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } - StringRef getCommandName() const { - return Name; + unsigned getCommandID() const { + return InlineCommandCommentBits.CommandID; + } + + StringRef getCommandName(const CommandTraits &Traits) const { + return Traits.getCommandInfo(getCommandID())->Name; } SourceRange getCommandNameRange() const { @@ -352,8 +360,6 @@ public: C->getCommentKind() <= LastHTMLTagCommentConstant; } - static bool classof(const HTMLTagComment *) { return true; } - StringRef getTagName() const LLVM_READONLY { return TagName; } SourceRange getTagNameSourceRange() const LLVM_READONLY { @@ -419,8 +425,6 @@ public: return C->getCommentKind() == HTMLStartTagCommentKind; } - static bool classof(const HTMLStartTagComment *) { return true; } - child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } @@ -476,8 +480,6 @@ public: return C->getCommentKind() == HTMLEndTagCommentKind; } - static bool classof(const HTMLEndTagComment *) { return true; } - child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } @@ -498,8 +500,6 @@ public: return C->getCommentKind() >= FirstBlockContentCommentConstant && C->getCommentKind() <= LastBlockContentCommentConstant; } - - static bool classof(const BlockContentComment *) { return true; } }; /// A single paragraph that contains inline content. @@ -529,8 +529,6 @@ public: return C->getCommentKind() == ParagraphCommentKind; } - static bool classof(const ParagraphComment *) { return true; } - child_iterator child_begin() const { return reinterpret_cast(Content.begin()); } @@ -566,9 +564,6 @@ public: }; protected: - /// Command name. - StringRef Name; - /// Word-like arguments. llvm::ArrayRef Args; @@ -578,21 +573,21 @@ protected: BlockCommandComment(CommentKind K, SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : + unsigned CommandID) : BlockContentComment(K, LocBegin, LocEnd), - Name(Name), Paragraph(NULL) { - setLocation(getCommandNameRange().getBegin()); + setLocation(getCommandNameBeginLoc()); + BlockCommandCommentBits.CommandID = CommandID; } public: BlockCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : + unsigned CommandID) : BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), - Name(Name), Paragraph(NULL) { - setLocation(getCommandNameRange().getBegin()); + setLocation(getCommandNameBeginLoc()); + BlockCommandCommentBits.CommandID = CommandID; } static bool classof(const Comment *C) { @@ -600,8 +595,6 @@ public: C->getCommentKind() <= LastBlockCommandCommentConstant; } - static bool classof(const BlockCommandComment *) { return true; } - child_iterator child_begin() const { return reinterpret_cast(&Paragraph); } @@ -610,12 +603,21 @@ public: return reinterpret_cast(&Paragraph + 1); } - StringRef getCommandName() const { - return Name; + unsigned getCommandID() const { + return BlockCommandCommentBits.CommandID; } - SourceRange getCommandNameRange() const { - return SourceRange(getLocStart().getLocWithOffset(1), + StringRef getCommandName(const CommandTraits &Traits) const { + return Traits.getCommandInfo(getCommandID())->Name; + } + + SourceLocation getCommandNameBeginLoc() const { + return getLocStart().getLocWithOffset(1); + } + + SourceRange getCommandNameRange(const CommandTraits &Traits) const { + StringRef Name = getCommandName(Traits); + return SourceRange(getCommandNameBeginLoc(), getLocStart().getLocWithOffset(1 + Name.size())); } @@ -667,8 +669,9 @@ public: ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : - BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name), + unsigned CommandID) : + BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, + CommandID), ParamIndex(InvalidParamIndex) { ParamCommandCommentBits.Direction = In; ParamCommandCommentBits.IsDirectionExplicit = false; @@ -678,8 +681,6 @@ public: return C->getCommentKind() == ParamCommandCommentKind; } - static bool classof(const ParamCommandComment *) { return true; } - enum PassDirection { In, Out, @@ -705,7 +706,9 @@ public: return getNumArgs() > 0; } - StringRef getParamName() const { + StringRef getParamName(const FullComment *FC) const; + + StringRef getParamNameAsWritten() const { return Args[0].Text; } @@ -748,21 +751,21 @@ private: public: TParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : - BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, Name) + unsigned CommandID) : + BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID) { } static bool classof(const Comment *C) { return C->getCommentKind() == TParamCommandCommentKind; } - static bool classof(const TParamCommandComment *) { return true; } - bool hasParamName() const { return getNumArgs() > 0; } - StringRef getParamName() const { + StringRef getParamName(const FullComment *FC) const; + + StringRef getParamNameAsWritten() const { return Args[0].Text; } @@ -807,8 +810,6 @@ public: return C->getCommentKind() == VerbatimBlockLineCommentKind; } - static bool classof(const VerbatimBlockLineComment *) { return true; } - child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } @@ -830,17 +831,15 @@ protected: public: VerbatimBlockComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name) : + unsigned CommandID) : BlockCommandComment(VerbatimBlockCommentKind, - LocBegin, LocEnd, Name) + LocBegin, LocEnd, CommandID) { } static bool classof(const Comment *C) { return C->getCommentKind() == VerbatimBlockCommentKind; } - static bool classof(const VerbatimBlockComment *) { return true; } - child_iterator child_begin() const { return reinterpret_cast(Lines.begin()); } @@ -882,12 +881,12 @@ protected: public: VerbatimLineComment(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name, + unsigned CommandID, SourceLocation TextBegin, StringRef Text) : BlockCommandComment(VerbatimLineCommentKind, LocBegin, LocEnd, - Name), + CommandID), Text(Text), TextBegin(TextBegin) { } @@ -896,8 +895,6 @@ public: return C->getCommentKind() == VerbatimLineCommentKind; } - static bool classof(const VerbatimLineComment *) { return true; } - child_iterator child_begin() const { return NULL; } child_iterator child_end() const { return NULL; } @@ -913,23 +910,34 @@ public: /// Information about the declaration, useful to clients of FullComment. struct DeclInfo { - /// Declaration the comment is attached to. Should not be NULL. - const Decl *ThisDecl; - - /// Parameters that can be referenced by \\param if \c ThisDecl is something + /// Declaration the comment is actually attached to (in the source). + /// Should not be NULL. + const Decl *CommentDecl; + + /// CurrentDecl is the declaration with which the FullComment is associated. + /// + /// It can be different from \c CommentDecl. It happens when we we decide + /// that the comment originally attached to \c CommentDecl is fine for + /// \c CurrentDecl too (for example, for a redeclaration or an overrider of + /// \c CommentDecl). + /// + /// The information in the DeclInfo corresponds to CurrentDecl. + const Decl *CurrentDecl; + + /// Parameters that can be referenced by \\param if \c CommentDecl is something /// that we consider a "function". ArrayRef ParamVars; - /// Function result type if \c ThisDecl is something that we consider + /// Function result type if \c CommentDecl is something that we consider /// a "function". QualType ResultType; - /// Template parameters that can be referenced by \\tparam if \c ThisDecl is + /// Template parameters that can be referenced by \\tparam if \c CommentDecl is /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is /// true). const TemplateParameterList *TemplateParameters; - /// A simplified description of \c ThisDecl kind that should be good enough + /// A simplified description of \c CommentDecl kind that should be good enough /// for documentation rendering purposes. enum DeclKind { /// Everything else not explicitly mentioned below. @@ -942,7 +950,9 @@ struct DeclInfo { /// \li member function, /// \li member function template, /// \li member function template specialization, - /// \li ObjC method. + /// \li ObjC method, + /// \li a typedef for a function pointer, member function pointer, + /// ObjC block. FunctionKind, /// Something that we consider a "class": @@ -968,7 +978,7 @@ struct DeclInfo { EnumKind }; - /// What kind of template specialization \c ThisDecl is. + /// What kind of template specialization \c CommentDecl is. enum TemplateDeclKind { NotTemplate, Template, @@ -976,24 +986,24 @@ struct DeclInfo { TemplatePartialSpecialization }; - /// If false, only \c ThisDecl is valid. + /// If false, only \c CommentDecl is valid. unsigned IsFilled : 1; - /// Simplified kind of \c ThisDecl, see\c DeclKind enum. + /// Simplified kind of \c CommentDecl, see \c DeclKind enum. unsigned Kind : 3; - /// Is \c ThisDecl a template declaration. + /// Is \c CommentDecl a template declaration. unsigned TemplateKind : 2; - /// Is \c ThisDecl an ObjCMethodDecl. + /// Is \c CommentDecl an ObjCMethodDecl. unsigned IsObjCMethod : 1; - /// Is \c ThisDecl a non-static member function of C++ class or + /// Is \c CommentDecl a non-static member function of C++ class or /// instance method of ObjC class. /// Can be true only if \c IsFunctionDecl is true. unsigned IsInstanceMethod : 1; - /// Is \c ThisDecl a static member function of C++ class or + /// Is \c CommentDecl a static member function of C++ class or /// class method of ObjC class. /// Can be true only if \c IsFunctionDecl is true. unsigned IsClassMethod : 1; @@ -1012,7 +1022,6 @@ struct DeclInfo { /// A full comment attached to a declaration, contains block content. class FullComment : public Comment { llvm::ArrayRef Blocks; - DeclInfo *ThisDeclInfo; public: @@ -1031,27 +1040,31 @@ public: return C->getCommentKind() == FullCommentKind; } - static bool classof(const FullComment *) { return true; } - child_iterator child_begin() const { return reinterpret_cast(Blocks.begin()); } child_iterator child_end() const { - return reinterpret_cast(Blocks.end()); + return reinterpret_cast(Blocks.end()); } const Decl *getDecl() const LLVM_READONLY { - return ThisDeclInfo->ThisDecl; + return ThisDeclInfo->CommentDecl; } - + const DeclInfo *getDeclInfo() const LLVM_READONLY { if (!ThisDeclInfo->IsFilled) ThisDeclInfo->fill(); return ThisDeclInfo; } + + DeclInfo *getThisDeclInfo() const LLVM_READONLY { + return ThisDeclInfo; + } + + llvm::ArrayRef getBlocks() const { return Blocks; } + }; - } // end namespace comments } // end namespace clang diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h index 003c33727e35..5d508860635d 100644 --- a/include/clang/AST/CommentBriefParser.h +++ b/include/clang/AST/CommentBriefParser.h @@ -44,8 +44,7 @@ class BriefParser { public: BriefParser(Lexer &L, const CommandTraits &Traits); - /// Return \\brief paragraph, if it exists; otherwise return the first - /// paragraph. + /// Return the best "brief description" we can find. std::string Parse(); }; diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index 5f0269a4650b..6d44c706c3dc 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -19,136 +19,132 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" namespace clang { namespace comments { -/// This class provides informaiton about commands that can be used -/// in comments. -class CommandTraits { -public: - CommandTraits() { } +/// \brief Information about a single command. +/// +/// When reordering, adding or removing members please update the corresponding +/// TableGen backend. +struct CommandInfo { + unsigned getID() const { + return ID; + } + + const char *Name; + + /// Name of the command that ends the verbatim block. + const char *EndCommandName; + + unsigned ID : 8; + + /// Number of word-like arguments for a given block command, except for + /// \\param and \\tparam commands -- these have special argument parsers. + unsigned NumArgs : 4; - /// \brief Check if a given command is a verbatim-like block command. + /// True if this command is a inline command (of any kind). + unsigned IsInlineCommand : 1; + + /// True if this command is a block command (of any kind). + unsigned IsBlockCommand : 1; + + /// True if this command is introducing a brief documentation + /// paragraph (\\brief or an alias). + unsigned IsBriefCommand : 1; + + /// True if this command is \\returns or an alias. + unsigned IsReturnsCommand : 1; + + /// True if this command is introducing documentation for a function + /// parameter (\\param or an alias). + unsigned IsParamCommand : 1; + + /// True if this command is introducing documentation for + /// a template parameter (\\tparam or an alias). + unsigned IsTParamCommand : 1; + + /// True if this command is \\deprecated or an alias. + unsigned IsDeprecatedCommand : 1; + + /// True if we don't want to warn about this command being passed an empty + /// paragraph. Meaningful only for block commands. + unsigned IsEmptyParagraphAllowed : 1; + + /// \brief True if this command is a verbatim-like block command. /// /// A verbatim-like block command eats every character (except line starting /// decorations) until matching end command is seen or comment end is hit. - /// - /// \param StartName name of the command that starts the verbatim block. - /// \param [out] EndName name of the command that ends the verbatim block. - /// - /// \returns true if a given command is a verbatim block command. - bool isVerbatimBlockCommand(StringRef StartName, StringRef &EndName) const; + unsigned IsVerbatimBlockCommand : 1; - /// \brief Register a new verbatim block command. - void addVerbatimBlockCommand(StringRef StartName, StringRef EndName); + /// \brief True if this command is an end command for a verbatim-like block. + unsigned IsVerbatimBlockEndCommand : 1; - /// \brief Check if a given command is a verbatim line command. + /// \brief True if this command is a verbatim line command. /// /// A verbatim-like line command eats everything until a newline is seen or /// comment end is hit. - bool isVerbatimLineCommand(StringRef Name) const; + unsigned IsVerbatimLineCommand : 1; - /// \brief Check if a given command is a command that contains a declaration - /// for the entity being documented. + /// \brief True if this command contains a declaration for the entity being + /// documented. /// /// For example: /// \code /// \fn void f(int a); /// \endcode - bool isDeclarationCommand(StringRef Name) const; + unsigned IsDeclarationCommand : 1; - /// \brief Register a new verbatim line command. - void addVerbatimLineCommand(StringRef Name); + /// \brief True if this command is unknown. This \c CommandInfo object was + /// created during parsing. + unsigned IsUnknownCommand : 1; +}; - /// \brief Check if a given command is a block command (of any kind). - bool isBlockCommand(StringRef Name) const; +/// This class provides information about commands that can be used +/// in comments. +class CommandTraits { +public: + CommandTraits(llvm::BumpPtrAllocator &Allocator); - /// \brief Check if a given command is introducing documentation for - /// a function parameter (\\param or an alias). - bool isParamCommand(StringRef Name) const; + /// \returns a CommandInfo object for a given command name or + /// NULL if no CommandInfo object exists for this command. + const CommandInfo *getCommandInfoOrNULL(StringRef Name) const; - /// \brief Check if a given command is introducing documentation for - /// a template parameter (\\tparam or an alias). - bool isTParamCommand(StringRef Name) const; + const CommandInfo *getCommandInfo(StringRef Name) const { + if (const CommandInfo *Info = getCommandInfoOrNULL(Name)) + return Info; + llvm_unreachable("the command should be known"); + } - /// \brief Check if a given command is introducing a brief documentation - /// paragraph (\\brief or an alias). - bool isBriefCommand(StringRef Name) const; + const CommandInfo *getCommandInfo(unsigned CommandID) const; - /// \brief Check if a given command is \\brief or an alias. - bool isReturnsCommand(StringRef Name) const; + const CommandInfo *registerUnknownCommand(StringRef CommandName); - /// \returns the number of word-like arguments for a given block command, - /// except for \\param and \\tparam commands -- these have special argument - /// parsers. - unsigned getBlockCommandNumArgs(StringRef Name) const; + /// \returns a CommandInfo object for a given command name or + /// NULL if \c Name is not a builtin command. + static const CommandInfo *getBuiltinCommandInfo(StringRef Name); - /// \brief Check if a given command is a inline command (of any kind). - bool isInlineCommand(StringRef Name) const; + /// \returns a CommandInfo object for a given command ID or + /// NULL if \c CommandID is not a builtin command. + static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID); private: - struct VerbatimBlockCommand { - StringRef StartName; - StringRef EndName; - }; - - typedef SmallVector VerbatimBlockCommandVector; + CommandTraits(const CommandTraits &) LLVM_DELETED_FUNCTION; + void operator=(const CommandTraits &) LLVM_DELETED_FUNCTION; - /// Registered additional verbatim-like block commands. - VerbatimBlockCommandVector VerbatimBlockCommands; + const CommandInfo *getRegisteredCommandInfo(StringRef Name) const; + const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const; - struct VerbatimLineCommand { - StringRef Name; - }; + unsigned NextID; - typedef SmallVector VerbatimLineCommandVector; + /// Allocator for CommandInfo objects. + llvm::BumpPtrAllocator &Allocator; - /// Registered verbatim-like line commands. - VerbatimLineCommandVector VerbatimLineCommands; + SmallVector RegisteredCommands; }; -inline bool CommandTraits::isBlockCommand(StringRef Name) const { - return isBriefCommand(Name) || isReturnsCommand(Name) || - isParamCommand(Name) || isTParamCommand(Name) || - llvm::StringSwitch(Name) - .Case("author", true) - .Case("authors", true) - .Case("pre", true) - .Case("post", true) - .Default(false); -} - -inline bool CommandTraits::isParamCommand(StringRef Name) const { - return Name == "param"; -} - -inline bool CommandTraits::isTParamCommand(StringRef Name) const { - return Name == "tparam" || // Doxygen - Name == "templatefield"; // HeaderDoc -} - -inline bool CommandTraits::isBriefCommand(StringRef Name) const { - return Name == "brief" || Name == "short"; -} - -inline bool CommandTraits::isReturnsCommand(StringRef Name) const { - return Name == "returns" || Name == "return" || Name == "result"; -} - -inline unsigned CommandTraits::getBlockCommandNumArgs(StringRef Name) const { - return 0; -} - -inline bool CommandTraits::isInlineCommand(StringRef Name) const { - return llvm::StringSwitch(Name) - .Case("b", true) - .Cases("c", "p", true) - .Cases("a", "e", "em", true) - .Default(false); -} - } // end namespace comments } // end namespace clang diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td new file mode 100644 index 000000000000..3d8bad89c26b --- /dev/null +++ b/include/clang/AST/CommentCommands.td @@ -0,0 +1,156 @@ +class Command { + string Name = name; + string EndCommandName = ""; + + int NumArgs = 0; + + bit IsInlineCommand = 0; + + bit IsBlockCommand = 0; + bit IsBriefCommand = 0; + bit IsReturnsCommand = 0; + bit IsParamCommand = 0; + bit IsTParamCommand = 0; + bit IsDeprecatedCommand = 0; + + bit IsEmptyParagraphAllowed = 0; + + bit IsVerbatimBlockCommand = 0; + bit IsVerbatimBlockEndCommand = 0; + bit IsVerbatimLineCommand = 0; + bit IsDeclarationCommand = 0; +} + +class InlineCommand : Command { + let IsInlineCommand = 1; +} + +class BlockCommand : Command { + let IsBlockCommand = 1; +} + +class VerbatimBlockCommand : Command { + let EndCommandName = name; + let IsVerbatimBlockCommand = 1; +} + +multiclass VerbatimBlockCommand { + def Begin : Command { + let EndCommandName = endCommandName; + let IsVerbatimBlockCommand = 1; + } + + def End : Command { + let IsVerbatimBlockEndCommand = 1; + } +} + +class VerbatimLineCommand : Command { + let IsVerbatimLineCommand = 1; +} + +class DeclarationVerbatimLineCommand : + VerbatimLineCommand { + let IsDeclarationCommand = 1; +} + +def B : InlineCommand<"b">; +def C : InlineCommand<"c">; +def P : InlineCommand<"p">; +def A : InlineCommand<"a">; +def E : InlineCommand<"e">; +def Em : InlineCommand<"em">; + +def Brief : BlockCommand<"brief"> { let IsBriefCommand = 1; } +def Short : BlockCommand<"short"> { let IsBriefCommand = 1; } + +def Returns : BlockCommand<"returns"> { let IsReturnsCommand = 1; } +def Return : BlockCommand<"return"> { let IsReturnsCommand = 1; } +def Result : BlockCommand<"result"> { let IsReturnsCommand = 1; } + +def Param : BlockCommand<"param"> { let IsParamCommand = 1; } + +// Doxygen +def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; } + +// HeaderDoc +def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; } + +def Deprecated : BlockCommand<"deprecated"> { + let IsEmptyParagraphAllowed = 1; + let IsDeprecatedCommand = 1; +} + +def Author : BlockCommand<"author">; +def Authors : BlockCommand<"authors">; +def Bug : BlockCommand<"bug">; +def Copyright : BlockCommand<"copyright">; +def Date : BlockCommand<"date">; +def Details : BlockCommand<"details">; +def Invariant : BlockCommand<"invariant">; +def Note : BlockCommand<"note">; +def Post : BlockCommand<"post">; +def Pre : BlockCommand<"pre">; +def Remark : BlockCommand<"remark">; +def Remarks : BlockCommand<"remarks">; +def Sa : BlockCommand<"sa">; +def See : BlockCommand<"see">; +def Since : BlockCommand<"since">; +def Todo : BlockCommand<"todo">; +def Version : BlockCommand<"version">; +def Warning : BlockCommand<"warning">; + +defm Code : VerbatimBlockCommand<"code", "endcode">; +defm Verbatim : VerbatimBlockCommand<"verbatim", "endverbatim">; +defm Htmlonly : VerbatimBlockCommand<"htmlonly", "endhtmlonly">; +defm Latexonly : VerbatimBlockCommand<"latexonly", "endlatexonly">; +defm Xmlonly : VerbatimBlockCommand<"xmlonly", "endxmlonly">; +defm Manonly : VerbatimBlockCommand<"manonly", "endmanonly">; +defm Rtfonly : VerbatimBlockCommand<"rtfonly", "endrtfonly">; + +defm Dot : VerbatimBlockCommand<"dot", "enddot">; +defm Msc : VerbatimBlockCommand<"msc", "endmsc">; + +// These commands have special support in lexer. +def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula +defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula +defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment + +def Defgroup : VerbatimLineCommand<"defgroup">; +def Ingroup : VerbatimLineCommand<"ingroup">; +def Addtogroup : VerbatimLineCommand<"addtogroup">; +def Weakgroup : VerbatimLineCommand<"weakgroup">; +def Name : VerbatimLineCommand<"name">; + +def Section : VerbatimLineCommand<"section">; +def Subsection : VerbatimLineCommand<"subsection">; +def Subsubsection : VerbatimLineCommand<"subsubsection">; +def Paragraph : VerbatimLineCommand<"paragraph">; + +def Mainpage : VerbatimLineCommand<"mainpage">; +def Subpage : VerbatimLineCommand<"subpage">; +def Ref : VerbatimLineCommand<"ref">; + +// Doxygen commands. +def Fn : DeclarationVerbatimLineCommand<"fn">; +def Namespace : DeclarationVerbatimLineCommand<"namespace">; +def Overload : DeclarationVerbatimLineCommand<"overload">; +def Property : DeclarationVerbatimLineCommand<"property">; +def Typedef : DeclarationVerbatimLineCommand<"typedef">; +def Var : DeclarationVerbatimLineCommand<"var">; + +// HeaderDoc commands. +def Class : DeclarationVerbatimLineCommand<"class">; +def Interface : DeclarationVerbatimLineCommand<"interface">; +def Protocol : DeclarationVerbatimLineCommand<"protocol">; +def Category : DeclarationVerbatimLineCommand<"category">; +def Template : DeclarationVerbatimLineCommand<"template">; +def Function : DeclarationVerbatimLineCommand<"function">; +def Method : DeclarationVerbatimLineCommand<"method">; +def Callback : DeclarationVerbatimLineCommand<"callback">; +def Const : DeclarationVerbatimLineCommand<"const">; +def Constant : DeclarationVerbatimLineCommand<"constant">; +def Struct : DeclarationVerbatimLineCommand<"struct">; +def Union : DeclarationVerbatimLineCommand<"union">; +def Enum : DeclarationVerbatimLineCommand<"enum">; + diff --git a/include/clang/AST/CommentHTMLTags.td b/include/clang/AST/CommentHTMLTags.td new file mode 100644 index 000000000000..f98e32ddca4f --- /dev/null +++ b/include/clang/AST/CommentHTMLTags.td @@ -0,0 +1,54 @@ +class Tag { + string Spelling = spelling; + bit EndTagOptional = 0; + bit EndTagForbidden = 0; +} + +def Em : Tag<"em">; +def Strong : Tag<"strong">; +def Tt : Tag<"tt">; +def I : Tag<"i">; +def B : Tag<"b">; +def Big : Tag<"big">; +def Small : Tag<"small">; +def Strike : Tag<"strike">; +def S : Tag<"s">; +def U : Tag<"u">; +def Font : Tag<"font">; +def A : Tag<"a">; +def Hr : Tag<"hr"> { let EndTagForbidden = 1; } +def Div : Tag<"div">; +def Span : Tag<"span">; +def H1 : Tag<"h1">; +def H2 : Tag<"h2">; +def H3 : Tag<"h3">; +def H4 : Tag<"h4">; +def H5 : Tag<"h5">; +def H6 : Tag<"h6">; +def Code : Tag<"code">; +def Blockquote : Tag<"blockquote">; +def Sub : Tag<"sub">; +def Sup : Tag<"sup">; +def Img : Tag<"img"> { let EndTagForbidden = 1; } +def P : Tag<"p"> { let EndTagOptional = 1; } +def Br : Tag<"br"> { let EndTagForbidden = 1; } +def Pre : Tag<"pre">; +def Ins : Tag<"ins">; +def Del : Tag<"del">; +def Ul : Tag<"ul">; +def Ol : Tag<"ol">; +def Li : Tag<"li"> { let EndTagOptional = 1; } +def Dl : Tag<"dl">; +def Dt : Tag<"dt"> { let EndTagOptional = 1; } +def Dd : Tag<"dd"> { let EndTagOptional = 1; } +def Table : Tag<"table">; +def Caption : Tag<"caption">; +def Thead : Tag<"thead"> { let EndTagOptional = 1; } +def Tfoot : Tag<"tfoot"> { let EndTagOptional = 1; } +def Tbody : Tag<"tbody"> { let EndTagOptional = 1; } +def Colgroup : Tag<"colgroup"> { let EndTagOptional = 1; } +def Col : Tag<"col"> { let EndTagForbidden = 1; } +def Tr : Tag<"tr"> { let EndTagOptional = 1; } +def Th : Tag<"th"> { let EndTagOptional = 1; } +def Td : Tag<"td"> { let EndTagOptional = 1; } + diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index 7a24b1163178..f2636973ff27 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -26,6 +26,7 @@ namespace comments { class Lexer; class TextTokenRetokenizer; +struct CommandInfo; class CommandTraits; namespace tok { @@ -33,7 +34,8 @@ enum TokenKind { eof, newline, text, - command, + unknown_command, // Command that does not have an ID. + command, // Command with an ID. verbatim_block_begin, verbatim_block_line, verbatim_block_end, @@ -49,11 +51,6 @@ enum TokenKind { }; } // end namespace tok -class CommentOptions { -public: - bool Markdown; -}; - /// \brief Comment token. class Token { friend class Lexer; @@ -70,8 +67,14 @@ class Token { unsigned Length; /// Contains text value associated with a token. - const char *TextPtr1; - unsigned TextLen1; + const char *TextPtr; + + /// Integer value associated with a token. + /// + /// If the token is a konwn command, contains command ID and TextPtr is + /// unused (command spelling can be found with CommandTraits). Otherwise, + /// contains the length of the string that starts at TextPtr. + unsigned IntVal; public: SourceLocation getLocation() const LLVM_READONLY { return Loc; } @@ -94,113 +97,120 @@ public: StringRef getText() const LLVM_READONLY { assert(is(tok::text)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setText(StringRef Text) { assert(is(tok::text)); - TextPtr1 = Text.data(); - TextLen1 = Text.size(); + TextPtr = Text.data(); + IntVal = Text.size(); + } + + StringRef getUnknownCommandName() const LLVM_READONLY { + assert(is(tok::unknown_command)); + return StringRef(TextPtr, IntVal); + } + + void setUnknownCommandName(StringRef Name) { + assert(is(tok::unknown_command)); + TextPtr = Name.data(); + IntVal = Name.size(); } - StringRef getCommandName() const LLVM_READONLY { + unsigned getCommandID() const LLVM_READONLY { assert(is(tok::command)); - return StringRef(TextPtr1, TextLen1); + return IntVal; } - void setCommandName(StringRef Name) { + void setCommandID(unsigned ID) { assert(is(tok::command)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + IntVal = ID; } - StringRef getVerbatimBlockName() const LLVM_READONLY { + unsigned getVerbatimBlockID() const LLVM_READONLY { assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); - return StringRef(TextPtr1, TextLen1); + return IntVal; } - void setVerbatimBlockName(StringRef Name) { + void setVerbatimBlockID(unsigned ID) { assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + IntVal = ID; } StringRef getVerbatimBlockText() const LLVM_READONLY { assert(is(tok::verbatim_block_line)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setVerbatimBlockText(StringRef Text) { assert(is(tok::verbatim_block_line)); - TextPtr1 = Text.data(); - TextLen1 = Text.size(); + TextPtr = Text.data(); + IntVal = Text.size(); } - /// Returns the name of verbatim line command. - StringRef getVerbatimLineName() const LLVM_READONLY { + unsigned getVerbatimLineID() const LLVM_READONLY { assert(is(tok::verbatim_line_name)); - return StringRef(TextPtr1, TextLen1); + return IntVal; } - void setVerbatimLineName(StringRef Name) { + void setVerbatimLineID(unsigned ID) { assert(is(tok::verbatim_line_name)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + IntVal = ID; } StringRef getVerbatimLineText() const LLVM_READONLY { assert(is(tok::verbatim_line_text)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setVerbatimLineText(StringRef Text) { assert(is(tok::verbatim_line_text)); - TextPtr1 = Text.data(); - TextLen1 = Text.size(); + TextPtr = Text.data(); + IntVal = Text.size(); } StringRef getHTMLTagStartName() const LLVM_READONLY { assert(is(tok::html_start_tag)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLTagStartName(StringRef Name) { assert(is(tok::html_start_tag)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + TextPtr = Name.data(); + IntVal = Name.size(); } StringRef getHTMLIdent() const LLVM_READONLY { assert(is(tok::html_ident)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLIdent(StringRef Name) { assert(is(tok::html_ident)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + TextPtr = Name.data(); + IntVal = Name.size(); } StringRef getHTMLQuotedString() const LLVM_READONLY { assert(is(tok::html_quoted_string)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLQuotedString(StringRef Str) { assert(is(tok::html_quoted_string)); - TextPtr1 = Str.data(); - TextLen1 = Str.size(); + TextPtr = Str.data(); + IntVal = Str.size(); } StringRef getHTMLTagEndName() const LLVM_READONLY { assert(is(tok::html_end_tag)); - return StringRef(TextPtr1, TextLen1); + return StringRef(TextPtr, IntVal); } void setHTMLTagEndName(StringRef Name) { assert(is(tok::html_end_tag)); - TextPtr1 = Name.data(); - TextLen1 = Name.size(); + TextPtr = Name.data(); + IntVal = Name.size(); } void dump(const Lexer &L, const SourceManager &SM) const; @@ -209,8 +219,8 @@ public: /// \brief Comment lexer. class Lexer { private: - Lexer(const Lexer&); // DO NOT IMPLEMENT - void operator=(const Lexer&); // DO NOT IMPLEMENT + Lexer(const Lexer &) LLVM_DELETED_FUNCTION; + void operator=(const Lexer &) LLVM_DELETED_FUNCTION; /// Allocator for strings that are semantic values of tokens and have to be /// computed (for example, resolved decimal character references). @@ -221,7 +231,6 @@ private: const char *const BufferStart; const char *const BufferEnd; SourceLocation FileLoc; - CommentOptions CommOpts; const char *BufferPtr; @@ -286,8 +295,8 @@ private: Result.setKind(Kind); Result.setLength(TokLen); #ifndef NDEBUG - Result.TextPtr1 = ""; - Result.TextLen1 = 7; + Result.TextPtr = ""; + Result.IntVal = 7; #endif BufferPtr = TokEnd; } @@ -314,13 +323,14 @@ private: void setupAndLexVerbatimBlock(Token &T, const char *TextBegin, - char Marker, StringRef EndName); + char Marker, const CommandInfo *Info); void lexVerbatimBlockFirstLine(Token &T); void lexVerbatimBlockBody(Token &T); - void setupAndLexVerbatimLine(Token &T, const char *TextBegin); + void setupAndLexVerbatimLine(Token &T, const char *TextBegin, + const CommandInfo *Info); void lexVerbatimLineText(Token &T); @@ -336,7 +346,7 @@ private: public: Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits, - SourceLocation FileLoc, const CommentOptions &CommOpts, + SourceLocation FileLoc, const char *BufferStart, const char *BufferEnd); void lex(Token &T); diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h index 039079931c58..19e1d57fc3f5 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -28,8 +28,8 @@ class CommandTraits; /// Doxygen comment parser. class Parser { - Parser(const Parser&); // DO NOT IMPLEMENT - void operator=(const Parser&); // DO NOT IMPLEMENT + Parser(const Parser &) LLVM_DELETED_FUNCTION; + void operator=(const Parser &) LLVM_DELETED_FUNCTION; friend class TextTokenRetokenizer; diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index e1756ca3e2f1..0340b3cfd52d 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -25,13 +25,14 @@ namespace clang { class Decl; class SourceMgr; +class Preprocessor; namespace comments { class CommandTraits; class Sema { - Sema(const Sema&); // DO NOT IMPLEMENT - void operator=(const Sema&); // DO NOT IMPLEMENT + Sema(const Sema &) LLVM_DELETED_FUNCTION; + void operator=(const Sema &) LLVM_DELETED_FUNCTION; /// Allocator for AST nodes. llvm::BumpPtrAllocator &Allocator; @@ -41,18 +42,13 @@ class Sema { DiagnosticsEngine &Diags; - const CommandTraits &Traits; + CommandTraits &Traits; + + const Preprocessor *PP; /// Information about the declaration this comment is attached to. DeclInfo *ThisDeclInfo; - /// Comment AST nodes that correspond to \c ParamVars for which we have - /// found a \\param command or NULL if no documentation was found so far. - /// - /// Has correct size and contains valid values if \c DeclInfo->IsFilled is - /// true. - llvm::SmallVector ParamVarDocs; - /// Comment AST nodes that correspond to parameter names in /// \c TemplateParameters. /// @@ -75,7 +71,8 @@ class Sema { public: Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, - DiagnosticsEngine &Diags, const CommandTraits &Traits); + DiagnosticsEngine &Diags, CommandTraits &Traits, + const Preprocessor *PP); void setDecl(const Decl *D); @@ -96,7 +93,7 @@ public: BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name); + unsigned CommandID); void actOnBlockCommandArgs(BlockCommandComment *Command, ArrayRef Args); @@ -106,7 +103,7 @@ public: ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name); + unsigned CommandID); void actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, @@ -123,7 +120,7 @@ public: TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name); + unsigned CommandID); void actOnTParamCommandParamNameArg(TParamCommandComment *Command, SourceLocation ArgLocBegin, @@ -135,25 +132,29 @@ public: InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, - StringRef CommandName); + unsigned CommandID); InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, - StringRef CommandName, + unsigned CommandID, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg); InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin, SourceLocation LocEnd, - StringRef Name); + StringRef CommandName); + + InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin, + SourceLocation LocEnd, + unsigned CommandID); TextComment *actOnText(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Text); VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc, - StringRef Name); + unsigned CommandID); VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc, StringRef Text); @@ -164,7 +165,7 @@ public: ArrayRef Lines); VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin, - StringRef Name, + unsigned CommandID, SourceLocation TextBegin, StringRef Text); @@ -190,6 +191,12 @@ public: /// used only once per comment, e.g., \\brief and \\returns. void checkBlockCommandDuplicate(const BlockCommandComment *Command); + void checkDeprecatedCommand(const BlockCommandComment *Comment); + + /// Resolve parameter names to parameter indexes in function declaration. + /// Emit diagnostics about unknown parametrs. + void resolveParamCommandIndexes(const FullComment *FC); + bool isFunctionDecl(); bool isTemplateOrSpecialization(); @@ -218,9 +225,6 @@ public: InlineCommandComment::RenderKind getInlineCommandRenderKind(StringRef Name) const; - - bool isHTMLEndTagOptional(StringRef Name); - bool isHTMLEndTagForbidden(StringRef Name); }; } // end namespace comments diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index e9f25b368aad..087a58587471 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -88,7 +88,6 @@ public: static TranslationUnitDecl *Create(ASTContext &C); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TranslationUnitDecl *D) { return true; } static bool classofKind(Kind K) { return K == TranslationUnit; } static DeclContext *castToDeclContext(const TranslationUnitDecl *D) { return static_cast(const_cast(D)); @@ -214,16 +213,19 @@ public: bool isCXXInstanceMember() const; class LinkageInfo { - Linkage linkage_; - Visibility visibility_; - bool explicit_; + uint8_t linkage_ : 2; + uint8_t visibility_ : 2; + uint8_t explicit_ : 1; void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; } public: LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility), explicit_(false) {} LinkageInfo(Linkage L, Visibility V, bool E) - : linkage_(L), visibility_(V), explicit_(E) {} + : linkage_(L), visibility_(V), explicit_(E) { + assert(linkage() == L && visibility() == V && visibilityExplicit() == E && + "Enum truncated!"); + } static LinkageInfo external() { return LinkageInfo(); @@ -238,8 +240,8 @@ public: return LinkageInfo(NoLinkage, DefaultVisibility, false); } - Linkage linkage() const { return linkage_; } - Visibility visibility() const { return visibility_; } + Linkage linkage() const { return (Linkage)linkage_; } + Visibility visibility() const { return (Visibility)visibility_; } bool visibilityExplicit() const { return explicit_; } void setLinkage(Linkage L) { linkage_ = L; } @@ -337,7 +339,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const NamedDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; } }; @@ -383,7 +384,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const LabelDecl *D) { return true; } static bool classofKind(Kind K) { return K == Label; } }; @@ -509,7 +509,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const NamespaceDecl *D) { return true; } static bool classofKind(Kind K) { return K == Namespace; } static DeclContext *castToDeclContext(const NamespaceDecl *D) { return static_cast(const_cast(D)); @@ -545,7 +544,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ValueDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; } }; @@ -578,8 +576,8 @@ struct QualifierInfo { private: // Copy constructor and copy assignment are disabled. - QualifierInfo(const QualifierInfo&); - QualifierInfo& operator=(const QualifierInfo&); + QualifierInfo(const QualifierInfo&) LLVM_DELETED_FUNCTION; + QualifierInfo& operator=(const QualifierInfo&) LLVM_DELETED_FUNCTION; }; /// \brief Represents a ValueDecl that came out of a declarator. @@ -666,7 +664,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const DeclaratorDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstDeclarator && K <= lastDeclarator; } @@ -712,7 +709,7 @@ public: typedef clang::StorageClass StorageClass; /// getStorageClassSpecifierString - Return the string used to - /// specify the storage class \arg SC. + /// specify the storage class \p SC. /// /// It is illegal to call this function with SC == None. static const char *getStorageClassSpecifierString(StorageClass SC); @@ -1208,7 +1205,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const VarDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; } }; @@ -1229,7 +1225,6 @@ public: } // Implement isa/cast/dyncast/etc. - static bool classof(const ImplicitParamDecl *D) { return true; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ImplicitParam; } }; @@ -1399,7 +1394,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ParmVarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ParmVar; } private: @@ -2070,7 +2064,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const FunctionDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstFunction && K <= lastFunction; } @@ -2204,7 +2197,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const FieldDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } friend class ASTDeclReader; @@ -2243,7 +2235,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const EnumConstantDecl *D) { return true; } static bool classofKind(Kind K) { return K == EnumConstant; } friend class StmtIteratorBase; @@ -2287,7 +2278,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const IndirectFieldDecl *D) { return true; } static bool classofKind(Kind K) { return K == IndirectField; } friend class ASTDeclReader; }; @@ -2334,7 +2324,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TypeDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstType && K <= lastType; } }; @@ -2390,7 +2379,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TypedefNameDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstTypedefName && K <= lastTypedefName; } @@ -2413,7 +2401,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TypedefDecl *D) { return true; } static bool classofKind(Kind K) { return K == Typedef; } }; @@ -2434,7 +2421,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TypeAliasDecl *D) { return true; } static bool classofKind(Kind K) { return K == TypeAlias; } }; @@ -2448,7 +2434,7 @@ public: private: // FIXME: This can be packed into the bitfields in Decl. /// TagDeclKind - The TagKind enum. - unsigned TagDeclKind : 2; + unsigned TagDeclKind : 3; /// IsCompleteDefinition - True if this is a definition ("struct foo /// {};"), false if it is a declaration ("struct foo;"). It is not @@ -2625,6 +2611,7 @@ public: void setTagKind(TagKind TK) { TagDeclKind = TK; } bool isStruct() const { return getTagKind() == TTK_Struct; } + bool isInterface() const { return getTagKind() == TTK_Interface; } bool isClass() const { return getTagKind() == TTK_Class; } bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } @@ -2665,7 +2652,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TagDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstTag && K <= lastTag; } static DeclContext *castToDeclContext(const TagDecl *D) { @@ -2895,7 +2881,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const EnumDecl *D) { return true; } static bool classofKind(Kind K) { return K == Enum; } friend class ASTDeclReader; @@ -3026,11 +3011,15 @@ public: virtual void completeDefinition(); static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const RecordDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstRecord && K <= lastRecord; } + /// isMsStrust - Get whether or not this is an ms_struct which can + /// be turned on with an attribute, pragma, or -mms-bitfields + /// commandline option. + bool isMsStruct(const ASTContext &C) const; + private: /// \brief Deserialize just the fields. void LoadFieldsFromExternalStorage() const; @@ -3062,7 +3051,6 @@ public: void setAsmString(StringLiteral *Asm) { AsmString = Asm; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const FileScopeAsmDecl *D) { return true; } static bool classofKind(Kind K) { return K == FileScopeAsm; } }; @@ -3208,7 +3196,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const BlockDecl *D) { return true; } static bool classofKind(Kind K) { return K == Block; } static DeclContext *castToDeclContext(const BlockDecl *D) { return static_cast(const_cast(D)); @@ -3282,7 +3269,6 @@ public: virtual SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ImportDecl *D) { return true; } static bool classofKind(Kind K) { return K == Import; } }; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 0f596095f74a..50e202738dd4 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -430,16 +430,10 @@ public: void dropAttr() { if (!HasAttrs) return; - AttrVec &Attrs = getAttrs(); - for (unsigned i = 0, e = Attrs.size(); i != e; /* in loop */) { - if (isa(Attrs[i])) { - Attrs.erase(Attrs.begin() + i); - --e; - } - else - ++i; - } - if (Attrs.empty()) + AttrVec &Vec = getAttrs(); + Vec.erase(std::remove_if(Vec.begin(), Vec.end(), isa), Vec.end()); + + if (Vec.empty()) HasAttrs = false; } @@ -844,8 +838,6 @@ public: IdentifierNamespace |= IDNS_NonMemberOperator; } - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *) { return true; } static bool classofKind(Kind K) { return true; } static DeclContext *castToDeclContext(const Decl *); static Decl *castFromDeclContext(const DeclContext *); @@ -1479,6 +1471,13 @@ public: inline ddiag_iterator ddiag_end() const; // Low-level accessors + + /// \brief Mark the lookup table as needing to be built. This should be + /// used only if setHasExternalLexicalStorage() has been called. + void setMustBuildLookupTable() { + assert(ExternalLexicalStorage && "Requires external lexical storage"); + LookupPtr.setInt(true); + } /// \brief Retrieve the internal representation of the lookup structure. /// This may omit some names if we are lazily building the structure. @@ -1516,10 +1515,6 @@ public: static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ - static bool classof(const NAME##Decl *D) { return true; } -#include "clang/AST/DeclNodes.inc" LLVM_ATTRIBUTE_USED void dumpDeclContext() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 2d95f038dfd4..9cb56e2b3ccc 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -145,7 +145,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const AccessSpecDecl *D) { return true; } static bool classofKind(Kind K) { return K == AccessSpec; } }; @@ -563,9 +562,10 @@ class CXXRecordDecl : public RecordDecl { struct LambdaDefinitionData : public DefinitionData { typedef LambdaExpr::Capture Capture; - LambdaDefinitionData(CXXRecordDecl *D, bool Dependent) + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent) : DefinitionData(D), Dependent(Dependent), NumCaptures(0), - NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0) + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0), + MethodTyInfo(Info) { IsLambda = true; } @@ -598,7 +598,10 @@ class CXXRecordDecl : public RecordDecl { /// \brief The list of captures, both explicit and implicit, for this /// lambda. - Capture *Captures; + Capture *Captures; + + /// \brief The type of the call method. + TypeSourceInfo *MethodTyInfo; }; struct DefinitionData &data() { @@ -705,7 +708,8 @@ public: IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, - SourceLocation Loc, bool DependentLambda); + TypeSourceInfo *Info, SourceLocation Loc, + bool DependentLambda); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); bool isDynamicClass() const { @@ -1303,7 +1307,7 @@ public: /// \brief Function type used by forallBases() as a callback. /// - /// \param Base the definition of the base class + /// \param BaseDefinition the definition of the base class /// /// \returns true if this base matched the search criteria typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition, @@ -1500,15 +1504,15 @@ public: bool isDependentLambda() const { return isLambda() && getLambdaData().Dependent; } - + + TypeSourceInfo *getLambdaTypeInfo() const { + return getLambdaData().MethodTyInfo; + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; } - static bool classof(const CXXRecordDecl *D) { return true; } - static bool classof(const ClassTemplateSpecializationDecl *D) { - return true; - } friend class ASTDeclReader; friend class ASTDeclWriter; @@ -1549,14 +1553,16 @@ public: bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } - bool isConst() { return getType()->castAs()->isConst(); } - bool isVolatile() { return getType()->castAs()->isVolatile(); } + bool isConst() const { return getType()->castAs()->isConst(); } + bool isVolatile() const { return getType()->castAs()->isVolatile(); } bool isVirtual() const { CXXMethodDecl *CD = cast(const_cast(this)->getCanonicalDecl()); - if (CD->isVirtualAsWritten()) + // Methods declared in interfaces are automatically (pure) virtual. + if (CD->isVirtualAsWritten() || + (CD->getParent()->isInterface() && CD->isUserProvided())) return true; return (CD->begin_overridden_methods() != CD->end_overridden_methods()); @@ -1661,7 +1667,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const CXXMethodDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstCXXMethod && K <= lastCXXMethod; } @@ -2141,7 +2146,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const CXXConstructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConstructor; } friend class ASTDeclReader; @@ -2213,7 +2217,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const CXXDestructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXDestructor; } friend class ASTDeclReader; @@ -2280,7 +2283,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const CXXConversionDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConversion; } friend class ASTDeclReader; @@ -2350,7 +2352,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const LinkageSpecDecl *D) { return true; } static bool classofKind(Kind K) { return K == LinkageSpec; } static DeclContext *castToDeclContext(const LinkageSpecDecl *D) { return static_cast(const_cast(D)); @@ -2454,7 +2455,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const UsingDirectiveDecl *D) { return true; } static bool classofKind(Kind K) { return K == UsingDirective; } // Friend for getUsingDirectiveName. @@ -2548,7 +2548,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const NamespaceAliasDecl *D) { return true; } static bool classofKind(Kind K) { return K == NamespaceAlias; } }; @@ -2619,7 +2618,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const UsingShadowDecl *D) { return true; } static bool classofKind(Kind K) { return K == Decl::UsingShadow; } friend class ASTDeclReader; @@ -2751,7 +2749,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const UsingDecl *D) { return true; } static bool classofKind(Kind K) { return K == Using; } friend class ASTDeclReader; @@ -2825,7 +2822,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const UnresolvedUsingValueDecl *D) { return true; } static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } friend class ASTDeclReader; @@ -2891,7 +2887,6 @@ public: CreateDeserialized(ASTContext &C, unsigned ID); static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } }; @@ -2931,7 +2926,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(StaticAssertDecl *D) { return true; } static bool classofKind(Kind K) { return K == StaticAssert; } friend class ASTDeclReader; diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 9a64f08dee50..37e45868b57c 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_AST_DECLFRIEND_H #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -104,9 +105,15 @@ public: /// Retrieves the source range for the friend declaration. SourceRange getSourceRange() const LLVM_READONLY { - /* FIXME: consider the case of templates wrt start of range. */ - if (NamedDecl *ND = getFriendDecl()) + if (NamedDecl *ND = getFriendDecl()) { + if (FunctionTemplateDecl *FTD = dyn_cast(ND)) + return FTD->getSourceRange(); + if (DeclaratorDecl *DD = dyn_cast(ND)) { + if (DD->getOuterLocStart() != DD->getInnerLocStart()) + return DD->getSourceRange(); + } return SourceRange(getFriendLoc(), ND->getLocEnd()); + } else if (TypeSourceInfo *TInfo = getFriendType()) return SourceRange(getFriendLoc(), TInfo->getTypeLoc().getEndLoc()); else @@ -123,7 +130,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const FriendDecl *D) { return true; } static bool classofKind(Kind K) { return K == Decl::Friend; } friend class ASTDeclReader; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 6c39f2c3abe1..8b27dd8e9e16 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -33,8 +33,8 @@ class ObjCPropertyImplDecl; class CXXCtorInitializer; class ObjCListBase { - void operator=(const ObjCListBase &); // DO NOT IMPLEMENT - ObjCListBase(const ObjCListBase&); // DO NOT IMPLEMENT + ObjCListBase(const ObjCListBase &) LLVM_DELETED_FUNCTION; + void operator=(const ObjCListBase &) LLVM_DELETED_FUNCTION; protected: /// List is an array of pointers to objects that are not owned by this object. void **List; @@ -123,8 +123,8 @@ private: unsigned IsInstance : 1; unsigned IsVariadic : 1; - // Synthesized declaration method for a property setter/getter - unsigned IsSynthesized : 1; + /// True if this method is the getter or setter for an explicit property. + unsigned IsPropertyAccessor : 1; // Method has a definition. unsigned IsDefined : 1; @@ -174,8 +174,7 @@ private: SourceLocation DeclEndLoc; // the location of the ';' or '{'. // The following are only used for method definitions, null otherwise. - // FIXME: space savings opportunity, consider a sub-class. - Stmt *Body; + LazyDeclStmtPtr Body; /// SelfDecl - Decl for the implicit self parameter. This is lazily /// constructed by createImplicitParams. @@ -227,7 +226,7 @@ private: DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, - bool isSynthesized = false, + bool isPropertyAccessor = false, bool isImplicitlyDeclared = false, bool isDefined = false, ImplementationControl impControl = None, @@ -235,14 +234,14 @@ private: : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), IsInstance(isInstance), IsVariadic(isVariadic), - IsSynthesized(isSynthesized), + IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), RelatedResultType(HasRelatedResultType), SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), MethodDeclType(T), ResultTInfo(ResultTInfo), ParamsAndSelLocs(0), NumParams(0), - DeclEndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) { + DeclEndLoc(endLoc), Body(), SelfDecl(0), CmdDecl(0) { setImplicit(isImplicitlyDeclared); } @@ -261,7 +260,7 @@ public: DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, - bool isSynthesized = false, + bool isPropertyAccessor = false, bool isImplicitlyDeclared = false, bool isDefined = false, ImplementationControl impControl = None, @@ -363,7 +362,7 @@ public: } /// \brief Sets the method's parameters and selector source locations. - /// If the method is implicit (not coming from source) \arg SelLocs is + /// If the method is implicit (not coming from source) \p SelLocs is /// ignored. void setMethodParams(ASTContext &C, ArrayRef Params, @@ -403,8 +402,8 @@ public: bool isClassMethod() const { return !IsInstance; } - bool isSynthesized() const { return IsSynthesized; } - void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } + bool isPropertyAccessor() const { return IsPropertyAccessor; } + void setPropertyAccessor(bool isAccessor) { IsPropertyAccessor = isAccessor; } bool isDefined() const { return IsDefined; } void setDefined(bool isDefined) { IsDefined = isDefined; } @@ -418,7 +417,25 @@ public: /// method in the interface or its categories. bool isOverriding() const { return IsOverriding; } void setOverriding(bool isOverriding) { IsOverriding = isOverriding; } - + + /// \brief Return overridden methods for the given \p Method. + /// + /// An ObjC method is considered to override any method in the class's + /// base classes (and base's categories), its protocols, or its categories' + /// protocols, that has + /// the same selector and is of the same kind (class or instance). + /// A method in an implementation is not considered as overriding the same + /// method in the interface or its categories. + void getOverriddenMethods( + SmallVectorImpl &Overridden) const; + + /// \brief Returns the property associated with this method's selector. + /// + /// Note that even if this particular method is not marked as a property + /// accessor, it is still possible for it to match a property declared in a + /// superclass. Pass \c false if you only want to check the current class. + const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const; + // Related to protocols declared in \@protocol void setDeclImplementation(ImplementationControl ic) { DeclImplementation = ic; @@ -427,10 +444,15 @@ public: return ImplementationControl(DeclImplementation); } - virtual Stmt *getBody() const { - return (Stmt*) Body; - } - CompoundStmt *getCompoundBody() { return (CompoundStmt*)Body; } + /// \brief Determine whether this method has a body. + virtual bool hasBody() const { return Body; } + + /// \brief Retrieve the body of this method, if it has one. + virtual Stmt *getBody() const; + + void setLazyBody(uint64_t Offset) { Body = Offset; } + + CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); } void setBody(Stmt *B) { Body = B; } /// \brief Returns whether this specific method is a definition. @@ -438,7 +460,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCMethodDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCMethod; } static DeclContext *castToDeclContext(const ObjCMethodDecl *D) { return static_cast(const_cast(D)); @@ -520,6 +541,13 @@ public: ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; + typedef llvm::DenseMap PropertyMap; + + /// This routine collects list of properties to be implemented in the class. + /// This includes, class's and its conforming protocols' properties. + /// Note, the superclass's properties are not included in the list. + virtual void collectPropertiesToImplement(PropertyMap &PM) const {} + SourceLocation getAtStartLoc() const { return AtStart; } void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; } @@ -537,7 +565,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCContainerDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstObjCContainer && K <= lastObjCContainer; @@ -880,6 +907,8 @@ public: ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; + virtual void collectPropertiesToImplement(PropertyMap &PM) const; + /// isSuperClassOf - Return true if this class is the specified class or is a /// super class of the specified interface class. bool isSuperClassOf(const ObjCInterfaceDecl *I) const { @@ -992,7 +1021,6 @@ public: void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCInterfaceDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCInterface; } friend class ASTReader; @@ -1065,7 +1093,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCIvarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCIvar; } private: /// NextIvar - Next Ivar in the list of ivars declared in class; class's @@ -1098,7 +1125,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCAtDefsField; } }; @@ -1277,8 +1303,9 @@ public: return getFirstDeclaration(); } + virtual void collectPropertiesToImplement(PropertyMap &PM) const; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCProtocolDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCProtocol; } friend class ASTReader; @@ -1402,7 +1429,6 @@ public: SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCCategoryDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCCategory; } friend class ASTDeclReader; @@ -1455,7 +1481,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCImplDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstObjCImpl && K <= lastObjCImpl; } @@ -1532,7 +1557,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCCategoryImplDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} friend class ASTDeclReader; @@ -1568,8 +1592,12 @@ class ObjCImplementationDecl : public ObjCImplDecl { CXXCtorInitializer **IvarInitializers; unsigned NumIvarInitializers; - /// true if class has a .cxx_[construct,destruct] method. - bool HasCXXStructors : 1; + /// Do the ivars of this class require initialization other than + /// zero-initialization? + bool HasNonZeroConstructors : 1; + + /// Do the ivars of this class require non-trivial destruction? + bool HasDestructors : 1; ObjCImplementationDecl(DeclContext *DC, ObjCInterfaceDecl *classInterface, @@ -1581,7 +1609,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc), IvarInitializers(0), NumIvarInitializers(0), - HasCXXStructors(false) {} + HasNonZeroConstructors(false), HasDestructors(false) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *classInterface, @@ -1625,8 +1653,15 @@ public: CXXCtorInitializer ** initializers, unsigned numInitializers); - bool hasCXXStructors() const { return HasCXXStructors; } - void setHasCXXStructors(bool val) { HasCXXStructors = val; } + /// Do any of the ivars of this class (not counting its base classes) + /// require construction other than zero-initialization? + bool hasNonZeroConstructors() const { return HasNonZeroConstructors; } + void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; } + + /// Do any of the ivars of this class (not counting its base classes) + /// require non-trivial destruction? + bool hasDestructors() const { return HasDestructors; } + void setHasDestructors(bool val) { HasDestructors = val; } /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. @@ -1676,7 +1711,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCImplementationDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCImplementation; } friend class ASTDeclReader; @@ -1708,7 +1742,6 @@ public: void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCCompatibleAliasDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; } }; @@ -1882,13 +1915,15 @@ public: virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AtLoc, getLocation()); } + + /// Get the default name of the synthesized ivar. + IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const; /// Lookup a property by name in the specified DeclContext. static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, IdentifierInfo *propertyID); static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCPropertyDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCProperty; } }; @@ -1999,7 +2034,6 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ObjCPropertyImplDecl *D) { return true; } static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; } friend class ASTDeclReader; diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 7affc7e15f27..862011666205 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -50,7 +50,11 @@ class TemplateParameterList { /// The number of template parameters in this template /// parameter list. - unsigned NumParams; + unsigned NumParams : 31; + + /// Whether this template parameter list contains an unexpanded parameter + /// pack. + unsigned ContainsUnexpandedParameterPack : 1; protected: TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, @@ -104,6 +108,12 @@ public: /// the second template parameter list will have depth 1, etc. unsigned getDepth() const; + /// \brief Determine whether this template parameter list contains an + /// unexpanded parameter pack. + bool containsUnexpandedParameterPack() const { + return ContainsUnexpandedParameterPack; + } + SourceLocation getTemplateLoc() const { return TemplateLoc; } SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } @@ -139,8 +149,8 @@ class TemplateArgumentList { /// argument list. unsigned NumArguments; - TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL - void operator=(const TemplateArgumentList &Other); // DO NOT IMPL + TemplateArgumentList(const TemplateArgumentList &Other) LLVM_DELETED_FUNCTION; + void operator=(const TemplateArgumentList &Other) LLVM_DELETED_FUNCTION; TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs, bool Owned) @@ -233,12 +243,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TemplateDecl *D) { return true; } - static bool classof(const RedeclarableTemplateDecl *D) { return true; } - static bool classof(const FunctionTemplateDecl *D) { return true; } - static bool classof(const ClassTemplateDecl *D) { return true; } - static bool classof(const TemplateTemplateParmDecl *D) { return true; } - static bool classof(const TypeAliasTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstTemplate && K <= lastTemplate; } @@ -678,10 +682,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const RedeclarableTemplateDecl *D) { return true; } - static bool classof(const FunctionTemplateDecl *D) { return true; } - static bool classof(const ClassTemplateDecl *D) { return true; } - static bool classof(const TypeAliasTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; } @@ -827,7 +827,6 @@ public: // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == FunctionTemplate; } friend class ASTDeclReader; @@ -969,7 +968,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TemplateTypeParmDecl *D) { return true; } static bool classofKind(Kind K) { return K == TemplateTypeParm; } }; @@ -1090,8 +1088,17 @@ public: /// \endcode bool isParameterPack() const { return ParameterPack; } + /// \brief Whether this parameter pack is a pack expansion. + /// + /// A non-type template parameter pack is a pack expansion if its type + /// contains an unexpanded parameter pack. In this case, we will have + /// built a PackExpansionType wrapping the type. + bool isPackExpansion() const { + return ParameterPack && getType()->getAs(); + } + /// \brief Whether this parameter is a non-type template parameter pack - /// that has different types at different positions. + /// that has a known list of different types at different positions. /// /// A parameter pack is an expanded parameter pack when the original /// parameter pack's type was itself a pack expansion, and that expansion @@ -1141,7 +1148,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const NonTypeTemplateParmDecl *D) { return true; } static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } }; @@ -1165,23 +1171,47 @@ class TemplateTemplateParmDecl : public TemplateDecl, /// \brief Whether this parameter is a parameter pack. bool ParameterPack; + /// \brief Whether this template template parameter is an "expanded" + /// parameter pack, meaning that it is a pack expansion and we + /// already know the set of template parameters that expansion expands to. + bool ExpandedParameterPack; + + /// \brief The number of parameters in an expanded parameter pack. + unsigned NumExpandedParams; + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), TemplateParmPosition(D, P), DefaultArgument(), - DefaultArgumentWasInherited(false), ParameterPack(ParameterPack) + DefaultArgumentWasInherited(false), ParameterPack(ParameterPack), + ExpandedParameterPack(false), NumExpandedParams(0) { } + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, + unsigned D, unsigned P, + IdentifierInfo *Id, TemplateParameterList *Params, + unsigned NumExpansions, + TemplateParameterList * const *Expansions); + public: static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params); + static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, + unsigned P, + IdentifierInfo *Id, + TemplateParameterList *Params, + llvm::ArrayRef Expansions); - static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, + static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned NumExpansions); using TemplateParmPosition::getDepth; using TemplateParmPosition::getPosition; @@ -1195,6 +1225,49 @@ public: /// \endcode bool isParameterPack() const { return ParameterPack; } + /// \brief Whether this parameter pack is a pack expansion. + /// + /// A template template parameter pack is a pack expansion if its template + /// parameter list contains an unexpanded parameter pack. + bool isPackExpansion() const { + return ParameterPack && + getTemplateParameters()->containsUnexpandedParameterPack(); + } + + /// \brief Whether this parameter is a template template parameter pack that + /// has a known list of different template parameter lists at different + /// positions. + /// + /// A parameter pack is an expanded parameter pack when the original parameter + /// pack's template parameter list was itself a pack expansion, and that + /// expansion has already been expanded. For exampe, given: + /// + /// \code + /// template struct Outer { + /// template class...Templates> struct Inner; + /// }; + /// \endcode + /// + /// The parameter pack \c Templates is a pack expansion, which expands the + /// pack \c Types. When \c Types is supplied with template arguments by + /// instantiating \c Outer, the instantiation of \c Templates is an expanded + /// parameter pack. + bool isExpandedParameterPack() const { return ExpandedParameterPack; } + + /// \brief Retrieves the number of expansion template parameters in + /// an expanded parameter pack. + unsigned getNumExpansionTemplateParameters() const { + assert(ExpandedParameterPack && "Not an expansion parameter pack"); + return NumExpandedParams; + } + + /// \brief Retrieve a particular expansion type within an expanded parameter + /// pack. + TemplateParameterList *getExpansionTemplateParameters(unsigned I) const { + assert(I < NumExpandedParams && "Out-of-range expansion type index"); + return reinterpret_cast(this + 1)[I]; + } + /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { @@ -1238,7 +1311,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classofKind(Kind K) { return K == TemplateTemplateParm; } friend class ASTDeclReader; @@ -1505,14 +1577,6 @@ public: K <= lastClassTemplateSpecialization; } - static bool classof(const ClassTemplateSpecializationDecl *) { - return true; - } - - static bool classof(const ClassTemplatePartialSpecializationDecl *) { - return true; - } - friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -1681,10 +1745,6 @@ public: return K == ClassTemplatePartialSpecialization; } - static bool classof(const ClassTemplatePartialSpecializationDecl *) { - return true; - } - friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -1886,7 +1946,6 @@ public: // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const ClassTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == ClassTemplate; } friend class ASTDeclReader; @@ -1984,7 +2043,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } - static bool classof(const FriendTemplateDecl *D) { return true; } friend class ASTDeclReader; }; @@ -2059,7 +2117,6 @@ public: // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classof(const TypeAliasTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == TypeAliasTemplate; } friend class ASTDeclReader; @@ -2123,9 +2180,6 @@ public: static bool classofKind(Kind K) { return K == Decl::ClassScopeFunctionSpecialization; } - static bool classof(const ClassScopeFunctionSpecializationDecl *D) { - return true; - } friend class ASTDeclReader; friend class ASTDeclWriter; diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 614652540679..d991c73612c2 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -334,8 +334,8 @@ class DeclarationNameTable { CXXOperatorIdName *CXXOperatorNames; // Operator names void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* - DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE - DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE + DeclarationNameTable(const DeclarationNameTable&) LLVM_DELETED_FUNCTION; + void operator=(const DeclarationNameTable&) LLVM_DELETED_FUNCTION; public: DeclarationNameTable(const ASTContext &C); diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 89c003c8f664..dc83654bd948 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -34,6 +34,7 @@ namespace clang { class ASTContext; class APValue; + class CastExpr; class Decl; class IdentifierInfo; class ParmVarDecl; @@ -42,6 +43,7 @@ namespace clang { class BlockDecl; class CXXBaseSpecifier; class CXXOperatorCallExpr; + class MaterializeTemporaryExpr; class CXXMemberCallExpr; class ObjCPropertyRefExpr; class OpaqueValueExpr; @@ -49,6 +51,48 @@ namespace clang { /// \brief A simple array of base specifiers. typedef SmallVector CXXCastPath; +/// \brief An adjustment to be made to the temporary created when emitting a +/// reference binding, which accesses a particular subobject of that temporary. +struct SubobjectAdjustment { + enum { + DerivedToBaseAdjustment, + FieldAdjustment, + MemberPointerAdjustment + } Kind; + + union { + struct { + const CastExpr *BasePath; + const CXXRecordDecl *DerivedClass; + } DerivedToBase; + + FieldDecl *Field; + + struct { + const MemberPointerType *MPT; + Expr *RHS; + } Ptr; + }; + + SubobjectAdjustment(const CastExpr *BasePath, + const CXXRecordDecl *DerivedClass) + : Kind(DerivedToBaseAdjustment) { + DerivedToBase.BasePath = BasePath; + DerivedToBase.DerivedClass = DerivedClass; + } + + SubobjectAdjustment(FieldDecl *Field) + : Kind(FieldAdjustment) { + this->Field = Field; + } + + SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS) + : Kind(MemberPointerAdjustment) { + this->Ptr.MPT = MPT; + this->Ptr.RHS = RHS; + } +}; + /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt /// is required. @@ -220,15 +264,6 @@ public: /// Reasons why an expression might not be an l-value. LValueClassification ClassifyLValue(ASTContext &Ctx) const; - /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, - /// does not have an incomplete type, does not have a const-qualified type, - /// and if it is a structure or union, does not have any member (including, - /// recursively, any member or element of all contained aggregates or unions) - /// with a const-qualified type. - /// - /// \param Loc [in,out] - A source location which *may* be filled - /// in with the location of the expression making this a - /// non-modifiable lvalue, if specified. enum isModifiableLvalueResult { MLV_Valid, MLV_NotObjectType, @@ -247,6 +282,15 @@ public: MLV_ClassTemporary, MLV_ArrayTemporary }; + /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, + /// does not have an incomplete type, does not have a const-qualified type, + /// and if it is a structure or union, does not have any member (including, + /// recursively, any member or element of all contained aggregates or unions) + /// with a const-qualified type. + /// + /// \param Loc [in,out] - A source location which *may* be filled + /// in with the location of the expression making this a + /// non-modifiable lvalue, if specified. isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; @@ -392,6 +436,9 @@ public: /// property, find the underlying property reference expression. const ObjCPropertyRefExpr *getObjCProperty() const; + /// \brief Check if this expression is the ObjC 'self' implicit parameter. + bool isObjCSelfExpr() const; + /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; @@ -692,11 +739,22 @@ public: /// behavior if the object isn't dynamically of the derived type. const CXXRecordDecl *getBestDynamicClassType() const; + /// Walk outwards from an expression we want to bind a reference to and + /// find the expression whose lifetime needs to be extended. Record + /// the adjustments needed along the path. + const Expr * + skipRValueSubobjectAdjustments( + SmallVectorImpl &Adjustments) const; + + /// Skip irrelevant expressions to find what should be materialize for + /// binding with a reference. + const Expr * + findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const; + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && T->getStmtClass() <= lastExprConstant; } - static bool classof(const Expr *) { return true; } }; @@ -762,7 +820,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == OpaqueValueExprClass; } - static bool classof(const OpaqueValueExpr *) { return true; } }; /// \brief A reference to a declared variable, function, enum, etc. @@ -1059,7 +1116,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } - static bool classof(const DeclRefExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1109,7 +1165,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == PredefinedExprClass; } - static bool classof(const PredefinedExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1132,8 +1187,8 @@ class APNumericStorage { bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } - APNumericStorage(const APNumericStorage&); // do not implement - APNumericStorage& operator=(const APNumericStorage&); // do not implement + APNumericStorage(const APNumericStorage &) LLVM_DELETED_FUNCTION; + void operator=(const APNumericStorage &) LLVM_DELETED_FUNCTION; protected: APNumericStorage() : VAL(0), BitWidth(0) { } @@ -1196,7 +1251,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == IntegerLiteralClass; } - static bool classof(const IntegerLiteral *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1243,7 +1297,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CharacterLiteralClass; } - static bool classof(const CharacterLiteral *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1286,7 +1339,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == FloatingLiteralClass; } - static bool classof(const FloatingLiteral *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1317,7 +1369,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ImaginaryLiteralClass; } - static bool classof(const ImaginaryLiteral *) { return true; } // Iterators child_range children() { return child_range(&Val, &Val+1); } @@ -1479,7 +1530,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == StringLiteralClass; } - static bool classof(const StringLiteral *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1520,7 +1570,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ParenExprClass; } - static bool classof(const ParenExpr *) { return true; } // Iterators child_range children() { return child_range(&Val, &Val+1); } @@ -1610,7 +1659,7 @@ public: /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++" - static const char *getOpcodeStr(Opcode Op); + static StringRef getOpcodeStr(Opcode Op); /// \brief Retrieve the unary opcode that corresponds to the given /// overloaded operator. @@ -1631,7 +1680,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryOperatorClass; } - static bool classof(const UnaryOperator *) { return true; } // Iterators child_range children() { return child_range(&Val, &Val+1); } @@ -1757,8 +1805,7 @@ private: OffsetOfExpr(ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, - OffsetOfNode* compsPtr, unsigned numComps, - Expr** exprsPtr, unsigned numExprs, + ArrayRef comps, ArrayRef exprs, SourceLocation RParenLoc); explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) @@ -1769,9 +1816,8 @@ public: static OffsetOfExpr *Create(ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, - OffsetOfNode* compsPtr, unsigned numComps, - Expr** exprsPtr, unsigned numExprs, - SourceLocation RParenLoc); + ArrayRef comps, + ArrayRef exprs, SourceLocation RParenLoc); static OffsetOfExpr *CreateEmpty(ASTContext &C, unsigned NumComps, unsigned NumExprs); @@ -1832,8 +1878,6 @@ public: return T->getStmtClass() == OffsetOfExprClass; } - static bool classof(const OffsetOfExpr *) { return true; } - // Iterators child_range children() { Stmt **begin = @@ -1937,7 +1981,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; } - static bool classof(const UnaryExprOrTypeTraitExpr *) { return true; } // Iterators child_range children(); @@ -2017,7 +2060,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ArraySubscriptExprClass; } - static bool classof(const ArraySubscriptExpr *) { return true; } // Iterators child_range children() { @@ -2041,7 +2083,7 @@ class CallExpr : public Expr { protected: // These versions of the constructor are for derived classes. CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, - Expr **args, unsigned numargs, QualType t, ExprValueKind VK, + ArrayRef args, QualType t, ExprValueKind VK, SourceLocation rparenloc); CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty); @@ -2061,7 +2103,7 @@ protected: unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } public: - CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t, + CallExpr(ASTContext& C, Expr *fn, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation rparenloc); /// \brief Build an empty call expression. @@ -2153,7 +2195,6 @@ public: return T->getStmtClass() >= firstCallExprConstant && T->getStmtClass() <= lastCallExprConstant; } - static bool classof(const CallExpr *) { return true; } // Iterators child_range children() { @@ -2440,7 +2481,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } - static bool classof(const MemberExpr *) { return true; } // Iterators child_range children() { return child_range(&Base, &Base+1); } @@ -2506,7 +2546,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CompoundLiteralExprClass; } - static bool classof(const CompoundLiteralExpr *) { return true; } // Iterators child_range children() { return child_range(&Init, &Init+1); } @@ -2597,7 +2636,6 @@ public: return T->getStmtClass() >= firstCastExprConstant && T->getStmtClass() <= lastCastExprConstant; } - static bool classof(const CastExpr *) { return true; } // Iterators child_range children() { return child_range(&Op, &Op+1); } @@ -2661,7 +2699,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitCastExprClass; } - static bool classof(const ImplicitCastExpr *) { return true; } }; inline Expr *Expr::IgnoreImpCasts() { @@ -2716,7 +2753,6 @@ public: return T->getStmtClass() >= firstExplicitCastExprConstant && T->getStmtClass() <= lastExplicitCastExprConstant; } - static bool classof(const ExplicitCastExpr *) { return true; } }; /// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style @@ -2757,7 +2793,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CStyleCastExprClass; } - static bool classof(const CStyleCastExpr *) { return true; } }; /// \brief A builtin binary operation expression such as "x + y" or "x <= y". @@ -2784,6 +2819,12 @@ public: private: unsigned Opc : 6; + + // Records the FP_CONTRACT pragma status at the point that this binary + // operator was parsed. This bit is only meaningful for operations on + // floating point types. For all other types it should default to + // false. + unsigned FPContractable : 1; SourceLocation OpLoc; enum { LHS, RHS, END_EXPR }; @@ -2792,7 +2833,7 @@ public: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc) + SourceLocation opLoc, bool fpContractable) : Expr(BinaryOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), @@ -2800,7 +2841,7 @@ public: rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), - Opc(opc), OpLoc(opLoc) { + Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(!isCompoundAssignmentOp() && @@ -2829,9 +2870,9 @@ public: /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "<<=". - static const char *getOpcodeStr(Opcode Op); + static StringRef getOpcodeStr(Opcode Op); - const char *getOpcodeStr() const { return getOpcodeStr(getOpcode()); } + StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); } /// \brief Retrieve the binary opcode that corresponds to the given /// overloaded operator. @@ -2894,17 +2935,24 @@ public: return S->getStmtClass() >= firstBinaryOperatorConstant && S->getStmtClass() <= lastBinaryOperatorConstant; } - static bool classof(const BinaryOperator *) { return true; } // Iterators child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); } + // Set the FP contractability status of this operator. Only meaningful for + // operations on floating point types. + void setFPContractable(bool FPC) { FPContractable = FPC; } + + // Get the FP contractability status of this operator. Only meaningful for + // operations on floating point types. + bool isFPContractable() const { return FPContractable; } + protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, bool dead) + SourceLocation opLoc, bool fpContractable, bool dead2) : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, lhs->isTypeDependent() || rhs->isTypeDependent(), lhs->isValueDependent() || rhs->isValueDependent(), @@ -2912,7 +2960,7 @@ protected: rhs->isInstantiationDependent()), (lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), - Opc(opc), OpLoc(opLoc) { + Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; } @@ -2934,8 +2982,9 @@ public: CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, ExprValueKind VK, ExprObjectKind OK, QualType CompLHSType, QualType CompResultType, - SourceLocation OpLoc) - : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true), + SourceLocation OpLoc, bool fpContractable) + : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable, + true), ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) { assert(isCompoundAssignmentOp() && @@ -2955,7 +3004,6 @@ public: QualType getComputationResultType() const { return ComputationResultType; } void setComputationResultType(QualType T) { ComputationResultType = T; } - static bool classof(const CompoundAssignOperator *) { return true; } static bool classof(const Stmt *S) { return S->getStmtClass() == CompoundAssignOperatorClass; } @@ -3001,7 +3049,6 @@ public: return T->getStmtClass() == ConditionalOperatorClass || T->getStmtClass() == BinaryConditionalOperatorClass; } - static bool classof(const AbstractConditionalOperator *) { return true; } }; /// ConditionalOperator - The ?: ternary operator. The GNU "missing @@ -3060,7 +3107,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ConditionalOperatorClass; } - static bool classof(const ConditionalOperator *) { return true; } // Iterators child_range children() { @@ -3142,7 +3188,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == BinaryConditionalOperatorClass; } - static bool classof(const BinaryConditionalOperator *) { return true; } // Iterators child_range children() { @@ -3198,7 +3243,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == AddrLabelExprClass; } - static bool classof(const AddrLabelExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -3242,7 +3286,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == StmtExprClass; } - static bool classof(const StmtExpr *) { return true; } // Iterators child_range children() { return child_range(&SubStmt, &SubStmt+1); } @@ -3266,9 +3309,8 @@ class ShuffleVectorExpr : public Expr { unsigned NumExprs; public: - ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, - QualType Type, SourceLocation BLoc, - SourceLocation RP); + ShuffleVectorExpr(ASTContext &C, ArrayRef args, QualType Type, + SourceLocation BLoc, SourceLocation RP); /// \brief Build an empty vector-shuffle expression. explicit ShuffleVectorExpr(EmptyShell Empty) @@ -3286,7 +3328,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ShuffleVectorExprClass; } - static bool classof(const ShuffleVectorExpr *) { return true; } /// getNumSubExprs - Return the size of the SubExprs array. This includes the /// constant expression, the actual arguments passed in, and the function @@ -3308,7 +3349,7 @@ public: void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs); - unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) { + unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) const { assert((N < NumExprs - 2) && "Shuffle idx out of range!"); return getExpr(N+2)->EvaluateKnownConstInt(Ctx).getZExtValue(); } @@ -3381,7 +3422,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ChooseExprClass; } - static bool classof(const ChooseExpr *) { return true; } // Iterators child_range children() { @@ -3418,7 +3458,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == GNUNullExprClass; } - static bool classof(const GNUNullExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -3464,7 +3503,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == VAArgExprClass; } - static bool classof(const VAArgExpr *) { return true; } // Iterators child_range children() { return child_range(&Val, &Val+1); } @@ -3501,21 +3539,32 @@ public: /// initializer lists may still have fewer initializers than there are /// elements to initialize within the object. /// +/// After semantic analysis has completed, given an initializer list, +/// method isSemanticForm() returns true if and only if this is the +/// semantic form of the initializer list (note: the same AST node +/// may at the same time be the syntactic form). /// Given the semantic form of the initializer list, one can retrieve -/// the original syntactic form of that initializer list (if it -/// exists) using getSyntacticForm(). Since many initializer lists -/// have the same syntactic and semantic forms, getSyntacticForm() may -/// return NULL, indicating that the current initializer list also -/// serves as its syntactic form. +/// the syntactic form of that initializer list (when different) +/// using method getSyntacticForm(); the method returns null if applied +/// to a initializer list which is already in syntactic form. +/// Similarly, given the syntactic form (i.e., an initializer list such +/// that isSemanticForm() returns false), one can retrieve the semantic +/// form using method getSemanticForm(). +/// Since many initializer lists have the same syntactic and semantic forms, +/// getSyntacticForm() may return NULL, indicating that the current +/// semantic initializer list also serves as its syntactic form. class InitListExpr : public Expr { // FIXME: Eliminate this vector in favor of ASTContext allocation typedef ASTVector InitExprsTy; InitExprsTy InitExprs; SourceLocation LBraceLoc, RBraceLoc; - /// Contains the initializer list that describes the syntactic form - /// written in the source code. - InitListExpr *SyntacticForm; + /// The alternative form of the initializer list (if it exists). + /// The int part of the pair stores whether this initalizer list is + /// in semantic form. If not null, the pointer points to: + /// - the syntactic form, if this is in semantic form; + /// - the semantic form, if this is in syntactic form. + llvm::PointerIntPair AltForm; /// \brief Either: /// If this initializer list initializes an array with more elements than @@ -3528,8 +3577,7 @@ class InitListExpr : public Expr { public: InitListExpr(ASTContext &C, SourceLocation lbraceloc, - Expr **initexprs, unsigned numinits, - SourceLocation rbraceloc); + ArrayRef initExprs, SourceLocation rbraceloc); /// \brief Build an empty initializer list. explicit InitListExpr(ASTContext &C, EmptyShell Empty) @@ -3621,12 +3669,20 @@ public: SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; } - /// @brief Retrieve the initializer list that describes the - /// syntactic form of the initializer. - /// - /// - InitListExpr *getSyntacticForm() const { return SyntacticForm; } - void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; } + bool isSemanticForm() const { return AltForm.getInt(); } + InitListExpr *getSemanticForm() const { + return isSemanticForm() ? 0 : AltForm.getPointer(); + } + InitListExpr *getSyntacticForm() const { + return isSemanticForm() ? AltForm.getPointer() : 0; + } + + void setSyntacticForm(InitListExpr *Init) { + AltForm.setPointer(Init); + AltForm.setInt(true); + Init->AltForm.setPointer(this); + Init->AltForm.setInt(false); + } bool hadArrayRangeDesignator() const { return InitListExprBits.HadArrayRangeDesignator != 0; @@ -3647,7 +3703,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == InitListExprClass; } - static bool classof(const InitListExpr *) { return true; } // Iterators child_range children() { @@ -3723,8 +3778,7 @@ private: DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators, const Designator *Designators, SourceLocation EqualOrColonLoc, bool GNUSyntax, - Expr **IndexExprs, unsigned NumIndexExprs, - Expr *Init); + ArrayRef IndexExprs, Expr *Init); explicit DesignatedInitExpr(unsigned NumSubExprs) : Expr(DesignatedInitExprClass, EmptyShell()), @@ -3885,7 +3939,7 @@ public: static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, unsigned NumDesignators, - Expr **IndexExprs, unsigned NumIndexExprs, + ArrayRef IndexExprs, SourceLocation EqualOrColonLoc, bool GNUSyntax, Expr *Init); @@ -3985,7 +4039,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == DesignatedInitExprClass; } - static bool classof(const DesignatedInitExpr *) { return true; } // Iterators child_range children() { @@ -4015,7 +4068,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitValueInitExprClass; } - static bool classof(const ImplicitValueInitExpr *) { return true; } SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(); @@ -4032,8 +4084,8 @@ class ParenListExpr : public Expr { SourceLocation LParenLoc, RParenLoc; public: - ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, - unsigned numexprs, SourceLocation rparenloc); + ParenListExpr(ASTContext& C, SourceLocation lparenloc, ArrayRef exprs, + SourceLocation rparenloc); /// \brief Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } @@ -4061,7 +4113,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ParenListExprClass; } - static bool classof(const ParenListExpr *) { return true; } // Iterators child_range children() { @@ -4109,18 +4160,18 @@ class GenericSelectionExpr : public Expr { public: GenericSelectionExpr(ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, - TypeSourceInfo **AssocTypes, Expr **AssocExprs, - unsigned NumAssocs, SourceLocation DefaultLoc, - SourceLocation RParenLoc, + ArrayRef AssocTypes, + ArrayRef AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, unsigned ResultIndex); /// This constructor is used in the result-dependent case. GenericSelectionExpr(ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, - TypeSourceInfo **AssocTypes, Expr **AssocExprs, - unsigned NumAssocs, SourceLocation DefaultLoc, - SourceLocation RParenLoc, + ArrayRef AssocTypes, + ArrayRef AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); explicit GenericSelectionExpr(EmptyShell Empty) @@ -4176,7 +4227,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == GenericSelectionExprClass; } - static bool classof(const GenericSelectionExpr *) { return true; } child_range children() { return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs); @@ -4247,7 +4297,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ExtVectorElementExprClass; } - static bool classof(const ExtVectorElementExpr *) { return true; } // Iterators child_range children() { return child_range(&Base, &Base+1); } @@ -4289,7 +4338,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == BlockExprClass; } - static bool classof(const BlockExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -4336,7 +4384,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == AsTypeExprClass; } - static bool classof(const AsTypeExpr *) { return true; } // Iterators child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } @@ -4473,7 +4520,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == PseudoObjectExprClass; } - static bool classof(const PseudoObjectExpr *) { return true; } }; /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, @@ -4501,7 +4547,7 @@ private: friend class ASTStmtReader; public: - AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, QualType t, + AtomicExpr(SourceLocation BLoc, ArrayRef args, QualType t, AtomicOp op, SourceLocation RP); /// \brief Determine the number of arguments the specified atomic builtin @@ -4563,7 +4609,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == AtomicExprClass; } - static bool classof(const AtomicExpr *) { return true; } // Iterators child_range children() { diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index ecfa9e213637..9c759db1f97a 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -53,14 +53,19 @@ class CXXOperatorCallExpr : public CallExpr { OverloadedOperatorKind Operator; SourceRange Range; + // Record the FP_CONTRACT state that applies to this operator call. Only + // meaningful for floating point types. For other types this value can be + // set to false. + unsigned FPContractable : 1; + SourceRange getSourceRangeImpl() const LLVM_READONLY; public: CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, - Expr **args, unsigned numargs, QualType t, - ExprValueKind VK, SourceLocation operatorloc) - : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK, + ArrayRef args, QualType t, ExprValueKind VK, + SourceLocation operatorloc, bool fpContractable) + : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, t, VK, operatorloc), - Operator(Op) { + Operator(Op), FPContractable(fpContractable) { Range = getSourceRangeImpl(); } explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : @@ -83,7 +88,14 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXOperatorCallExprClass; } - static bool classof(const CXXOperatorCallExpr *) { return true; } + + // Set the FP contractability status of this operator. Only meaningful for + // operations on floating point types. + void setFPContractable(bool FPC) { FPContractable = FPC; } + + // Get the FP contractability status of this operator. Only meaningful for + // operations on floating point types. + bool isFPContractable() const { return FPContractable; } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -99,9 +111,9 @@ public: /// the object argument). class CXXMemberCallExpr : public CallExpr { public: - CXXMemberCallExpr(ASTContext &C, Expr *fn, Expr **args, unsigned numargs, + CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, numargs, t, VK, RP) {} + : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, t, VK, RP) {} CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) : CallExpr(C, CXXMemberCallExprClass, Empty) { } @@ -124,7 +136,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; } - static bool classof(const CXXMemberCallExpr *) { return true; } }; /// CUDAKernelCallExpr - Represents a call to a CUDA kernel function. @@ -134,10 +145,9 @@ private: public: CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config, - Expr **args, unsigned numargs, QualType t, - ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, numargs, t, VK, - RP) { + ArrayRef args, QualType t, ExprValueKind VK, + SourceLocation RP) + : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, t, VK, RP) { setConfig(Config); } @@ -153,7 +163,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CUDAKernelCallExprClass; } - static bool classof(const CUDAKernelCallExpr *) { return true; } }; /// CXXNamedCastExpr - Abstract class common to all of the C++ "named" @@ -205,7 +214,6 @@ public: return false; } } - static bool classof(const CXXNamedCastExpr *) { return true; } }; /// CXXStaticCastExpr - A C++ @c static_cast expression @@ -235,7 +243,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXStaticCastExprClass; } - static bool classof(const CXXStaticCastExpr *) { return true; } }; /// CXXDynamicCastExpr - A C++ @c dynamic_cast expression @@ -269,7 +276,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; } - static bool classof(const CXXDynamicCastExpr *) { return true; } }; /// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++ @@ -301,7 +307,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXReinterpretCastExprClass; } - static bool classof(const CXXReinterpretCastExpr *) { return true; } }; /// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]), @@ -329,7 +334,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstCastExprClass; } - static bool classof(const CXXConstCastExpr *) { return true; } }; /// UserDefinedLiteral - A call to a literal operator (C++11 [over.literal]) @@ -346,11 +350,11 @@ class UserDefinedLiteral : public CallExpr { SourceLocation UDSuffixLoc; public: - UserDefinedLiteral(ASTContext &C, Expr *Fn, Expr **Args, unsigned NumArgs, + UserDefinedLiteral(ASTContext &C, Expr *Fn, ArrayRef Args, QualType T, ExprValueKind VK, SourceLocation LitEndLoc, SourceLocation SuffixLoc) - : CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, NumArgs, T, VK, - LitEndLoc), UDSuffixLoc(SuffixLoc) {} + : CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, T, VK, LitEndLoc), + UDSuffixLoc(SuffixLoc) {} explicit UserDefinedLiteral(ASTContext &C, EmptyShell Empty) : CallExpr(C, UserDefinedLiteralClass, Empty) {} @@ -398,7 +402,6 @@ public: static bool classof(const Stmt *S) { return S->getStmtClass() == UserDefinedLiteralClass; } - static bool classof(const UserDefinedLiteral *) { return true; } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -429,7 +432,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXBoolLiteralExprClass; } - static bool classof(const CXXBoolLiteralExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -455,7 +457,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNullPtrLiteralExprClass; } - static bool classof(const CXXNullPtrLiteralExpr *) { return true; } child_range children() { return child_range(); } }; @@ -536,7 +537,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTypeidExprClass; } - static bool classof(const CXXTypeidExpr *) { return true; } // Iterators child_range children() { @@ -611,7 +611,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUuidofExprClass; } - static bool classof(const CXXUuidofExpr *) { return true; } + + /// Grabs __declspec(uuid()) off a type, or returns 0 if there is none. + static UuidAttr *GetUuidAttrOfType(QualType QT); // Iterators child_range children() { @@ -659,7 +661,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXThisExprClass; } - static bool classof(const CXXThisExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -710,7 +711,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXThrowExprClass; } - static bool classof(const CXXThrowExpr *) { return true; } // Iterators child_range children() { @@ -798,7 +798,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDefaultArgExprClass; } - static bool classof(const CXXDefaultArgExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -875,7 +874,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXBindTemporaryExprClass; } - static bool classof(const CXXBindTemporaryExpr *) { return true; } // Iterators child_range children() { return child_range(&SubExpr, &SubExpr + 1); } @@ -908,7 +906,7 @@ protected: CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, CXXConstructorDecl *d, bool elidable, - Expr **args, unsigned numargs, + ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, bool ZeroInitialization, @@ -934,7 +932,7 @@ public: static CXXConstructExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, - Expr **Args, unsigned NumArgs, + ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, bool ZeroInitialization, @@ -1011,7 +1009,6 @@ public: return T->getStmtClass() == CXXConstructExprClass || T->getStmtClass() == CXXTemporaryObjectExprClass; } - static bool classof(const CXXConstructExpr *) { return true; } // Iterators child_range children() { @@ -1066,7 +1063,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFunctionalCastExprClass; } - static bool classof(const CXXFunctionalCastExpr *) { return true; } }; /// @brief Represents a C++ functional cast expression that builds a @@ -1090,7 +1086,7 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr { public: CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, TypeSourceInfo *Type, - Expr **Args,unsigned NumArgs, + ArrayRef Args, SourceRange parenRange, bool HadMultipleCandidates, bool ZeroInitialization = false); @@ -1104,7 +1100,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTemporaryObjectExprClass; } - static bool classof(const CXXTemporaryObjectExpr *) { return true; } friend class ASTStmtReader; }; @@ -1281,8 +1276,11 @@ private: /// \brief Retrieve the complete set of array-index variables. VarDecl **getArrayIndexVars() const { + unsigned ArrayIndexSize = + llvm::RoundUpToAlignment(sizeof(unsigned) * (NumCaptures + 1), + llvm::alignOf()); return reinterpret_cast( - getArrayIndexStarts() + NumCaptures + 1); + reinterpret_cast(getArrayIndexStarts()) + ArrayIndexSize); } public: @@ -1394,7 +1392,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == LambdaExprClass; } - static bool classof(const LambdaExpr *) { return true; } SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(IntroducerRange.getBegin(), ClosingBrace); @@ -1442,7 +1439,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXScalarValueInitExprClass; } - static bool classof(const CXXScalarValueInitExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1467,8 +1463,8 @@ class CXXNewExpr : public Expr { /// the source range covering the parenthesized type-id. SourceRange TypeIdParens; - /// \brief Location of the first token. - SourceLocation StartLoc; + /// \brief Range of the entire new expression. + SourceRange Range; /// \brief Source-range of a paren-delimited initializer. SourceRange DirectInitRange; @@ -1498,11 +1494,11 @@ public: CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, - Expr **placementArgs, unsigned numPlaceArgs, + ArrayRef placementArgs, SourceRange typeIdParens, Expr *arraySize, InitializationStyle initializationStyle, Expr *initializer, QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceRange directInitRange); + SourceRange Range, SourceRange directInitRange); explicit CXXNewExpr(EmptyShell Shell) : Expr(CXXNewExprClass, Shell), SubExprs(0) { } @@ -1580,7 +1576,7 @@ public: } /// \brief Returns the CXXConstructExpr from this new-expression, or NULL. - const CXXConstructExpr* getConstructExpr() { + const CXXConstructExpr* getConstructExpr() const { return dyn_cast_or_null(getInitializer()); } @@ -1617,19 +1613,18 @@ public: return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } - SourceLocation getStartLoc() const { return StartLoc; } - SourceLocation getEndLoc() const; + SourceLocation getStartLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } SourceRange getDirectInitRange() const { return DirectInitRange; } SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getStartLoc(), getEndLoc()); + return Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNewExprClass; } - static bool classof(const CXXNewExpr *) { return true; } // Iterators child_range children() { @@ -1700,7 +1695,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDeleteExprClass; } - static bool classof(const CXXDeleteExpr *) { return true; } // Iterators child_range children() { return child_range(&Argument, &Argument+1); } @@ -1889,7 +1883,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXPseudoDestructorExprClass; } - static bool classof(const CXXPseudoDestructorExpr *) { return true; } // Iterators child_range children() { return child_range(&Base, &Base + 1); } @@ -1945,7 +1938,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryTypeTraitExprClass; } - static bool classof(const UnaryTypeTraitExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -2017,7 +2009,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == BinaryTypeTraitExprClass; } - static bool classof(const BinaryTypeTraitExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -2111,7 +2102,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == TypeTraitExprClass; } - static bool classof(const TypeTraitExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -2186,7 +2176,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ArrayTypeTraitExprClass; } - static bool classof(const ArrayTypeTraitExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -2245,7 +2234,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ExpressionTraitExprClass; } - static bool classof(const ExpressionTraitExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -2432,7 +2420,6 @@ public: return T->getStmtClass() == UnresolvedLookupExprClass || T->getStmtClass() == UnresolvedMemberExprClass; } - static bool classof(const OverloadExpr *) { return true; } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -2454,10 +2441,6 @@ class UnresolvedLookupExpr : public OverloadExpr { /// call. bool RequiresADL; - /// True if namespace ::std should be considered an associated namespace - /// for the purposes of argument-dependent lookup. See C++0x [stmt.ranged]p1. - bool StdIsAssociatedNamespace; - /// True if these lookup results are overloaded. This is pretty /// trivially rederivable if we urgently need to kill this field. bool Overloaded; @@ -2476,19 +2459,16 @@ class UnresolvedLookupExpr : public OverloadExpr { const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool StdIsAssociatedNamespace) + UnresolvedSetIterator Begin, UnresolvedSetIterator End) : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, false, false, false), RequiresADL(RequiresADL), - StdIsAssociatedNamespace(StdIsAssociatedNamespace), Overloaded(Overloaded), NamingClass(NamingClass) {} UnresolvedLookupExpr(EmptyShell Empty) : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), StdIsAssociatedNamespace(false), Overloaded(false), - NamingClass(0) + RequiresADL(false), Overloaded(false), NamingClass(0) {} friend class ASTStmtReader; @@ -2500,14 +2480,10 @@ public: const DeclarationNameInfo &NameInfo, bool ADL, bool Overloaded, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, - bool StdIsAssociatedNamespace = false) { - assert((ADL || !StdIsAssociatedNamespace) && - "std considered associated namespace when not performing ADL"); + UnresolvedSetIterator End) { return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, SourceLocation(), NameInfo, - ADL, Overloaded, 0, Begin, End, - StdIsAssociatedNamespace); + ADL, Overloaded, 0, Begin, End); } static UnresolvedLookupExpr *Create(ASTContext &C, @@ -2528,10 +2504,6 @@ public: /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } - /// True if namespace \::std should be artificially added to the set of - /// associated namespaces for argument-dependent lookup purposes. - bool isStdAssociatedNamespace() const { return StdIsAssociatedNamespace; } - /// True if this lookup is overloaded. bool isOverloaded() const { return Overloaded; } @@ -2554,7 +2526,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == UnresolvedLookupExprClass; } - static bool classof(const UnresolvedLookupExpr *) { return true; } }; /// \brief A qualified reference to a name whose declaration cannot @@ -2705,7 +2676,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == DependentScopeDeclRefExprClass; } - static bool classof(const DependentScopeDeclRefExpr *) { return true; } child_range children() { return child_range(); } @@ -2778,7 +2748,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ExprWithCleanupsClass; } - static bool classof(const ExprWithCleanups *) { return true; } // Iterators child_range children() { return child_range(&SubExpr, &SubExpr + 1); } @@ -2820,8 +2789,7 @@ class CXXUnresolvedConstructExpr : public Expr { CXXUnresolvedConstructExpr(TypeSourceInfo *Type, SourceLocation LParenLoc, - Expr **Args, - unsigned NumArgs, + ArrayRef Args, SourceLocation RParenLoc); CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) @@ -2833,8 +2801,7 @@ public: static CXXUnresolvedConstructExpr *Create(ASTContext &C, TypeSourceInfo *Type, SourceLocation LParenLoc, - Expr **Args, - unsigned NumArgs, + ArrayRef Args, SourceLocation RParenLoc); static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C, @@ -2893,7 +2860,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUnresolvedConstructExprClass; } - static bool classof(const CXXUnresolvedConstructExpr *) { return true; } // Iterators child_range children() { @@ -3142,7 +3108,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDependentScopeMemberExprClass; } - static bool classof(const CXXDependentScopeMemberExpr *) { return true; } // Iterators child_range children() { @@ -3276,7 +3241,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == UnresolvedMemberExprClass; } - static bool classof(const UnresolvedMemberExpr *) { return true; } // Iterators child_range children() { @@ -3320,7 +3284,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNoexceptExprClass; } - static bool classof(const CXXNoexceptExpr *) { return true; } // Iterators child_range children() { return child_range(&Operand, &Operand + 1); } @@ -3397,7 +3360,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == PackExpansionExprClass; } - static bool classof(const PackExpansionExpr *) { return true; } // Iterators child_range children() { @@ -3503,7 +3465,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SizeOfPackExprClass; } - static bool classof(const SizeOfPackExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -3548,9 +3509,6 @@ public: static bool classof(const Stmt *s) { return s->getStmtClass() == SubstNonTypeTemplateParmExprClass; } - static bool classof(const SubstNonTypeTemplateParmExpr *) { - return true; - } // Iterators child_range children() { return child_range(&Replacement, &Replacement+1); } @@ -3561,7 +3519,7 @@ public: /// /// When a pack expansion in the source code contains multiple parameter packs /// and those parameter packs correspond to different levels of template -/// parameter lists, this node node is used to represent a non-type template +/// parameter lists, this node is used to represent a non-type template /// parameter pack from an outer level, which has already had its argument pack /// substituted but that still lives within a pack expansion that itself /// could not be instantiated. When actually performing a substitution into @@ -3608,14 +3566,77 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass; } - static bool classof(const SubstNonTypeTemplateParmPackExpr *) { - return true; - } // Iterators child_range children() { return child_range(); } }; +/// \brief Represents a reference to a function parameter pack that has been +/// substituted but not yet expanded. +/// +/// When a pack expansion contains multiple parameter packs at different levels, +/// this node is used to represent a function parameter pack at an outer level +/// which we have already substituted to refer to expanded parameters, but where +/// the containing pack expansion cannot yet be expanded. +/// +/// \code +/// template struct S { +/// template auto f(Ts ...ts) -> decltype(g(Us(ts)...)); +/// }; +/// template struct S; +/// \endcode +class FunctionParmPackExpr : public Expr { + /// \brief The function parameter pack which was referenced. + ParmVarDecl *ParamPack; + + /// \brief The location of the function parameter pack reference. + SourceLocation NameLoc; + + /// \brief The number of expansions of this pack. + unsigned NumParameters; + + FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, + SourceLocation NameLoc, unsigned NumParams, + Decl * const *Params); + + friend class ASTReader; + friend class ASTStmtReader; + +public: + static FunctionParmPackExpr *Create(ASTContext &Context, QualType T, + ParmVarDecl *ParamPack, + SourceLocation NameLoc, + llvm::ArrayRef Params); + static FunctionParmPackExpr *CreateEmpty(ASTContext &Context, + unsigned NumParams); + + /// \brief Get the parameter pack which this expression refers to. + ParmVarDecl *getParameterPack() const { return ParamPack; } + + /// \brief Get the location of the parameter pack. + SourceLocation getParameterPackLocation() const { return NameLoc; } + + /// \brief Iterators over the parameters which the parameter pack expanded + /// into. + typedef ParmVarDecl * const *iterator; + iterator begin() const { return reinterpret_cast(this+1); } + iterator end() const { return begin() + NumParameters; } + + /// \brief Get the number of parameters in this parameter pack. + unsigned getNumExpansions() const { return NumParameters; } + + /// \brief Get an expansion of the parameter pack by index. + ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; } + + SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == FunctionParmPackExprClass; + } + + child_range children() { return child_range(); } +}; + /// \brief Represents a prvalue temporary that written into memory so that /// a reference can bind to it. /// @@ -3670,9 +3691,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == MaterializeTemporaryExprClass; } - static bool classof(const MaterializeTemporaryExpr *) { - return true; - } // Iterators child_range children() { return child_range(&Temporary, &Temporary + 1); } diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 93a5ada27915..27f5da0ce707 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -51,7 +51,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCStringLiteralClass; } - static bool classof(const ObjCStringLiteral *) { return true; } // Iterators child_range children() { return child_range(&String, &String+1); } @@ -81,7 +80,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCBoolLiteralExprClass; } - static bool classof(const ObjCBoolLiteralExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -121,7 +119,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCBoxedExprClass; } - static bool classof(const ObjCBoxedExpr *) { return true; } // Iterators child_range children() { return child_range(&SubExpr, &SubExpr+1); } @@ -156,7 +153,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCArrayLiteralClass; } - static bool classof(const ObjCArrayLiteral *) { return true; } /// \brief Retrieve elements of array of literals. Expr **getElements() { return reinterpret_cast(this + 1); } @@ -319,7 +315,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCDictionaryLiteralClass; } - static bool classof(const ObjCDictionaryLiteral *) { return true; } // Iterators child_range children() { @@ -372,7 +367,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCEncodeExprClass; } - static bool classof(const ObjCEncodeExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -409,7 +403,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSelectorExprClass; } - static bool classof(const ObjCSelectorExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -447,7 +440,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCProtocolExprClass; } - static bool classof(const ObjCProtocolExpr *) { return true; } // Iterators child_range children() { return child_range(); } @@ -501,7 +493,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIvarRefExprClass; } - static bool classof(const ObjCIvarRefExpr *) { return true; } // Iterators child_range children() { return child_range(&Base, &Base+1); } @@ -715,7 +706,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCPropertyRefExprClass; } - static bool classof(const ObjCPropertyRefExpr *) { return true; } // Iterators child_range children() { @@ -813,7 +803,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSubscriptRefExprClass; } - static bool classof(const ObjCSubscriptRefExpr *) { return true; } Expr *getBaseExpr() const { return cast(SubExprs[BASE]); } void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; } @@ -1156,10 +1145,8 @@ public: return getReceiverKind() == Class || getReceiverKind() == SuperClass; } - /// \brief Returns the receiver of an instance message. - /// - /// \brief Returns the object expression for an instance message, or - /// NULL for a message that is not an instance message. + /// \brief Returns the object expression (receiver) for an instance message, + /// or null for a message that is not an instance message. Expr *getInstanceReceiver() { if (getReceiverKind() == Instance) return static_cast(getReceiverPointer()); @@ -1208,6 +1195,17 @@ public: return SourceLocation(); } + /// \brief Retrieve the receiver type to which this message is being directed. + /// + /// This routine cross-cuts all of the different kinds of message + /// sends to determine what the underlying (statically known) type + /// of the receiver will be; use \c getReceiverKind() to determine + /// whether the message is a class or an instance method, whether it + /// is a send to super or not, etc. + /// + /// \returns The type of the receiver. + QualType getReceiverType() const; + /// \brief Retrieve the Objective-C interface to which this message /// is being directed, if known. /// @@ -1344,7 +1342,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCMessageExprClass; } - static bool classof(const ObjCMessageExpr *) { return true; } // Iterators child_range children(); @@ -1409,7 +1406,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIsaExprClass; } - static bool classof(const ObjCIsaExpr *) { return true; } // Iterators child_range children() { return child_range(&Base, &Base+1); } @@ -1483,7 +1479,6 @@ public: static bool classof(const Stmt *s) { return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass; } - static bool classof(const ObjCIndirectCopyRestoreExpr *) { return true; } }; /// \brief An Objective-C "bridged" cast expression, which casts between @@ -1532,8 +1527,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCBridgedCastExprClass; } - static bool classof(const ObjCBridgedCastExpr *) { return true; } - }; } // end namespace clang diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 7aedfe2ef600..db2bddb4bfca 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -162,7 +162,7 @@ public: } /// \brief Get the decls that are contained in a file in the Offset/Length - /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of + /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, SmallVectorImpl &Decls) {} diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index f6dd4ce6e69a..7fb33f27741a 100644 --- a/include/clang/AST/Makefile +++ b/include/clang/AST/Makefile @@ -1,6 +1,8 @@ CLANG_LEVEL := ../../.. TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc CommentNodes.inc +BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc \ + CommentNodes.inc CommentHTMLTags.inc \ + CommentHTMLTagsProperties.inc CommentCommandInfo.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -33,3 +35,18 @@ $(ObjDir)/CommentNodes.inc.tmp : $(TD_SRC_DIR)/CommentNodes.td $(CLANG_TBLGEN) \ $(Echo) "Building Clang comment node tables with tblgen" $(Verb) $(ClangTableGen) -gen-clang-comment-nodes -o $(call SYSPATH, $@) $< +$(ObjDir)/CommentHTMLTags.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td $(CLANG_TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang comment HTML tag matchers with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags -o $(call SYSPATH, $@) $< + +$(ObjDir)/CommentHTMLTagsProperties.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td \ + $(CLANG_TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang comment HTML tag properties with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags-properties -o $(call SYSPATH, $@) $< + +$(ObjDir)/CommentCommandInfo.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ + $(CLANG_TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang comment command info with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-comment-command-info -o $(call SYSPATH, $@) $< + diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index 51ae1daf14f3..f9fd1f906b55 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -83,7 +83,7 @@ public: /// \brief The Objective-C NSArray selectors. Selector getNSArraySelector(NSArrayMethodKind MK) const; - /// \brief Return NSArrayMethodKind if \arg Sel is such a selector. + /// \brief Return NSArrayMethodKind if \p Sel is such a selector. llvm::Optional getNSArrayMethodKind(Selector Sel); /// \brief Enumerates the NSDictionary methods used to generate literals. @@ -104,7 +104,7 @@ public: /// \brief The Objective-C NSDictionary selectors. Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; - /// \brief Return NSDictionaryMethodKind if \arg Sel is such a selector. + /// \brief Return NSDictionaryMethodKind if \p Sel is such a selector. llvm::Optional getNSDictionaryMethodKind(Selector Sel); @@ -169,7 +169,7 @@ public: Sel == getNSNumberLiteralSelector(MK, true); } - /// \brief Return NSNumberLiteralMethodKind if \arg Sel is such a selector. + /// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector. llvm::Optional getNSNumberLiteralMethodKind(Selector Sel) const; diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index a5aec1fdda6b..bf9e1cbc764b 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -97,8 +97,7 @@ private: Specifier(Other.Specifier) { } - NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not - // implement + void operator=(const NestedNameSpecifier &) LLVM_DELETED_FUNCTION; /// \brief Either find or insert the given nested name specifier /// mockup in the given context. diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 63594141ac66..18169fd60c83 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -288,7 +288,11 @@ enum CastKind { /// /// This particular cast kind is used for the conversion from a C++11 /// lambda expression to a block pointer. - CK_CopyAndAutoreleaseBlockObject + CK_CopyAndAutoreleaseBlockObject, + + // Convert a builtin function to a function pointer; only allowed in the + // callee of a call expression. + CK_BuiltinFnToFnPtr }; static const CastKind CK_Invalid = static_cast(-1); diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index f2c015fffe94..7babc1b24a13 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -39,6 +39,7 @@ struct PrintingPolicy { SuppressUnwrittenScope(false), SuppressInitializers(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), Bool(LO.Bool), + TerseOutput(false), SuppressAttributes(false), DumpSourceManager(0) { } /// \brief What language we're printing. @@ -134,6 +135,17 @@ struct PrintingPolicy { /// doesn't actually have 'bool' (because, e.g., it is defined as a macro). unsigned Bool : 1; + /// \brief Provide a 'terse' output. + /// + /// For example, in this mode we don't print function bodies, class members, + /// declarations inside namespaces etc. Effectively, this should print + /// only the requested declaration. + unsigned TerseOutput : 1; + + /// \brief When true, do not print attributes attached to the declaration. + /// + unsigned SuppressAttributes : 1; + /// \brief If we are "dumping" rather than "pretty-printing", this points to /// a SourceManager which will be used to dump SourceLocations. Dumping /// involves printing the internal details of the AST and pretty-printing diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 630626b438ee..3a8b2183a557 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -18,6 +18,7 @@ namespace clang { class ASTContext; class ASTReader; class Decl; +class Preprocessor; namespace comments { class FullComment; @@ -114,7 +115,8 @@ public: } /// Parse the comment, assuming it is attached to decl \c D. - comments::FullComment *parse(const ASTContext &Context, const Decl *D) const; + comments::FullComment *parse(const ASTContext &Context, + const Preprocessor *PP, const Decl *D) const; private: SourceRange Range; @@ -188,7 +190,7 @@ public: private: SourceManager &SourceMgr; std::vector Comments; - RawComment LastComment; + SourceLocation PrevCommentEndLoc; bool OnlyWhitespaceSeen; void addCommentsToFront(const std::vector &C) { diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 3a870d057bad..36556469eaf8 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -136,8 +136,8 @@ private: void Destroy(ASTContext &Ctx); - ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT - void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT + ASTRecordLayout(const ASTRecordLayout &) LLVM_DELETED_FUNCTION; + void operator=(const ASTRecordLayout &) LLVM_DELETED_FUNCTION; public: /// getAlignment - Get the record alignment in characters. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 2e56a486f3d0..f96e06797855 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -721,6 +721,7 @@ bool RecursiveASTVisitor::TraverseTemplateArgument( case TemplateArgument::Null: case TemplateArgument::Declaration: case TemplateArgument::Integral: + case TemplateArgument::NullPtr: return true; case TemplateArgument::Type: @@ -753,6 +754,7 @@ bool RecursiveASTVisitor::TraverseTemplateArgumentLoc( case TemplateArgument::Null: case TemplateArgument::Declaration: case TemplateArgument::Integral: + case TemplateArgument::NullPtr: return true; case TemplateArgument::Type: { @@ -799,7 +801,7 @@ bool RecursiveASTVisitor::TraverseConstructorInitializer( if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); - if (Init->isWritten()) + if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) TRY_TO(TraverseStmt(Init->getInit())); return true; } @@ -1827,7 +1829,7 @@ bool RecursiveASTVisitor::Traverse##STMT (STMT *S) { \ return true; \ } -DEF_TRAVERSE_STMT(AsmStmt, { +DEF_TRAVERSE_STMT(GCCAsmStmt, { TRY_TO(TraverseStmt(S->getAsmString())); for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I))); @@ -1836,7 +1838,7 @@ DEF_TRAVERSE_STMT(AsmStmt, { TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I))); } for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { - TRY_TO(TraverseStmt(S->getClobber(I))); + TRY_TO(TraverseStmt(S->getClobberStringLiteral(I))); } // children() iterates over inputExpr and outputExpr. }) @@ -2141,7 +2143,9 @@ DEF_TRAVERSE_STMT(BlockExpr, { return true; // no child statements to loop through. }) DEF_TRAVERSE_STMT(ChooseExpr, { }) -DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) +DEF_TRAVERSE_STMT(CompoundLiteralExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); +}) DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) @@ -2219,6 +2223,7 @@ DEF_TRAVERSE_STMT(PackExpansionExpr, { }) DEF_TRAVERSE_STMT(SizeOfPackExpr, { }) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { }) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { }) +DEF_TRAVERSE_STMT(FunctionParmPackExpr, { }) DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { }) DEF_TRAVERSE_STMT(AtomicExpr, { }) diff --git a/include/clang/AST/SelectorLocationsKind.h b/include/clang/AST/SelectorLocationsKind.h index cd43a5c49c55..6d903f820cd4 100644 --- a/include/clang/AST/SelectorLocationsKind.h +++ b/include/clang/AST/SelectorLocationsKind.h @@ -42,7 +42,7 @@ enum SelectorLocationsKind { SelLoc_StandardWithSpace = 2 }; -/// \brief Returns true if all \arg SelLocs are in a "standard" location. +/// \brief Returns true if all \p SelLocs are in a "standard" location. SelectorLocationsKind hasStandardSelectorLocs(Selector Sel, ArrayRef SelLocs, ArrayRef Args, @@ -60,7 +60,7 @@ SourceLocation getStandardSelectorLoc(unsigned Index, ArrayRef Args, SourceLocation EndLoc); -/// \brief Returns true if all \arg SelLocs are in a "standard" location. +/// \brief Returns true if all \p SelLocs are in a "standard" location. SelectorLocationsKind hasStandardSelectorLocs(Selector Sel, ArrayRef SelLocs, ArrayRef Args, diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 35fb69312b6e..a9bbb48f0368 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -392,9 +392,6 @@ public: const_cast(this)->stripLabelLikeStatements()); } - // Implement isa support. - static bool classof(const Stmt *) { return true; } - /// hasImplicitControlFlow - Some statements (e.g. short circuited operations) /// contain implicit control-flow in the order their subexpressions /// are evaluated. This predicate returns true if this statement has @@ -424,12 +421,12 @@ public: /// \brief Produce a unique representation of the given statement. /// - /// \brief ID once the profiling operation is complete, will contain + /// \param ID once the profiling operation is complete, will contain /// the unique representation of the given statement. /// - /// \brief Context the AST context in which the statement resides + /// \param Context the AST context in which the statement resides /// - /// \brief Canonical whether the profile should be based on the canonical + /// \param Canonical whether the profile should be based on the canonical /// representation of this statement (e.g., where non-type template /// parameters are identified by index/level rather than their /// declaration pointers) or the exact representation of the statement as @@ -480,7 +477,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == DeclStmtClass; } - static bool classof(const DeclStmt *) { return true; } // Iterators over subexpressions. child_range children() { @@ -535,7 +531,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == NullStmtClass; } - static bool classof(const NullStmt *) { return true; } child_range children() { return child_range(); } @@ -615,7 +610,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CompoundStmtClass; } - static bool classof(const CompoundStmt *) { return true; } // Iterators child_range children() { @@ -654,7 +648,6 @@ public: return T->getStmtClass() == CaseStmtClass || T->getStmtClass() == DefaultStmtClass; } - static bool classof(const SwitchCase *) { return true; } }; class CaseStmt : public SwitchCase { @@ -714,7 +707,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CaseStmtClass; } - static bool classof(const CaseStmt *) { return true; } // Iterators child_range children() { @@ -749,7 +741,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == DefaultStmtClass; } - static bool classof(const DefaultStmt *) { return true; } // Iterators child_range children() { return child_range(&SubStmt, &SubStmt+1); } @@ -788,7 +779,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == LabelStmtClass; } - static bool classof(const LabelStmt *) { return true; } }; @@ -837,7 +827,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == AttributedStmtClass; } - static bool classof(const AttributedStmt *) { return true; } }; @@ -906,7 +895,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == IfStmtClass; } - static bool classof(const IfStmt *) { return true; } }; /// SwitchStmt - This represents a 'switch' stmt. @@ -1000,7 +988,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SwitchStmtClass; } - static bool classof(const SwitchStmt *) { return true; } }; @@ -1050,7 +1037,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == WhileStmtClass; } - static bool classof(const WhileStmt *) { return true; } // Iterators child_range children() { @@ -1099,7 +1085,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == DoStmtClass; } - static bool classof(const DoStmt *) { return true; } // Iterators child_range children() { @@ -1171,7 +1156,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ForStmtClass; } - static bool classof(const ForStmt *) { return true; } // Iterators child_range children() { @@ -1206,7 +1190,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == GotoStmtClass; } - static bool classof(const GotoStmt *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1251,7 +1234,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == IndirectGotoStmtClass; } - static bool classof(const IndirectGotoStmt *) { return true; } // Iterators child_range children() { return child_range(&Target, &Target+1); } @@ -1278,7 +1260,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ContinueStmtClass; } - static bool classof(const ContinueStmt *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1302,7 +1283,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == BreakStmtClass; } - static bool classof(const BreakStmt *) { return true; } // Iterators child_range children() { return child_range(); } @@ -1354,7 +1334,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ReturnStmtClass; } - static bool classof(const ReturnStmt *) { return true; } // Iterators child_range children() { @@ -1363,48 +1342,184 @@ public: } }; -/// AsmStmt - This represents a GNU inline-assembly statement extension. +/// AsmStmt is the base class for GCCAsmStmt and MSAsmStmt. /// class AsmStmt : public Stmt { - SourceLocation AsmLoc, RParenLoc; - StringLiteral *AsmStr; - +protected: + SourceLocation AsmLoc; + /// \brief True if the assembly statement does not have any input or output + /// operands. bool IsSimple; + + /// \brief If true, treat this inline assembly as having side effects. + /// This assembly statement should not be optimized, deleted or moved. bool IsVolatile; - bool MSAsm; unsigned NumOutputs; unsigned NumInputs; unsigned NumClobbers; - // FIXME: If we wanted to, we could allocate all of these in one big array. IdentifierInfo **Names; - StringLiteral **Constraints; Stmt **Exprs; - StringLiteral **Clobbers; -public: - AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, - bool msasm, unsigned numoutputs, unsigned numinputs, - IdentifierInfo **names, StringLiteral **constraints, - Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, - StringLiteral **clobbers, SourceLocation rparenloc); + AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile, + unsigned numoutputs, unsigned numinputs, unsigned numclobbers) : + Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile), + NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { } +public: /// \brief Build an empty inline-assembly statement. - explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty), - Names(0), Constraints(0), Exprs(0), Clobbers(0) { } + explicit AsmStmt(StmtClass SC, EmptyShell Empty) : + Stmt(SC, Empty), Names(0), Exprs(0) { } SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - bool isVolatile() const { return IsVolatile; } - void setVolatile(bool V) { IsVolatile = V; } bool isSimple() const { return IsSimple; } void setSimple(bool V) { IsSimple = V; } - bool isMSAsm() const { return MSAsm; } - void setMSAsm(bool V) { MSAsm = V; } + + bool isVolatile() const { return IsVolatile; } + void setVolatile(bool V) { IsVolatile = V; } + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(); } + + //===--- Asm String Analysis ---===// + + /// Assemble final IR asm string. + std::string generateAsmString(ASTContext &C) const; + + //===--- Output operands ---===// + + unsigned getNumOutputs() const { return NumOutputs; } + + IdentifierInfo *getOutputIdentifier(unsigned i) const { + return Names[i]; + } + + StringRef getOutputName(unsigned i) const { + if (IdentifierInfo *II = getOutputIdentifier(i)) + return II->getName(); + + return StringRef(); + } + + /// getOutputConstraint - Return the constraint string for the specified + /// output operand. All output constraints are known to be non-empty (either + /// '=' or '+'). + StringRef getOutputConstraint(unsigned i) const; + + /// isOutputPlusConstraint - Return true if the specified output constraint + /// is a "+" constraint (which is both an input and an output) or false if it + /// is an "=" constraint (just an output). + bool isOutputPlusConstraint(unsigned i) const { + return getOutputConstraint(i)[0] == '+'; + } + + const Expr *getOutputExpr(unsigned i) const; + + /// getNumPlusOperands - Return the number of output operands that have a "+" + /// constraint. + unsigned getNumPlusOperands() const; + + //===--- Input operands ---===// + + unsigned getNumInputs() const { return NumInputs; } + + IdentifierInfo *getInputIdentifier(unsigned i) const { + return Names[i + NumOutputs]; + } + + StringRef getInputName(unsigned i) const { + if (IdentifierInfo *II = getInputIdentifier(i)) + return II->getName(); + + return StringRef(); + } + + /// getInputConstraint - Return the specified input constraint. Unlike output + /// constraints, these can be empty. + StringRef getInputConstraint(unsigned i) const; + + const Expr *getInputExpr(unsigned i) const; + + //===--- Other ---===// + + unsigned getNumClobbers() const { return NumClobbers; } + StringRef getClobber(unsigned i) const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == GCCAsmStmtClass || + T->getStmtClass() == MSAsmStmtClass; + } + + // Input expr iterators. + + typedef ExprIterator inputs_iterator; + typedef ConstExprIterator const_inputs_iterator; + + inputs_iterator begin_inputs() { + return &Exprs[0] + NumOutputs; + } + + inputs_iterator end_inputs() { + return &Exprs[0] + NumOutputs + NumInputs; + } + + const_inputs_iterator begin_inputs() const { + return &Exprs[0] + NumOutputs; + } + + const_inputs_iterator end_inputs() const { + return &Exprs[0] + NumOutputs + NumInputs; + } + + // Output expr iterators. + + typedef ExprIterator outputs_iterator; + typedef ConstExprIterator const_outputs_iterator; + + outputs_iterator begin_outputs() { + return &Exprs[0]; + } + outputs_iterator end_outputs() { + return &Exprs[0] + NumOutputs; + } + + const_outputs_iterator begin_outputs() const { + return &Exprs[0]; + } + const_outputs_iterator end_outputs() const { + return &Exprs[0] + NumOutputs; + } + + child_range children() { + return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs); + } +}; + +/// This represents a GCC inline-assembly statement extension. +/// +class GCCAsmStmt : public AsmStmt { + SourceLocation RParenLoc; + StringLiteral *AsmStr; + + // FIXME: If we wanted to, we could allocate all of these in one big array. + StringLiteral **Constraints; + StringLiteral **Clobbers; + +public: + GCCAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, + bool isvolatile, unsigned numoutputs, unsigned numinputs, + IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, + StringLiteral *asmstr, unsigned numclobbers, + StringLiteral **clobbers, SourceLocation rparenloc); + + /// \brief Build an empty inline-assembly statement. + explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty), + Constraints(0), Clobbers(0) { } + + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } //===--- Asm String Analysis ---===// @@ -1461,25 +1576,11 @@ public: unsigned AnalyzeAsmString(SmallVectorImpl &Pieces, ASTContext &C, unsigned &DiagOffs) const; + /// Assemble final IR asm string. + std::string generateAsmString(ASTContext &C) const; //===--- Output operands ---===// - unsigned getNumOutputs() const { return NumOutputs; } - - IdentifierInfo *getOutputIdentifier(unsigned i) const { - return Names[i]; - } - - StringRef getOutputName(unsigned i) const { - if (IdentifierInfo *II = getOutputIdentifier(i)) - return II->getName(); - - return StringRef(); - } - - /// getOutputConstraint - Return the constraint string for the specified - /// output operand. All output constraints are known to be non-empty (either - /// '=' or '+'). StringRef getOutputConstraint(unsigned i) const; const StringLiteral *getOutputConstraintLiteral(unsigned i) const { @@ -1492,37 +1593,11 @@ public: Expr *getOutputExpr(unsigned i); const Expr *getOutputExpr(unsigned i) const { - return const_cast(this)->getOutputExpr(i); + return const_cast(this)->getOutputExpr(i); } - /// isOutputPlusConstraint - Return true if the specified output constraint - /// is a "+" constraint (which is both an input and an output) or false if it - /// is an "=" constraint (just an output). - bool isOutputPlusConstraint(unsigned i) const { - return getOutputConstraint(i)[0] == '+'; - } - - /// getNumPlusOperands - Return the number of output operands that have a "+" - /// constraint. - unsigned getNumPlusOperands() const; - //===--- Input operands ---===// - unsigned getNumInputs() const { return NumInputs; } - - IdentifierInfo *getInputIdentifier(unsigned i) const { - return Names[i + NumOutputs]; - } - - StringRef getInputName(unsigned i) const { - if (IdentifierInfo *II = getInputIdentifier(i)) - return II->getName(); - - return StringRef(); - } - - /// getInputConstraint - Return the specified input constraint. Unlike output - /// constraints, these can be empty. StringRef getInputConstraint(unsigned i) const; const StringLiteral *getInputConstraintLiteral(unsigned i) const { @@ -1536,7 +1611,7 @@ public: void setInputExpr(unsigned i, Expr *E); const Expr *getInputExpr(unsigned i) const { - return const_cast(this)->getInputExpr(i); + return const_cast(this)->getInputExpr(i); } void setOutputsAndInputsAndClobbers(ASTContext &C, @@ -1555,90 +1630,45 @@ public: /// This returns -1 if the operand name is invalid. int getNamedOperand(StringRef SymbolicName) const; - unsigned getNumClobbers() const { return NumClobbers; } - StringLiteral *getClobber(unsigned i) { return Clobbers[i]; } - const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; } + StringRef getClobber(unsigned i) const; + StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; } + const StringLiteral *getClobberStringLiteral(unsigned i) const { + return Clobbers[i]; + } SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AsmLoc, RParenLoc); } - static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;} - static bool classof(const AsmStmt *) { return true; } - - // Input expr iterators. - - typedef ExprIterator inputs_iterator; - typedef ConstExprIterator const_inputs_iterator; - - inputs_iterator begin_inputs() { - return &Exprs[0] + NumOutputs; - } - - inputs_iterator end_inputs() { - return &Exprs[0] + NumOutputs + NumInputs; - } - - const_inputs_iterator begin_inputs() const { - return &Exprs[0] + NumOutputs; - } - - const_inputs_iterator end_inputs() const { - return &Exprs[0] + NumOutputs + NumInputs; - } - - // Output expr iterators. - - typedef ExprIterator outputs_iterator; - typedef ConstExprIterator const_outputs_iterator; - - outputs_iterator begin_outputs() { - return &Exprs[0]; - } - outputs_iterator end_outputs() { - return &Exprs[0] + NumOutputs; - } - - const_outputs_iterator begin_outputs() const { - return &Exprs[0]; - } - const_outputs_iterator end_outputs() const { - return &Exprs[0] + NumOutputs; - } - - child_range children() { - return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs); + static bool classof(const Stmt *T) { + return T->getStmtClass() == GCCAsmStmtClass; } }; -/// MSAsmStmt - This represents a MS inline-assembly statement extension. +/// This represents a Microsoft inline-assembly statement extension. /// -class MSAsmStmt : public Stmt { +class MSAsmStmt : public AsmStmt { SourceLocation AsmLoc, LBraceLoc, EndLoc; std::string AsmStr; - bool IsSimple; - bool IsVolatile; - unsigned NumAsmToks; - unsigned NumInputs; - unsigned NumOutputs; - unsigned NumClobbers; Token *AsmToks; - IdentifierInfo **Names; - Stmt **Exprs; + StringRef *Constraints; StringRef *Clobbers; public: MSAsmStmt(ASTContext &C, SourceLocation asmloc, SourceLocation lbraceloc, bool issimple, bool isvolatile, ArrayRef asmtoks, - ArrayRef inputs, ArrayRef outputs, - StringRef asmstr, ArrayRef clobbers, - SourceLocation endloc); + unsigned numoutputs, unsigned numinputs, + ArrayRef names, ArrayRef constraints, + ArrayRef exprs, StringRef asmstr, + ArrayRef clobbers, SourceLocation endloc); + + /// \brief Build an empty MS-style inline-assembly statement. + explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty), + NumAsmToks(0), AsmToks(0), Constraints(0), Clobbers(0) { } - SourceLocation getAsmLoc() const { return AsmLoc; } - void setAsmLoc(SourceLocation L) { AsmLoc = L; } SourceLocation getLBraceLoc() const { return LBraceLoc; } void setLBraceLoc(SourceLocation L) { LBraceLoc = L; } SourceLocation getEndLoc() const { return EndLoc; } @@ -1649,20 +1679,42 @@ public: unsigned getNumAsmToks() { return NumAsmToks; } Token *getAsmToks() { return AsmToks; } - bool isVolatile() const { return IsVolatile; } - void setVolatile(bool V) { IsVolatile = V; } - bool isSimple() const { return IsSimple; } - void setSimple(bool V) { IsSimple = V; } - //===--- Asm String Analysis ---===// const std::string *getAsmString() const { return &AsmStr; } std::string *getAsmString() { return &AsmStr; } void setAsmString(StringRef &E) { AsmStr = E.str(); } + /// Assemble final IR asm string. + std::string generateAsmString(ASTContext &C) const; + + //===--- Output operands ---===// + + StringRef getOutputConstraint(unsigned i) const { + return Constraints[i]; + } + + Expr *getOutputExpr(unsigned i); + + const Expr *getOutputExpr(unsigned i) const { + return const_cast(this)->getOutputExpr(i); + } + + //===--- Input operands ---===// + + StringRef getInputConstraint(unsigned i) const { + return Constraints[i + NumOutputs]; + } + + Expr *getInputExpr(unsigned i); + void setInputExpr(unsigned i, Expr *E); + + const Expr *getInputExpr(unsigned i) const { + return const_cast(this)->getInputExpr(i); + } + //===--- Other ---===// - unsigned getNumClobbers() const { return NumClobbers; } StringRef getClobber(unsigned i) const { return Clobbers[i]; } SourceRange getSourceRange() const LLVM_READONLY { @@ -1671,7 +1723,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == MSAsmStmtClass; } - static bool classof(const MSAsmStmt *) { return true; } child_range children() { return child_range(&Exprs[0], &Exprs[0]); @@ -1720,8 +1771,6 @@ public: return T->getStmtClass() == SEHExceptStmtClass; } - static bool classof(SEHExceptStmt *) { return true; } - }; class SEHFinallyStmt : public Stmt { @@ -1757,8 +1806,6 @@ public: return T->getStmtClass() == SEHFinallyStmtClass; } - static bool classof(SEHFinallyStmt *) { return true; } - }; class SEHTryStmt : public Stmt { @@ -1810,8 +1857,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHTryStmtClass; } - - static bool classof(SEHTryStmt *) { return true; } }; } // end namespace clang diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index a948722cc1d5..f4e4dcdd4a5e 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -50,7 +50,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXCatchStmtClass; } - static bool classof(const CXXCatchStmt *) { return true; } child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); } @@ -111,7 +110,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTryStmtClass; } - static bool classof(const CXXTryStmt *) { return true; } child_range children() { return child_range(getStmts(), getStmts() + getNumHandlers() + 1); @@ -196,7 +194,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXForRangeStmtClass; } - static bool classof(const CXXForRangeStmt *) { return true; } // Iterators child_range children() { @@ -286,8 +283,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == MSDependentExistsStmtClass; } - - static bool classof(MSDependentExistsStmt *) { return true; } }; } // end namespace clang diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index e7e1232989e3..d7a73a70bd54 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -61,7 +61,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCForCollectionStmtClass; } - static bool classof(const ObjCForCollectionStmt *) { return true; } // Iterators child_range children() { @@ -112,7 +111,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtCatchStmtClass; } - static bool classof(const ObjCAtCatchStmt *) { return true; } child_range children() { return child_range(&Body, &Body + 1); } }; @@ -143,7 +141,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtFinallyStmtClass; } - static bool classof(const ObjCAtFinallyStmt *) { return true; } child_range children() { return child_range(&AtFinallyStmt, &AtFinallyStmt+1); @@ -244,7 +241,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtTryStmtClass; } - static bool classof(const ObjCAtTryStmt *) { return true; } child_range children() { return child_range(getStmts(), @@ -303,7 +299,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtSynchronizedStmtClass; } - static bool classof(const ObjCAtSynchronizedStmt *) { return true; } child_range children() { return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR); @@ -339,7 +334,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtThrowStmtClass; } - static bool classof(const ObjCAtThrowStmt *) { return true; } child_range children() { return child_range(&Throw, &Throw+1); } }; @@ -371,7 +365,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAutoreleasePoolStmtClass; } - static bool classof(const ObjCAutoreleasePoolStmt *) { return true; } child_range children() { return child_range(&SubStmt, &SubStmt + 1); } }; diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 5047028e5eac..1c0abde5b761 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -28,11 +28,11 @@ namespace llvm { namespace clang { -class Decl; class DiagnosticBuilder; class Expr; struct PrintingPolicy; class TypeSourceInfo; +class ValueDecl; /// \brief Represents a template argument within a class template /// specialization. @@ -43,12 +43,14 @@ public: /// \brief Represents an empty template argument, e.g., one that has not /// been deduced. Null = 0, - /// The template argument is a type. Its value is stored in the - /// TypeOrValue field. + /// The template argument is a type. Type, - /// The template argument is a declaration that was provided for a pointer - /// or reference non-type template parameter. + /// The template argument is a declaration that was provided for a pointer, + /// reference, or pointer to member non-type template parameter. Declaration, + /// The template argument is a null pointer or null pointer to member that + /// was provided for a non-type template parameter. + NullPtr, /// The template argument is an integral value stored in an llvm::APSInt /// that was provided for an integral non-type template parameter. Integral, @@ -72,6 +74,10 @@ private: union { uintptr_t TypeOrValue; + struct { + ValueDecl *D; + bool ForRefParam; + } DeclArg; struct { // We store a decomposed APSInt with the data allocated by ASTContext if // BitWidth > 64. The memory may be shared between multiple @@ -101,15 +107,18 @@ public: TemplateArgument() : Kind(Null), TypeOrValue(0) { } /// \brief Construct a template type argument. - TemplateArgument(QualType T) : Kind(Type) { + TemplateArgument(QualType T, bool isNullPtr = false) + : Kind(isNullPtr ? NullPtr : Type) { TypeOrValue = reinterpret_cast(T.getAsOpaquePtr()); } /// \brief Construct a template argument that refers to a /// declaration, which is either an external declaration or a /// template declaration. - TemplateArgument(Decl *D) : Kind(Declaration) { - TypeOrValue = reinterpret_cast(D); + TemplateArgument(ValueDecl *D, bool ForRefParam) : Kind(Declaration) { + assert(D && "Expected decl"); + DeclArg.D = D; + DeclArg.ForRefParam = ForRefParam; } /// \brief Construct an integral constant template argument. The memory to @@ -177,6 +186,10 @@ public: this->Args.NumArgs = NumArgs; } + static TemplateArgument getEmptyPack() { + return TemplateArgument((TemplateArgument*)0, 0); + } + /// \brief Create a new template argument pack by copying the given set of /// template arguments. static TemplateArgument CreatePackCopy(ASTContext &Context, @@ -205,34 +218,43 @@ public: /// \brief Determine whether this template argument is a pack expansion. bool isPackExpansion() const; - /// \brief Retrieve the template argument as a type. + /// \brief Retrieve the type for a type template argument. QualType getAsType() const { - if (Kind != Type) - return QualType(); - + assert(Kind == Type && "Unexpected kind"); return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue)); } - /// \brief Retrieve the template argument as a declaration. - Decl *getAsDecl() const { - if (Kind != Declaration) - return 0; - return reinterpret_cast(TypeOrValue); + /// \brief Retrieve the declaration for a declaration non-type + /// template argument. + ValueDecl *getAsDecl() const { + assert(Kind == Declaration && "Unexpected kind"); + return DeclArg.D; + } + + /// \brief Retrieve whether a declaration is binding to a + /// reference parameter in a declaration non-type template argument. + bool isDeclForReferenceParam() const { + assert(Kind == Declaration && "Unexpected kind"); + return DeclArg.ForRefParam; } - /// \brief Retrieve the template argument as a template name. + /// \brief Retrieve the type for null non-type template argument. + QualType getNullPtrType() const { + assert(Kind == NullPtr && "Unexpected kind"); + return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue)); + } + + /// \brief Retrieve the template name for a template name argument. TemplateName getAsTemplate() const { - if (Kind != Template) - return TemplateName(); - + assert(Kind == Template && "Unexpected kind"); return TemplateName::getFromVoidPointer(TemplateArg.Name); } /// \brief Retrieve the template argument as a template name; if the argument /// is a pack expansion, return the pattern as a template name. TemplateName getAsTemplateOrTemplatePattern() const { - if (Kind != Template && Kind != TemplateExpansion) - return TemplateName(); + assert((Kind == Template || Kind == TemplateExpansion) && + "Unexpected kind"); return TemplateName::getFromVoidPointer(TemplateArg.Name); } @@ -244,6 +266,7 @@ public: /// \brief Retrieve the template argument as an integral value. // FIXME: Provide a way to read the integral data without copying the value. llvm::APSInt getAsIntegral() const { + assert(Kind == Integral && "Unexpected kind"); using namespace llvm; if (Integer.BitWidth <= 64) return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); @@ -255,23 +278,18 @@ public: /// \brief Retrieve the type of the integral value. QualType getIntegralType() const { - if (Kind != Integral) - return QualType(); - + assert(Kind == Integral && "Unexpected kind"); return QualType::getFromOpaquePtr(Integer.Type); } void setIntegralType(QualType T) { - assert(Kind == Integral && - "Cannot set the integral type of a non-integral template argument"); + assert(Kind == Integral && "Unexpected kind"); Integer.Type = T.getAsOpaquePtr(); } /// \brief Retrieve the template argument as an expression. Expr *getAsExpr() const { - if (Kind != Expression) - return 0; - + assert(Kind == Expression && "Unexpected kind"); return reinterpret_cast(TypeOrValue); } @@ -436,7 +454,17 @@ public: assert(Argument.getKind() == TemplateArgument::Declaration); return LocInfo.getAsExpr(); } - + + Expr *getSourceNullPtrExpression() const { + assert(Argument.getKind() == TemplateArgument::NullPtr); + return LocInfo.getAsExpr(); + } + + Expr *getSourceIntegralExpression() const { + assert(Argument.getKind() == TemplateArgument::Integral); + return LocInfo.getAsExpr(); + } + NestedNameSpecifierLoc getTemplateQualifierLoc() const { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 6564b66548a4..6900a7d40af9 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -20,6 +20,7 @@ #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/Visibility.h" +#include "clang/Basic/Specifiers.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "llvm/Support/type_traits.h" @@ -160,6 +161,44 @@ public: Qualifiers() : Mask(0) {} + /// \brief Returns the common set of qualifiers while removing them from + /// the given sets. + static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { + // If both are only CVR-qualified, bit operations are sufficient. + if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) { + Qualifiers Q; + Q.Mask = L.Mask & R.Mask; + L.Mask &= ~Q.Mask; + R.Mask &= ~Q.Mask; + return Q; + } + + Qualifiers Q; + unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers(); + Q.addCVRQualifiers(CommonCRV); + L.removeCVRQualifiers(CommonCRV); + R.removeCVRQualifiers(CommonCRV); + + if (L.getObjCGCAttr() == R.getObjCGCAttr()) { + Q.setObjCGCAttr(L.getObjCGCAttr()); + L.removeObjCGCAttr(); + R.removeObjCGCAttr(); + } + + if (L.getObjCLifetime() == R.getObjCLifetime()) { + Q.setObjCLifetime(L.getObjCLifetime()); + L.removeObjCLifetime(); + R.removeObjCLifetime(); + } + + if (L.getAddressSpace() == R.getAddressSpace()) { + Q.setAddressSpace(L.getAddressSpace()); + L.removeAddressSpace(); + R.removeAddressSpace(); + } + return Q; + } + static Qualifiers fromFastMask(unsigned Mask) { Qualifiers Qs; Qs.addFastQualifiers(Mask); @@ -333,6 +372,23 @@ public: } } + /// \brief Remove the qualifiers from the given set from this set. + void removeQualifiers(Qualifiers Q) { + // If the other set doesn't have any non-boolean qualifiers, just + // bit-and the inverse in. + if (!(Q.Mask & ~CVRMask)) + Mask &= ~Q.Mask; + else { + Mask &= ~(Q.Mask & CVRMask); + if (getObjCGCAttr() == Q.getObjCGCAttr()) + removeObjCGCAttr(); + if (getObjCLifetime() == Q.getObjCLifetime()) + removeObjCLifetime(); + if (getAddressSpace() == Q.getAddressSpace()) + removeAddressSpace(); + } + } + /// \brief Add the qualifiers from the given set to this set, given that /// they don't conflict. void addConsistentQualifiers(Qualifiers qs) { @@ -400,7 +456,7 @@ public: } Qualifiers &operator-=(Qualifiers R) { - Mask = Mask & ~(R.Mask); + removeQualifiers(R); return *this; } @@ -435,18 +491,6 @@ private: static const uint32_t AddressSpaceShift = 8; }; -/// CallingConv - Specifies the calling convention that a function uses. -enum CallingConv { - CC_Default, - CC_C, // __attribute__((cdecl)) - CC_X86StdCall, // __attribute__((stdcall)) - CC_X86FastCall, // __attribute__((fastcall)) - CC_X86ThisCall, // __attribute__((thiscall)) - CC_X86Pascal, // __attribute__((pascal)) - CC_AAPCS, // __attribute__((pcs("aapcs"))) - CC_AAPCS_VFP // __attribute__((pcs("aapcs-vfp"))) -}; - /// A std::pair-like structure for storing a qualified type split /// into its local qualifiers and its locally-unqualified type. struct SplitQualType { @@ -1126,8 +1170,8 @@ public: }; private: - Type(const Type&); // DO NOT IMPLEMENT. - void operator=(const Type&); // DO NOT IMPLEMENT. + Type(const Type &) LLVM_DELETED_FUNCTION; + void operator=(const Type &) LLVM_DELETED_FUNCTION; /// Bitfields required by the Type class. class TypeBitfields { @@ -1225,7 +1269,7 @@ protected: /// Extra information which affects how the function is called, like /// regparm and the calling convention. - unsigned ExtInfo : 8; + unsigned ExtInfo : 9; /// TypeQuals - Used only by FunctionProtoType, put here to pack with the /// other bitfields. @@ -1512,6 +1556,7 @@ public: bool isRecordType() const; bool isClassType() const; bool isStructureType() const; + bool isInterfaceType() const; bool isStructureOrClassType() const; bool isUnionType() const; bool isComplexIntegerType() const; // GCC _Complex integer type. @@ -1630,13 +1675,19 @@ public: const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; const ObjCObjectPointerType *getAsObjCQualifiedClassType() const; const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; - const CXXRecordDecl *getCXXRecordDeclForPointerType() const; /// \brief Retrieves the CXXRecordDecl that this type refers to, either /// because the type is a RecordType or because it is the injected-class-name /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; + /// If this is a pointer or reference to a RecordType, return the + /// CXXRecordDecl that that type refers to. + /// + /// If this is not a pointer or reference, or the type being pointed to does + /// not refer to a CXXRecordDecl, returns NULL. + const CXXRecordDecl *getPointeeCXXRecordDecl() const; + /// \brief Get the AutoType whose type will be deduced for a variable with /// an initializer of this type. This looks through declarators like pointer /// types, but not through decltype or typedefs. @@ -1738,8 +1789,6 @@ public: CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h LLVM_ATTRIBUTE_USED void dump() const; - static bool classof(const Type *) { return true; } - friend class ASTReader; friend class ASTWriter; }; @@ -1748,6 +1797,11 @@ public: /// until it reaches a TypedefType or a non-sugared type. template <> const TypedefType *Type::getAs() const; +/// \brief This will check for a TemplateSpecializationType by removing any +/// existing sugar until it reaches a TemplateSpecializationType or a +/// non-sugared type. +template <> const TemplateSpecializationType *Type::getAs() const; + // We can do canonical leaf types faster, because we don't have to // worry about preserving child type decoration. #define TYPE(Class, Base) @@ -1834,7 +1888,6 @@ public: } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } - static bool classof(const BuiltinType *) { return true; } }; /// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex @@ -1865,7 +1918,6 @@ public: } static bool classof(const Type *T) { return T->getTypeClass() == Complex; } - static bool classof(const ComplexType *) { return true; } }; /// ParenType - Sugar for parentheses used when specifying types. @@ -1897,7 +1949,6 @@ public: } static bool classof(const Type *T) { return T->getTypeClass() == Paren; } - static bool classof(const ParenType *) { return true; } }; /// PointerType - C99 6.7.5.1 - Pointer Declarators. @@ -1929,7 +1980,6 @@ public: } static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } - static bool classof(const PointerType *) { return true; } }; /// BlockPointerType - pointer to a block type. @@ -1965,7 +2015,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == BlockPointer; } - static bool classof(const BlockPointerType *) { return true; } }; /// ReferenceType - Base for LValueReferenceType and RValueReferenceType @@ -2013,7 +2062,6 @@ public: return T->getTypeClass() == LValueReference || T->getTypeClass() == RValueReference; } - static bool classof(const ReferenceType *) { return true; } }; /// LValueReferenceType - C++ [dcl.ref] - Lvalue reference @@ -2031,7 +2079,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == LValueReference; } - static bool classof(const LValueReferenceType *) { return true; } }; /// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference @@ -2048,7 +2095,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == RValueReference; } - static bool classof(const RValueReferenceType *) { return true; } }; /// MemberPointerType - C++ 8.3.3 - Pointers to members @@ -2103,7 +2149,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == MemberPointer; } - static bool classof(const MemberPointerType *) { return true; } }; /// ArrayType - C99 6.7.5.2 - Array Declarators. @@ -2159,7 +2204,6 @@ public: T->getTypeClass() == IncompleteArray || T->getTypeClass() == DependentSizedArray; } - static bool classof(const ArrayType *) { return true; } }; /// ConstantArrayType - This class represents the canonical version of @@ -2211,7 +2255,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray; } - static bool classof(const ConstantArrayType *) { return true; } }; /// IncompleteArrayType - This class represents C arrays with an unspecified @@ -2231,7 +2274,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == IncompleteArray; } - static bool classof(const IncompleteArrayType *) { return true; } friend class StmtIteratorBase; @@ -2294,7 +2336,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == VariableArray; } - static bool classof(const VariableArrayType *) { return true; } friend class StmtIteratorBase; @@ -2351,7 +2392,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == DependentSizedArray; } - static bool classof(const DependentSizedArrayType *) { return true; } friend class StmtIteratorBase; @@ -2397,7 +2437,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == DependentSizedExtVector; } - static bool classof(const DependentSizedExtVectorType *) { return true; } void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getElementType(), getSizeExpr()); @@ -2463,7 +2502,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector; } - static bool classof(const VectorType *) { return true; } }; /// ExtVectorType - Extended vector type. This type is created using @@ -2529,7 +2567,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == ExtVector; } - static bool classof(const ExtVectorType *) { return true; } }; /// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base @@ -2561,19 +2598,19 @@ class FunctionType : public Type { // * AST read and write // * Codegen class ExtInfo { - // Feel free to rearrange or add bits, but if you go over 8, + // Feel free to rearrange or add bits, but if you go over 9, // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. // | CC |noreturn|produces|regparm| - // |0 .. 2| 3 | 4 | 5 .. 7| + // |0 .. 3| 4 | 5 | 6 .. 8| // // regparm is either 0 (no regparm attribute) or the regparm value+1. - enum { CallConvMask = 0x7 }; - enum { NoReturnMask = 0x8 }; - enum { ProducesResultMask = 0x10 }; + enum { CallConvMask = 0xF }; + enum { NoReturnMask = 0x10 }; + enum { ProducesResultMask = 0x20 }; enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask), - RegParmOffset = 5 }; // Assumed to be the last field + RegParmOffset = 6 }; // Assumed to be the last field uint16_t Bits; @@ -2692,7 +2729,6 @@ public: return T->getTypeClass() == FunctionNoProto || T->getTypeClass() == FunctionProto; } - static bool classof(const FunctionType *) { return true; } }; /// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has @@ -2724,7 +2760,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == FunctionNoProto; } - static bool classof(const FunctionNoProtoType *) { return true; } }; /// FunctionProtoType - Represents a prototype with argument type info, e.g. @@ -2972,14 +3007,13 @@ public: // FIXME: Remove the string version. void printExceptionSpecification(std::string &S, - PrintingPolicy Policy) const; + const PrintingPolicy &Policy) const; void printExceptionSpecification(raw_ostream &OS, - PrintingPolicy Policy) const; + const PrintingPolicy &Policy) const; static bool classof(const Type *T) { return T->getTypeClass() == FunctionProto; } - static bool classof(const FunctionProtoType *) { return true; } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, @@ -3010,7 +3044,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == UnresolvedUsing; } - static bool classof(const UnresolvedUsingType *) { return true; } void Profile(llvm::FoldingSetNodeID &ID) { return Profile(ID, Decl); @@ -3042,7 +3075,6 @@ public: QualType desugar() const; static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } - static bool classof(const TypedefType *) { return true; } }; /// TypeOfExprType (GCC extension). @@ -3062,7 +3094,6 @@ public: bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } - static bool classof(const TypeOfExprType *) { return true; } }; /// \brief Internal representation of canonical, dependent @@ -3109,7 +3140,6 @@ public: bool isSugared() const { return true; } static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } - static bool classof(const TypeOfType *) { return true; } }; /// DecltypeType (C++0x) @@ -3131,7 +3161,6 @@ public: bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } - static bool classof(const DecltypeType *) { return true; } }; /// \brief Internal representation of canonical, dependent @@ -3184,7 +3213,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == UnaryTransform; } - static bool classof(const UnaryTransformType *) { return true; } }; class TagType : public Type { @@ -3207,7 +3235,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; } - static bool classof(const TagType *) { return true; } }; /// RecordType - This is a helper class that allows the use of isa/cast/dyncast @@ -3234,7 +3261,6 @@ public: QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == Record; } - static bool classof(const RecordType *) { return true; } }; /// EnumType - This is a helper class that allows the use of isa/cast/dyncast @@ -3253,7 +3279,6 @@ public: QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == Enum; } - static bool classof(const EnumType *) { return true; } }; /// AttributedType - An attributed type is a type to which a type @@ -3297,7 +3322,8 @@ public: attr_fastcall, attr_stdcall, attr_thiscall, - attr_pascal + attr_pascal, + attr_pnaclcall }; private: @@ -3341,7 +3367,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Attributed; } - static bool classof(const AttributedType *T) { return true; } }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { @@ -3415,7 +3440,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == TemplateTypeParm; } - static bool classof(const TemplateTypeParmType *T) { return true; } }; /// \brief Represents the result of substituting a type for a template @@ -3466,7 +3490,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == SubstTemplateTypeParm; } - static bool classof(const SubstTemplateTypeParmType *T) { return true; } }; /// \brief Represents the result of substituting a set of types for a template @@ -3519,7 +3542,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == SubstTemplateTypeParmPack; } - static bool classof(const SubstTemplateTypeParmPackType *T) { return true; } }; /// \brief Represents a C++0x auto type. @@ -3562,7 +3584,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Auto; } - static bool classof(const AutoType *T) { return true; } }; /// \brief Represents a type template specialization; the template @@ -3726,7 +3747,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == TemplateSpecialization; } - static bool classof(const TemplateSpecializationType *T) { return true; } }; /// \brief The injected class name of a C++ class template or class @@ -3789,13 +3809,14 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == InjectedClassName; } - static bool classof(const InjectedClassNameType *T) { return true; } }; /// \brief The kind of a tag type. enum TagTypeKind { /// \brief The "struct" keyword. TTK_Struct, + /// \brief The "__interface" keyword. + TTK_Interface, /// \brief The "union" keyword. TTK_Union, /// \brief The "class" keyword. @@ -3809,6 +3830,8 @@ enum TagTypeKind { enum ElaboratedTypeKeyword { /// \brief The "struct" keyword introduces the elaborated-type-specifier. ETK_Struct, + /// \brief The "__interface" keyword introduces the elaborated-type-specifier. + ETK_Interface, /// \brief The "union" keyword introduces the elaborated-type-specifier. ETK_Union, /// \brief The "class" keyword introduces the elaborated-type-specifier. @@ -3932,7 +3955,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Elaborated; } - static bool classof(const ElaboratedType *T) { return true; } }; /// \brief Represents a qualified type name for which the type name is @@ -3996,7 +4018,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == DependentName; } - static bool classof(const DependentNameType *T) { return true; } }; /// DependentTemplateSpecializationType - Represents a template @@ -4067,9 +4088,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == DependentTemplateSpecialization; } - static bool classof(const DependentTemplateSpecializationType *T) { - return true; - } }; /// \brief Represents a pack expansion of types. @@ -4150,9 +4168,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == PackExpansion; } - static bool classof(const PackExpansionType *T) { - return true; - } }; /// ObjCObjectType - Represents a class type in Objective C. @@ -4263,7 +4278,6 @@ public: return T->getTypeClass() == ObjCObject || T->getTypeClass() == ObjCInterface; } - static bool classof(const ObjCObjectType *) { return true; } }; /// ObjCObjectTypeImpl - A class providing a concrete implementation @@ -4327,7 +4341,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == ObjCInterface; } - static bool classof(const ObjCInterfaceType *) { return true; } // Nonsense to "hide" certain members of ObjCObjectType within this // class. People asking for protocols on an ObjCInterfaceType are @@ -4477,7 +4490,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } - static bool classof(const ObjCObjectPointerType *) { return true; } }; class AtomicType : public Type, public llvm::FoldingSetNode { @@ -4508,7 +4520,6 @@ class AtomicType : public Type, public llvm::FoldingSetNode { static bool classof(const Type *T) { return T->getTypeClass() == Atomic; } - static bool classof(const AtomicType *) { return true; } }; /// A qualifier set is used to build a set of qualifiers. diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 11a878d6b0f3..8a04bd8d5ee0 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -159,8 +159,6 @@ public: return !(LHS == RHS); } - static bool classof(const TypeLoc *TL) { return true; } - private: static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc); @@ -192,7 +190,6 @@ public: static bool classof(const TypeLoc *TL) { return !TL->getType().hasLocalQualifiers(); } - static bool classof(const UnqualTypeLoc *TL) { return true; } }; /// \brief Wrapper of type source information for a type with @@ -237,7 +234,6 @@ public: static bool classof(const TypeLoc *TL) { return TL->getType().hasLocalQualifiers(); } - static bool classof(const QualifiedTypeLoc *TL) { return true; } }; inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { @@ -250,11 +246,11 @@ inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { /// to a particular Type subclass. It is accepted for a single /// TypeLoc class to correspond to multiple Type classes. /// -/// \param Base a class from which to derive -/// \param Derived the class deriving from this one -/// \param TypeClass the concrete Type subclass associated with this +/// \tparam Base a class from which to derive +/// \tparam Derived the class deriving from this one +/// \tparam TypeClass the concrete Type subclass associated with this /// location type -/// \param LocalData the structure type of local location data for +/// \tparam LocalData the structure type of local location data for /// this type /// /// sizeof(LocalData) needs to be a multiple of sizeof(void*) or @@ -303,9 +299,6 @@ public: static bool classof(const UnqualTypeLoc *TL) { return Derived::classofType(TL->getTypePtr()); } - static bool classof(const Derived *TL) { - return true; - } TypeLoc getNextTypeLoc() const { return getNextTypeLoc(asDerived()->getInnerType()); @@ -380,9 +373,6 @@ public: static bool classof(const UnqualTypeLoc *TL) { return Derived::classofType(TL->getTypePtr()); } - static bool classof(const Derived *TL) { - return true; - } const TypeClass *getTypePtr() const { return cast(Base::getTypePtr()); @@ -417,7 +407,6 @@ public: } static bool classof(const TypeLoc *TL); - static bool classof(const TypeSpecTypeLoc *TL) { return true; } }; @@ -866,6 +855,7 @@ public: void initializeLocal(ASTContext &Context, SourceLocation Loc) { setNameLoc(Loc); + setNameEndLoc(Loc); } }; @@ -1060,6 +1050,8 @@ public: struct FunctionLocInfo { SourceLocation LocalRangeBegin; + SourceLocation LParenLoc; + SourceLocation RParenLoc; SourceLocation LocalRangeEnd; }; @@ -1083,6 +1075,24 @@ public: getLocalData()->LocalRangeEnd = L; } + SourceLocation getLParenLoc() const { + return this->getLocalData()->LParenLoc; + } + void setLParenLoc(SourceLocation Loc) { + this->getLocalData()->LParenLoc = Loc; + } + + SourceLocation getRParenLoc() const { + return this->getLocalData()->RParenLoc; + } + void setRParenLoc(SourceLocation Loc) { + this->getLocalData()->RParenLoc = Loc; + } + + SourceRange getParensRange() const { + return SourceRange(getLParenLoc(), getRParenLoc()); + } + ArrayRef getParams() const { return ArrayRef(getParmArray(), getNumArgs()); } @@ -1110,6 +1120,8 @@ public: void initializeLocal(ASTContext &Context, SourceLocation Loc) { setLocalRangeBegin(Loc); + setLParenLoc(Loc); + setRParenLoc(Loc); setLocalRangeEnd(Loc); for (unsigned i = 0, e = getNumArgs(); i != e; ++i) setArg(i, NULL); diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 0918dc44aa73..9f11ee5fe3e2 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -94,7 +94,7 @@ class UnresolvedSetImpl { private: template friend class UnresolvedSet; UnresolvedSetImpl() {} - UnresolvedSetImpl(const UnresolvedSetImpl &) {} + UnresolvedSetImpl(const UnresolvedSetImpl &) LLVM_DELETED_FUNCTION; public: // We don't currently support assignment through this iterator, so we might diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h index 392dad94a4a3..a6aa40b9d68b 100644 --- a/include/clang/AST/VTableBuilder.h +++ b/include/clang/AST/VTableBuilder.h @@ -147,9 +147,10 @@ private: assert((ComponentKind == CK_VCallOffset || ComponentKind == CK_VBaseOffset || ComponentKind == CK_OffsetToTop) && "Invalid component kind!"); - assert(Offset.getQuantity() <= ((1LL << 56) - 1) && "Offset is too big!"); + assert(Offset.getQuantity() < (1LL << 56) && "Offset is too big!"); + assert(Offset.getQuantity() >= -(1LL << 56) && "Offset is too small!"); - Value = ((Offset.getQuantity() << 3) | ComponentKind); + Value = (uint64_t(Offset.getQuantity()) << 3) | ComponentKind; } VTableComponent(Kind ComponentKind, uintptr_t Ptr) { diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index dd237eece3e4..30b4050e1c81 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -85,7 +85,14 @@ public: class MatchCallback { public: virtual ~MatchCallback(); + + /// \brief Called on every match by the \c MatchFinder. virtual void run(const MatchResult &Result) = 0; + + /// \brief Called at the start of each translation unit. + /// + /// Optionally override to do per translation unit tasks. + virtual void onStartOfTranslationUnit() {} }; /// \brief Called when parsing is finished. Intended for testing only. @@ -112,11 +119,24 @@ public: MatchCallback *Action); void addMatcher(const StatementMatcher &NodeMatch, MatchCallback *Action); + void addMatcher(const NestedNameSpecifierMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const TypeLocMatcher &NodeMatch, + MatchCallback *Action); /// @} /// \brief Creates a clang ASTConsumer that finds all matches. clang::ASTConsumer *newASTConsumer(); + /// \brief Finds all matches on the given \c Node. + /// + /// @{ + void findAll(const Decl &Node, ASTContext &Context); + void findAll(const Stmt &Node, ASTContext &Context); + /// @} + /// \brief Registers a callback to notify the end of parsing. /// /// The provided closure is called after parsing is done, before the AST is @@ -125,11 +145,10 @@ public: void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); private: - /// \brief The MatchCallback*'s will be called every time the - /// UntypedBaseMatcher matches on the AST. - std::vector< std::pair< - const internal::UntypedBaseMatcher*, - MatchCallback*> > Triggers; + /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called + /// when it matches. + std::vector > + MatcherCallbackPairs; /// \brief Called when parsing is done. ParsingDoneTestCallback *ParsingDone; diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 33ef3dc8d6e0..a70dd5c378bd 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -14,7 +14,7 @@ // a functional in-language DSL to express queries over the C++ AST. // // For example, to match a class with a certain name, one would call: -// record(hasName("MyClass")) +// recordDecl(hasName("MyClass")) // which returns a matcher that can be used to find all AST nodes that declare // a class named 'MyClass'. // @@ -25,7 +25,7 @@ // // For example, when we're interested in child classes of a certain class, we // would write: -// record(hasName("MyClass"), hasChild(id("child", record()))) +// recordDecl(hasName("MyClass"), hasChild(id("child", recordDecl()))) // When the match is found via the MatchFinder, a user provided callback will // be called with a BoundNodes instance that contains a mapping from the // strings that we provided for the id(...) calls to the nodes that were @@ -57,52 +57,47 @@ namespace ast_matchers { /// \brief Maps string IDs to AST nodes matched by parts of a matcher. /// -/// The bound nodes are generated by adding id(...) matchers into the -/// match expression around the matchers for the nodes we want to access later. +/// The bound nodes are generated by calling \c bind("id") on the node matchers +/// of the nodes we want to access later. /// -/// The instances of BoundNodes are created by MatchFinder when the user's +/// The instances of BoundNodes are created by \c MatchFinder when the user's /// callbacks are executed every time a match is found. class BoundNodes { public: - /// \brief Returns the AST node bound to 'ID'. - /// Returns NULL if there was no node bound to 'ID' or if there is a node but + /// \brief Returns the AST node bound to \c ID. + /// + /// Returns NULL if there was no node bound to \c ID or if there is a node but /// it cannot be converted to the specified type. - /// FIXME: We'll need one of those for every base type. + template + const T *getNodeAs(StringRef ID) const { + return MyBoundNodes.getNodeAs(ID); + } + + /// \brief Deprecated. Please use \c getNodeAs instead. /// @{ template const T *getDeclAs(StringRef ID) const { - return getNodeAs(DeclBindings, ID); + return getNodeAs(ID); } template const T *getStmtAs(StringRef ID) const { - return getNodeAs(StmtBindings, ID); + return getNodeAs(ID); } /// @} private: /// \brief Create BoundNodes from a pre-filled map of bindings. - BoundNodes(const std::map &DeclBindings, - const std::map &StmtBindings) - : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {} - - template - const T *getNodeAs(const MapT &Bindings, StringRef ID) const { - typename MapT::const_iterator It = Bindings.find(ID); - if (It == Bindings.end()) { - return NULL; - } - return llvm::dyn_cast(It->second); - } + BoundNodes(internal::BoundNodesMap &MyBoundNodes) + : MyBoundNodes(MyBoundNodes) {} - std::map DeclBindings; - std::map StmtBindings; + internal::BoundNodesMap MyBoundNodes; friend class internal::BoundNodesTree; }; -/// \brief If the provided matcher matches a node, binds the node to 'ID'. +/// \brief If the provided matcher matches a node, binds the node to \c ID. /// -/// FIXME: Add example for accessing it. +/// FIXME: Do we want to support this now that we have bind()? template internal::Matcher id(const std::string &ID, const internal::BindableMatcher &InnerMatcher) { @@ -113,20 +108,27 @@ internal::Matcher id(const std::string &ID, /// hierarchy. /// @{ typedef internal::Matcher DeclarationMatcher; -typedef internal::Matcher TypeMatcher; typedef internal::Matcher StatementMatcher; +typedef internal::Matcher TypeMatcher; +typedef internal::Matcher TypeLocMatcher; +typedef internal::Matcher NestedNameSpecifierMatcher; +typedef internal::Matcher NestedNameSpecifierLocMatcher; /// @} /// \brief Matches any node. /// /// Useful when another matcher requires a child matcher, but there's no /// additional constraint. This will often be used with an explicit conversion -/// to a internal::Matcher<> type such as TypeMatcher. +/// to an \c internal::Matcher<> type such as \c TypeMatcher. /// -/// Example: DeclarationMatcher(anything()) matches all declarations, e.g., +/// Example: \c DeclarationMatcher(anything()) matches all declarations, e.g., +/// \code /// "int* p" and "void f()" in /// int* p; /// void f(); +/// \endcode +/// +/// Usable as: Any Matcher inline internal::PolymorphicMatcherWithParam0 anything() { return internal::PolymorphicMatcherWithParam0(); } @@ -144,53 +146,69 @@ const internal::VariadicDynCastAllOfMatcher decl; /// \brief Matches a declaration of anything that could have a name. /// -/// Example matches X, S, the anonymous union type, i, and U; +/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U; +/// \code /// typedef int X; /// struct S { /// union { /// int i; /// } U; /// }; -const internal::VariadicDynCastAllOfMatcher< - Decl, - NamedDecl> nameableDeclaration; +/// \endcode +const internal::VariadicDynCastAllOfMatcher namedDecl; /// \brief Matches C++ class declarations. /// -/// Example matches X, Z +/// Example matches \c X, \c Z +/// \code /// class X; /// template class Z {}; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXRecordDecl> recordDecl; + +/// \brief Matches C++ class template declarations. +/// +/// Example matches \c Z +/// \code +/// template class Z {}; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - CXXRecordDecl> record; + ClassTemplateDecl> classTemplateDecl; /// \brief Matches C++ class template specializations. /// /// Given +/// \code /// template class A {}; /// template<> class A {}; /// A a; -/// classTemplateSpecialization() +/// \endcode +/// classTemplateSpecializationDecl() /// matches the specializations \c A and \c A const internal::VariadicDynCastAllOfMatcher< Decl, - ClassTemplateSpecializationDecl> classTemplateSpecialization; + ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; /// \brief Matches classTemplateSpecializations that have at least one -/// TemplateArgument matching the given Matcher. +/// TemplateArgument matching the given InnerMatcher. /// /// Given +/// \code /// template class A {}; /// template<> class A {}; /// A a; -/// classTemplateSpecialization(hasAnyTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(asString("int")))) /// matches the specialization \c A AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { const TemplateArgumentList &List = Node.getTemplateArgs(); for (unsigned i = 0; i < List.size(); ++i) { - if (Matcher.matches(List.get(i), Finder, Builder)) + if (InnerMatcher.matches(List.get(i), Finder, Builder)) return true; } return false; @@ -201,19 +219,25 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, /// /// Parentheses and explicit casts are not discarded. /// Given +/// \code /// int arr[5]; /// int a = 0; /// char b = 0; /// const int c = a; /// int *d = arr; /// long e = (long) 0l; +/// \endcode /// The matchers -/// variable(hasInitializer(ignoringImpCasts(integerLiteral()))) -/// variable(hasInitializer(ignoringImpCasts(declarationReference()))) +/// \code +/// varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringImpCasts(declRefExpr()))) +/// \endcode /// would match the declarations for a, b, c, and d, but not e. -/// while -/// variable(hasInitializer(integerLiteral())) -/// variable(hasInitializer(declarationReference())) +/// While +/// \code +/// varDecl(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(declRefExpr())) +/// \endcode /// only match the declarations for b, c, and d. AST_MATCHER_P(Expr, ignoringImpCasts, internal::Matcher, InnerMatcher) { @@ -225,15 +249,17 @@ AST_MATCHER_P(Expr, ignoringImpCasts, /// /// Implicit and non-C Style casts are also discarded. /// Given +/// \code /// int a = 0; /// char b = (0); /// void* c = reinterpret_cast(0); /// char d = char(0); +/// \endcode /// The matcher -/// variable(hasInitializer(ignoringParenCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringParenCasts(integerLiteral()))) /// would match the declarations for a, b, c, and d. /// while -/// variable(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(integerLiteral())) /// only match the declaration for a. AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher, InnerMatcher) { return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder); @@ -244,21 +270,21 @@ AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher, InnerMatcher) { /// /// Explicit casts are not discarded. /// Given +/// \code /// int arr[5]; /// int a = 0; /// char b = (0); /// const int c = a; /// int *d = (arr); /// long e = ((long) 0l); +/// \endcode /// The matchers -/// variable(hasInitializer(ignoringParenImpCasts( -/// integerLiteral()))) -/// variable(hasInitializer(ignoringParenImpCasts( -/// declarationReference()))) +/// varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr()))) /// would match the declarations for a, b, c, and d, but not e. /// while -/// variable(hasInitializer(integerLiteral())) -/// variable(hasInitializer(declarationReference())) +/// varDecl(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(declRefExpr())) /// would only match the declaration for a. AST_MATCHER_P(Expr, ignoringParenImpCasts, internal::Matcher, InnerMatcher) { @@ -266,101 +292,119 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts, } /// \brief Matches classTemplateSpecializations where the n'th TemplateArgument -/// matches the given Matcher. +/// matches the given InnerMatcher. /// /// Given +/// \code /// template class A {}; /// A b; /// A c; -/// classTemplateSpecialization(hasTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasTemplateArgument( /// 1, refersToType(asString("int")))) /// matches the specialization \c A AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument, - unsigned, N, internal::Matcher, Matcher) { + unsigned, N, internal::Matcher, InnerMatcher) { const TemplateArgumentList &List = Node.getTemplateArgs(); if (List.size() <= N) return false; - return Matcher.matches(List.get(N), Finder, Builder); + return InnerMatcher.matches(List.get(N), Finder, Builder); } /// \brief Matches a TemplateArgument that refers to a certain type. /// /// Given +/// \code /// struct X {}; /// template struct A {}; /// A a; -/// classTemplateSpecialization(hasAnyTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(class(hasName("X"))))) /// matches the specialization \c A AST_MATCHER_P(TemplateArgument, refersToType, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { if (Node.getKind() != TemplateArgument::Type) return false; - return Matcher.matches(Node.getAsType(), Finder, Builder); + return InnerMatcher.matches(Node.getAsType(), Finder, Builder); } /// \brief Matches a TemplateArgument that refers to a certain declaration. /// /// Given +/// \code /// template struct A {}; /// struct B { B* next; }; /// A<&B::next> a; -/// classTemplateSpecialization(hasAnyTemplateArgument( -/// refersToDeclaration(field(hasName("next")))) -/// matches the specialization \c A<&B::next> with \c field(...) matching +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( +/// refersToDeclaration(fieldDecl(hasName("next")))) +/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching /// \c B::next AST_MATCHER_P(TemplateArgument, refersToDeclaration, - internal::Matcher, Matcher) { - if (const Decl *Declaration = Node.getAsDecl()) - return Matcher.matches(*Declaration, Finder, Builder); + internal::Matcher, InnerMatcher) { + if (Node.getKind() == TemplateArgument::Declaration) + return InnerMatcher.matches(*Node.getAsDecl(), Finder, Builder); return false; } /// \brief Matches C++ constructor declarations. /// /// Example matches Foo::Foo() and Foo::Foo(int) +/// \code /// class Foo { /// public: /// Foo(); /// Foo(int); /// int DoSomething(); /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - CXXConstructorDecl> constructor; + CXXConstructorDecl> constructorDecl; /// \brief Matches explicit C++ destructor declarations. /// /// Example matches Foo::~Foo() +/// \code /// class Foo { /// public: /// virtual ~Foo(); /// }; -const internal::VariadicDynCastAllOfMatcher destructor; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXDestructorDecl> destructorDecl; /// \brief Matches enum declarations. /// /// Example matches X +/// \code /// enum X { /// A, B, C /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher enumDecl; /// \brief Matches enum constants. /// /// Example matches A, B, C +/// \code /// enum X { /// A, B, C /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - EnumConstantDecl> enumConstant; + EnumConstantDecl> enumConstantDecl; /// \brief Matches method declarations. /// /// Example matches y +/// \code /// class X { void y() }; -const internal::VariadicDynCastAllOfMatcher method; +/// \endcode +const internal::VariadicDynCastAllOfMatcher methodDecl; /// \brief Matches variable declarations. /// @@ -368,76 +412,111 @@ const internal::VariadicDynCastAllOfMatcher method; /// "field" declarations in Clang parlance. /// /// Example matches a +/// \code /// int a; -const internal::VariadicDynCastAllOfMatcher variable; +/// \endcode +const internal::VariadicDynCastAllOfMatcher varDecl; /// \brief Matches field declarations. /// /// Given +/// \code /// class X { int m; }; -/// field() +/// \endcode +/// fieldDecl() /// matches 'm'. -const internal::VariadicDynCastAllOfMatcher field; +const internal::VariadicDynCastAllOfMatcher fieldDecl; /// \brief Matches function declarations. /// /// Example matches f +/// \code /// void f(); -const internal::VariadicDynCastAllOfMatcher function; +/// \endcode +const internal::VariadicDynCastAllOfMatcher functionDecl; +/// \brief Matches C++ function template declarations. +/// +/// Example matches f +/// \code +/// template void f(T t) {} +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + FunctionTemplateDecl> functionTemplateDecl; /// \brief Matches statements. /// /// Given +/// \code /// { ++a; } -/// statement() +/// \endcode +/// stmt() /// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicDynCastAllOfMatcher statement; +const internal::VariadicDynCastAllOfMatcher stmt; /// \brief Matches declaration statements. /// /// Given +/// \code /// int a; -/// declarationStatement() +/// \endcode +/// declStmt() /// matches 'int a'. const internal::VariadicDynCastAllOfMatcher< Stmt, - DeclStmt> declarationStatement; + DeclStmt> declStmt; /// \brief Matches member expressions. /// /// Given +/// \code /// class Y { /// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } /// int a; static int b; /// }; -/// memberExpression() +/// \endcode +/// memberExpr() /// matches this->x, x, y.x, a, this->b -const internal::VariadicDynCastAllOfMatcher< - Stmt, - MemberExpr> memberExpression; +const internal::VariadicDynCastAllOfMatcher memberExpr; /// \brief Matches call expressions. /// /// Example matches x.y() and y() +/// \code /// X x; /// x.y(); /// y(); -const internal::VariadicDynCastAllOfMatcher call; +/// \endcode +const internal::VariadicDynCastAllOfMatcher callExpr; + +/// \brief Matches lambda expressions. +/// +/// Example matches [&](){return 5;} +/// \code +/// [&](){return 5;} +/// \endcode +const internal::VariadicDynCastAllOfMatcher lambdaExpr; /// \brief Matches member call expressions. /// /// Example matches x.y() +/// \code /// X x; /// x.y(); -const internal::VariadicDynCastAllOfMatcher memberCall; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXMemberCallExpr> memberCallExpr; /// \brief Matches init list expressions. /// /// Given +/// \code /// int a[] = { 1, 2 }; /// struct B { int x, y; }; /// B b = { 5, 6 }; +/// \endcode /// initList() /// matches "{ 1, 2 }" and "{ 5, 6 }" const internal::VariadicDynCastAllOfMatcher initListExpr; @@ -445,8 +524,10 @@ const internal::VariadicDynCastAllOfMatcher initListExpr; /// \brief Matches using declarations. /// /// Given +/// \code /// namespace X { int x; } /// using X::x; +/// \endcode /// usingDecl() /// matches \code using X::x \endcode const internal::VariadicDynCastAllOfMatcher usingDecl; @@ -454,49 +535,89 @@ const internal::VariadicDynCastAllOfMatcher usingDecl; /// \brief Matches constructor call expressions (including implicit ones). /// /// Example matches string(ptr, n) and ptr within arguments of f -/// (matcher = constructorCall()) +/// (matcher = constructExpr()) +/// \code /// void f(const string &a, const string &b); /// char *ptr; /// int n; /// f(string(ptr, n), ptr); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXConstructExpr> constructorCall; + CXXConstructExpr> constructExpr; + +/// \brief Matches implicit and explicit this expressions. +/// +/// Example matches the implicit this expression in "return i". +/// (matcher = thisExpr()) +/// \code +/// struct foo { +/// int i; +/// int f() { return i; } +/// }; +/// \endcode +const internal::VariadicDynCastAllOfMatcher thisExpr; /// \brief Matches nodes where temporaries are created. /// /// Example matches FunctionTakesString(GetStringByValue()) -/// (matcher = bindTemporaryExpression()) +/// (matcher = bindTemporaryExpr()) +/// \code /// FunctionTakesString(GetStringByValue()); /// FunctionTakesStringByPointer(GetStringPointer()); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXBindTemporaryExpr> bindTemporaryExpression; + CXXBindTemporaryExpr> bindTemporaryExpr; + +/// \brief Matches nodes where temporaries are materialized. +/// +/// Example: Given +/// \code +/// struct T {void func()}; +/// T f(); +/// void g(T); +/// \endcode +/// materializeTemporaryExpr() matches 'f()' in these statements +/// \code +/// T u(f()); +/// g(f()); +/// \endcode +/// but does not match +/// \code +/// f(); +/// f().func(); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + MaterializeTemporaryExpr> materializeTemporaryExpr; /// \brief Matches new expressions. /// /// Given +/// \code /// new X; -/// newExpression() +/// \endcode +/// newExpr() /// matches 'new X'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXNewExpr> newExpression; +const internal::VariadicDynCastAllOfMatcher newExpr; /// \brief Matches delete expressions. /// /// Given +/// \code /// delete X; -/// deleteExpression() +/// \endcode +/// deleteExpr() /// matches 'delete X'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXDeleteExpr> deleteExpression; +const internal::VariadicDynCastAllOfMatcher deleteExpr; /// \brief Matches array subscript expressions. /// /// Given +/// \code /// int i = a[1]; +/// \endcode /// arraySubscriptExpr() /// matches "a[1]" const internal::VariadicDynCastAllOfMatcher< @@ -507,12 +628,14 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches the CXXDefaultArgExpr placeholder inserted for the /// default value of the second parameter in the call expression f(42) -/// (matcher = defaultArgument()) +/// (matcher = defaultArgExpr()) +/// \code /// void f(int x, int y = 0); /// f(42); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXDefaultArgExpr> defaultArgument; + CXXDefaultArgExpr> defaultArgExpr; /// \brief Matches overloaded operator calls. /// @@ -522,50 +645,67 @@ const internal::VariadicDynCastAllOfMatcher< /// FIXME: figure out why these do not match? /// /// Example matches both operator<<((o << b), c) and operator<<(o, b) -/// (matcher = overloadedOperatorCall()) +/// (matcher = operatorCallExpr()) +/// \code /// ostream &operator<< (ostream &out, int i) { }; /// ostream &o; int b = 1, c = 1; /// o << b << c; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXOperatorCallExpr> overloadedOperatorCall; + CXXOperatorCallExpr> operatorCallExpr; /// \brief Matches expressions. /// /// Example matches x() +/// \code /// void f() { x(); } -const internal::VariadicDynCastAllOfMatcher< - Stmt, - Expr> expression; +/// \endcode +const internal::VariadicDynCastAllOfMatcher expr; /// \brief Matches expressions that refer to declarations. /// /// Example matches x in if (x) +/// \code /// bool x; /// if (x) {} -const internal::VariadicDynCastAllOfMatcher< - Stmt, - DeclRefExpr> declarationReference; +/// \endcode +const internal::VariadicDynCastAllOfMatcher declRefExpr; /// \brief Matches if statements. /// /// Example matches 'if (x) {}' +/// \code /// if (x) {} +/// \endcode const internal::VariadicDynCastAllOfMatcher ifStmt; /// \brief Matches for statements. /// /// Example matches 'for (;;) {}' +/// \code /// for (;;) {} -const internal::VariadicDynCastAllOfMatcher< - Stmt, ForStmt> forStmt; +/// int i[] = {1, 2, 3}; for (auto a : i); +/// \endcode +const internal::VariadicDynCastAllOfMatcher forStmt; + +/// \brief Matches range-based for statements. +/// +/// forRangeStmt() matches 'for (auto a : i)' +/// \code +/// int i[] = {1, 2, 3}; for (auto a : i); +/// for(int j = 0; j < 5; ++j); +/// \endcode +const internal::VariadicDynCastAllOfMatcher forRangeStmt; /// \brief Matches the increment statement of a for loop. /// /// Example: /// forStmt(hasIncrement(unaryOperator(hasOperatorName("++")))) /// matches '++x' in +/// \code /// for (x; x < N; ++x) { } +/// \endcode AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher, InnerMatcher) { const Stmt *const Increment = Node.getInc(); @@ -576,9 +716,11 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher, /// \brief Matches the initialization statement of a for loop. /// /// Example: -/// forStmt(hasLoopInit(declarationStatement())) +/// forStmt(hasLoopInit(declStmt())) /// matches 'int x = 0' in +/// \code /// for (int x = 0; x < N; ++x) { } +/// \endcode AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher, InnerMatcher) { const Stmt *const Init = Node.getInit(); @@ -588,53 +730,167 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher, /// \brief Matches while statements. /// /// Given +/// \code /// while (true) {} +/// \endcode /// whileStmt() /// matches 'while (true) {}'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - WhileStmt> whileStmt; +const internal::VariadicDynCastAllOfMatcher whileStmt; /// \brief Matches do statements. /// /// Given +/// \code /// do {} while (true); +/// \endcode /// doStmt() /// matches 'do {} while(true)' const internal::VariadicDynCastAllOfMatcher doStmt; +/// \brief Matches break statements. +/// +/// Given +/// \code +/// while (true) { break; } +/// \endcode +/// breakStmt() +/// matches 'break' +const internal::VariadicDynCastAllOfMatcher breakStmt; + +/// \brief Matches continue statements. +/// +/// Given +/// \code +/// while (true) { continue; } +/// \endcode +/// continueStmt() +/// matches 'continue' +const internal::VariadicDynCastAllOfMatcher continueStmt; + +/// \brief Matches return statements. +/// +/// Given +/// \code +/// return 1; +/// \endcode +/// returnStmt() +/// matches 'return 1' +const internal::VariadicDynCastAllOfMatcher returnStmt; + +/// \brief Matches goto statements. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// gotoStmt() +/// matches 'goto FOO' +const internal::VariadicDynCastAllOfMatcher gotoStmt; + +/// \brief Matches label statements. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// labelStmt() +/// matches 'FOO:' +const internal::VariadicDynCastAllOfMatcher labelStmt; + +/// \brief Matches switch statements. +/// +/// Given +/// \code +/// switch(a) { case 42: break; default: break; } +/// \endcode +/// switchStmt() +/// matches 'switch(a)'. +const internal::VariadicDynCastAllOfMatcher switchStmt; + /// \brief Matches case and default statements inside switch statements. /// /// Given +/// \code /// switch(a) { case 42: break; default: break; } +/// \endcode /// switchCase() /// matches 'case 42: break;' and 'default: break;'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - SwitchCase> switchCase; +const internal::VariadicDynCastAllOfMatcher switchCase; /// \brief Matches compound statements. /// /// Example matches '{}' and '{{}}'in 'for (;;) {{}}' +/// \code /// for (;;) {{}} -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CompoundStmt> compoundStatement; +/// \endcode +const internal::VariadicDynCastAllOfMatcher compoundStmt; + +/// \brief Matches catch statements. +/// +/// \code +/// try {} catch(int i) {} +/// \endcode +/// catchStmt() +/// matches 'catch(int i)' +const internal::VariadicDynCastAllOfMatcher catchStmt; + +/// \brief Matches try statements. +/// +/// \code +/// try {} catch(int i) {} +/// \endcode +/// tryStmt() +/// matches 'try {}' +const internal::VariadicDynCastAllOfMatcher tryStmt; + +/// \brief Matches throw expressions. +/// +/// \code +/// try { throw 5; } catch(int i) {} +/// \endcode +/// throwExpr() +/// matches 'throw 5' +const internal::VariadicDynCastAllOfMatcher throwExpr; + +/// \brief Matches null statements. +/// +/// \code +/// foo();; +/// \endcode +/// nullStmt() +/// matches the second ';' +const internal::VariadicDynCastAllOfMatcher nullStmt; + +/// \brief Matches asm statements. +/// +/// \code +/// int i = 100; +/// __asm("mov al, 2"); +/// \endcode +/// asmStmt() +/// matches '__asm("mov al, 2")' +const internal::VariadicDynCastAllOfMatcher asmStmt; /// \brief Matches bool literals. /// /// Example matches true +/// \code /// true +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, CXXBoolLiteralExpr> boolLiteral; /// \brief Matches string literals (also matches wide string literals). /// /// Example matches "abcd", L"abcd" +/// \code /// char *s = "abcd"; wchar_t *ws = L"abcd" +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, StringLiteral> stringLiteral; /// \brief Matches character literals (also matches wchar_t). @@ -643,9 +899,11 @@ const internal::VariadicDynCastAllOfMatcher< /// though. /// /// Example matches 'a', L'a' +/// \code /// char ch = 'a'; wchar_t chw = L'a'; +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, CharacterLiteral> characterLiteral; /// \brief Matches integer literals of all sizes / encodings. @@ -654,13 +912,27 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches 1, 1L, 0x1, 1U const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, IntegerLiteral> integerLiteral; +/// \brief Matches user defined literal operator call. +/// +/// Example match: "foo"_suffix +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UserDefinedLiteral> userDefinedLiteral; + +/// \brief Matches nullptr literal. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXNullPtrLiteralExpr> nullPtrLiteralExpr; + /// \brief Matches binary operator expressions. /// /// Example matches a || b +/// \code /// !(a || b) +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator> binaryOperator; @@ -668,7 +940,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches unary operator expressions. /// /// Example matches !a +/// \code /// !a || b +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, UnaryOperator> unaryOperator; @@ -676,7 +950,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches conditional operator expressions. /// /// Example matches a ? b : c +/// \code /// (a ? b : c) + 42 +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, ConditionalOperator> conditionalOperator; @@ -688,10 +964,12 @@ const internal::VariadicDynCastAllOfMatcher< /// more readable. /// /// Example matches reinterpret_cast(&p) in +/// \code /// void* p = reinterpret_cast(&p); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXReinterpretCastExpr> reinterpretCast; + Stmt, + CXXReinterpretCastExpr> reinterpretCastExpr; /// \brief Matches a C++ static_cast expression. /// @@ -699,38 +977,54 @@ const internal::VariadicDynCastAllOfMatcher< /// \see reinterpretCast /// /// Example: -/// staticCast() +/// staticCastExpr() /// matches /// static_cast(8) /// in +/// \code /// long eight(static_cast(8)); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXStaticCastExpr> staticCast; + Stmt, + CXXStaticCastExpr> staticCastExpr; /// \brief Matches a dynamic_cast expression. /// /// Example: -/// dynamicCast() +/// dynamicCastExpr() /// matches /// dynamic_cast(&b); /// in +/// \code /// struct B { virtual ~B() {} }; struct D : B {}; /// B b; /// D* p = dynamic_cast(&b); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXDynamicCastExpr> dynamicCast; + Stmt, + CXXDynamicCastExpr> dynamicCastExpr; /// \brief Matches a const_cast expression. /// /// Example: Matches const_cast(&r) in +/// \code /// int n = 42; -/// const int& r(n); +/// const int &r(n); /// int* p = const_cast(&r); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXConstCastExpr> constCast; + Stmt, + CXXConstCastExpr> constCastExpr; + +/// \brief Matches a C-style cast expression. +/// +/// Example: Matches (int*) 2.2f in +/// \code +/// int i = (int) 2.2f; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CStyleCastExpr> cStyleCastExpr; /// \brief Matches explicit cast expressions. /// @@ -746,98 +1040,127 @@ const internal::VariadicDynCastAllOfMatcher< /// \see hasDestinationType. /// /// Example: matches all five of the casts in +/// \code /// int((int)(reinterpret_cast(static_cast(const_cast(42))))) +/// \endcode /// but does not match the implicit conversion in +/// \code /// long ell = 42; +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - ExplicitCastExpr> explicitCast; + Stmt, + ExplicitCastExpr> explicitCastExpr; /// \brief Matches the implicit cast nodes of Clang's AST. /// /// This matches many different places, including function call return value /// eliding, as well as any type conversions. const internal::VariadicDynCastAllOfMatcher< - Expr, - ImplicitCastExpr> implicitCast; + Stmt, + ImplicitCastExpr> implicitCastExpr; /// \brief Matches any cast nodes of Clang's AST. /// /// Example: castExpr() matches each of the following: +/// \code /// (int) 3; /// const_cast(SubExpr); /// char c = 0; +/// \endcode /// but does not match +/// \code /// int i = (0); /// int k = 0; -const internal::VariadicDynCastAllOfMatcher< - Expr, - CastExpr> castExpr; +/// \endcode +const internal::VariadicDynCastAllOfMatcher castExpr; /// \brief Matches functional cast expressions /// /// Example: Matches Foo(bar); +/// \code /// Foo f = bar; /// Foo g = (Foo) bar; /// Foo h = Foo(bar); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXFunctionalCastExpr> functionalCast; + Stmt, + CXXFunctionalCastExpr> functionalCastExpr; + +/// \brief Matches \c QualTypes in the clang AST. +const internal::VariadicAllOfMatcher qualType; + +/// \brief Matches \c Types in the clang AST. +const internal::VariadicDynCastAllOfMatcher type; + +/// \brief Matches \c TypeLocs in the clang AST. +const internal::VariadicDynCastAllOfMatcher typeLoc; /// \brief Various overloads for the anyOf matcher. /// @{ -template -internal::PolymorphicMatcherWithParam2 -anyOf(const C1 &P1, const C2 &P2) { + +/// \brief Matches if any of the given matchers matches. +/// +/// Usable as: Any Matcher +template +internal::PolymorphicMatcherWithParam2 +anyOf(const M1 &P1, const M2 &P2) { return internal::PolymorphicMatcherWithParam2(P1, P2); + M1, M2 >(P1, P2); } -template -internal::PolymorphicMatcherWithParam2 > -anyOf(const C1 &P1, const C2 &P2, const C3 &P3) { +template +internal::PolymorphicMatcherWithParam2 > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3) { return anyOf(P1, anyOf(P2, P3)); } -template -internal::PolymorphicMatcherWithParam2 +internal::PolymorphicMatcherWithParam2 > > -anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) { + M3, M4> > > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) { return anyOf(P1, anyOf(P2, anyOf(P3, P4))); } -template -internal::PolymorphicMatcherWithParam2 +internal::PolymorphicMatcherWithParam2 > > > -anyOf(const C1& P1, const C2& P2, const C3& P3, const C4& P4, const C5& P5) { + M4, M5> > > > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5)))); } + /// @} /// \brief Various overloads for the allOf matcher. /// @{ -template -internal::PolymorphicMatcherWithParam2 -allOf(const C1 &P1, const C2 &P2) { + +/// \brief Matches if all given matchers match. +/// +/// Usable as: Any Matcher +template +internal::PolymorphicMatcherWithParam2 +allOf(const M1 &P1, const M2 &P2) { return internal::PolymorphicMatcherWithParam2(P1, P2); + M1, M2>(P1, P2); } -template -internal::PolymorphicMatcherWithParam2 > -allOf(const C1& P1, const C2& P2, const C3& P3) { +template +internal::PolymorphicMatcherWithParam2 > +allOf(const M1 &P1, const M2 &P2, const M3 &P3) { return allOf(P1, allOf(P2, P3)); } + /// @} /// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) /// /// Given +/// \code /// Foo x = bar; /// int y = sizeof(x) + alignof(x); +/// \endcode /// unaryExprOrTypeTraitExpr() /// matches \c sizeof(x) and \c alignof(x) const internal::VariadicDynCastAllOfMatcher< @@ -847,20 +1170,24 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches unary expressions that have a specific type of argument. /// /// Given +/// \code /// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c); +/// \endcode /// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")) /// matches \c sizeof(a) and \c alignof(c) AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { const QualType ArgumentType = Node.getTypeOfArgument(); - return Matcher.matches(ArgumentType, Finder, Builder); + return InnerMatcher.matches(ArgumentType, Finder, Builder); } /// \brief Matches unary expressions of a certain kind. /// /// Given +/// \code /// int x; /// int s = sizeof(x) + alignof(x) +/// \endcode /// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf)) /// matches \c sizeof(x) AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { @@ -870,17 +1197,17 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { /// \brief Same as unaryExprOrTypeTraitExpr, but only matching /// alignof. inline internal::Matcher alignOfExpr( - const internal::Matcher &Matcher) { + const internal::Matcher &InnerMatcher) { return internal::Matcher(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_AlignOf), Matcher))); + ofKind(UETT_AlignOf), InnerMatcher))); } /// \brief Same as unaryExprOrTypeTraitExpr, but only matching /// sizeof. inline internal::Matcher sizeOfExpr( - const internal::Matcher &Matcher) { + const internal::Matcher &InnerMatcher) { return internal::Matcher(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_SizeOf), Matcher))); + ofKind(UETT_SizeOf), InnerMatcher))); } /// \brief Matches NamedDecl nodes that have the specified name. @@ -890,10 +1217,14 @@ inline internal::Matcher sizeOfExpr( /// Does not match typedefs of an underlying type with the given name. /// /// Example matches X (Name == "X") +/// \code /// class X; +/// \endcode /// /// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X") -/// namespace a { namespace b { class X; } } +/// \code +/// namespace a { namespace b { class X; } } +/// \endcode AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { assert(!Name.empty()); const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); @@ -914,10 +1245,14 @@ AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { /// of an underlying type with the given name. /// /// Example matches X (regexp == "::X") +/// \code /// class X; +/// \endcode /// /// Example matches X (regexp is one of "::X", "^foo::.*X", among others) -/// namespace foo { namespace bar { class X; } } +/// \code +/// namespace foo { namespace bar { class X; } } +/// \endcode AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { assert(!RegExp.empty()); std::string FullNameString = "::" + Node.getQualifiedNameAsString(); @@ -931,10 +1266,12 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// "operator" prefix, such as "<<", for OverloadedOperatorCall's. /// /// Example matches a << b -/// (matcher == overloadedOperatorCall(hasOverloadedOperatorName("<<"))) +/// (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) +/// \code /// a << b; /// c && d; // assuming both operator<< /// // and operator&& are overloaded somewhere. +/// \endcode AST_MATCHER_P(CXXOperatorCallExpr, hasOverloadedOperatorName, std::string, Name) { return getOperatorSpelling(Node.getOperator()) == Name; @@ -943,20 +1280,24 @@ AST_MATCHER_P(CXXOperatorCallExpr, /// \brief Matches C++ classes that are directly or indirectly derived from /// a class matching \c Base. /// -/// Note that a class is considered to be also derived from itself. +/// Note that a class is not considered to be derived from itself. /// -/// Example matches X, Y, Z, C (Base == hasName("X")) -/// class X; // A class is considered to be derived from itself +/// Example matches Y, Z, C (Base == hasName("X")) +/// \code +/// class X; /// class Y : public X {}; // directly derived /// class Z : public Y {}; // indirectly derived /// typedef X A; /// typedef A B; /// class C : public B {}; // derived from a typedef of X +/// \endcode /// /// In the following example, Bar matches isDerivedFrom(hasName("X")): +/// \code /// class Foo; /// typedef Foo X; /// class Bar : public Foo {}; // derived from a type that X is a typedef of +/// \endcode AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, internal::Matcher, Base) { return Finder->classIsDerivedFrom(&Node, Base, Builder); @@ -968,15 +1309,34 @@ inline internal::Matcher isDerivedFrom(StringRef BaseName) { return isDerivedFrom(hasName(BaseName)); } +/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly +/// match \c Base. +inline internal::Matcher isSameOrDerivedFrom( + internal::Matcher Base) { + return anyOf(Base, isDerivedFrom(Base)); +} + +/// \brief Overloaded method as shortcut for +/// \c isSameOrDerivedFrom(hasName(...)). +inline internal::Matcher isSameOrDerivedFrom( + StringRef BaseName) { + assert(!BaseName.empty()); + return isSameOrDerivedFrom(hasName(BaseName)); +} + /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// -/// Example matches X, Y (matcher = record(has(record(hasName("X"))) +/// Example matches X, Y (matcher = recordDecl(has(recordDecl(hasName("X"))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class Y { class X {}; }; /// class Z { class Y { class X {}; }; }; // Does not match Z. +/// \endcode /// /// ChildT must be an AST base type. +/// +/// Usable as: Any Matcher template internal::ArgumentAdaptingMatcher has( const internal::Matcher &ChildMatcher) { @@ -988,12 +1348,16 @@ internal::ArgumentAdaptingMatcher has( /// provided matcher. /// /// Example matches X, Y, Z -/// (matcher = record(hasDescendant(record(hasName("X"))))) +/// (matcher = recordDecl(hasDescendant(recordDecl(hasName("X"))))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class Y { class X {}; }; /// class Z { class Y { class X {}; }; }; +/// \endcode /// /// DescendantT must be an AST base type. +/// +/// Usable as: Any Matcher template internal::ArgumentAdaptingMatcher hasDescendant(const internal::Matcher &DescendantMatcher) { @@ -1002,22 +1366,25 @@ hasDescendant(const internal::Matcher &DescendantMatcher) { DescendantT>(DescendantMatcher); } - /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// -/// Example matches X, Y (matcher = record(forEach(record(hasName("X"))) +/// Example matches X, Y (matcher = recordDecl(forEach(recordDecl(hasName("X"))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class Y { class X {}; }; /// class Z { class Y { class X {}; }; }; // Does not match Z. +/// \endcode /// /// ChildT must be an AST base type. /// /// As opposed to 'has', 'forEach' will cause a match for each result that /// matches instead of only on the first one. +/// +/// Usable as: Any Matcher template internal::ArgumentAdaptingMatcher forEach( - const internal::Matcher& ChildMatcher) { + const internal::Matcher &ChildMatcher) { return internal::ArgumentAdaptingMatcher< internal::ForEachMatcher, ChildT>(ChildMatcher); @@ -1027,10 +1394,12 @@ internal::ArgumentAdaptingMatcher forEach( /// provided matcher. /// /// Example matches X, A, B, C -/// (matcher = record(forEachDescendant(record(hasName("X"))))) +/// (matcher = recordDecl(forEachDescendant(recordDecl(hasName("X"))))) +/// \code /// class X {}; // Matches X, because X::X is a class of name X inside X. /// class A { class X {}; }; /// class B { class C { class X {}; }; }; +/// \endcode /// /// DescendantT must be an AST base type. /// @@ -1038,25 +1407,72 @@ internal::ArgumentAdaptingMatcher forEach( /// each result that matches instead of only on the first one. /// /// Note: Recursively combined ForEachDescendant can cause many matches: -/// record(forEachDescendant(record(forEachDescendant(record())))) +/// recordDecl(forEachDescendant(recordDecl(forEachDescendant(recordDecl())))) /// will match 10 times (plus injected class name matches) on: +/// \code /// class A { class B { class C { class D { class E {}; }; }; }; }; +/// \endcode +/// +/// Usable as: Any Matcher template -internal::ArgumentAdaptingMatcher +internal::ArgumentAdaptingMatcher forEachDescendant( - const internal::Matcher& DescendantMatcher) { + const internal::Matcher &DescendantMatcher) { return internal::ArgumentAdaptingMatcher< internal::ForEachDescendantMatcher, DescendantT>(DescendantMatcher); } +/// \brief Matches AST nodes that have a parent that matches the provided +/// matcher. +/// +/// Given +/// \code +/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } } +/// \endcode +/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }". +/// +/// Usable as: Any Matcher +template +internal::ArgumentAdaptingMatcher +hasParent(const internal::Matcher &ParentMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasParentMatcher, + ParentT>(ParentMatcher); +} + +/// \brief Matches AST nodes that have an ancestor that matches the provided +/// matcher. +/// +/// Given +/// \code +/// void f() { if (true) { int x = 42; } } +/// void g() { for (;;) { int x = 43; } } +/// \endcode +/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43. +/// +/// Usable as: Any Matcher +template +internal::ArgumentAdaptingMatcher +hasAncestor(const internal::Matcher &AncestorMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasAncestorMatcher, + AncestorT>(AncestorMatcher); +} + /// \brief Matches if the provided matcher does not match. /// -/// Example matches Y (matcher = record(unless(hasName("X")))) +/// Example matches Y (matcher = recordDecl(unless(hasName("X")))) +/// \code /// class X {}; /// class Y {}; +/// \endcode +/// +/// Usable as: Any Matcher template -internal::PolymorphicMatcherWithParam1 unless(const M &InnerMatcher) { +internal::PolymorphicMatcherWithParam1 +unless(const M &InnerMatcher) { return internal::PolymorphicMatcherWithParam1< internal::NotMatcher, M>(InnerMatcher); } @@ -1064,7 +1480,8 @@ internal::PolymorphicMatcherWithParam1 unless(const M & /// \brief Matches a type if the declaration of the type matches the given /// matcher. /// -/// Usable as: Matcher, Matcher, Matcher +/// Usable as: Matcher, Matcher, Matcher, +/// Matcher inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher > hasDeclaration(const internal::Matcher &InnerMatcher) { @@ -1075,9 +1492,11 @@ inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, /// \brief Matches on the implicit object argument of a member call expression. /// -/// Example matches y.x() (matcher = call(on(hasType(record(hasName("Y")))))) +/// Example matches y.x() (matcher = callExpr(on(hasType(recordDecl(hasName("Y")))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y y; y.x(); }", +/// \endcode /// /// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher, @@ -1092,9 +1511,11 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher, /// \brief Matches if the call expression's callee expression matches. /// /// Given +/// \code /// class Y { void x() { this->x(); x(); Y y; y.x(); } }; /// void f() { f(); } -/// call(callee(expression())) +/// \endcode +/// callExpr(callee(expr())) /// matches this->x(), x(), y.x(), f() /// with callee(...) /// matching this->x, x, y.x, f respectively @@ -1113,9 +1534,11 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher, /// \brief Matches if the call expression's callee's declaration matches the /// given matcher. /// -/// Example matches y.x() (matcher = call(callee(method(hasName("x"))))) +/// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x"))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y y; y.x(); +/// \endcode inline internal::Matcher callee( const internal::Matcher &InnerMatcher) { return internal::Matcher(hasDeclaration(InnerMatcher)); @@ -1124,12 +1547,12 @@ inline internal::Matcher callee( /// \brief Matches if the expression's or declaration's type matches a type /// matcher. /// -/// Example matches x (matcher = expression(hasType( -/// hasDeclaration(record(hasName("X")))))) -/// and z (matcher = variable(hasType( -/// hasDeclaration(record(hasName("X")))))) +/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X"))))) +/// and z (matcher = varDecl(hasType(recordDecl(hasName("X"))))) +/// \code /// class X {}; /// void y(X &x) { x; X z; } +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher, InnerMatcher) { TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || @@ -1143,14 +1566,16 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher, /// /// In case of a value declaration (for example a variable declaration), /// this resolves one layer of indirection. For example, in the value -/// declaration "X x;", record(hasName("X")) matches the declaration of X, -/// while variable(hasType(record(hasName("X")))) matches the declaration +/// declaration "X x;", recordDecl(hasName("X")) matches the declaration of X, +/// while varDecl(hasType(recordDecl(hasName("X")))) matches the declaration /// of x." /// -/// Example matches x (matcher = expression(hasType(record(hasName("X"))))) -/// and z (matcher = variable(hasType(record(hasName("X"))))) +/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X"))))) +/// and z (matcher = varDecl(hasType(recordDecl(hasName("X"))))) +/// \code /// class X {}; /// void y(X &x) { x; X z; } +/// \endcode /// /// Usable as: Matcher, Matcher inline internal::PolymorphicMatcherWithParam1< @@ -1164,9 +1589,11 @@ hasType(const internal::Matcher &InnerMatcher) { /// \brief Matches if the matched type is represented by the given string. /// /// Given +/// \code /// class Y { public: void x(); }; /// void z() { Y* y; y->x(); } -/// call(on(hasType(asString("class Y *")))) +/// \endcode +/// callExpr(on(hasType(asString("class Y *")))) /// matches y->x() AST_MATCHER_P(QualType, asString, std::string, Name) { return Name == Node.getAsString(); @@ -1176,9 +1603,11 @@ AST_MATCHER_P(QualType, asString, std::string, Name) { /// matches the specified matcher. /// /// Example matches y->x() -/// (matcher = call(on(hasType(pointsTo(record(hasName("Y"))))))) +/// (matcher = callExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y *y; y->x(); } +/// \endcode AST_MATCHER_P( QualType, pointsTo, internal::Matcher, InnerMatcher) { @@ -1197,12 +1626,14 @@ inline internal::Matcher pointsTo( /// type matches the specified matcher. /// /// Example matches X &x and const X &y -/// (matcher = variable(hasType(references(record(hasName("X")))))) +/// (matcher = varDecl(hasType(references(recordDecl(hasName("X")))))) +/// \code /// class X { /// void a(X b) { /// X &x = b; /// const X &y = b; /// }; +/// \endcode AST_MATCHER_P(QualType, references, internal::Matcher, InnerMatcher) { return (!Node.isNull() && Node->isReferenceType() && @@ -1243,9 +1674,11 @@ inline internal::Matcher thisPointerType( /// specified matcher. /// /// Example matches x in if(x) -/// (matcher = declarationReference(to(variable(hasName("x"))))) +/// (matcher = declRefExpr(to(varDecl(hasName("x"))))) +/// \code /// bool x; /// if (x) {} +/// \endcode AST_MATCHER_P(DeclRefExpr, to, internal::Matcher, InnerMatcher) { const Decl *DeclNode = Node.getDecl(); @@ -1259,29 +1692,33 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher, /// FIXME: This currently only works for functions. Fix. /// /// Given +/// \code /// namespace a { void f() {} } /// using a::f; /// void g() { /// f(); // Matches this .. /// a::f(); // .. but not this. /// } -/// declarationReference(throughUsingDeclaration(anything())) +/// \endcode +/// declRefExpr(throughUsingDeclaration(anything())) /// matches \c f() AST_MATCHER_P(DeclRefExpr, throughUsingDecl, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { const NamedDecl *FoundDecl = Node.getFoundDecl(); if (const UsingShadowDecl *UsingDecl = llvm::dyn_cast(FoundDecl)) - return Matcher.matches(*UsingDecl, Finder, Builder); + return InnerMatcher.matches(*UsingDecl, Finder, Builder); return false; } /// \brief Matches the Decl of a DeclStmt which has a single declaration. /// /// Given +/// \code /// int a, b; /// int c; -/// declarationStatement(hasSingleDecl(anything())) +/// \endcode +/// declStmt(hasSingleDecl(anything())) /// matches 'int c;' but not 'int a, b;'. AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher, InnerMatcher) { if (Node.isSingleDecl()) { @@ -1294,9 +1731,11 @@ AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher, InnerMatcher) { /// \brief Matches a variable declaration that has an initializer expression /// that matches the given matcher. /// -/// Example matches x (matcher = variable(hasInitializer(call()))) +/// Example matches x (matcher = varDecl(hasInitializer(callExpr()))) +/// \code /// bool y() { return true; } /// bool x = y(); +/// \endcode AST_MATCHER_P( VarDecl, hasInitializer, internal::Matcher, InnerMatcher) { @@ -1308,9 +1747,11 @@ AST_MATCHER_P( /// \brief Checks that a call expression or a constructor call expression has /// a specific number of arguments (including absent default arguments). /// -/// Example matches f(0, 0) (matcher = call(argumentCountIs(2))) +/// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2))) +/// \code /// void f(int x, int y); /// f(0, 0); +/// \endcode AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || llvm::is_base_of, InnerMatcher) { TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || @@ -1340,13 +1783,15 @@ AST_POLYMORPHIC_MATCHER_P2( /// declarations. /// /// Example: Given +/// \code /// int a, b; /// int c; /// int d = 2, e; +/// \endcode /// declCountIs(2) /// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'. AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { - return std::distance(Node.decl_begin(), Node.decl_end()) == N; + return std::distance(Node.decl_begin(), Node.decl_end()) == (ptrdiff_t)N; } /// \brief Matches the n'th declaration of a declaration statement. @@ -1355,15 +1800,19 @@ AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { /// breaks up multiple-declaration DeclStmt's into multiple single-declaration /// DeclStmt's. /// Example: Given non-global declarations +/// \code /// int a, b = 0; /// int c; /// int d = 2, e; -/// declarationStatement(containsDeclaration( -/// 0, variable(hasInitializer(anything())))) +/// \endcode +/// declStmt(containsDeclaration( +/// 0, varDecl(hasInitializer(anything())))) /// matches only 'int d = 2, e;', and -/// declarationStatement(containsDeclaration(1, variable())) +/// declStmt(containsDeclaration(1, varDecl())) +/// \code /// matches 'int a, b = 0' as well as 'int d = 2, e;' /// but 'int c;' is not matched. +/// \endcode AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, internal::Matcher, InnerMatcher) { const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end()); @@ -1377,11 +1826,13 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, /// \brief Matches a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer(anything())))) +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(anything())))) /// record matches Foo, hasAnyConstructorInitializer matches foo_(1) AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, internal::Matcher, InnerMatcher) { @@ -1397,11 +1848,13 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, /// \brief Matches the field declaration of a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer( +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer( /// forField(hasName("foo_")))))) /// matches Foo /// with forField matching foo_ @@ -1415,11 +1868,13 @@ AST_MATCHER_P(CXXCtorInitializer, forField, /// \brief Matches the initializer expression of a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer( +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer( /// withInitializer(integerLiteral(equals(1))))))) /// matches Foo /// with withInitializer matching (1) @@ -1434,12 +1889,14 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer, /// code (as opposed to implicitly added by the compiler). /// /// Given +/// \code /// struct Foo { /// Foo() { } /// Foo(int) : foo_("A") { } /// string foo_; /// }; -/// constructor(hasAnyConstructorInitializer(isWritten())) +/// \endcode +/// constructorDecl(hasAnyConstructorInitializer(isWritten())) /// will match Foo(int), but not Foo() AST_MATCHER(CXXCtorInitializer, isWritten) { return Node.isWritten(); @@ -1455,8 +1912,10 @@ AST_MATCHER(CXXConstructorDecl, isImplicit) { /// expression. /// /// Given +/// \code /// void x(int, int, int) { int y; x(1, y, 42); } -/// call(hasAnyArgument(declarationReference())) +/// \endcode +/// callExpr(hasAnyArgument(declRefExpr())) /// matches x(1, y, 42) /// with hasAnyArgument(...) /// matching y @@ -1478,8 +1937,10 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher, /// \brief Matches the n'th parameter of a function declaration. /// /// Given +/// \code /// class X { void f(int x) {} }; -/// method(hasParameter(0, hasType(variable()))) +/// \endcode +/// methodDecl(hasParameter(0, hasType(varDecl()))) /// matches f(int x) {} /// with hasParameter(...) /// matching int x @@ -1496,8 +1957,10 @@ AST_MATCHER_P2(FunctionDecl, hasParameter, /// Does not match the 'this' parameter of a method. /// /// Given +/// \code /// class X { void f(int x, int y, int z) {} }; -/// method(hasAnyParameter(hasName("y"))) +/// \endcode +/// methodDecl(hasAnyParameter(hasName("y"))) /// matches f(int x, int y, int z) {} /// with hasAnyParameter(...) /// matching int y @@ -1514,20 +1977,25 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, /// \brief Matches the return type of a function declaration. /// /// Given: +/// \code /// class X { int f() { return 1; } }; -/// method(returns(asString("int"))) +/// \endcode +/// methodDecl(returns(asString("int"))) /// matches int f() { return 1; } -AST_MATCHER_P(FunctionDecl, returns, internal::Matcher, Matcher) { - return Matcher.matches(Node.getResultType(), Finder, Builder); +AST_MATCHER_P(FunctionDecl, returns, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(Node.getResultType(), Finder, Builder); } /// \brief Matches extern "C" function declarations. /// /// Given: +/// \code /// extern "C" void f() {} /// extern "C" { void g() {} } /// void h() {} -/// function(isExternC()) +/// \endcode +/// functionDecl(isExternC()) /// matches the declaration of f and g, but not the declaration h AST_MATCHER(FunctionDecl, isExternC) { return Node.isExternC(); @@ -1537,7 +2005,9 @@ AST_MATCHER(FunctionDecl, isExternC) { /// or conditional operator. /// /// Example matches true (matcher = hasCondition(boolLiteral(equals(true)))) +/// \code /// if (true) {} +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher, InnerMatcher) { TOOLING_COMPILE_ASSERT( @@ -1555,7 +2025,9 @@ AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher, /// \brief Matches the condition variable statement in an if statement. /// /// Given +/// \code /// if (A* a = GetAPointer()) {} +/// \endcode /// hasConditionVariableStatment(...) /// matches 'A* a = GetAPointer()'. AST_MATCHER_P(IfStmt, hasConditionVariableStatement, @@ -1569,29 +2041,33 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement, /// \brief Matches the index expression of an array subscript expression. /// /// Given +/// \code /// int i[5]; /// void f() { i[1] = 42; } +/// \endcode /// arraySubscriptExpression(hasIndex(integerLiteral())) /// matches \c i[1] with the \c integerLiteral() matching \c 1 AST_MATCHER_P(ArraySubscriptExpr, hasIndex, - internal::Matcher, matcher) { + internal::Matcher, InnerMatcher) { if (const Expr* Expression = Node.getIdx()) - return matcher.matches(*Expression, Finder, Builder); + return InnerMatcher.matches(*Expression, Finder, Builder); return false; } /// \brief Matches the base expression of an array subscript expression. /// /// Given +/// \code /// int i[5]; /// void f() { i[1] = 42; } -/// arraySubscriptExpression(hasBase(implicitCast( -/// hasSourceExpression(declarationReference())))) -/// matches \c i[1] with the \c declarationReference() matching \c i +/// \endcode +/// arraySubscriptExpression(hasBase(implicitCastExpr( +/// hasSourceExpression(declRefExpr())))) +/// matches \c i[1] with the \c declRefExpr() matching \c i AST_MATCHER_P(ArraySubscriptExpr, hasBase, - internal::Matcher, matcher) { + internal::Matcher, InnerMatcher) { if (const Expr* Expression = Node.getBase()) - return matcher.matches(*Expression, Finder, Builder); + return InnerMatcher.matches(*Expression, Finder, Builder); return false; } @@ -1599,10 +2075,12 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, /// a given body. /// /// Given +/// \code /// for (;;) {} -/// hasBody(compoundStatement()) +/// \endcode +/// hasBody(compoundStmt()) /// matches 'for (;;) {}' -/// with compoundStatement() +/// with compoundStmt() /// matching '{}' AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher, InnerMatcher) { @@ -1620,10 +2098,12 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher, /// a given matcher. /// /// Given +/// \code /// { {}; 1+2; } -/// hasAnySubstatement(compoundStatement()) +/// \endcode +/// hasAnySubstatement(compoundStmt()) /// matches '{ {}; 1+2; }' -/// with compoundStatement() +/// with compoundStmt() /// matching '{}' AST_MATCHER_P(CompoundStmt, hasAnySubstatement, internal::Matcher, InnerMatcher) { @@ -1639,8 +2119,10 @@ AST_MATCHER_P(CompoundStmt, hasAnySubstatement, /// child statements. /// /// Example: Given +/// \code /// { for (;;) {} } -/// compoundStatement(statementCountIs(0))) +/// \endcode +/// compoundStmt(statementCountIs(0))) /// matches '{}' /// but does not match the outer compound statement. AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { @@ -1650,7 +2132,9 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { /// \brief Matches literals that are equal to the given value. /// /// Example matches true (matcher = boolLiteral(equals(true))) +/// \code /// true +/// \endcode /// /// Usable as: Matcher, Matcher, /// Matcher, Matcher @@ -1666,7 +2150,9 @@ equals(const ValueT &Value) { /// unary). /// /// Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) +/// \code /// !(a || b) +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { TOOLING_COMPILE_ASSERT( (llvm::is_base_of::value) || @@ -1678,7 +2164,9 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { /// \brief Matches the left hand side of binary operator expressions. /// /// Example matches a (matcher = binaryOperator(hasLHS())) +/// \code /// a || b +/// \endcode AST_MATCHER_P(BinaryOperator, hasLHS, internal::Matcher, InnerMatcher) { Expr *LeftHandSide = Node.getLHS(); @@ -1689,7 +2177,9 @@ AST_MATCHER_P(BinaryOperator, hasLHS, /// \brief Matches the right hand side of binary operator expressions. /// /// Example matches b (matcher = binaryOperator(hasRHS())) +/// \code /// a || b +/// \endcode AST_MATCHER_P(BinaryOperator, hasRHS, internal::Matcher, InnerMatcher) { Expr *RightHandSide = Node.getRHS(); @@ -1706,8 +2196,10 @@ inline internal::Matcher hasEitherOperand( /// \brief Matches if the operand of a unary operator matches. /// -/// Example matches true (matcher = hasOperand(boolLiteral(equals(true)))) +/// Example matches true (matcher = hasUnaryOperand(boolLiteral(equals(true)))) +/// \code /// !true +/// \endcode AST_MATCHER_P(UnaryOperator, hasUnaryOperand, internal::Matcher, InnerMatcher) { const Expr * const Operand = Node.getSubExpr(); @@ -1718,8 +2210,8 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand, /// \brief Matches if the cast's source expression matches the given matcher. /// /// Example: matches "a string" (matcher = -/// hasSourceExpression(constructorCall())) -/// +/// hasSourceExpression(constructExpr())) +/// \code /// class URL { URL(string); }; /// URL url = "a string"; AST_MATCHER_P(CastExpr, hasSourceExpression, @@ -1751,7 +2243,9 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, /// \brief Matches the true branch expression of a conditional operator. /// /// Example matches a +/// \code /// condition ? a : b +/// \endcode AST_MATCHER_P(ConditionalOperator, hasTrueExpression, internal::Matcher, InnerMatcher) { Expr *Expression = Node.getTrueExpr(); @@ -1762,7 +2256,9 @@ AST_MATCHER_P(ConditionalOperator, hasTrueExpression, /// \brief Matches the false branch expression of a conditional operator. /// /// Example matches b +/// \code /// condition ? a : b +/// \endcode AST_MATCHER_P(ConditionalOperator, hasFalseExpression, internal::Matcher, InnerMatcher) { Expr *Expression = Node.getFalseExpr(); @@ -1773,12 +2269,14 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression, /// \brief Matches if a declaration has a body attached. /// /// Example matches A, va, fa +/// \code /// class A {}; /// class B; // Doesn't match, as it has no body. /// int va; /// extern int vb; // Doesn't match, as it doesn't define the variable. /// void fa() {} /// void fb(); // Doesn't match, as it has no body. +/// \endcode /// /// Usable as: Matcher, Matcher, Matcher inline internal::PolymorphicMatcherWithParam0 @@ -1795,13 +2293,15 @@ isDefinition() { /// this to? /// /// Example matches A() in the last line -/// (matcher = constructorCall(hasDeclaration(method( +/// (matcher = constructExpr(hasDeclaration(methodDecl( /// ofClass(hasName("A")))))) +/// \code /// class A { /// public: /// A(); /// }; /// A a = A(); +/// \endcode AST_MATCHER_P(CXXMethodDecl, ofClass, internal::Matcher, InnerMatcher) { const CXXRecordDecl *Parent = Node.getParent(); @@ -1815,12 +2315,14 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, /// Member calls on the implicit this pointer match as called with '->'. /// /// Given +/// \code /// class Y { /// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } /// int a; /// static int b; /// }; -/// memberExpression(isArrow()) +/// \endcode +/// memberExpr(isArrow()) /// matches this->x, x, y.x, a, this->b inline internal::Matcher isArrow() { return makeMatcher(new internal::IsArrowMatcher()); @@ -1829,10 +2331,12 @@ inline internal::Matcher isArrow() { /// \brief Matches QualType nodes that are of integer type. /// /// Given +/// \code /// void a(int); /// void b(long); /// void c(double); -/// function(hasAnyParameter(hasType(isInteger()))) +/// \endcode +/// functionDecl(hasAnyParameter(hasType(isInteger()))) /// matches "a(int)", "b(long)", but not "c(double)". AST_MATCHER(QualType, isInteger) { return Node->isIntegerType(); @@ -1842,12 +2346,14 @@ AST_MATCHER(QualType, isInteger) { /// include "top-level" const. /// /// Given +/// \code /// void a(int); /// void b(int const); /// void c(const int); /// void d(const int*); /// void e(int const) {}; -/// function(hasAnyParameter(hasType(isConstQualified()))) +/// \endcode +/// functionDecl(hasAnyParameter(hasType(isConstQualified()))) /// matches "void b(int const)", "void c(const int)" and /// "void e(int const) {}". It does not match d as there /// is no top-level const on the parameter type "const int *". @@ -1859,10 +2365,12 @@ inline internal::Matcher isConstQualified() { /// given matcher. /// /// Given +/// \code /// struct { int first, second; } first, second; /// int i(second.first); /// int j(first.second); -/// memberExpression(member(hasName("first"))) +/// \endcode +/// memberExpr(member(hasName("first"))) /// matches second.first /// but not first.second (because the member name there is "second"). AST_MATCHER_P(MemberExpr, member, @@ -1874,9 +2382,11 @@ AST_MATCHER_P(MemberExpr, member, /// matched by a given matcher. /// /// Given +/// \code /// struct X { int m; }; /// void f(X x) { x.m; m; } -/// memberExpression(hasObjectExpression(hasType(record(hasName("X"))))))) +/// \endcode +/// memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))) /// matches "x.m" and "m" /// with hasObjectExpression(...) /// matching "x" and the implicit object expression of "m" which has type X*. @@ -1888,15 +2398,17 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression, /// \brief Matches any using shadow declaration. /// /// Given +/// \code /// namespace X { void b(); } /// using X::b; +/// \endcode /// usingDecl(hasAnyUsingShadowDecl(hasName("b")))) /// matches \code using X::b \endcode AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, - internal::Matcher, Matcher) { + internal::Matcher, InnerMatcher) { for (UsingDecl::shadow_iterator II = Node.shadow_begin(); II != Node.shadow_end(); ++II) { - if (Matcher.matches(**II, Finder, Builder)) + if (InnerMatcher.matches(**II, Finder, Builder)) return true; } return false; @@ -1906,31 +2418,39 @@ AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, /// matched by the given matcher. /// /// Given +/// \code /// namespace X { int a; void b(); } /// using X::a; /// using X::b; -/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(function()))) +/// \endcode +/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl()))) /// matches \code using X::b \endcode /// but not \code using X::a \endcode AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, - internal::Matcher, Matcher) { - return Matcher.matches(*Node.getTargetDecl(), Finder, Builder); + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder); } /// \brief Matches template instantiations of function, class, or static /// member variable template instantiations. /// /// Given +/// \code /// template class X {}; class A {}; X x; +/// \endcode /// or +/// \code /// template class X {}; class A {}; template class X; -/// record(hasName("::X"), isTemplateInstantiation()) +/// \endcode +/// recordDecl(hasName("::X"), isTemplateInstantiation()) /// matches the template instantiation of X. /// /// But given -/// template class X {}; class A {}; +/// \code +/// template class X {}; class A {}; /// template <> class X {}; X x; -/// record(hasName("::X"), isTemplateInstantiation()) +/// \endcode +/// recordDecl(hasName("::X"), isTemplateInstantiation()) /// does not match, as X is an explicit template specialization. /// /// Usable as: Matcher, Matcher, Matcher @@ -1941,6 +2461,411 @@ isTemplateInstantiation() { internal::IsTemplateInstantiationMatcher>(); } +/// \brief Matches explicit template specializations of function, class, or +/// static member variable template instantiations. +/// +/// Given +/// \code +/// template void A(T t) { } +/// template<> void A(int N) { } +/// \endcode +/// functionDecl(isExplicitTemplateSpecialization()) +/// matches the specialization A(). +/// +/// Usable as: Matcher, Matcher, Matcher +inline internal::PolymorphicMatcherWithParam0< + internal::IsExplicitTemplateSpecializationMatcher> +isExplicitTemplateSpecialization() { + return internal::PolymorphicMatcherWithParam0< + internal::IsExplicitTemplateSpecializationMatcher>(); +} + +/// \brief Matches \c TypeLocs for which the given inner +/// QualType-matcher matches. +inline internal::BindableMatcher loc( + const internal::Matcher &InnerMatcher) { + return internal::BindableMatcher( + new internal::TypeLocTypeMatcher(InnerMatcher)); +} + +/// \brief Matches builtin Types. +/// +/// Given +/// \code +/// struct A {}; +/// A a; +/// int b; +/// float c; +/// bool d; +/// \endcode +/// builtinType() +/// matches "int b", "float c" and "bool d" +AST_TYPE_MATCHER(BuiltinType, builtinType); + +/// \brief Matches all kinds of arrays. +/// +/// Given +/// \code +/// int a[] = { 2, 3 }; +/// int b[4]; +/// void f() { int c[a[0]]; } +/// \endcode +/// arrayType() +/// matches "int a[]", "int b[4]" and "int c[a[0]]"; +AST_TYPE_MATCHER(ArrayType, arrayType); + +/// \brief Matches C99 complex types. +/// +/// Given +/// \code +/// _Complex float f; +/// \endcode +/// complexType() +/// matches "_Complex float f" +AST_TYPE_MATCHER(ComplexType, complexType); + +/// \brief Matches arrays and C99 complex types that have a specific element +/// type. +/// +/// Given +/// \code +/// struct A {}; +/// A a[7]; +/// int b[7]; +/// \endcode +/// arrayType(hasElementType(builtinType())) +/// matches "int b[7]" +/// +/// Usable as: Matcher, Matcher +AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement); + +/// \brief Matches C arrays with a specified constant size. +/// +/// Given +/// \code +/// void() { +/// int a[2]; +/// int b[] = { 2, 3 }; +/// int c[b[0]]; +/// } +/// \endcode +/// constantArrayType() +/// matches "int a[2]" +AST_TYPE_MATCHER(ConstantArrayType, constantArrayType); + +/// \brief Matches \c ConstantArrayType nodes that have the specified size. +/// +/// Given +/// \code +/// int a[42]; +/// int b[2 * 21]; +/// int c[41], d[43]; +/// \endcode +/// constantArrayType(hasSize(42)) +/// matches "int a[42]" and "int b[2 * 21]" +AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) { + return Node.getSize() == N; +} + +/// \brief Matches C++ arrays whose size is a value-dependent expression. +/// +/// Given +/// \code +/// template +/// class array { +/// T data[Size]; +/// }; +/// \endcode +/// dependentSizedArrayType +/// matches "T data[Size]" +AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType); + +/// \brief Matches C arrays with unspecified size. +/// +/// Given +/// \code +/// int a[] = { 2, 3 }; +/// int b[42]; +/// void f(int c[]) { int d[a[0]]; }; +/// \endcode +/// incompleteArrayType() +/// matches "int a[]" and "int c[]" +AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); + +/// \brief Matches C arrays with a specified size that is not an +/// integer-constant-expression. +/// +/// Given +/// \code +/// void f() { +/// int a[] = { 2, 3 } +/// int b[42]; +/// int c[a[0]]; +/// \endcode +/// variableArrayType() +/// matches "int c[a[0]]" +AST_TYPE_MATCHER(VariableArrayType, variableArrayType); + +/// \brief Matches \c VariableArrayType nodes that have a specific size +/// expression. +/// +/// Given +/// \code +/// void f(int b) { +/// int a[b]; +/// } +/// \endcode +/// variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to( +/// varDecl(hasName("b"))))))) +/// matches "int a[b]" +AST_MATCHER_P(VariableArrayType, hasSizeExpr, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder); +} + +/// \brief Matches atomic types. +/// +/// Given +/// \code +/// _Atomic(int) i; +/// \endcode +/// atomicType() +/// matches "_Atomic(int) i" +AST_TYPE_MATCHER(AtomicType, atomicType); + +/// \brief Matches atomic types with a specific value type. +/// +/// Given +/// \code +/// _Atomic(int) i; +/// _Atomic(float) f; +/// \endcode +/// atomicType(hasValueType(isInteger())) +/// matches "_Atomic(int) i" +/// +/// Usable as: Matcher +AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue); + +/// \brief Matches types nodes representing C++11 auto types. +/// +/// Given: +/// \code +/// auto n = 4; +/// int v[] = { 2, 3 } +/// for (auto i : v) { } +/// \endcode +/// autoType() +/// matches "auto n" and "auto i" +AST_TYPE_MATCHER(AutoType, autoType); + +/// \brief Matches \c AutoType nodes where the deduced type is a specific type. +/// +/// Note: There is no \c TypeLoc for the deduced type and thus no +/// \c getDeducedLoc() matcher. +/// +/// Given +/// \code +/// auto a = 1; +/// auto b = 2.0; +/// \endcode +/// autoType(hasDeducedType(isInteger())) +/// matches "auto a" +/// +/// Usable as: Matcher +AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); + +/// \brief Matches \c FunctionType nodes. +/// +/// Given +/// \code +/// int (*f)(int); +/// void g(); +/// \endcode +/// functionType() +/// matches "int (*f)(int)" and the type of "g". +AST_TYPE_MATCHER(FunctionType, functionType); + +/// \brief Matches block pointer types, i.e. types syntactically represented as +/// "void (^)(int)". +/// +/// The \c pointee is always required to be a \c FunctionType. +AST_TYPE_MATCHER(BlockPointerType, blockPointerType); + +/// \brief Matches member pointer types. +/// Given +/// \code +/// struct A { int i; } +/// A::* ptr = A::i; +/// \endcode +/// memberPointerType() +/// matches "A::* ptr" +AST_TYPE_MATCHER(MemberPointerType, memberPointerType); + +/// \brief Matches pointer types. +/// +/// Given +/// \code +/// int *a; +/// int &b = *a; +/// int c = 5; +/// \endcode +/// pointerType() +/// matches "int *a" +AST_TYPE_MATCHER(PointerType, pointerType); + +/// \brief Matches reference types. +/// +/// Given +/// \code +/// int *a; +/// int &b = *a; +/// int c = 5; +/// \endcode +/// pointerType() +/// matches "int &b" +AST_TYPE_MATCHER(ReferenceType, referenceType); + +/// \brief Narrows PointerType (and similar) matchers to those where the +/// \c pointee matches a given matcher. +/// +/// Given +/// \code +/// int *a; +/// int const *b; +/// float const *f; +/// \endcode +/// pointerType(pointee(isConstQualified(), isInteger())) +/// matches "int const *b" +/// +/// Usable as: Matcher, Matcher, +/// Matcher, Matcher +AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); + +/// \brief Matches typedef types. +/// +/// Given +/// \code +/// typedef int X; +/// \endcode +/// typedefType() +/// matches "typedef int X" +AST_TYPE_MATCHER(TypedefType, typedefType); + +/// \brief Matches \c TypedefTypes referring to a specific +/// \c TypedefNameDecl. +AST_MATCHER_P(TypedefType, hasDecl, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getDecl(), Finder, Builder); +} + +/// \brief Matches nested name specifiers. +/// +/// Given +/// \code +/// namespace ns { +/// struct A { static void f(); }; +/// void A::f() {} +/// void g() { A::f(); } +/// } +/// ns::A a; +/// \endcode +/// nestedNameSpecifier() +/// matches "ns::" and both "A::" +const internal::VariadicAllOfMatcher nestedNameSpecifier; + +/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc. +const internal::VariadicAllOfMatcher< + NestedNameSpecifierLoc> nestedNameSpecifierLoc; + +/// \brief Matches \c NestedNameSpecifierLocs for which the given inner +/// NestedNameSpecifier-matcher matches. +inline internal::BindableMatcher loc( + const internal::Matcher &InnerMatcher) { + return internal::BindableMatcher( + new internal::LocMatcher( + InnerMatcher)); +} + +/// \brief Matches nested name specifiers that specify a type matching the +/// given \c QualType matcher without qualifiers. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifier(specifiesType(hasDeclaration(recordDecl(hasName("A"))))) +/// matches "A::" +AST_MATCHER_P(NestedNameSpecifier, specifiesType, + internal::Matcher, InnerMatcher) { + if (Node.getAsType() == NULL) + return false; + return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder); +} + +/// \brief Matches nested name specifier locs that specify a type matching the +/// given \c TypeLoc. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type( +/// hasDeclaration(recordDecl(hasName("A"))))))) +/// matches "A::" +AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); +} + +/// \brief Matches on the prefix of a \c NestedNameSpecifier. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and +/// matches "A::" +inline internal::Matcher hasPrefix( + const internal::Matcher &InnerMatcher) { + return internal::makeMatcher( + new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher)); +} + +/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A"))))) +/// matches "A::" +inline internal::Matcher hasPrefix( + const internal::Matcher &InnerMatcher) { + return internal::makeMatcher( + new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher)); +} + +/// \brief Matches nested name specifiers that specify a namespace matching the +/// given namespace matcher. +/// +/// Given +/// \code +/// namespace ns { struct A {}; } +/// ns::A a; +/// \endcode +/// nestedNameSpecifier(specifiesNamespace(hasName("ns"))) +/// matches "ns::" +AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, + internal::Matcher, InnerMatcher) { + if (Node.getAsNamespace() == NULL) + return false; + return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); +} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 3f5568521c0e..e5365ff89d72 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -39,7 +39,11 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/Type.h" +#include "clang/ASTMatchers/ASTTypeTraits.h" #include "llvm/ADT/VariadicFunction.h" +#include "llvm/Support/type_traits.h" #include #include #include @@ -57,6 +61,45 @@ class BoundNodes; namespace internal { class BoundNodesTreeBuilder; +/// \brief Internal version of BoundNodes. Holds all the bound nodes. +class BoundNodesMap { +public: + /// \brief Adds \c Node to the map with key \c ID. + /// + /// The node's base type should be in NodeBaseType or it will be unaccessible. + template + void addNode(StringRef ID, const T* Node) { + NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node); + } + void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) { + NodeMap[ID] = Node; + } + + /// \brief Returns the AST node bound to \c ID. + /// + /// Returns NULL if there was no node bound to \c ID or if there is a node but + /// it cannot be converted to the specified type. + template + const T *getNodeAs(StringRef ID) const { + IDToNodeMap::const_iterator It = NodeMap.find(ID); + if (It == NodeMap.end()) { + return NULL; + } + return It->second.get(); + } + + /// \brief Copies all ID/Node pairs to BoundNodesTreeBuilder \c Builder. + void copyTo(BoundNodesTreeBuilder *Builder) const; + + /// \brief Copies all ID/Node pairs to BoundNodesMap \c Other. + void copyTo(BoundNodesMap *Other) const; + +private: + /// \brief A map from IDs to the bound nodes. + typedef std::map IDToNodeMap; + + IDToNodeMap NodeMap; +}; /// \brief A tree of bound nodes in match results. /// @@ -84,11 +127,10 @@ public: BoundNodesTree(); /// \brief Create a BoundNodesTree from pre-filled maps of bindings. - BoundNodesTree(const std::map& DeclBindings, - const std::map& StmtBindings, + BoundNodesTree(const BoundNodesMap& Bindings, const std::vector RecursiveBindings); - /// \brief Adds all bound nodes to bound_nodes_builder. + /// \brief Adds all bound nodes to \c Builder. void copyTo(BoundNodesTreeBuilder* Builder) const; /// \brief Visits all matches that this BoundNodesTree represents. @@ -99,17 +141,12 @@ public: private: void visitMatchesRecursively( Visitor* ResultVistior, - std::map DeclBindings, - std::map StmtBindings); - - template - void copyBindingsTo(const T& bindings, BoundNodesTreeBuilder* Builder) const; + const BoundNodesMap& AggregatedBindings); // FIXME: Find out whether we want to use different data structures here - // first benchmarks indicate that it doesn't matter though. - std::map DeclBindings; - std::map StmtBindings; + BoundNodesMap Bindings; std::vector RecursiveBindings; }; @@ -123,12 +160,13 @@ public: BoundNodesTreeBuilder(); /// \brief Add a binding from an id to a node. - /// - /// FIXME: Add overloads for all AST base types. - /// @{ - void setBinding(const std::string &Id, const Decl *Node); - void setBinding(const std::string &Id, const Stmt *Node); - /// @} + template + void setBinding(const std::string &Id, const T *Node) { + Bindings.addNode(Id, Node); + } + void setBinding(const std::string &Id, ast_type_traits::DynTypedNode Node) { + Bindings.addNode(Id, Node); + } /// \brief Adds a branch in the tree. void addMatch(const BoundNodesTree& Bindings); @@ -137,11 +175,10 @@ public: BoundNodesTree build() const; private: - BoundNodesTreeBuilder(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT - void operator=(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT + BoundNodesTreeBuilder(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; + void operator=(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; - std::map DeclBindings; - std::map StmtBindings; + BoundNodesMap Bindings; std::vector RecursiveBindings; }; @@ -169,7 +206,8 @@ public: BoundNodesTreeBuilder *Builder) const = 0; }; -/// \brief Interface for matchers that only evaluate properties on a single node. +/// \brief Interface for matchers that only evaluate properties on a single +/// node. template class SingleNodeMatcherInterface : public MatcherInterface { public: @@ -187,6 +225,24 @@ private: } }; +/// \brief Base class for all matchers that works on a \c DynTypedNode. +/// +/// Matcher implementations will check whether the \c DynTypedNode is +/// convertible into the respecitve types and then do the actual match +/// on the actual node, or return false if it is not convertible. +class DynTypedMatcher { +public: + virtual ~DynTypedMatcher() {} + + /// \brief Returns true if the matcher matches the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; + + /// \brief Returns a unique ID for the matcher. + virtual uint64_t getID() const = 0; +}; + /// \brief Wrapper of a MatcherInterface *that allows copying. /// /// A Matcher can be used anywhere a Matcher is @@ -196,12 +252,32 @@ private: /// operator rather than a type hierarchy to be able to templatize the /// type hierarchy instead of spelling it out. template -class Matcher { +class Matcher : public DynTypedMatcher { public: /// \brief Takes ownership of the provided implementation pointer. explicit Matcher(MatcherInterface *Implementation) : Implementation(Implementation) {} + /// \brief Implicitly converts \c Other to a Matcher. + /// + /// Requires \c T to be derived from \c From. + template + Matcher(const Matcher &Other, + typename llvm::enable_if_c< + llvm::is_base_of::value && + !llvm::is_same::value >::type* = 0) + : Implementation(new ImplicitCastMatcher(Other)) {} + + /// \brief Implicitly converts \c Matcher to \c Matcher. + /// + /// The resulting matcher is not strict, i.e. ignores qualifiers. + template + Matcher(const Matcher &Other, + typename llvm::enable_if_c< + llvm::is_same::value && + llvm::is_same::value >::type* = 0) + : Implementation(new TypeToQualType(Other)) {} + /// \brief Forwards the call to the underlying MatcherInterface pointer. bool matches(const T &Node, ASTMatchFinder *Finder, @@ -209,14 +285,6 @@ public: return Implementation->matches(Node, Finder, Builder); } - /// \brief Implicitly converts this object to a Matcher. - /// - /// Requires Derived to be derived from T. - template - operator Matcher() const { - return Matcher(new ImplicitCastMatcher(*this)); - } - /// \brief Returns an ID that uniquely identifies the matcher. uint64_t getID() const { /// FIXME: Document the requirements this imposes on matcher @@ -224,23 +292,55 @@ public: return reinterpret_cast(Implementation.getPtr()); } + /// \brief Returns whether the matcher matches on the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const T *Node = DynNode.get(); + if (!Node) return false; + return matches(*Node, Finder, Builder); + } + + /// \brief Allows the conversion of a \c Matcher to a \c + /// Matcher. + /// + /// Depending on the constructor argument, the matcher is either strict, i.e. + /// does only matches in the absence of qualifiers, or not, i.e. simply + /// ignores any qualifiers. + template + class TypeToQualType : public MatcherInterface { + public: + TypeToQualType(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const QualType &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (Node.isNull()) + return false; + return InnerMatcher.matches(*Node, Finder, Builder); + } + private: + const Matcher InnerMatcher; + }; + private: - /// \brief Allows conversion from Matcher to Matcher if Derived - /// is derived from T. - template - class ImplicitCastMatcher : public MatcherInterface { + /// \brief Allows conversion from Matcher to Matcher if T + /// is derived from Base. + template + class ImplicitCastMatcher : public MatcherInterface { public: - explicit ImplicitCastMatcher(const Matcher &From) + explicit ImplicitCastMatcher(const Matcher &From) : From(From) {} - virtual bool matches(const Derived &Node, + virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return From.matches(Node, Finder, Builder); } private: - const Matcher From; + const Matcher From; }; llvm::IntrusiveRefCntPtr< MatcherInterface > Implementation; @@ -280,18 +380,14 @@ private: /// FIXME: Add other ways to convert... if (Node.isNull()) return false; - CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl(); - return NodeAsRecordDecl != NULL && - InnerMatcher.matches(*NodeAsRecordDecl, Finder, Builder); + return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder); } /// \brief Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const Decl *NodeAsDecl = Node.getCalleeDecl(); - return NodeAsDecl != NULL && - InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + return matchesDecl(Node.getCalleeDecl(), Finder, Builder); } /// \brief Extracts the Decl of the constructor call and returns whether the @@ -299,96 +395,63 @@ private: bool matchesSpecialized(const CXXConstructExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const Decl *NodeAsDecl = Node.getConstructor(); - return NodeAsDecl != NULL && - InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + return matchesDecl(Node.getConstructor(), Finder, Builder); + } + + /// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns + /// whether the inner matcher matches on it. + bool matchesSpecialized(const MemberExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getMemberDecl(), Finder, Builder); + } + + /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node + /// is \c NULL. + bool matchesDecl(const Decl *Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Node != NULL && InnerMatcher.matches(*Node, Finder, Builder); } const Matcher InnerMatcher; }; /// \brief IsBaseType::value is true if T is a "base" type in the AST -/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType). +/// node class hierarchies. template struct IsBaseType { static const bool value = (llvm::is_same::value || llvm::is_same::value || llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value || llvm::is_same::value); }; template const bool IsBaseType::value; -/// \brief Interface that can match any AST base node type and contains default -/// implementations returning false. -class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR { -public: - virtual ~UntypedBaseMatcher() {} - - virtual bool matches(const Decl &DeclNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const QualType &TypeNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const Stmt &StmtNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const CXXCtorInitializer &CtorInitNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - - /// \brief Returns a unique ID for the matcher. - virtual uint64_t getID() const = 0; -}; - -/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method for -/// node type T. T must be an AST base type. -template -class TypedBaseMatcher : public UntypedBaseMatcher { - TOOLING_COMPILE_ASSERT(IsBaseType::value, - typed_base_matcher_can_only_be_used_with_base_type); -public: - explicit TypedBaseMatcher(const Matcher &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - using UntypedBaseMatcher::matches; - /// \brief Implements UntypedBaseMatcher::Matches. - /// - /// Since T is guaranteed to be a "base" AST node type, this method is - /// guaranteed to override one of the matches() methods from - /// UntypedBaseMatcher. - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return InnerMatcher.matches(Node, Finder, Builder); - } - - /// \brief Implements UntypedBaseMatcher::getID. - virtual uint64_t getID() const { - return InnerMatcher.getID(); - } - -private: - Matcher InnerMatcher; -}; - /// \brief Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. /// -/// This provides two entry methods for each base node type in the AST: -/// - matchesChildOf: +/// This provides three entry methods for each base node type in the AST: +/// - \c matchesChildOf: /// Matches a matcher on every child node of the given node. Returns true /// if at least one child node could be matched. -/// - matchesDescendantOf: +/// - \c matchesDescendantOf: /// Matches a matcher on all descendant nodes of the given node. Returns true /// if at least one descendant matched. +/// - \c matchesAncestorOf: +/// Matches a matcher on all ancestors of the given node. Returns true if +/// at least one ancestor matched. +/// +/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal. +/// In the future, we wan to implement this for all nodes for which it makes +/// sense. In the case of matchesAncestorOf, we'll want to implement it for +/// all nodes, as all nodes have ancestors. class ASTMatchFinder { public: /// \brief Defines how we descend a level in the AST when we pass @@ -408,6 +471,14 @@ public: BK_All }; + /// \brief Defines which ancestors are considered for a match. + enum AncestorMatchMode { + /// All ancestors. + AMM_All, + /// Direct parent only. + AMM_ParentOnly + }; + virtual ~ASTMatchFinder() {} /// \brief Returns true if the given class is directly or indirectly derived @@ -418,26 +489,70 @@ public: const Matcher &Base, BoundNodesTreeBuilder *Builder) = 0; - // FIXME: Implement for other base nodes. - virtual bool matchesChildOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - TraversalKind Traverse, - BindKind Bind) = 0; - virtual bool matchesChildOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + template + bool matchesChildOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traverse, + BindKind Bind) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value), + unsupported_type_for_recursive_matching); + return matchesChildOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, Traverse, Bind); + } + + template + bool matchesDescendantOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value || + llvm::is_base_of::value), + unsupported_type_for_recursive_matching); + return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, Bind); + } + + // FIXME: Implement support for BindKind. + template + bool matchesAncestorOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || + llvm::is_base_of::value), + only_Decl_or_Stmt_allowed_for_recursive_matching); + return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, MatchMode); + } + +protected: + virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, TraversalKind Traverse, BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) = 0; + + virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) = 0; }; /// \brief Converts a \c Matcher to a matcher of desired type \c To by @@ -606,9 +721,6 @@ public: /// The returned matcher is equivalent to this matcher, but will /// bind the matched node on a match. Matcher bind(StringRef ID) const { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || - llvm::is_base_of::value), - trying_to_bind_unsupported_node_type__only_decl_and_stmt_supported); return Matcher(new IdMatcher(ID, *this)); } }; @@ -635,7 +747,7 @@ public: } private: - const TypedBaseMatcher ChildMatcher; + const Matcher ChildMatcher; }; /// \brief Matches nodes of type T that have child nodes of type ChildT for @@ -661,7 +773,7 @@ class ForEachMatcher : public MatcherInterface { } private: - const TypedBaseMatcher ChildMatcher; + const Matcher ChildMatcher; }; /// \brief Matches nodes of type T if the given Matcher does not match. @@ -733,6 +845,20 @@ private: const Matcher InnertMatcher2; }; +/// \brief Creates a Matcher that matches if all inner matchers match. +template +BindableMatcher makeAllOfComposite( + ArrayRef *> InnerMatchers) { + if (InnerMatchers.empty()) + return BindableMatcher(new TrueMatcher); + MatcherInterface *InnerMatcher = new TrueMatcher; + for (int i = InnerMatchers.size() - 1; i >= 0; --i) { + InnerMatcher = new AllOfMatcher, Matcher >( + *InnerMatchers[i], makeMatcher(InnerMatcher)); + } + return BindableMatcher(InnerMatcher); +} + /// \brief Creates a Matcher that matches if /// T is dyn_cast'able into InnerT and all inner matchers match. /// @@ -742,17 +868,8 @@ private: template BindableMatcher makeDynCastAllOfComposite( ArrayRef *> InnerMatchers) { - if (InnerMatchers.empty()) { - Matcher InnerMatcher = makeMatcher(new TrueMatcher); - return BindableMatcher(new DynCastMatcher(InnerMatcher)); - } - Matcher InnerMatcher = *InnerMatchers.back(); - for (int i = InnerMatchers.size() - 2; i >= 0; --i) { - InnerMatcher = makeMatcher( - new AllOfMatcher, Matcher >( - *InnerMatchers[i], InnerMatcher)); - } - return BindableMatcher(new DynCastMatcher(InnerMatcher)); + return BindableMatcher(new DynCastMatcher( + makeAllOfComposite(InnerMatchers))); } /// \brief Matches nodes of type T that have at least one descendant node of @@ -775,7 +892,53 @@ public: } private: - const TypedBaseMatcher DescendantMatcher; + const Matcher DescendantMatcher; +}; + +/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT +/// for which the given inner matcher matches. +/// +/// \c ParentT must be an AST base type. +template +class HasParentMatcher : public MatcherInterface { + TOOLING_COMPILE_ASSERT(IsBaseType::value, + has_parent_only_accepts_base_type_matcher); +public: + explicit HasParentMatcher(const Matcher &ParentMatcher) + : ParentMatcher(ParentMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesAncestorOf( + Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly); + } + + private: + const Matcher ParentMatcher; +}; + +/// \brief Matches nodes of type \c T that have at least one ancestor node of +/// type \c AncestorT for which the given inner matcher matches. +/// +/// \c AncestorT must be an AST base type. +template +class HasAncestorMatcher : public MatcherInterface { + TOOLING_COMPILE_ASSERT(IsBaseType::value, + has_ancestor_only_accepts_base_type_matcher); +public: + explicit HasAncestorMatcher(const Matcher &AncestorMatcher) + : AncestorMatcher(AncestorMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesAncestorOf( + Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All); + } + + private: + const Matcher AncestorMatcher; }; /// \brief Matches nodes of type T that have at least one descendant node of @@ -801,7 +964,7 @@ class ForEachDescendantMatcher : public MatcherInterface { } private: - const TypedBaseMatcher DescendantMatcher; + const Matcher DescendantMatcher; }; /// \brief Matches on nodes that have a getValue() method if getValue() equals @@ -858,6 +1021,22 @@ class IsTemplateInstantiationMatcher : public MatcherInterface { } }; +/// \brief Matches on explicit template specializations for FunctionDecl, +/// VarDecl or CXXRecordDecl nodes. +template +class IsExplicitTemplateSpecializationMatcher : public MatcherInterface { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) || + (llvm::is_base_of::value) || + (llvm::is_base_of::value), + requires_getTemplateSpecializationKind_method); + public: + virtual bool matches(const T& Node, + ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const { + return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); + } +}; + class IsArrowMatcher : public SingleNodeMatcherInterface { public: virtual bool matchesNode(const MemberExpr &Node) const { @@ -894,6 +1073,166 @@ public: VariadicDynCastAllOfMatcher() {} }; +/// \brief A \c VariadicAllOfMatcher object is a variadic functor that takes +/// a number of \c Matcher and returns a \c Matcher that matches \c T +/// nodes that are matched by all of the given matchers. +/// +/// For example: +/// const VariadicAllOfMatcher nestedNameSpecifier; +/// Creates a functor nestedNameSpecifier(...) that creates a +/// \c Matcher given a variable number of arguments of type +/// \c Matcher. +/// The returned matcher matches if all given matchers match. +template +class VariadicAllOfMatcher : public llvm::VariadicFunction< + BindableMatcher, Matcher, + makeAllOfComposite > { +public: + VariadicAllOfMatcher() {} +}; + +/// \brief Matches nodes of type \c TLoc for which the inner +/// \c Matcher matches. +template +class LocMatcher : public MatcherInterface { +public: + explicit LocMatcher(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const TLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (!Node) + return false; + return InnerMatcher.matches(*extract(Node), Finder, Builder); + } + +private: + const NestedNameSpecifier *extract(const NestedNameSpecifierLoc &Loc) const { + return Loc.getNestedNameSpecifier(); + } + + const Matcher InnerMatcher; +}; + +/// \brief Matches \c NestedNameSpecifiers with a prefix matching another +/// \c Matcher. +class NestedNameSpecifierPrefixMatcher + : public MatcherInterface { +public: + explicit NestedNameSpecifierPrefixMatcher( + const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const NestedNameSpecifier &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + NestedNameSpecifier *NextNode = Node.getPrefix(); + if (NextNode == NULL) + return false; + return InnerMatcher.matches(*NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; +}; + +/// \brief Matches \c NestedNameSpecifierLocs with a prefix matching another +/// \c Matcher. +class NestedNameSpecifierLocPrefixMatcher + : public MatcherInterface { +public: + explicit NestedNameSpecifierLocPrefixMatcher( + const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const NestedNameSpecifierLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + NestedNameSpecifierLoc NextNode = Node.getPrefix(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; +}; + +/// \brief Matches \c TypeLocs based on an inner matcher matching a certain +/// \c QualType. +/// +/// Used to implement the \c loc() matcher. +class TypeLocTypeMatcher : public MatcherInterface { +public: + explicit TypeLocTypeMatcher(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const TypeLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (!Node) + return false; + return InnerMatcher.matches(Node.getType(), Finder, Builder); + } + +private: + const Matcher InnerMatcher; +}; + +/// \brief Matches nodes of type \c T for which the inner matcher matches on a +/// another node of type \c T that can be reached using a given traverse +/// function. +template +class TypeTraverseMatcher : public MatcherInterface { +public: + explicit TypeTraverseMatcher(const Matcher &InnerMatcher, + QualType (T::*TraverseFunction)() const) + : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + QualType NextNode = (Node.*TraverseFunction)(); + if (NextNode.isNull()) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; + QualType (T::*TraverseFunction)() const; +}; + +/// \brief Matches nodes of type \c T in a ..Loc hierarchy, for which the inner +/// matcher matches on a another node of type \c T that can be reached using a +/// given traverse function. +template +class TypeLocTraverseMatcher : public MatcherInterface { +public: + explicit TypeLocTraverseMatcher(const Matcher &InnerMatcher, + TypeLoc (T::*TraverseFunction)() const) + : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + TypeLoc NextNode = (Node.*TraverseFunction)(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher InnerMatcher; + TypeLoc (T::*TraverseFunction)() const; +}; + +template +T makeTypeAllOfComposite(ArrayRef *> InnerMatchers) { + return T(makeAllOfComposite(InnerMatchers)); +} + } // end namespace internal } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index c68534acae35..953abc2a2ec9 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -221,4 +221,69 @@ const NodeType &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const +/// \brief Creates a variadic matcher for both a specific \c Type as well as +/// the corresponding \c TypeLoc. +#define AST_TYPE_MATCHER(NodeType, MatcherName) \ + const internal::VariadicDynCastAllOfMatcher MatcherName; \ + const internal::VariadicDynCastAllOfMatcher MatcherName##Loc + +/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines +/// the matcher \c MatcherName that can be used to traverse from one \c Type +/// to another. +/// +/// For a specific \c SpecificType, the traversal is done using +/// \c SpecificType::FunctionName. The existance of such a function determines +/// whether a corresponding matcher can be used on \c SpecificType. +#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \ +class Polymorphic##MatcherName##TypeMatcher { \ +public: \ + Polymorphic##MatcherName##TypeMatcher( \ + const internal::Matcher &InnerMatcher) \ + : InnerMatcher(InnerMatcher) {} \ + template operator internal::Matcher() { \ + return internal::Matcher(new internal::TypeTraverseMatcher( \ + InnerMatcher, &T::FunctionName)); \ + } \ +private: \ + const internal::Matcher InnerMatcher; \ +}; \ +class Variadic##MatcherName##TypeTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeMatcher, \ + internal::Matcher, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeMatcher, QualType> > { \ +public: \ + Variadic##MatcherName##TypeTraverseMatcher() {} \ +}; \ +const Variadic##MatcherName##TypeTraverseMatcher MatcherName + +/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works +/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. +#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \ +class Polymorphic##MatcherName##TypeLocMatcher { \ +public: \ + Polymorphic##MatcherName##TypeLocMatcher( \ + const internal::Matcher &InnerMatcher) \ + : InnerMatcher(InnerMatcher) {} \ + template operator internal::Matcher() { \ + return internal::Matcher(new internal::TypeLocTraverseMatcher( \ + InnerMatcher, &T::FunctionName##Loc)); \ + } \ +private: \ + const internal::Matcher InnerMatcher; \ +}; \ +class Variadic##MatcherName##TypeLocTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeLocMatcher, \ + internal::Matcher, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ +public: \ + Variadic##MatcherName##TypeLocTraverseMatcher() {} \ +}; \ +const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ +AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) + #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H diff --git a/include/clang/ASTMatchers/ASTTypeTraits.h b/include/clang/ASTMatchers/ASTTypeTraits.h new file mode 100644 index 000000000000..bda53eaf70f6 --- /dev/null +++ b/include/clang/ASTMatchers/ASTTypeTraits.h @@ -0,0 +1,209 @@ +//===--- ASTMatchersTypeTraits.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a dynamically typed node container that can be used to store +// an AST base node at runtime in the same storage in a type safe way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H +#define LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H + +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "llvm/Support/AlignOf.h" + +namespace clang { +namespace ast_type_traits { + +/// \brief A dynamically typed AST node container. +/// +/// Stores an AST node in a type safe way. This allows writing code that +/// works with different kinds of AST nodes, despite the fact that they don't +/// have a common base class. +/// +/// Use \c create(Node) to create a \c DynTypedNode from an AST node, +/// and \c get() to retrieve the node as type T if the types match. +/// +/// See \c NodeTypeTag for which node base types are currently supported; +/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of +/// the supported base types. +class DynTypedNode { +public: + /// \brief Creates a \c DynTypedNode from \c Node. + template + static DynTypedNode create(const T &Node) { + return BaseConverter::create(Node); + } + + /// \brief Retrieve the stored node as type \c T. + /// + /// Returns NULL if the stored node does not have a type that is + /// convertible to \c T. + /// + /// For types that have identity via their pointer in the AST + /// (like \c Stmt and \c Decl) the returned pointer points to the + /// referenced AST node. + /// For other types (like \c QualType) the value is stored directly + /// in the \c DynTypedNode, and the returned pointer points at + /// the storage inside DynTypedNode. For those nodes, do not + /// use the pointer outside the scope of the DynTypedNode. + template + const T *get() const { + return BaseConverter::get(Tag, Storage.buffer); + } + + /// \brief Returns a pointer that identifies the stored AST node. + /// + /// Note that this is not supported by all AST nodes. For AST nodes + /// that don't have a pointer-defined identity inside the AST, this + /// method returns NULL. + const void *getMemoizationData() const; + +private: + /// \brief Takes care of converting from and to \c T. + template struct BaseConverter; + + /// \brief Supported base node types. + enum NodeTypeTag { + NT_Decl, + NT_Stmt, + NT_NestedNameSpecifier, + NT_NestedNameSpecifierLoc, + NT_QualType, + NT_Type, + NT_TypeLoc + } Tag; + + /// \brief Stores the data of the node. + /// + /// Note that we can store \c Decls and \c Stmts by pointer as they are + /// guaranteed to be unique pointers pointing to dedicated storage in the + /// AST. \c QualTypes on the other hand do not have storage or unique + /// pointers and thus need to be stored by value. + llvm::AlignedCharArrayUnion + Storage; +}; + +// FIXME: Pull out abstraction for the following. +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Decl) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Decl &Node) { + DynTypedNode Result; + Result.Tag = NT_Decl; + new (Result.Storage.buffer) const Decl*(&Node); + return Result; + } +}; +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Stmt) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Stmt &Node) { + DynTypedNode Result; + Result.Tag = NT_Stmt; + new (Result.Storage.buffer) const Stmt*(&Node); + return Result; + } +}; +template struct DynTypedNode::BaseConverter >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Type) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const Type &Node) { + DynTypedNode Result; + Result.Tag = NT_Type; + new (Result.Storage.buffer) const Type*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_NestedNameSpecifier) + return *reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifier &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifier; + new (Result.Storage.buffer) const NestedNameSpecifier*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const NestedNameSpecifierLoc *get(NodeTypeTag Tag, + const char Storage[]) { + if (Tag == NT_NestedNameSpecifierLoc) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifierLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifierLoc; + new (Result.Storage.buffer) NestedNameSpecifierLoc(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const QualType *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_QualType) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const QualType &Node) { + DynTypedNode Result; + Result.Tag = NT_QualType; + new (Result.Storage.buffer) QualType(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter { + static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_TypeLoc) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const TypeLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_TypeLoc; + new (Result.Storage.buffer) TypeLoc(Node); + return Result; + } +}; +// The only operation we allow on unsupported types is \c get. +// This allows to conveniently use \c DynTypedNode when having an arbitrary +// AST node that is not supported, but prevents misuse - a user cannot create +// a DynTypedNode from arbitrary types. +template struct DynTypedNode::BaseConverter { + static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; } +}; + +inline const void *DynTypedNode::getMemoizationData() const { + switch (Tag) { + case NT_Decl: return BaseConverter::get(Tag, Storage.buffer); + case NT_Stmt: return BaseConverter::get(Tag, Storage.buffer); + default: return NULL; + }; +} + +} // end namespace ast_type_traits +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 7f50ee392be6..5cb973122d72 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -23,6 +23,8 @@ namespace clang { +class TargetInfo; + //===----------------------------------------------------------------------===// /// Common components of both fprintf and fscanf format strings. namespace analyze_format_string { @@ -115,11 +117,14 @@ public: // C99 conversion specifiers. cArg, dArg, + DArg, // Apple extension iArg, - IntArgBeg = cArg, IntArgEnd = iArg, + IntArgBeg = dArg, IntArgEnd = iArg, oArg, + OArg, // Apple extension uArg, + UArg, // Apple extension xArg, XArg, UIntArgBeg = oArg, UIntArgEnd = XArg, @@ -157,7 +162,7 @@ public: ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg }; - ConversionSpecifier(bool isPrintf) + ConversionSpecifier(bool isPrintf = true) : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {} ConversionSpecifier(bool isPrintf, const char *pos, Kind k) @@ -189,10 +194,14 @@ public: return EndScanList ? EndScanList - Position : 1; } + bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; } bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } + bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; } const char *toString() const; bool isPrintfKind() const { return IsPrintf; } + + llvm::Optional getStandardSpecifier() const; protected: bool IsPrintf; @@ -348,10 +357,12 @@ public: bool usesPositionalArg() const { return UsesPositionalArg; } - bool hasValidLengthModifier() const; + bool hasValidLengthModifier(const TargetInfo &Target) const; bool hasStandardLengthModifier() const; + llvm::Optional getCorrectedLengthModifier() const; + bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; bool hasStandardLengthConversionCombination() const; @@ -378,7 +389,6 @@ public: : ConversionSpecifier(true, pos, k) {} bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } - bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; } bool isDoubleArg() const { return kind >= DoubleArgBeg && kind <= DoubleArgEnd; } unsigned getLength() const { @@ -623,10 +633,12 @@ public: }; bool ParsePrintfString(FormatStringHandler &H, - const char *beg, const char *end, const LangOptions &LO); + const char *beg, const char *end, const LangOptions &LO, + const TargetInfo &Target); bool ParseScanfString(FormatStringHandler &H, - const char *beg, const char *end, const LangOptions &LO); + const char *beg, const char *end, const LangOptions &LO, + const TargetInfo &Target); } // end analyze_format_string namespace } // end clang namespace diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index 742cc0434456..ef6b821e390b 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -132,7 +132,8 @@ public: /// \param Loc -- The location of the protected operation. virtual void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, Name LockName, - LockKind LK, SourceLocation Loc) {} + LockKind LK, SourceLocation Loc, + Name *PossibleMatch=0) {} /// Warn when a function is called while an excluded mutex is locked. For /// example, the mutex may be locked inside the function. diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 46b4e93bb7d4..52466786b341 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -72,7 +72,7 @@ class AnalysisDeclContext { /// AnalysisDeclContext. This may be null. AnalysisDeclContextManager *Manager; - const Decl *D; + const Decl * const D; OwningPtr cfg, completeCFG; OwningPtr cfgStmtMap; @@ -81,9 +81,6 @@ class AnalysisDeclContext { CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; bool builtCFG, builtCompleteCFG; - - OwningPtr liveness; - OwningPtr relaxedLiveness; OwningPtr PM; OwningPtr PCA; OwningPtr CFA; @@ -104,9 +101,15 @@ public: ~AnalysisDeclContext(); - ASTContext &getASTContext() { return D->getASTContext(); } + ASTContext &getASTContext() const { return D->getASTContext(); } const Decl *getDecl() const { return D; } + /// Return the AnalysisDeclContextManager (if any) that created + /// this AnalysisDeclContext. + AnalysisDeclContextManager *getManager() const { + return Manager; + } + /// Return the build options used to construct the CFG. CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; @@ -234,9 +237,10 @@ public: const StackFrameContext *getCurrentStackFrame() const; - virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; + /// Return true if the current LocationContext has no caller context. + virtual bool inTopFrame() const; - static bool classof(const LocationContext*) { return true; } + virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; public: static void ProfileCommon(llvm::FoldingSetNodeID &ID, @@ -270,6 +274,9 @@ public: const CFGBlock *getCallSiteBlock() const { return Block; } + /// Return true if the current LocationContext has no caller context. + virtual bool inTopFrame() const { return getParent() == 0; } + unsigned getIndex() const { return Index; } void Profile(llvm::FoldingSetNodeID &ID); @@ -379,11 +386,17 @@ class AnalysisDeclContextManager { ContextMap Contexts; LocationContextManager LocContexts; CFG::BuildOptions cfgBuildOptions; + + /// Flag to indicate whether or not bodies should be synthesized + /// for well-known functions. + bool SynthesizeBodies; public: AnalysisDeclContextManager(bool useUnoptimizedCFG = false, - bool addImplicitDtors = false, - bool addInitializers = false); + bool addImplicitDtors = false, + bool addInitializers = false, + bool addTemporaryDtors = false, + bool synthesizeBodies = false); ~AnalysisDeclContextManager(); @@ -396,6 +409,10 @@ public: CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; } + + /// Return true if faux bodies should be synthesized for well-known + /// functions. + bool synthesizeBodies() const { return SynthesizeBodies; } const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx, LocationContext const *Parent, diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 4d087e749830..8cc5d814e822 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -88,8 +88,6 @@ public: return static_cast(this); return 0; } - - static bool classof(const CFGElement *E) { return true; } }; class CFGStmt : public CFGElement { @@ -568,6 +566,7 @@ public: bool AddEHEdges; bool AddInitializers; bool AddImplicitDtors; + bool AddTemporaryDtors; bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; @@ -587,7 +586,8 @@ public: : forcedBlkExprs(0), PruneTriviallyFalseEdges(true) ,AddEHEdges(false) ,AddInitializers(false) - ,AddImplicitDtors(false) {} + ,AddImplicitDtors(false) + ,AddTemporaryDtors(false) {} }; /// \brief Provides a custom implementation of the iterator class to have the diff --git a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h new file mode 100644 index 000000000000..930c2bd0925b --- /dev/null +++ b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h @@ -0,0 +1,46 @@ +//= ObjCNoReturn.h - Handling of Cocoa APIs known not to return --*- C++ -*---// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements special handling of recognizing ObjC API hooks that +// do not return but aren't marked as such in API headers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN +#define LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN + +#include "clang/Basic/IdentifierTable.h" + +namespace clang { + +class ASTContext; +class ObjCMessageExpr; + +class ObjCNoReturn { + /// Cached "raise" selector. + Selector RaiseSel; + + /// Cached identifier for "NSException". + IdentifierInfo *NSExceptionII; + + enum { NUM_RAISE_SELECTORS = 2 }; + + /// Cached set of selectors in NSException that are 'noreturn'. + Selector NSExceptionInstanceRaiseSelectors[NUM_RAISE_SELECTORS]; + +public: + ObjCNoReturn(ASTContext &C); + + /// Return true if the given message expression is known to never + /// return. + bool isImplicitNoReturn(const ObjCMessageExpr *ME); +}; +} + +#endif diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 5de06cd3a54d..947997804388 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -140,8 +140,6 @@ public: return ID.ComputeHash(); } - static bool classof(const ProgramPoint*) { return true; } - bool operator==(const ProgramPoint & RHS) const { return Data1 == RHS.Data1 && Data2 == RHS.Data2 && @@ -213,7 +211,9 @@ class StmtPoint : public ProgramPoint { public: StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, const ProgramPointTag *tag) - : ProgramPoint(S, p2, k, L, tag) {} + : ProgramPoint(S, p2, k, L, tag) { + assert(S); + } const Stmt *getStmt() const { return (const Stmt*) getData1(); } @@ -461,6 +461,7 @@ public: }; /// Represents a point when we begin processing an inlined call. +/// CallEnter uses the caller's location context. class CallEnter : public ProgramPoint { public: CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index fade83ef9361..bfe8093079b7 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -190,7 +190,7 @@ def Availability : InheritableAttr { [{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { return llvm::StringSwitch(Platform) .Case("ios", "iOS") - .Case("macosx", "Mac OS X") + .Case("macosx", "OS X") .Default(llvm::StringRef()); } }]; } @@ -341,6 +341,11 @@ def Final : InheritableAttr { let SemaHandler = 0; } +def MinSize : InheritableAttr { + let Spellings = [GNU<"minsize">]; + let Subjects = [Function]; +} + def Format : InheritableAttr { let Spellings = [GNU<"format">]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, @@ -528,6 +533,11 @@ def ObjCReturnsInnerPointer : Attr { let Subjects = [ObjCMethod]; } +def ObjCRequiresSuper : InheritableAttr { + let Spellings = [GNU<"objc_requires_super">]; + let Subjects = [ObjCMethod]; +} + def ObjCRootClass : Attr { let Spellings = [GNU<"objc_root_class">]; let Subjects = [ObjCInterface]; @@ -556,6 +566,10 @@ def Packed : InheritableAttr { let Spellings = [GNU<"packed">]; } +def PnaclCall : InheritableAttr { + let Spellings = [GNU<"pnaclcall">]; +} + def Pcs : InheritableAttr { let Spellings = [GNU<"pcs">]; let Args = [EnumArgument<"PCS", "PCSType", diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 84b28811728e..d48eadcd6b61 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -41,6 +41,7 @@ // J -> jmp_buf // SJ -> sigjmp_buf // K -> ucontext_t +// p -> pid_t // . -> "...". This may only occur at the end of the function list. // // Types may be prefixed with the following modifiers: @@ -388,6 +389,7 @@ BUILTIN(__builtin_popcountll, "iULLi", "nc") // FIXME: These type signatures are not correct for targets with int != 32-bits // or with ULL != 64-bits. +BUILTIN(__builtin_bswap16, "UsUs", "nc") BUILTIN(__builtin_bswap32, "UiUi", "nc") BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") @@ -478,6 +480,7 @@ BUILTIN(__builtin_expect, "LiLiLi" , "nc") BUILTIN(__builtin_prefetch, "vvC*.", "nc") BUILTIN(__builtin_readcyclecounter, "ULLi", "n") BUILTIN(__builtin_trap, "v", "nr") +BUILTIN(__builtin_debugtrap, "v", "n") BUILTIN(__builtin_unreachable, "v", "nr") BUILTIN(__builtin_shufflevector, "v." , "nc") BUILTIN(__builtin_alloca, "v*z" , "n") @@ -735,7 +738,7 @@ LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_LANGUAGES) LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_LANGUAGES) // POSIX unistd.h LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES) -LIBBUILTIN(vfork, "i", "fj", "unistd.h", ALL_LANGUAGES) +LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_LANGUAGES) // POSIX setjmp.h // In some systems setjmp is a macro that expands to _setjmp. We undefine @@ -826,9 +829,13 @@ LIBBUILTIN(atan2, "ddd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(atan2l, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(atan2f, "fff", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(ceil, "dd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(ceill, "LdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(ceilf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(ceil, "dd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(ceill, "LdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(ceilf, "ff", "fc", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(copysign, "ddd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(copysignl, "LdLdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(copysignf, "fff", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(cos, "dd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosl, "LdLd", "fe", "math.h", ALL_LANGUAGES) @@ -838,37 +845,53 @@ LIBBUILTIN(exp, "dd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(expl, "LdLd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(expf, "ff", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fabs, "dd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fabsl, "LdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fabsf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(exp2, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(exp2l, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(exp2f, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(fabs, "dd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fabsl, "LdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fabsf, "ff", "fc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(floor, "dd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(floorl, "LdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(floorf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(floor, "dd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(floorl, "LdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(floorf, "ff", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fma, "dddd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmal, "LdLdLdLd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmaf, "ffff", "fc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fmax, "ddd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fmaxl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fmaxf, "fff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmax, "ddd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmaxl, "LdLdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmaxf, "fff", "fc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fmin, "ddd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fminl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(fminf, "fff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmin, "ddd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fminl, "LdLdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fminf, "fff", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(log, "dd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(logl, "LdLd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(logf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(log2, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(log2l, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(log2f, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(nearbyint, "dd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nearbyintl, "LdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nearbyintf, "ff", "fc", "math.h", ALL_LANGUAGES) + LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(powf, "fff", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(round, "dd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(roundl, "LdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(roundf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(rint, "dd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(rintl, "LdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(rintf, "ff", "fc", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(round, "dd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(roundl, "LdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(roundf, "ff", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(sin, "dd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(sinl, "LdLd", "fe", "math.h", ALL_LANGUAGES) @@ -882,6 +905,10 @@ LIBBUILTIN(tan, "dd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(tanl, "LdLd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(tanf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(trunc, "dd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(truncl, "LdLd", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(truncf, "ff", "fc", "math.h", ALL_LANGUAGES) + // Blocks runtime Builtin math library functions LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES) LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES) diff --git a/include/clang/Basic/BuiltinsMips.def b/include/clang/Basic/BuiltinsMips.def index d0137155a2d0..43fb90756efb 100644 --- a/include/clang/Basic/BuiltinsMips.def +++ b/include/clang/Basic/BuiltinsMips.def @@ -14,6 +14,8 @@ // The format of this database matches clang/Basic/Builtins.def. +// MIPS DSP Rev 1 + // Add/subtract with optional saturation BUILTIN(__builtin_mips_addu_qb, "V4ScV4ScV4Sc", "n") BUILTIN(__builtin_mips_addu_s_qb, "V4ScV4ScV4Sc", "n") @@ -122,4 +124,65 @@ BUILTIN(__builtin_mips_lbux, "iv*i", "n") BUILTIN(__builtin_mips_lhx, "iv*i", "n") BUILTIN(__builtin_mips_lwx, "iv*i", "n") +// MIPS DSP Rev 2 + +BUILTIN(__builtin_mips_absq_s_qb, "V4ScV4Sc", "n") + +BUILTIN(__builtin_mips_addqh_ph, "V2sV2sV2s", "nc") +BUILTIN(__builtin_mips_addqh_r_ph, "V2sV2sV2s", "nc") +BUILTIN(__builtin_mips_addqh_w, "iii", "nc") +BUILTIN(__builtin_mips_addqh_r_w, "iii", "nc") + +BUILTIN(__builtin_mips_addu_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_addu_s_ph, "V2sV2sV2s", "n") + +BUILTIN(__builtin_mips_adduh_qb, "V4ScV4ScV4Sc", "nc") +BUILTIN(__builtin_mips_adduh_r_qb, "V4ScV4ScV4Sc", "nc") + +BUILTIN(__builtin_mips_append, "iiiIi", "nc") +BUILTIN(__builtin_mips_balign, "iiiIi", "nc") + +BUILTIN(__builtin_mips_cmpgdu_eq_qb, "iV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmpgdu_lt_qb, "iV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmpgdu_le_qb, "iV4ScV4Sc", "n") + +BUILTIN(__builtin_mips_dpa_w_ph, "LLiLLiV2sV2s", "nc") +BUILTIN(__builtin_mips_dps_w_ph, "LLiLLiV2sV2s", "nc") + +BUILTIN(__builtin_mips_dpaqx_s_w_ph, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_dpaqx_sa_w_ph, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_dpax_w_ph, "LLiLLiV2sV2s", "nc") +BUILTIN(__builtin_mips_dpsx_w_ph, "LLiLLiV2sV2s", "nc") +BUILTIN(__builtin_mips_dpsqx_s_w_ph, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_dpsqx_sa_w_ph, "LLiLLiV2sV2s", "n") + +BUILTIN(__builtin_mips_mul_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_mul_s_ph, "V2sV2sV2s", "n") + +BUILTIN(__builtin_mips_mulq_rs_w, "iii", "n") +BUILTIN(__builtin_mips_mulq_s_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_mulq_s_w, "iii", "n") +BUILTIN(__builtin_mips_mulsa_w_ph, "LLiLLiV2sV2s", "nc") + +BUILTIN(__builtin_mips_precr_qb_ph, "V4ScV2sV2s", "n") +BUILTIN(__builtin_mips_precr_sra_ph_w, "V2siiIi", "nc") +BUILTIN(__builtin_mips_precr_sra_r_ph_w, "V2siiIi", "nc") + +BUILTIN(__builtin_mips_prepend, "iiiIi", "nc") + +BUILTIN(__builtin_mips_shra_qb, "V4ScV4Sci", "nc") +BUILTIN(__builtin_mips_shra_r_qb, "V4ScV4Sci", "nc") +BUILTIN(__builtin_mips_shrl_ph, "V2sV2si", "nc") + +BUILTIN(__builtin_mips_subqh_ph, "V2sV2sV2s", "nc") +BUILTIN(__builtin_mips_subqh_r_ph, "V2sV2sV2s", "nc") +BUILTIN(__builtin_mips_subqh_w, "iii", "nc") +BUILTIN(__builtin_mips_subqh_r_w, "iii", "nc") + +BUILTIN(__builtin_mips_subu_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_subu_s_ph, "V2sV2sV2s", "n") + +BUILTIN(__builtin_mips_subuh_qb, "V4ScV4ScV4Sc", "nc") +BUILTIN(__builtin_mips_subuh_r_qb, "V4ScV4ScV4Sc", "nc") + #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def index f90a43f7f404..3c3f06c5ea3a 100644 --- a/include/clang/Basic/BuiltinsNVPTX.def +++ b/include/clang/Basic/BuiltinsNVPTX.def @@ -14,6 +14,7 @@ // The format of this database matches clang/Basic/Builtins.def. +// Builtins retained from previous PTX back-end BUILTIN(__builtin_ptx_read_tid_x, "i", "nc") BUILTIN(__builtin_ptx_read_tid_y, "i", "nc") BUILTIN(__builtin_ptx_read_tid_z, "i", "nc") @@ -59,4 +60,249 @@ BUILTIN(__builtin_ptx_read_pm3, "i", "n") BUILTIN(__builtin_ptx_bar_sync, "vi", "n") +// Builtins exposed as part of NVVM +BUILTIN(__syncthreads, "v", "n") +BUILTIN(__nvvm_bar0, "v", "n") +BUILTIN(__nvvm_bar0_popc, "ii", "n") +BUILTIN(__nvvm_bar0_and, "ii", "n") +BUILTIN(__nvvm_bar0_or, "ii", "n") +BUILTIN(__nvvm_membar_cta, "v", "n") +BUILTIN(__nvvm_membar_gl, "v", "n") +BUILTIN(__nvvm_membar_sys, "v", "n") +BUILTIN(__nvvm_popc_i, "ii", "nc") +BUILTIN(__nvvm_popc_ll, "LiLi", "nc") +BUILTIN(__nvvm_prmt, "UiUiUiUi", "nc") +BUILTIN(__nvvm_min_i, "iii", "nc") +BUILTIN(__nvvm_min_ui, "UiUiUi", "nc") +BUILTIN(__nvvm_min_ll, "LLiLLiLLi", "nc") +BUILTIN(__nvvm_min_ull, "ULLiULLiULLi", "nc") +BUILTIN(__nvvm_max_i, "iii", "nc") +BUILTIN(__nvvm_max_ui, "UiUiUi", "nc") +BUILTIN(__nvvm_max_ll, "LLiLLiLLi", "nc") +BUILTIN(__nvvm_max_ull, "ULLiULLiULLi", "nc") +BUILTIN(__nvvm_mulhi_i, "iii", "nc") +BUILTIN(__nvvm_mulhi_ui, "UiUiUi", "nc") +BUILTIN(__nvvm_mulhi_ll, "LLiLLiLLi", "nc") +BUILTIN(__nvvm_mulhi_ull, "ULLiULLiULLi", "nc") +BUILTIN(__nvvm_mul24_i, "iii", "nc") +BUILTIN(__nvvm_mul24_ui, "UiUiUi", "nc") +BUILTIN(__nvvm_brev32, "UiUi", "nc") +BUILTIN(__nvvm_brev64, "ULLiULLi", "nc") +BUILTIN(__nvvm_sad_i, "iiii", "nc") +BUILTIN(__nvvm_sad_ui, "UiUiUiUi", "nc") +BUILTIN(__nvvm_abs_i, "ii", "nc") +BUILTIN(__nvvm_abs_ll, "LiLi", "nc") +BUILTIN(__nvvm_floor_ftz_f, "ff", "nc") +BUILTIN(__nvvm_floor_f, "ff", "nc") +BUILTIN(__nvvm_floor_d, "dd", "nc") +BUILTIN(__nvvm_fabs_ftz_f, "ff", "nc") +BUILTIN(__nvvm_fabs_f, "ff", "nc") +BUILTIN(__nvvm_fabs_d, "dd", "nc") +BUILTIN(__nvvm_rcp_approx_ftz_d, "dd", "nc") +BUILTIN(__nvvm_fmin_ftz_f, "fff", "nc") +BUILTIN(__nvvm_fmin_f, "fff", "nc") +BUILTIN(__nvvm_fmax_ftz_f, "fff", "nc") +BUILTIN(__nvvm_fmax_f, "fff", "nc") +BUILTIN(__nvvm_rsqrt_approx_ftz_f, "ff", "nc") +BUILTIN(__nvvm_rsqrt_approx_f, "ff", "nc") +BUILTIN(__nvvm_fmin_d, "ddd", "nc") +BUILTIN(__nvvm_fmax_d, "ddd", "nc") +BUILTIN(__nvvm_rsqrt_approx_d, "dd", "nc") +BUILTIN(__nvvm_ceil_d, "dd", "nc") +BUILTIN(__nvvm_trunc_d, "dd", "nc") +BUILTIN(__nvvm_round_d, "dd", "nc") +BUILTIN(__nvvm_ex2_approx_d, "dd", "nc") +BUILTIN(__nvvm_lg2_approx_d, "dd", "nc") +BUILTIN(__nvvm_round_ftz_f, "ff", "nc") +BUILTIN(__nvvm_round_f, "ff", "nc") +BUILTIN(__nvvm_ex2_approx_ftz_f, "ff", "nc") +BUILTIN(__nvvm_ex2_approx_f, "ff", "nc") +BUILTIN(__nvvm_lg2_approx_ftz_f, "ff", "nc") +BUILTIN(__nvvm_lg2_approx_f, "ff", "nc") +BUILTIN(__nvvm_sin_approx_ftz_f, "ff", "nc") +BUILTIN(__nvvm_sin_approx_f, "ff", "nc") +BUILTIN(__nvvm_cos_approx_ftz_f, "ff", "nc") +BUILTIN(__nvvm_cos_approx_f, "ff", "nc") +BUILTIN(__nvvm_trunc_ftz_f, "ff", "nc") +BUILTIN(__nvvm_trunc_f, "ff", "nc") +BUILTIN(__nvvm_ceil_ftz_f, "ff", "nc") +BUILTIN(__nvvm_ceil_f, "ff", "nc") +BUILTIN(__nvvm_saturate_d, "dd", "nc") +BUILTIN(__nvvm_saturate_ftz_f, "ff", "nc") +BUILTIN(__nvvm_saturate_f, "ff", "nc") +BUILTIN(__nvvm_fma_rn_ftz_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rn_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rz_ftz_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rz_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rm_ftz_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rm_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rp_ftz_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rp_f, "ffff", "nc") +BUILTIN(__nvvm_fma_rn_d, "dddd", "nc") +BUILTIN(__nvvm_fma_rz_d, "dddd", "nc") +BUILTIN(__nvvm_fma_rm_d, "dddd", "nc") +BUILTIN(__nvvm_fma_rp_d, "dddd", "nc") +BUILTIN(__nvvm_div_approx_ftz_f, "fff", "nc") +BUILTIN(__nvvm_div_approx_f, "fff", "nc") +BUILTIN(__nvvm_div_rn_ftz_f, "fff", "nc") +BUILTIN(__nvvm_div_rn_f, "fff", "nc") +BUILTIN(__nvvm_div_rz_ftz_f, "fff", "nc") +BUILTIN(__nvvm_div_rz_f, "fff", "nc") +BUILTIN(__nvvm_div_rm_ftz_f, "fff", "nc") +BUILTIN(__nvvm_div_rm_f, "fff", "nc") +BUILTIN(__nvvm_div_rp_ftz_f, "fff", "nc") +BUILTIN(__nvvm_div_rp_f, "fff", "nc") +BUILTIN(__nvvm_rcp_rn_ftz_f, "ff", "nc") +BUILTIN(__nvvm_rcp_rn_f, "ff", "nc") +BUILTIN(__nvvm_rcp_rz_ftz_f, "ff", "nc") +BUILTIN(__nvvm_rcp_rz_f, "ff", "nc") +BUILTIN(__nvvm_rcp_rm_ftz_f, "ff", "nc") +BUILTIN(__nvvm_rcp_rm_f, "ff", "nc") +BUILTIN(__nvvm_rcp_rp_ftz_f, "ff", "nc") +BUILTIN(__nvvm_rcp_rp_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rn_ftz_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rn_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rz_ftz_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rz_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rm_ftz_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rm_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rp_ftz_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_rp_f, "ff", "nc") +BUILTIN(__nvvm_div_rn_d, "ddd", "nc") +BUILTIN(__nvvm_div_rz_d, "ddd", "nc") +BUILTIN(__nvvm_div_rm_d, "ddd", "nc") +BUILTIN(__nvvm_div_rp_d, "ddd", "nc") +BUILTIN(__nvvm_rcp_rn_d, "dd", "nc") +BUILTIN(__nvvm_rcp_rz_d, "dd", "nc") +BUILTIN(__nvvm_rcp_rm_d, "dd", "nc") +BUILTIN(__nvvm_rcp_rp_d, "dd", "nc") +BUILTIN(__nvvm_sqrt_rn_d, "dd", "nc") +BUILTIN(__nvvm_sqrt_rz_d, "dd", "nc") +BUILTIN(__nvvm_sqrt_rm_d, "dd", "nc") +BUILTIN(__nvvm_sqrt_rp_d, "dd", "nc") +BUILTIN(__nvvm_sqrt_approx_ftz_f, "ff", "nc") +BUILTIN(__nvvm_sqrt_approx_f, "ff", "nc") +BUILTIN(__nvvm_add_rn_d, "ddd", "nc") +BUILTIN(__nvvm_add_rz_d, "ddd", "nc") +BUILTIN(__nvvm_add_rm_d, "ddd", "nc") +BUILTIN(__nvvm_add_rp_d, "ddd", "nc") +BUILTIN(__nvvm_mul_rn_d, "ddd", "nc") +BUILTIN(__nvvm_mul_rz_d, "ddd", "nc") +BUILTIN(__nvvm_mul_rm_d, "ddd", "nc") +BUILTIN(__nvvm_mul_rp_d, "ddd", "nc") +BUILTIN(__nvvm_add_rm_ftz_f, "fff", "nc") +BUILTIN(__nvvm_add_rm_f, "fff", "nc") +BUILTIN(__nvvm_add_rp_ftz_f, "fff", "nc") +BUILTIN(__nvvm_add_rp_f, "fff", "nc") +BUILTIN(__nvvm_mul_rm_ftz_f, "fff", "nc") +BUILTIN(__nvvm_mul_rm_f, "fff", "nc") +BUILTIN(__nvvm_mul_rp_ftz_f, "fff", "nc") +BUILTIN(__nvvm_mul_rp_f, "fff", "nc") +BUILTIN(__nvvm_add_rn_ftz_f, "fff", "nc") +BUILTIN(__nvvm_add_rn_f, "fff", "nc") +BUILTIN(__nvvm_add_rz_ftz_f, "fff", "nc") +BUILTIN(__nvvm_add_rz_f, "fff", "nc") +BUILTIN(__nvvm_mul_rn_ftz_f, "fff", "nc") +BUILTIN(__nvvm_mul_rn_f, "fff", "nc") +BUILTIN(__nvvm_mul_rz_ftz_f, "fff", "nc") +BUILTIN(__nvvm_mul_rz_f, "fff", "nc") +BUILTIN(__nvvm_d2f_rn_ftz, "fd", "nc") +BUILTIN(__nvvm_d2f_rn, "fd", "nc") +BUILTIN(__nvvm_d2f_rz_ftz, "fd", "nc") +BUILTIN(__nvvm_d2f_rz, "fd", "nc") +BUILTIN(__nvvm_d2f_rm_ftz, "fd", "nc") +BUILTIN(__nvvm_d2f_rm, "fd", "nc") +BUILTIN(__nvvm_d2f_rp_ftz, "fd", "nc") +BUILTIN(__nvvm_d2f_rp, "fd", "nc") +BUILTIN(__nvvm_d2i_rn, "id", "nc") +BUILTIN(__nvvm_d2i_rz, "id", "nc") +BUILTIN(__nvvm_d2i_rm, "id", "nc") +BUILTIN(__nvvm_d2i_rp, "id", "nc") +BUILTIN(__nvvm_d2ui_rn, "Uid", "nc") +BUILTIN(__nvvm_d2ui_rz, "Uid", "nc") +BUILTIN(__nvvm_d2ui_rm, "Uid", "nc") +BUILTIN(__nvvm_d2ui_rp, "Uid", "nc") +BUILTIN(__nvvm_i2d_rn, "di", "nc") +BUILTIN(__nvvm_i2d_rz, "di", "nc") +BUILTIN(__nvvm_i2d_rm, "di", "nc") +BUILTIN(__nvvm_i2d_rp, "di", "nc") +BUILTIN(__nvvm_ui2d_rn, "dUi", "nc") +BUILTIN(__nvvm_ui2d_rz, "dUi", "nc") +BUILTIN(__nvvm_ui2d_rm, "dUi", "nc") +BUILTIN(__nvvm_ui2d_rp, "dUi", "nc") +BUILTIN(__nvvm_f2i_rn_ftz, "if", "nc") +BUILTIN(__nvvm_f2i_rn, "if", "nc") +BUILTIN(__nvvm_f2i_rz_ftz, "if", "nc") +BUILTIN(__nvvm_f2i_rz, "if", "nc") +BUILTIN(__nvvm_f2i_rm_ftz, "if", "nc") +BUILTIN(__nvvm_f2i_rm, "if", "nc") +BUILTIN(__nvvm_f2i_rp_ftz, "if", "nc") +BUILTIN(__nvvm_f2i_rp, "if", "nc") +BUILTIN(__nvvm_f2ui_rn_ftz, "Uif", "nc") +BUILTIN(__nvvm_f2ui_rn, "Uif", "nc") +BUILTIN(__nvvm_f2ui_rz_ftz, "Uif", "nc") +BUILTIN(__nvvm_f2ui_rz, "Uif", "nc") +BUILTIN(__nvvm_f2ui_rm_ftz, "Uif", "nc") +BUILTIN(__nvvm_f2ui_rm, "Uif", "nc") +BUILTIN(__nvvm_f2ui_rp_ftz, "Uif", "nc") +BUILTIN(__nvvm_f2ui_rp, "Uif", "nc") +BUILTIN(__nvvm_i2f_rn, "fi", "nc") +BUILTIN(__nvvm_i2f_rz, "fi", "nc") +BUILTIN(__nvvm_i2f_rm, "fi", "nc") +BUILTIN(__nvvm_i2f_rp, "fi", "nc") +BUILTIN(__nvvm_ui2f_rn, "fUi", "nc") +BUILTIN(__nvvm_ui2f_rz, "fUi", "nc") +BUILTIN(__nvvm_ui2f_rm, "fUi", "nc") +BUILTIN(__nvvm_ui2f_rp, "fUi", "nc") +BUILTIN(__nvvm_lohi_i2d, "dii", "nc") +BUILTIN(__nvvm_d2i_lo, "id", "nc") +BUILTIN(__nvvm_d2i_hi, "id", "nc") +BUILTIN(__nvvm_f2ll_rn_ftz, "LLif", "nc") +BUILTIN(__nvvm_f2ll_rn, "LLif", "nc") +BUILTIN(__nvvm_f2ll_rz_ftz, "LLif", "nc") +BUILTIN(__nvvm_f2ll_rz, "LLif", "nc") +BUILTIN(__nvvm_f2ll_rm_ftz, "LLif", "nc") +BUILTIN(__nvvm_f2ll_rm, "LLif", "nc") +BUILTIN(__nvvm_f2ll_rp_ftz, "LLif", "nc") +BUILTIN(__nvvm_f2ll_rp, "LLif", "nc") +BUILTIN(__nvvm_f2ull_rn_ftz, "ULLif", "nc") +BUILTIN(__nvvm_f2ull_rn, "ULLif", "nc") +BUILTIN(__nvvm_f2ull_rz_ftz, "ULLif", "nc") +BUILTIN(__nvvm_f2ull_rz, "ULLif", "nc") +BUILTIN(__nvvm_f2ull_rm_ftz, "ULLif", "nc") +BUILTIN(__nvvm_f2ull_rm, "ULLif", "nc") +BUILTIN(__nvvm_f2ull_rp_ftz, "ULLif", "nc") +BUILTIN(__nvvm_f2ull_rp, "ULLif", "nc") +BUILTIN(__nvvm_d2ll_rn, "LLid", "nc") +BUILTIN(__nvvm_d2ll_rz, "LLid", "nc") +BUILTIN(__nvvm_d2ll_rm, "LLid", "nc") +BUILTIN(__nvvm_d2ll_rp, "LLid", "nc") +BUILTIN(__nvvm_d2ull_rn, "ULLid", "nc") +BUILTIN(__nvvm_d2ull_rz, "ULLid", "nc") +BUILTIN(__nvvm_d2ull_rm, "ULLid", "nc") +BUILTIN(__nvvm_d2ull_rp, "ULLid", "nc") +BUILTIN(__nvvm_ll2f_rn, "fLLi", "nc") +BUILTIN(__nvvm_ll2f_rz, "fLLi", "nc") +BUILTIN(__nvvm_ll2f_rm, "fLLi", "nc") +BUILTIN(__nvvm_ll2f_rp, "fLLi", "nc") +BUILTIN(__nvvm_ull2f_rn, "fULLi", "nc") +BUILTIN(__nvvm_ull2f_rz, "fULLi", "nc") +BUILTIN(__nvvm_ull2f_rm, "fULLi", "nc") +BUILTIN(__nvvm_ull2f_rp, "fULLi", "nc") +BUILTIN(__nvvm_ll2d_rn, "dLLi", "nc") +BUILTIN(__nvvm_ll2d_rz, "dLLi", "nc") +BUILTIN(__nvvm_ll2d_rm, "dLLi", "nc") +BUILTIN(__nvvm_ll2d_rp, "dLLi", "nc") +BUILTIN(__nvvm_ull2d_rn, "dULLi", "nc") +BUILTIN(__nvvm_ull2d_rz, "dULLi", "nc") +BUILTIN(__nvvm_ull2d_rm, "dULLi", "nc") +BUILTIN(__nvvm_ull2d_rp, "dULLi", "nc") +BUILTIN(__nvvm_f2h_rn_ftz, "Usf", "nc") +BUILTIN(__nvvm_f2h_rn, "Usf", "nc") +BUILTIN(__nvvm_h2f, "fUs", "nc") +BUILTIN(__nvvm_bitcast_i2f, "fi", "nc") +BUILTIN(__nvvm_bitcast_f2i, "if", "nc") +BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "nc") +BUILTIN(__nvvm_bitcast_d2ll, "LLid", "nc") + #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 75e60742148d..5b46f8e6ad11 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -613,6 +613,12 @@ BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iV8iC*V8iV8iIc", "") BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iV4iC*V2LLiV4iIc", "") BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iV4iC*V4LLiV4iIc", "") +// F16C +BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "") +BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "") +BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "") +BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "") + // RDRAND BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "") BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "") @@ -730,5 +736,8 @@ BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "") BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "") BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "") BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "") +BUILTIN(__builtin_ia32_xbegin, "i", "") +BUILTIN(__builtin_ia32_xend, "v", "") +BUILTIN(__builtin_ia32_xabort, "vIc", "") #undef BUILTIN diff --git a/include/clang/Basic/ConvertUTF.h b/include/clang/Basic/ConvertUTF.h index e7cfa8a7677c..cdc42699e3eb 100644 --- a/include/clang/Basic/ConvertUTF.h +++ b/include/clang/Basic/ConvertUTF.h @@ -147,7 +147,6 @@ ConversionResult ConvertUTF32toUTF8 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); -#ifdef CLANG_NEEDS_THESE_ONE_DAY ConversionResult ConvertUTF16toUTF32 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); @@ -159,7 +158,9 @@ ConversionResult ConvertUTF32toUTF16 ( Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); -Boolean isLegalUTF8String(const UTF8 *source, const UTF8 *sourceEnd); +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); + +unsigned getNumBytesForUTF8(UTF8 firstByte); #ifdef __cplusplus } @@ -175,11 +176,13 @@ namespace clang { * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on * WideCharWidth. The converted data is written to ResultPtr, which needs to * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, - * ResultPtr will point one after the end of the copied string. + * ResultPtr will point one after the end of the copied string. On failure, + * ResultPtr will not be changed, and ErrorPtr will be set to the location of + * the first character which could not be converted. * \return true on success. */ bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, - char *&ResultPtr); + char *&ResultPtr, const UTF8 *&ErrorPtr); /** * Convert an Unicode code point to UTF8 sequence. @@ -194,7 +197,6 @@ bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); } -#endif #endif diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 3997fb89ba82..e47f3e185741 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_DIAGNOSTIC_H #include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -29,6 +30,7 @@ namespace clang { class DiagnosticConsumer; class DiagnosticBuilder; + class DiagnosticOptions; class IdentifierInfo; class DeclContext; class LangOptions; @@ -160,13 +162,6 @@ public: ak_qualtype_pair ///< pair }; - /// \brief Specifies which overload candidates to display when overload - /// resolution fails. - enum OverloadsShown { - Ovl_All, ///< Show all overloads. - Ovl_Best ///< Show just the "best" overload candidates. - }; - /// \brief Represents on argument value, which is a union discriminated /// by ArgumentKind, with a value. typedef std::pair ArgumentValue; @@ -190,6 +185,7 @@ private: // backtrace stack, 0 -> no limit. ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? IntrusiveRefCntPtr Diags; + IntrusiveRefCntPtr DiagOpts; DiagnosticConsumer *Client; bool OwnsDiagClient; SourceManager *SourceMgr; @@ -341,6 +337,7 @@ private: public: explicit DiagnosticsEngine( const IntrusiveRefCntPtr &Diags, + DiagnosticOptions *DiagOpts, DiagnosticConsumer *client = 0, bool ShouldOwnClient = true); ~DiagnosticsEngine(); @@ -349,6 +346,9 @@ public: return Diags; } + /// \brief Retrieve the diagnostic options. + DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; } + DiagnosticConsumer *getClient() { return Client; } const DiagnosticConsumer *getClient() const { return Client; } @@ -478,10 +478,13 @@ public: } OverloadsShown getShowOverloads() const { return ShowOverloads; } - /// \brief Pretend that the last diagnostic issued was ignored. + /// \brief Pretend that the last diagnostic issued was ignored, so any + /// subsequent notes will be suppressed. /// /// This can be used by clients who suppress diagnostics themselves. void setLastDiagnosticIgnored() { + if (LastDiagLevel == DiagnosticIDs::Fatal) + FatalErrorOccurred = true; LastDiagLevel = DiagnosticIDs::Ignored; } @@ -584,7 +587,7 @@ public: const char *Argument, unsigned ArgLen, const ArgumentValue *PrevArgs, unsigned NumPrevArgs, SmallVectorImpl &Output, - SmallVectorImpl &QualTypeVals) const { + ArrayRef QualTypeVals) const { ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, PrevArgs, NumPrevArgs, Output, ArgToStringCookie, QualTypeVals); @@ -837,7 +840,7 @@ class DiagnosticBuilder { /// call to ForceEmit. mutable bool IsForceEmit; - void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT + void operator=(const DiagnosticBuilder &) LLVM_DELETED_FUNCTION; friend class DiagnosticsEngine; DiagnosticBuilder() @@ -961,6 +964,10 @@ public: "Too many arguments to diagnostic!"); DiagObj->DiagFixItHints[NumFixits++] = Hint; } + + bool hasMaxRanges() const { + return NumRanges == DiagnosticsEngine::MaxRanges; + } }; inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index 9cfe5efae259..d869c9983bd7 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -137,7 +137,7 @@ def err_odr_function_type_inconsistent : Error< def warn_odr_tag_type_inconsistent : Warning< "type %0 has incompatible definitions in different translation units">; def note_odr_tag_kind_here: Note< - "%0 is a %select{struct|union|class|enum}1 here">; + "%0 is a %select{struct|interface|union|class|enum}1 here">; def note_odr_field : Note<"field %0 has type %1 here">; def note_odr_missing_field : Note<"no corresponding field here">; def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">; diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td index 235ca79564d3..e6dfe5b6387c 100644 --- a/include/clang/Basic/DiagnosticCommentKinds.td +++ b/include/clang/Basic/DiagnosticCommentKinds.td @@ -121,5 +121,21 @@ def warn_doc_returns_attached_to_a_void_function : Warning< "method returning void}1">, InGroup, DefaultIgnore; +// \deprecated command + +def warn_doc_deprecated_not_sync : Warning< + "declaration is marked with '\\deprecated' command but does not have " + "a deprecation attribute">, + InGroup, DefaultIgnore; + +def note_add_deprecation_attr : Note< + "add a deprecation attribute to the declaration to silence this warning">; + +// verbatim block commands + +def warn_verbatim_block_end_without_start : Warning< + "'\\%0' command does not terminate a verbatim text block">, + InGroup, DefaultIgnore; + } // end of documentation issue category } // end of AST component diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index f85928740b4c..a6ce9d4a2d21 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -78,9 +78,12 @@ def note_decl_hiding_tag_type : Note< "%1 %0 is hidden by a non-type declaration of %0 here">; // Sema && Lex -def ext_longlong : Extension< +def ext_c99_longlong : Extension< "'long long' is an extension when C99 mode is not enabled">, InGroup; +def ext_cxx11_longlong : Extension< + "'long long' is a C++11 extension">, + InGroup; def warn_cxx98_compat_longlong : Warning< "'long long' is incompatible with C++98">, InGroup, DefaultIgnore; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 583b2345c935..4b430351756a 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -11,6 +11,8 @@ let Component = "Driver" in { def err_drv_no_such_file : Error<"no such file or directory: '%0'">; def err_drv_unsupported_opt : Error<"unsupported option '%0'">; +def err_drv_unsupported_opt_for_target : Error< + "unsupported option '%0' for target '%1'">; def err_drv_unsupported_option_argument : Error< "unsupported argument '%1' to option '%0'">; def err_drv_unknown_stdin_type : Error< @@ -91,10 +93,10 @@ def err_drv_invalid_arch_for_deployment_target : Error< "invalid architecture '%0' for deployment target '%1'">; def err_drv_objc_gc_arr : Error< "cannot specify both '-fobjc-arc' and '%0'">; -def err_arc_nonfragile_abi : Error< - "-fobjc-arc is not supported with legacy abi">; -def err_arc_unsupported : Error< - "-fobjc-arc is not supported on current deployment target">; +def err_arc_unsupported_on_runtime : Error< + "-fobjc-arc is not supported on platforms using the legacy runtime">; +def err_arc_unsupported_on_toolchain : Error< // feel free to generalize this + "-fobjc-arc is not supported on versions of OS X prior to 10.6">; def err_drv_mg_requires_m_or_mm : Error< "option '-MG' requires '-M' or '-MM'">; def err_drv_asan_android_requires_pie : Error< @@ -119,14 +121,10 @@ def warn_drv_unused_argument : Warning< def warn_drv_empty_joined_argument : Warning< "joined argument expects additional value: '%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< - "not using the clang compiler for C++ inputs">; -def warn_drv_not_using_clang_arch : Warning< - "not using the clang compiler for the '%0' architecture">; def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; +def warn_drv_deprecated_arg : Warning< + "argument '%0' is deprecated, use '%1' instead">, InGroup; def warn_drv_assuming_mfloat_abi_is : Warning< "unknown platform, assuming -mfloat-abi=%0">; def warn_ignoring_ftabstop_value : Warning< @@ -141,5 +139,9 @@ def warn_drv_pch_not_first_include : Warning< def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; - + +def err_analyzer_config_no_value : Error< + "analyzer-config option '%0' has a key but no value">; +def err_analyzer_config_multiple_values : Error< + "analyzer-config option '%0' should contain only one '='">; } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 417a22c96df5..b7a84764391b 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -58,6 +58,8 @@ def warn_fe_cc_print_header_failure : Warning< "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">; def warn_fe_cc_log_diagnostics_failure : Warning< "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">; +def err_fe_no_pch_in_dir : Error< + "no suitable precompiled header file found in directory '%0'">; def warn_fe_serialized_diag_failure : Warning< "unable to open file %0 for serializing diagnostics (%1)">, @@ -76,6 +78,11 @@ def err_verify_invalid_content : Error< def err_verify_inconsistent_diags : Error< "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: " "%2">; +def err_verify_invalid_no_diags : Error< + "%select{expected|'expected-no-diagnostics'}0 directive cannot follow " + "%select{'expected-no-diagnostics' directive|other expected directives}0">; +def err_verify_no_directives : Error< + "no expected directives found: consider use of 'expected-no-diagnostics'">; def note_fixit_applied : Note<"FIX-IT applied suggested code changes">; def note_fixit_in_macro : Note< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index d8632dd8c39d..f9f9ec78309a 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -22,8 +22,6 @@ def : DiagGroup<"address">; def AddressOfTemporary : DiagGroup<"address-of-temporary">; def : DiagGroup<"aggregate-return">; def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; -def : DiagGroup<"attributes">; -def : DiagGroup<"bad-function-cast">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; @@ -33,8 +31,11 @@ def StringConversion : DiagGroup<"string-conversion">; def SignConversion : DiagGroup<"sign-conversion">; def BoolConversion : DiagGroup<"bool-conversion">; def IntConversion : DiagGroup<"int-conversion">; +def EnumConversion : DiagGroup<"enum-conversion">; def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">; def NullConversion : DiagGroup<"null-conversion">; +def ImplicitConversionFloatingPointToBool : + DiagGroup<"implicit-conversion-floating-point-to-bool">; def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; def CXXCompat: DiagGroup<"c++-compat">; def CastAlign : DiagGroup<"cast-align">; @@ -42,11 +43,11 @@ def : DiagGroup<"cast-qual">; def : DiagGroup<"char-align">; def Comment : DiagGroup<"comment">; def : DiagGroup<"ctor-dtor-privacy">; -def : DiagGroup<"declaration-after-statement">; def DefaultArgSpecialMember : DiagGroup<"default-arg-special-member">; def GNUDesignator : DiagGroup<"gnu-designator">; def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">; +def AbstractFinalClass : DiagGroup<"abstract-final-class">; def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings">; @@ -58,9 +59,14 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; def : DiagGroup<"disabled-optimization">; def : DiagGroup<"discard-qual">; def : DiagGroup<"div-by-zero">; + def DocumentationHTML : DiagGroup<"documentation-html">; def DocumentationPedantic : DiagGroup<"documentation-pedantic">; -def Documentation : DiagGroup<"documentation", [DocumentationHTML]>; +def DocumentationDeprecatedSync : DiagGroup<"documentation-deprecated-sync">; +def Documentation : DiagGroup<"documentation", + [DocumentationHTML, + DocumentationDeprecatedSync]>; + def EmptyBody : DiagGroup<"empty-body">; def ExtraTokens : DiagGroup<"extra-tokens">; def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">; @@ -108,9 +114,9 @@ def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">; def FourByteMultiChar : DiagGroup<"four-char-constants">; def GlobalConstructors : DiagGroup<"global-constructors">; -def : DiagGroup<"idiomatic-parentheses">; def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">; def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">; +def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def : DiagGroup<"import">; @@ -119,7 +125,6 @@ def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; def : DiagGroup<"init-self">; def : DiagGroup<"inline">; -def : DiagGroup<"int-to-pointer-cast">; def : DiagGroup<"invalid-pch">; def LiteralRange : DiagGroup<"literal-range">; def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args", @@ -131,11 +136,12 @@ def MissingBraces : DiagGroup<"missing-braces">; def MissingDeclarations: DiagGroup<"missing-declarations">; def : DiagGroup<"missing-format-attribute">; def : DiagGroup<"missing-include-dirs">; -def : DiagGroup<"missing-noreturn">; def MultiChar : DiagGroup<"multichar">; def : DiagGroup<"nested-externs">; -def : DiagGroup<"newline-eof">; -def LongLong : DiagGroup<"long-long">; +def CXX11LongLong : DiagGroup<"c++11-long-long">; +def LongLong : DiagGroup<"long-long", [CXX11LongLong]>; +def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">; +def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">; def MismatchedTags : DiagGroup<"mismatched-tags">; def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; def ModuleBuild : DiagGroup<"module-build">; @@ -157,6 +163,7 @@ def OverlengthStrings : DiagGroup<"overlength-strings">; def OverloadedVirtual : DiagGroup<"overloaded-virtual">; def PrivateExtern : DiagGroup<"private-extern">; def SelTypeCast : DiagGroup<"cast-of-sel-type">; +def BadFunctionCast : DiagGroup<"bad-function-cast">; def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">; def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; @@ -183,7 +190,7 @@ def Sentinel : DiagGroup<"sentinel">; def MissingMethodReturnType : DiagGroup<"missing-method-return-type">; def : DiagGroup<"sequence-point">; def Shadow : DiagGroup<"shadow">; -def : DiagGroup<"shorten-64-to-32">; +def Shorten64To32 : DiagGroup<"shorten-64-to-32">; def : DiagGroup<"sign-promo">; def SignCompare : DiagGroup<"sign-compare">; def : DiagGroup<"stack-protector">; @@ -192,11 +199,15 @@ def : DiagGroup<"synth">; def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; def StringPlusInt : DiagGroup<"string-plus-int">; def StrncatSize : DiagGroup<"strncat-size">; -def TautologicalCompare : DiagGroup<"tautological-compare">; +def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; +def TautologicalCompare : DiagGroup<"tautological-compare", + [TautologicalOutOfRangeCompare]>; def HeaderHygiene : DiagGroup<"header-hygiene">; +def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">; +def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">; // Preprocessor warnings. -def : DiagGroup<"builtin-macro-redefined">; +def AmbiguousMacro : DiagGroup<"ambiguous-macro">; // Just silence warnings about -Wstrict-aliasing for now. def : DiagGroup<"strict-aliasing=0">; @@ -262,26 +273,29 @@ def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">; def CustomAtomic : DiagGroup<"custom-atomic-properties">; def AtomicProperties : DiagGroup<"atomic-properties", [ImplicitAtomic, CustomAtomic]>; -def AutomaticReferenceCountingABI : DiagGroup<"arc-abi">; +// FIXME: Remove arc-abi once an Xcode is released that doesn't pass this flag. +def : DiagGroup<"arc-abi">; def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">; def ARCRetainCycles : DiagGroup<"arc-retain-cycles">; def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">; def AutomaticReferenceCounting : DiagGroup<"arc", - [AutomaticReferenceCountingABI, - ARCUnsafeRetainedAssign, + [ARCUnsafeRetainedAssign, ARCRetainCycles, ARCNonPodMemAccess]>; +def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">; +def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak", + [ARCRepeatedUseOfWeakMaybe]>; def Selector : DiagGroup<"selector">; def Protocol : DiagGroup<"protocol">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">; -def : DiagGroup<"variadic-macros">; def VariadicMacros : DiagGroup<"variadic-macros">; def VectorConversion : DiagGroup<"vector-conversion">; // clang specific def VexingParse : DiagGroup<"vexing-parse">; def VLA : DiagGroup<"vla">; def VolatileRegisterVar : DiagGroup<"volatile-register-var">; def Visibility : DiagGroup<"visibility">; +def ZeroLengthArray : DiagGroup<"zero-length-array">; // GCC calls -Wdeprecated-writable-strings -Wwrite-strings. def GCCWriteStrings : DiagGroup<"write-strings" , [DeprecatedWritableStr]>; @@ -300,6 +314,7 @@ def ParenthesesOnEquality : DiagGroup<"parentheses-equality">; def Parentheses : DiagGroup<"parentheses", [LogicalOpParentheses, BitwiseOpParentheses, + ShiftOpParentheses, ParenthesesOnEquality, DanglingElse]>; @@ -311,15 +326,16 @@ def Parentheses : DiagGroup<"parentheses", // - bool-to-pointer conversion warnings are on by default // - __null-to-integer conversion warnings are on by default def Conversion : DiagGroup<"conversion", - [DiagGroup<"shorten-64-to-32">, + [BoolConversion, ConstantConversion, + EnumConversion, + Shorten64To32, + IntConversion, LiteralConversion, - StringConversion, - SignConversion, - BoolConversion, - NullConversion, // NULL->non-pointer NonLiteralNullConversion, // (1-1)->pointer (etc) - IntConversion]>, + NullConversion, // NULL->non-pointer + SignConversion, + StringConversion]>, DiagCategory<"Value Conversion Issue">; def Unused : DiagGroup<"unused", @@ -345,6 +361,8 @@ def Format2 : DiagGroup<"format=2", def TypeSafety : DiagGroup<"type-safety">; +def IntToPointerCast : DiagGroup<"int-to-pointer-cast">; + def Extra : DiagGroup<"extra", [ MissingFieldInitializers, IgnoredQualifiers, @@ -361,6 +379,7 @@ def Most : DiagGroup<"most", [ DeleteNonVirtualDtor, Format, Implicit, + IntToPointerCast, MismatchedTags, MissingBraces, MultiChar, @@ -382,9 +401,12 @@ def Most : DiagGroup<"most", [ // Thread Safety warnings def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">; -def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">; -def ThreadSafety : DiagGroup<"thread-safety", - [ThreadSafetyAttributes, ThreadSafetyAnalysis]>; +def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">; +def ThreadSafetyPrecise : DiagGroup<"thread-safety-precise">; +def ThreadSafety : DiagGroup<"thread-safety", + [ThreadSafetyAttributes, + ThreadSafetyAnalysis, + ThreadSafetyPrecise]>; // Note that putting warnings in -Wall will not disable them by default. If a // warning should be active _only_ when -Wall is passed in, mark it as @@ -414,7 +436,8 @@ def NonGCC : DiagGroup<"non-gcc", // A warning group for warnings about using C++11 features as extensions in // earlier C++ versions. -def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi]>; +def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11LongLong]>; + def : DiagGroup<"c++0x-extensions", [CXX11]>; def DelegatingCtorCycles : DiagGroup<"delegating-ctor-cycles">; @@ -426,7 +449,7 @@ def C11 : DiagGroup<"c11-extensions">; def C99 : DiagGroup<"c99-extensions">; // A warning group for warnings about GCC extensions. -def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>; +def GNU : DiagGroup<"gnu", [GNUDesignator, VLA, ZeroLengthArray]>; // A warning group for warnings about code that clang accepts but gcc doesn't. def GccCompat : DiagGroup<"gcc-compat">; @@ -451,3 +474,9 @@ def ObjCStringComparison : DiagGroup<"objc-string-compare">; def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [ ObjCStringComparison ]>; + +// Inline ASM warnings. +def ASMOperandWidths : DiagGroup<"asm-operand-widths">; +def ASM : DiagGroup<"asm", [ + ASMOperandWidths + ]>; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index cc958dbdfea2..c6c50ab37b87 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -41,9 +41,9 @@ def trigraph_ends_block_comment : Warning<"trigraph ends block comment">, def trigraph_converted : Warning<"trigraph converted to '%0' character">, InGroup; -def ext_multi_line_bcpl_comment : Extension<"multi-line // comment">, +def ext_multi_line_line_comment : Extension<"multi-line // comment">, InGroup; -def ext_bcpl_comment : Extension< +def ext_line_comment : Extension< "// comments are not allowed in this language">, InGroup; def ext_no_newline_eof : Extension<"no newline at end of file">, @@ -55,7 +55,7 @@ def warn_cxx98_compat_no_newline_eof : Warning< def ext_dollar_in_identifier : Extension<"'$' in identifier">, InGroup>; -def ext_charize_microsoft : Extension<"@# is a microsoft extension">, +def ext_charize_microsoft : Extension<"charizing operator #@ is a Microsoft extension">, InGroup; def ext_token_used : Extension<"extension used">, @@ -127,15 +127,16 @@ def warn_char_constant_too_large : Warning< def err_multichar_utf_character_literal : Error< "Unicode character literals may not contain multiple characters">; def err_exponent_has_no_digits : Error<"exponent has no digits">; -def ext_imaginary_constant : Extension<"imaginary constants are an extension">; +def ext_imaginary_constant : Extension< + "imaginary constants are a GNU extension">, InGroup; def err_hexconstant_requires_exponent : Error< "hexadecimal floating constants require an exponent">; def err_hexconstant_requires_digits : Error< "hexadecimal floating constants require a significand">; def ext_hexconstant_invalid : Extension< - "hexadecimal floating constants are a C99 feature">; + "hexadecimal floating constants are a C99 feature">, InGroup; def ext_binary_literal : Extension< - "binary integer literals are an extension">; + "binary integer literals are a GNU extension">, InGroup; def err_pascal_string_too_long : Error<"Pascal string is too long">; def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">; def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">; @@ -228,6 +229,12 @@ def pp_macro_not_used : Warning<"macro is not used">, DefaultIgnore, def warn_pp_undef_identifier : Warning< "%0 is not defined, evaluates to 0">, InGroup>, DefaultIgnore; +def warn_pp_ambiguous_macro : Warning< + "ambiguous expansion of macro %0">, InGroup; +def note_pp_ambiguous_macro_chosen : Note< + "expanding this definition of %0">; +def note_pp_ambiguous_macro_other : Note< + "other definition of %0">; def pp_invalid_string_literal : Warning< "invalid string literal, ignoring final '\\'">; @@ -484,15 +491,21 @@ def err_mmap_missing_module_unqualified : Error< def err_mmap_missing_module_qualified : Error< "no module named '%0' in '%1'">; def err_mmap_top_level_inferred_submodule : Error< - "only submodules may be inferred with wildcard syntax">; + "only submodules and framework modules may be inferred with wildcard syntax">; def err_mmap_inferred_no_umbrella : Error< "inferred submodules require a module with an umbrella">; +def err_mmap_inferred_framework_submodule : Error< + "inferred submodule cannot be a framework submodule">; +def err_mmap_explicit_inferred_framework : Error< + "inferred framework modules cannot be 'explicit'">; +def err_mmap_missing_exclude_name : Error< + "expected excluded module name">; def err_mmap_inferred_redef : Error< "redefinition of inferred submodule">; def err_mmap_expected_lbrace_wildcard : Error< "expected '{' to start inferred submodule">; -def err_mmap_expected_wildcard_member : Error< - "expected module export wildcard">; +def err_mmap_expected_inferred_member : Error< + "expected %select{module exclusion with 'exclude'|'export *'}0">; def err_mmap_expected_export_wildcard : Error< "only '*' can be exported from an inferred submodule">; def err_mmap_explicit_top_level : Error< @@ -509,5 +522,7 @@ def warn_auto_module_import : Warning< "import of module '%1'">, InGroup, DefaultIgnore; def warn_uncovered_module_header : Warning< "umbrella header does not include header '%0'">, InGroup; - +def err_expected_id_building_module : Error< + "expected a module name in '__building_module' expression">; + } diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def new file mode 100644 index 000000000000..476ac1e373f0 --- /dev/null +++ b/include/clang/Basic/DiagnosticOptions.def @@ -0,0 +1,93 @@ +//===--- DiagOptions.def - Diagnostic option database ------------- 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 diagnostic options. Users of this file +// must define the DIAGOPT macro to make use of this information. +// Optionally, the user may also define ENUM_DIAGOPT (for options +// that have enumeration type and VALUE_DIAGOPT (for options that +// describe a value rather than a flag). The SEMANTIC_* variants of these macros +// indicate options that affect the processing of the program, rather than +// simply the output. +// +//===----------------------------------------------------------------------===// +#ifndef DIAGOPT +# error Define the DIAGOPT macro to handle language options +#endif + +#ifndef VALUE_DIAGOPT +# define VALUE_DIAGOPT(Name, Bits, Default) \ +DIAGOPT(Name, Bits, Default) +#endif + +#ifndef ENUM_DIAGOPT +# define ENUM_DIAGOPT(Name, Type, Bits, Default) \ +DIAGOPT(Name, Bits, Default) +#endif + +#ifndef SEMANTIC_DIAGOPT +# define SEMANTIC_DIAGOPT(Name, Bits, Default) DIAGOPT(Name, Bits, Default) +#endif + +#ifndef SEMANTIC_VALUE_DIAGOPT +# define SEMANTIC_VALUE_DIAGOPT(Name, Bits, Default) \ + VALUE_DIAGOPT(Name, Bits, Default) +#endif + +#ifndef SEMANTIC_ENUM_DIAGOPT +# define SEMANTIC_ENUM_DIAGOPT(Name, Type, Bits, Default) \ + ENUM_DIAGOPT(Name, Type, Bits, Default) +#endif + +SEMANTIC_DIAGOPT(IgnoreWarnings, 1, 0) /// -w +DIAGOPT(NoRewriteMacros, 1, 0) /// -Wno-rewrite-macros +DIAGOPT(Pedantic, 1, 0) /// -pedantic +DIAGOPT(PedanticErrors, 1, 0) /// -pedantic-errors +DIAGOPT(ShowColumn, 1, 1) /// Show column number on diagnostics. +DIAGOPT(ShowLocation, 1, 1) /// Show source location information. +DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics. +DIAGOPT(ShowFixits, 1, 1) /// Show fixit information. +DIAGOPT(ShowSourceRanges, 1, 0) /// Show source ranges in numeric form. +DIAGOPT(ShowParseableFixits, 1, 0) /// Show machine parseable fix-its. +DIAGOPT(ShowOptionNames, 1, 0) /// Show the option name for mappable + /// diagnostics. +DIAGOPT(ShowNoteIncludeStack, 1, 0) /// Show include stacks for notes. +VALUE_DIAGOPT(ShowCategories, 2, 0) /// Show categories: 0 -> none, 1 -> Number, + /// 2 -> Full Name. + +ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics: + +DIAGOPT(ShowColors, 1, 0) /// Show diagnostics with ANSI color sequences. +ENUM_DIAGOPT(ShowOverloads, OverloadsShown, 1, + Ovl_All) /// Overload candidates to show. +DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected + /// diagnostics, indicated by markers in the + /// input source file. + +DIAGOPT(ElideType, 1, 0) /// Elide identical types in template diffing +DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing + +VALUE_DIAGOPT(ErrorLimit, 32, 0) /// Limit # errors emitted. +/// Limit depth of macro expansion backtrace. +VALUE_DIAGOPT(MacroBacktraceLimit, 32, DefaultMacroBacktraceLimit) +/// Limit depth of instantiation backtrace. +VALUE_DIAGOPT(TemplateBacktraceLimit, 32, DefaultTemplateBacktraceLimit) +/// Limit depth of constexpr backtrace. +VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit) + +VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops. +/// Column limit for formatting message diagnostics, or 0 if unused. +VALUE_DIAGOPT(MessageLength, 32, 0) + +#undef DIAGOPT +#undef ENUM_DIAGOPT +#undef VALUE_DIAGOPT +#undef SEMANTIC_DIAGOPT +#undef SEMANTIC_ENUM_DIAGOPT +#undef SEMANTIC_VALUE_DIAGOPT + diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h new file mode 100644 index 000000000000..b75cb0c24da3 --- /dev/null +++ b/include/clang/Basic/DiagnosticOptions.h @@ -0,0 +1,85 @@ +//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H +#define LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H + +#include "llvm/ADT/IntrusiveRefCntPtr.h" + +#include +#include + +namespace clang { + +/// \brief Specifies which overload candidates to display when overload +/// resolution fails. +enum OverloadsShown { + Ovl_All, ///< Show all overloads. + Ovl_Best ///< Show just the "best" overload candidates. +}; + +/// DiagnosticOptions - Options for controlling the compiler diagnostics +/// engine. +class DiagnosticOptions : public llvm::RefCountedBase{ +public: + enum TextDiagnosticFormat { Clang, Msvc, Vi }; + + // Default values. + enum { DefaultTabStop = 8, MaxTabStop = 100, + DefaultMacroBacktraceLimit = 6, + DefaultTemplateBacktraceLimit = 10, + DefaultConstexprBacktraceLimit = 10 }; + + // Define simple diagnostic options (with no accessors). +#define DIAGOPT(Name, Bits, Default) unsigned Name : Bits; +#define ENUM_DIAGOPT(Name, Type, Bits, Default) +#include "clang/Basic/DiagnosticOptions.def" + +protected: + // Define diagnostic options of enumeration type. These are private, and will + // have accessors (below). +#define DIAGOPT(Name, Bits, Default) +#define ENUM_DIAGOPT(Name, Type, Bits, Default) unsigned Name : Bits; +#include "clang/Basic/DiagnosticOptions.def" + +public: + /// If non-empty, a file to log extended build information to, for development + /// testing and analysis. + std::string DumpBuildInformation; + + /// The file to log diagnostic output to. + std::string DiagnosticLogFile; + + /// The file to serialize diagnostics to (non-appending). + std::string DiagnosticSerializationFile; + + /// The list of -W... options used to alter the diagnostic mappings, with the + /// prefixes removed. + std::vector Warnings; + +public: + // Define accessors/mutators for diagnostic options of enumeration type. +#define DIAGOPT(Name, Bits, Default) +#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ + Type get##Name() const { return static_cast(Name); } \ + void set##Name(Type Value) { Name = static_cast(Value); } +#include "clang/Basic/DiagnosticOptions.def" + + DiagnosticOptions() { +#define DIAGOPT(Name, Bits, Default) Name = Default; +#define ENUM_DIAGOPT(Name, Type, Bits, Default) set##Name(Default); +#include "clang/Basic/DiagnosticOptions.def" + } +}; + +typedef DiagnosticOptions::TextDiagnosticFormat TextDiagnosticFormat; + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index b1c16fa8529f..21eeccb5a3e4 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -18,10 +18,13 @@ def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">, def warn_file_asm_volatile : Warning< "meaningless 'volatile' on asm outside function">, CatInlineAsm; +def warn_unsupported_msasm : Warning< + "MS-style inline assembly is not supported">, InGroup; + let CategoryName = "Parse Issue" in { def ext_empty_translation_unit : Extension< - "ISO C requires a translation unit to contain at least one declaration.">, + "ISO C requires a translation unit to contain at least one declaration">, InGroup>; def warn_cxx98_compat_top_level_semi : Warning< "extra ';' outside of a function is incompatible with C++98">, @@ -40,11 +43,14 @@ def warn_extra_semi_after_mem_fn_def : Warning< "extra ';' after member function definition">, InGroup, DefaultIgnore; -def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">; +def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">, + InGroup; +def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">, + InGroup; def ext_plain_complex : ExtWarn< "plain '_Complex' requires a type specifier; assuming '_Complex double'">; def ext_integer_complex : Extension< - "complex integer types are an extension">; + "complex integer types are a GNU extension">, InGroup; def ext_thread_before : Extension<"'__thread' before '%0'">; def ext_empty_struct_union : Extension< @@ -80,8 +86,11 @@ def err_enumerator_list_missing_comma : Error< "missing ',' between enumerators">; def err_enumerator_unnamed_no_def : Error< "unnamed enumeration must be a definition">; -def ext_ms_enum_fixed_underlying_type : Extension< - "enumeration types with a fixed underlying type are a Microsoft extension">, +def ext_cxx11_enum_fixed_underlying_type : Extension< + "enumeration types with a fixed underlying type are a C++11 extension">, + InGroup; +def ext_c_enum_fixed_underlying_type : Extension< + "enumeration types with a fixed underlying type are a Microsoft extension">, InGroup; def warn_cxx98_compat_enum_fixed_underlying_type : Warning< "enumeration types with a fixed underlying type are incompatible with C++98">, @@ -207,6 +216,17 @@ def err_expected_semi_after_static_assert : Error< "expected ';' after static_assert">; def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">; def err_expected_colon_after : Error<"expected ':' after %0">; +def warn_missing_selector_name : Warning< + "%0 used as the name of the previous parameter rather than as part " + "of the selector">, + InGroup>; +def note_missing_selector_name : Note< + "introduce a parameter name to make %0 part of the selector">; +def note_force_empty_selector_name : Note< + "or insert whitespace before ':' to use %0 as parameter name " + "and have an empty entry in the selector">; +def note_missing_argument_name : Note< + "did you mean to use %0 as the selector name instead of %1">; def err_label_end_of_compound_statement : Error< "label at end of compound statement: expected statement">; def err_address_of_label_outside_fn : Error< @@ -331,6 +351,8 @@ def ext_c11_static_assert : Extension< def warn_cxx98_compat_static_assert : Warning< "static_assert declarations are incompatible with C++98">, InGroup, DefaultIgnore; +def err_paren_after_colon_colon : Error< + "unexpected parenthesis after '::'">; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< @@ -423,7 +445,8 @@ def err_expected_member_or_base_name : Error< def err_expected_lbrace_after_base_specifiers : Error< "expected '{' after base class list">; def ext_ellipsis_exception_spec : Extension< - "exception specification of '...' is a Microsoft extension">; + "exception specification of '...' is a Microsoft extension">, + InGroup; def err_dynamic_and_noexcept_specification : Error< "cannot have both throw() and noexcept() clause on the same function">; def warn_cxx98_compat_noexcept_decl : Warning< @@ -455,9 +478,6 @@ def err_literal_operator_string_prefix : Error< "string literal after 'operator' cannot have an encoding prefix">; def err_literal_operator_string_not_empty : Error< "string literal after 'operator' must be '\"\"'">; -def err_literal_operator_missing_space : Error< - "C++11 requires a space between the \"\" and the user-defined suffix in a " - "literal operator">; def warn_cxx98_compat_literal_operator : Warning< "literal operators are incompatible with C++98">, InGroup, DefaultIgnore; @@ -570,7 +590,7 @@ def err_expected_type_name_after_typename : Error< "expected an identifier or template-id after '::'">; def err_explicit_spec_non_template : Error< "explicit %select{specialization|instantiation}0 of non-template " - "%select{class|struct|union}1 %2">; + "%select{class|struct|union|interface}1 %2">; def err_default_template_template_parameter_not_template : Error< "default template argument for a template template parameter must be a class " @@ -627,6 +647,11 @@ def ext_override_control_keyword : ExtWarn< def warn_cxx98_compat_override_control_keyword : Warning< "'%0' keyword is incompatible with C++98">, InGroup, DefaultIgnore; +def err_override_control_interface : Error< + "'%0' keyword not permitted with interface types">; + +def err_access_specifier_interface : Error< + "interface types cannot specify '%select{private|protected}0' access">; def err_duplicate_virt_specifier : Error< "class member already marked '%0'">; @@ -710,6 +735,11 @@ def warn_pragma_unused_expected_var : Warning< "expected '#pragma unused' argument to be a variable name">; def warn_pragma_unused_expected_punc : Warning< "expected ')' or ',' in '#pragma unused'">; +// - #pragma fp_contract +def err_pragma_fp_contract_scope : Error< + "'#pragma fp_contract' should only appear at file scope or at the start of a " + "compound expression">; + // OpenCL Section 6.8.g def err_not_opencl_storage_class_specifier : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2d63dc42fd94..0d64bf38ad7c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -20,13 +20,6 @@ def warn_variables_not_in_loop_body : Warning< "used in loop condition not modified in loop body">, InGroup>, DefaultIgnore; -def warn_identical_enum_values : Warning< - "all elements of %0 are initialized with literals to value %1">, - InGroup>; -def note_identical_enum_values : Note< - "initialize the last element with the previous element to silence " - "this warning">; - // Constant expressions def err_expr_not_ice : Error< "expression is not an %select{integer|integral}0 constant expression">; @@ -102,7 +95,7 @@ def err_variably_modified_new_type : Error< // C99 Designated Initializers def ext_designated_init : Extension< - "designated initializers are a C99 feature">; + "designated initializers are a C99 feature">, InGroup; def err_array_designator_negative : Error< "array designator value '%0' is negative">; def err_array_designator_empty_range : Error< @@ -410,12 +403,10 @@ def err_statically_allocated_object : Error< "interface type cannot be statically allocated">; def err_object_cannot_be_passed_returned_by_value : Error< "interface type %1 cannot be %select{returned|passed}0 by value" - "; did you forget * in %1">; + "; did you forget * in %1?">; def err_parameters_retval_cannot_have_fp16_type : Error< "%select{parameters|function return value}0 cannot have __fp16 type; did you forget * ?">; def warn_enum_value_overflow : Warning<"overflow in enumeration value">; -def warn_pragma_options_align_unsupported_option : Warning< - "unsupported alignment option in '#pragma options align'">; def warn_pragma_options_align_reset_failed : Warning< "#pragma options align=reset failed: %0">; def err_pragma_options_align_mac68k_target_unsupported : Error< @@ -521,7 +512,8 @@ def warn_conflicting_overriding_ret_types : Warning< def warn_conflicting_ret_types : Warning< "conflicting return type in " - "implementation of %0%diff{: $ vs $|}1,2">; + "implementation of %0%diff{: $ vs $|}1,2">, + InGroup; def warn_conflicting_overriding_ret_type_modifiers : Warning< "conflicting distributed object modifiers on return type " @@ -550,7 +542,9 @@ def warn_conflicting_overriding_param_types : Warning< def warn_conflicting_param_types : Warning< "conflicting parameter types in " - "implementation of %0%diff{: $ vs $|}1,2">; + "implementation of %0%diff{: $ vs $|}1,2">, + InGroup; + def warn_conflicting_param_modifiers : Warning< "conflicting distributed object modifiers on parameter type " "in implementation of %0">, @@ -595,6 +589,8 @@ def warn_accessor_property_type_mismatch : Warning< "type of property %0 does not match type of accessor %1">; def not_conv_function_declared_at : Note<"type conversion function declared here">; def note_method_declared_at : Note<"method %0 declared here">; +def note_property_attribute : Note<"property %0 is declared " + "%select{deprecated|unavailable}1 here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; def warn_duplicate_method_decl : @@ -700,7 +696,7 @@ def error_bad_property_context : Error< "property implementation must be in a class or category implementation">; def error_missing_property_ivar_decl : Error< "synthesized property %0 must either be named the same as a compatible" - " ivar or must explicitly name an ivar">; + " instance variable or must explicitly name an instance variable">; def error_synthesize_weak_non_arc_or_gc : Error< "@synthesize of 'weak' property is only allowed in ARC or GC mode">; def err_arc_perform_selector_retains : Error< @@ -712,38 +708,55 @@ def err_gc_weak_property_strong_type : Error< "weak attribute declared on a __strong type property in GC mode">; def warn_receiver_is_weak : Warning < "weak %select{receiver|property|implicit property}0 may be " - "unpredictably null in ARC mode">, + "unpredictably set to nil">, InGroup>, DefaultIgnore; +def note_arc_assign_to_strong : Note< + "assign the value to a strong variable to keep the object alive during use">; +def warn_arc_repeated_use_of_weak : Warning < + "weak %select{variable|property|implicit property|instance variable}0 %1 is " + "accessed multiple times in this %select{function|method|block|lambda}2 " + "but may be unpredictably set to nil; assign to a strong variable to keep " + "the object alive">, + InGroup, DefaultIgnore; +def warn_implicitly_retains_self : Warning < + "block implicitly retains 'self'; explicitly mention 'self' to indicate " + "this is intended behavior">, + InGroup>, DefaultIgnore; +def warn_arc_possible_repeated_use_of_weak : Warning < + "weak %select{variable|property|implicit property|instance variable}0 %1 may " + "be accessed multiple times in this %select{function|method|block|lambda}2 " + "and may be unpredictably set to nil; assign to a strong variable to keep " + "the object alive">, + InGroup, DefaultIgnore; +def note_arc_weak_also_accessed_here : Note< + "also accessed here">; def err_incomplete_synthesized_property : Error< "cannot synthesize property %0 with incomplete type %1">; def error_property_ivar_type : Error< - "type of property %0 (%1) does not match type of ivar %2 (%3)">; + "type of property %0 (%1) does not match type of instance variable %2 (%3)">; def error_property_accessor_type : Error< "type of property %0 (%1) does not match type of accessor %2 (%3)">; def error_ivar_in_superclass_use : Error< - "property %0 attempting to use ivar %1 declared in super class %2">; + "property %0 attempting to use instance variable %1 declared in super class %2">; def error_weak_property : Error< - "existing ivar %1 for __weak property %0 must be __weak">; + "existing instance variable %1 for __weak property %0 must be __weak">; def error_strong_property : Error< - "existing ivar %1 for strong property %0 may not be __weak">; + "existing instance variable %1 for strong property %0 may not be __weak">; def error_dynamic_property_ivar_decl : Error< - "dynamic property can not have ivar specification">; + "dynamic property can not have instance variable specification">; def error_duplicate_ivar_use : Error< - "synthesized properties %0 and %1 both claim ivar %2">; + "synthesized properties %0 and %1 both claim instance variable %2">; def error_property_implemented : Error<"property %0 is already implemented">; def warn_objc_property_attr_mutually_exclusive : Warning< "property attributes '%0' and '%1' are mutually exclusive">, InGroup, DefaultIgnore; -def warn_objc_missing_super_dealloc : Warning< - "method possibly missing a [super dealloc] call">, +def warn_objc_missing_super_call : Warning< + "method possibly missing a [super %0] call">, InGroup; def error_dealloc_bad_result_type : Error< "dealloc return type must be correctly specified as 'void' under ARC, " "instead of %0">; -def warn_objc_missing_super_finalize : Warning< - "method possibly missing a [super finalize] call">, - InGroup; def warn_undeclared_selector : Warning< "undeclared selector %0">, InGroup, DefaultIgnore; def warn_implicit_atomic_property : Warning< @@ -768,7 +781,7 @@ def err_static_assert_expression_is_not_constant : Error< def err_static_assert_failed : Error<"static_assert failed %0">; def warn_inline_namespace_reopened_noninline : Warning< - "inline namespace cannot be re-opened as a non-inline namespace">; + "inline namespace cannot be reopened as a non-inline namespace">; def err_inline_namespace_mismatch : Error< "%select{|non-}0inline namespace " "cannot be reopened as %select{non-|}0inline">; @@ -792,10 +805,11 @@ def warn_cxx98_compat_friend_is_member : Warning< "with C++98">, InGroup, DefaultIgnore; def ext_unelaborated_friend_type : ExtWarn< "unelaborated friend declaration is a C++11 extension; specify " - "'%select{struct|union|class|enum}0' to befriend %1">, InGroup; + "'%select{struct|interface|union|class|enum}0' to befriend %1">, + InGroup; def warn_cxx98_compat_unelaborated_friend_type : Warning< - "befriending %1 without '%select{struct|union|class|enum}0' keyword is " - "incompatible with C++98">, InGroup, DefaultIgnore; + "befriending %1 without '%select{struct|interface|union|class|enum}0' " + "keyword is incompatible with C++98">, InGroup, DefaultIgnore; def err_qualified_friend_not_found : Error< "no function named %0 with type %1 was found in the specified scope">; def err_introducing_special_friend : Error< @@ -806,16 +820,26 @@ def err_tagless_friend_type_template : Error< def err_no_matching_local_friend : Error< "no matching function found in local scope">; def err_no_matching_local_friend_suggest : Error< - "no matching function %0 found in local scope; did you mean %2">; + "no matching function %0 found in local scope; did you mean %2?">; def err_partial_specialization_friend : Error< "partial specialization cannot be declared as a friend">; def err_qualified_friend_def : Error< "friend function definition cannot be qualified with '%0'">; def err_friend_def_in_local_class : Error< "friend function cannot be defined in a local class">; +def err_friend_not_first_in_declaration : Error< + "'friend' must appear first in a non-function declaration">; +def err_invalid_member_in_interface : Error< + "%select{data member |non-public member function |static member function |" + "user-declared constructor|user-declared destructor|operator |" + "nested class }0%1 is not permitted within an interface type">; +def err_invalid_base_in_interface : Error< + "interface type cannot inherit from " + "%select{'struct|non-public 'interface|'class}0 %1'">; + def err_abstract_type_in_decl : Error< - "%select{return|parameter|variable|field|ivar}0 type %1 is an abstract class">; + "%select{return|parameter|variable|field|instance variable}0 type %1 is an abstract class">; def err_allocation_of_abstract_type : Error< "allocating an object of abstract class type %0">; def err_throw_abstract_type : Error< @@ -841,6 +865,12 @@ def note_pure_virtual_function : Note< def err_deleted_decl_not_first : Error< "deleted definition must be first declaration">; +def err_deleted_override : Error< + "deleted function %0 cannot override a non-deleted function">; + +def err_non_deleted_override : Error< + "non-deleted function %0 cannot override a deleted function">; + def warn_weak_vtable : Warning< "%0 has no out-of-line virtual method definitions; its vtable will be " "emitted in every translation unit">, @@ -1030,7 +1060,7 @@ def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning< "not available in the %select{constructor|destructor}1 of %2">; def note_field_decl : Note<"member is declared here">; -def note_ivar_decl : Note<"ivar is declared here">; +def note_ivar_decl : Note<"instance variable is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; def note_previous_decl : Note<"%0 declared here">; def note_member_synthesized_at : Note< @@ -1113,8 +1143,8 @@ def err_constructor_redeclared : Error<"constructor cannot be redeclared">; def err_constructor_byvalue_arg : Error< "copy constructor must pass its first argument by reference">; def warn_no_constructor_for_refconst : Warning< - "%select{struct|union|class|enum}0 %1 does not declare any constructor to " - "initialize its non-modifiable members">; + "%select{struct|interface|union|class|enum}0 %1 does not declare any " + "constructor to initialize its non-modifiable members">; def note_refconst_member_not_initialized : Note< "%select{const|reference}0 member %1 will never be initialized">; def ext_ms_explicit_constructor_call : ExtWarn< @@ -1214,11 +1244,18 @@ def err_init_reference_member_uninitialized : Error< "reference member of type %0 uninitialized">; def note_uninit_reference_member : Note< "uninitialized reference member is here">; -def warn_field_is_uninit : Warning<"field is uninitialized when used here">, +def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">, + InGroup; +def warn_reference_field_is_uninit : Warning< + "reference %0 is not yet bound to a value when used here">, InGroup; def warn_uninit_self_reference_in_init : Warning< "variable %0 is uninitialized when used within its own initialization">, InGroup; +def warn_uninit_self_reference_in_reference_init : Warning< + "reference %0 is not yet bound to a value when used within its own" + " initialization">, + InGroup; def warn_uninit_var : Warning< "variable %0 is uninitialized when %select{used here|captured by block}1">, InGroup, DefaultIgnore; @@ -1300,9 +1337,10 @@ def err_new_array_of_auto : Error< "cannot allocate array of 'auto'">; def err_auto_not_allowed : Error< "'auto' not allowed %select{in function prototype|in non-static struct member" - "|in non-static union member|in non-static class member|in exception declaration" - "|in template parameter|in block literal|in template argument" - "|in typedef|in type alias|in function return type|here}0">; + "|in non-static union member|in non-static class member|in interface member" + "|in exception declaration|in template parameter|in block literal" + "|in template argument|in typedef|in type alias|in function return type" + "|here}0">; def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< @@ -1346,6 +1384,8 @@ def err_function_marked_override_not_overriding : Error< "%0 marked 'override' but does not override any member functions">; def err_class_marked_final_used_as_base : Error< "base %0 is marked 'final'">; +def warn_abstract_final_class : Warning< + "abstract class is marked 'final'">, InGroup; // C++11 attributes def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; @@ -1408,7 +1448,17 @@ def err_for_range_member_begin_end_mismatch : Error< "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">; def err_for_range_begin_end_types_differ : Error< "'begin' and 'end' must return the same type (got %0 and %1)">; -def note_for_range_type : Note<"range has type %0">; +def note_in_for_range: Note< + "when looking up '%select{begin|end}0' function for range expression " + "of type %1">; +def err_for_range_invalid: Error< + "invalid range expression of type %0; no viable '%select{begin|end}1' " + "function available">; +def err_for_range_dereference : Error< + "invalid range expression of type %0; did you mean to dereference it " + "with '*'?">; +def note_for_range_invalid_iterator : Note < + "in implicit call to 'operator%select{!=|*|++}0' for iterator of type %1">; def note_for_range_begin_end : Note< "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">; @@ -1420,7 +1470,7 @@ def err_invalid_constexpr : Error< "%select{function parameter|typedef|non-static data member}0 " "cannot be constexpr">; def err_constexpr_tag : Error< - "%select{class|struct|union|enum}0 cannot be marked constexpr">; + "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">; def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">; def err_constexpr_no_declarators : Error< "constexpr can only be used in variable and function declarations">; @@ -1438,11 +1488,12 @@ def err_constexpr_redecl_mismatch : Error< def err_constexpr_virtual : Error<"virtual function cannot be constexpr">; def err_constexpr_virtual_base : Error< "constexpr %select{member function|constructor}0 not allowed in " - "%select{class|struct}1 with virtual base %plural{1:class|:classes}2">; + "%select{struct|interface|class}1 with virtual base " + "%plural{1:class|:classes}2">; def note_non_literal_incomplete : Note< "incomplete type %0 is not a literal type">; -def note_non_literal_virtual_base : Note<"%select{class|struct}0 with virtual " - "base %plural{1:class|:classes}1 is not a literal type">; +def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 " + "with virtual base %plural{1:class|:classes}1 is not a literal type">; def note_constexpr_virtual_base_here : Note<"virtual base class declared here">; def err_constexpr_non_literal_return : Error< "constexpr function's return type %0 is not a literal type">; @@ -1490,10 +1541,10 @@ def note_non_literal_user_provided_dtor : Note< def note_non_literal_nontrivial_dtor : Note< "%0 is not literal because it has a non-trivial destructor">; def warn_private_extern : Warning< - "Use of __private_extern__ on tentative definition has unexpected" - " behaviour - use __attribute__((visibility(\"hidden\"))) on extern" - " declaration or definition instead">, - InGroup, DefaultIgnore; + "use of __private_extern__ on a declaration may not produce external symbol " + "private to the linkage unit and is deprecated">, InGroup; +def note_private_extern : Note< + "use __attribute__((visibility(\"hidden\"))) attribute instead">; // C++11 char16_t/char32_t def warn_cxx98_compat_unicode_type : Warning< @@ -1681,7 +1732,9 @@ def warn_attribute_invalid_on_stmt : Warning< "attribute %0 cannot be specified on a statement">, InGroup; def warn_declspec_attribute_ignored : Warning< - "attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup; + "attribute %0 is ignored, place it after " + "\"%select{class|struct|union|interface|enum}1\" to apply attribute to " + "type declaration">, InGroup; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">, InGroup; @@ -1699,7 +1752,8 @@ def warn_nsobject_attribute : Warning< "__attribute ((NSObject)) may be put on a typedef only, " "attribute is ignored">, InGroup; def warn_attribute_weak_on_local : Warning< - "__weak attribute cannot be specified on an automatic variable">, + "__weak attribute cannot be specified on an automatic variable when ARC " + "is not enabled">, InGroup; def warn_weak_identifier_undeclared : Warning< "weak identifier %0 never declared">; @@ -1753,6 +1807,8 @@ def err_attribute_vecreturn_only_pod_record : Error< def err_cconv_change : Error< "function declared '%0' here was previously declared " "%select{'%2'|without calling convention}1">; +def warn_cconv_ignored : Warning< + "calling convention %0 ignored for this target">, InGroup; def err_cconv_knr : Error< "function with no prototype cannot use %0 calling convention">; def err_cconv_varargs : Error< @@ -1840,14 +1896,6 @@ def warn_lock_exclusive_and_shared : Warning< InGroup, DefaultIgnore; def note_lock_exclusive_and_shared : Note< "the other lock of mutex '%0' is here">; -def warn_variable_requires_lock : Warning< - "%select{reading|writing}2 variable '%0' requires locking " - "%select{'%1'|'%1' exclusively}2">, - InGroup, DefaultIgnore; -def warn_var_deref_requires_lock : Warning< - "%select{reading|writing}2 the value pointed to by '%0' requires locking " - "%select{'%1'|'%1' exclusively}2">, - InGroup, DefaultIgnore; def warn_variable_requires_any_lock : Warning< "%select{reading|writing}1 variable '%0' requires locking " "%select{any mutex|any mutex exclusively}1">, @@ -1856,9 +1904,6 @@ def warn_var_deref_requires_any_lock : Warning< "%select{reading|writing}1 the value pointed to by '%0' requires locking " "%select{any mutex|any mutex exclusively}1">, InGroup, DefaultIgnore; -def warn_fun_requires_lock : Warning< - "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">, - InGroup, DefaultIgnore; def warn_fun_excludes_mutex : Warning< "cannot call function '%0' while mutex '%1' is locked">, InGroup, DefaultIgnore; @@ -1866,6 +1911,32 @@ def warn_cannot_resolve_lock : Warning< "cannot resolve lock expression">, InGroup, DefaultIgnore; +// Imprecise thread safety warnings +def warn_variable_requires_lock : Warning< + "%select{reading|writing}2 variable '%0' requires locking " + "%select{'%1'|'%1' exclusively}2">, + InGroup, DefaultIgnore; +def warn_var_deref_requires_lock : Warning< + "%select{reading|writing}2 the value pointed to by '%0' requires locking " + "%select{'%1'|'%1' exclusively}2">, + InGroup, DefaultIgnore; +def warn_fun_requires_lock : Warning< + "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">, + InGroup, DefaultIgnore; + +// Precise thread safety warnings +def warn_variable_requires_lock_precise : Warning< + "%select{reading|writing}2 variable '%0' requires locking " + "%select{'%1'|'%1' exclusively}2">, + InGroup, DefaultIgnore; +def warn_var_deref_requires_lock_precise : Warning< + "%select{reading|writing}2 the value pointed to by '%0' requires locking " + "%select{'%1'|'%1' exclusively}2">, + InGroup, DefaultIgnore; +def warn_fun_requires_lock_precise : Warning< + "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">, + InGroup, DefaultIgnore; +def note_found_mutex_near_match : Note<"found near match '%0'">; def warn_impcast_vector_scalar : Warning< "implicit conversion turns vector to scalar: %0 to %1">, @@ -1890,7 +1961,7 @@ def warn_impcast_integer_precision : Warning< InGroup>, DefaultIgnore; def warn_impcast_integer_64_32 : Warning< "implicit conversion loses integer precision: %0 to %1">, - InGroup>, DefaultIgnore; + InGroup, DefaultIgnore; def warn_impcast_integer_precision_constant : Warning< "implicit conversion from %2 to %3 changes value from %0 to %1">, InGroup; @@ -1905,7 +1976,7 @@ def warn_impcast_string_literal_to_bool : Warning< InGroup, DefaultIgnore; def warn_impcast_different_enum_types : Warning< "implicit conversion from enumeration type %0 to different enumeration type " - "%1">, InGroup>; + "%1">, InGroup; def warn_impcast_bool_to_null_pointer : Warning< "initialization of pointer of type %0 to null from a constant boolean " "expression">, InGroup; @@ -1915,6 +1986,9 @@ def warn_non_literal_null_pointer : Warning< def warn_impcast_null_pointer_to_integer : Warning< "implicit conversion of NULL constant to %0">, InGroup; +def warn_impcast_floating_point_to_bool : Warning< + "implicit conversion turns floating-point number into bool: %0 to %1">, + InGroup; def warn_impcast_function_to_bool : Warning< "address of function %q0 will always evaluate to 'true'">, InGroup; @@ -1927,6 +2001,10 @@ def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, InGroup, DefaultIgnore; +def warn_int_to_pointer_cast : Warning< + "cast to %1 from smaller integer type %0">, + InGroup; + def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">, InGroup; @@ -2008,7 +2086,7 @@ def warn_attribute_ibaction: Warning< def err_iboutletcollection_type : Error< "invalid type %0 as argument of iboutletcollection attribute">; def warn_iboutlet_object_type : Warning< - "%select{ivar|property}2 with %0 attribute must " + "%select{instance variable|property}2 with %0 attribute must " "be an object type (invalid %1)">, InGroup>; def err_attribute_overloadable_not_function : Error< @@ -2028,6 +2106,12 @@ def warn_ns_attribute_wrong_parameter_type : Warning< "%0 attribute only applies to %select{Objective-C object|pointer}1 " "parameters">, InGroup; +def warn_objc_requires_super_protocol : Warning< + "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">, + InGroup>; +def note_protocol_decl : Note< + "protocol is declared here">; + def err_ns_bridged_not_interface : Error< "parameter of 'ns_bridged' attribute does not name an Objective-C class">; @@ -3058,6 +3142,9 @@ def note_sentinel_here : Note< def warn_missing_prototype : Warning< "no previous prototype for function %0">, InGroup>, DefaultIgnore; +def warn_missing_variable_declarations : Warning< + "no previous extern declaration for non-static variable %0">, + InGroup>, DefaultIgnore; def err_redefinition : Error<"redefinition of %0">; def err_definition_of_implicitly_declared_member : Error< "definition of implicitly declared %select{default constructor|copy " @@ -3144,7 +3231,7 @@ def err_non_thread_thread : Error< def err_thread_non_thread : Error< "thread-local declaration of %0 follows non-thread-local declaration">; def err_redefinition_different_type : Error< - "redefinition of %0 with a different type">; + "redefinition of %0 with a different type%diff{: $ vs $|}1,2">; def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; def warn_forward_class_redefinition : Warning< @@ -3159,8 +3246,8 @@ def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with " "%select{a declaration|a typedef|a type alias|a template}0 of the same name">; def err_dependent_tag_decl : Error< - "%select{declaration|definition}0 of %select{struct|union|class|enum}1 " - "in a dependent scope">; + "%select{declaration|definition}0 of " + "%select{struct|interface|union|class|enum}1 in a dependent scope">; def err_tag_definition_of_typedef : Error< "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">; def err_conflicting_types : Error<"conflicting types for %0">; @@ -3168,15 +3255,16 @@ def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; def warn_struct_class_tag_mismatch : Warning< - "%select{struct|class}0%select{| template}1 %2 was previously declared " - "as a %select{class|struct}0%select{| template}1">, + "%select{struct|interface|class}0%select{| template}1 %2 was previously " + "declared as a %select{struct|interface|class}3%select{| template}1">, InGroup, DefaultIgnore; def warn_struct_class_previous_tag_mismatch : Warning< - "%2 defined as a %select{struct|class}0%select{| template}1 here but " - "previously declared as a %select{class|struct}0%select{| template}1">, + "%2 defined as %select{a struct|an interface|a class}0%select{| template}1 " + "here but previously declared as " + "%select{a struct|an interface|a class}3%select{| template}1">, InGroup, DefaultIgnore; def note_struct_class_suggestion : Note< - "did you mean %select{struct|class}0 here?">; + "did you mean %select{struct|interface|class}0 here?">; def ext_forward_ref_enum : Extension< "ISO C forbids forward references to 'enum' types">; def err_forward_ref_enum : Error< @@ -3189,9 +3277,9 @@ def ext_forward_ref_enum_def : Extension< def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; def err_misplaced_ivar : Error< - "ivars may not be placed in %select{categories|class extension}0">; + "instance variables may not be placed in %select{categories|class extension}0">; def warn_ivars_in_interface : Warning< - "declaration of ivars in the interface is deprecated">, + "declaration of instance variables in the interface is deprecated">, InGroup>, DefaultIgnore; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " @@ -3220,11 +3308,13 @@ def warn_array_new_too_large : Warning<"array is too large (%0 elements)">, // -Wpadded, -Wpacked def warn_padded_struct_field : Warning< - "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 " - "to align %5">, InGroup, DefaultIgnore; + "padding %select{struct|interface|class}0 %1 with %2 " + "%select{byte|bit}3%select{|s}4 to align %5">, + InGroup, DefaultIgnore; def warn_padded_struct_anon_field : Warning< - "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 " - "to align anonymous bit-field">, InGroup, DefaultIgnore; + "padding %select{struct|interface|class}0 %1 with %2 " + "%select{byte|bit}3%select{|s}4 to align anonymous bit-field">, + InGroup, DefaultIgnore; def warn_padded_struct_size : Warning< "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 " "to alignment boundary">, InGroup, DefaultIgnore; @@ -3244,7 +3334,7 @@ def err_typecheck_invalid_restrict_not_pointer_noarg : Error< def err_typecheck_invalid_restrict_invalid_pointee : Error< "pointer to function type %0 may not be 'restrict' qualified">; def ext_typecheck_zero_array_size : Extension< - "zero size arrays are an extension">; + "zero size arrays are an extension">, InGroup; def err_typecheck_zero_array_size : Error< "zero-length arrays are not permitted in C++">; def warn_typecheck_zero_static_array_size : Warning< @@ -3354,7 +3444,7 @@ def warn_anon_bitfield_width_exceeds_type_size : Warning< def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, - InGroup>, DefaultIgnore; + InGroup, DefaultIgnore; def err_missing_braces : Error< "cannot omit braces around initialization of subobject when using direct " "list-initialization">; @@ -3472,14 +3562,16 @@ def ext_flexible_array_in_array : Extension< def err_flexible_array_init : Error< "initialization of flexible array member is not allowed">; def ext_flexible_array_empty_aggregate_ms : Extension< - "flexible array member %0 in otherwise empty %select{struct|class}1 " - "is a Microsoft extension">, InGroup; + "flexible array member %0 in otherwise empty " + "%select{struct|interface|union|class|enum}1 is a Microsoft extension">, + InGroup; def ext_flexible_array_union_ms : Extension< "flexible array member %0 in a union is a Microsoft extension">, InGroup; def ext_flexible_array_empty_aggregate_gnu : Extension< - "flexible array member %0 in otherwise empty %select{struct|class}1 " - "is a GNU extension">, InGroup; + "flexible array member %0 in otherwise empty " + "%select{struct|interface|union|class|enum}1 is a GNU extension">, + InGroup; def ext_flexible_array_union_gnu : Extension< "flexible array member %0 in a union is a GNU extension">, InGroup; @@ -3497,7 +3589,7 @@ def err_arc_weak_unavailable_assign : Error< "assignment of a weak-unavailable object to a __weak object">; def err_arc_weak_unavailable_property : Error< "synthesis of a weak-unavailable property is disallowed " - "because it requires synthesis of an ivar of the __weak object">; + "because it requires synthesis of an instance variable of the __weak object">; def err_arc_convesion_of_weak_unavailable : Error< "%select{implicit conversion|cast}0 of weak-unavailable object of type %1 to" " a __weak object of type %2">; @@ -3527,6 +3619,9 @@ def err_arc_illegal_selector : Error< "ARC forbids use of %0 in a @selector">; def err_arc_illegal_method_def : Error< "ARC forbids implementation of %0">; +def warn_arc_strong_pointer_objc_pointer : Warning< + "method parameter of type %0 with no explicit ownership">, + InGroup>, DefaultIgnore; } // end "ARC Restrictions" category @@ -3549,11 +3644,6 @@ def err_typecheck_arc_assign_self_class_method : Error< def err_typecheck_arr_assign_enumeration : Error< "fast enumeration variables can't be modified in ARC by default; " "declare the variable __strong to allow this">; -def warn_arc_non_pod_class_with_object_member : Warning< - "%0 cannot be shared between ARC and non-ARC " - "code; add a copy constructor, a copy assignment operator, and a destructor " - "to make it ABI-compatible">, InGroup, - DefaultIgnore; def warn_arc_retained_assign : Warning< "assigning retained object to %select{weak|unsafe_unretained}0 " "%select{property|variable}1" @@ -3563,19 +3653,10 @@ def warn_arc_retained_property_assign : Warning< "assigning retained object to unsafe property" "; object will be released after assignment">, InGroup; -def warn_arc_trivial_member_function_with_object_member : Warning< - "%0 cannot be shared between ARC and non-ARC " - "code; add a non-trivial %select{copy constructor|copy assignment operator|" - "destructor}1 to make it ABI-compatible">, - InGroup, DefaultIgnore; def err_arc_new_array_without_ownership : Error< "'new' cannot allocate an array of %0 with no explicit ownership">; -def warn_err_new_delete_object_array : Warning< - "%select{allocating|destroying}0 an array of %1; this array must not " - "%select{be deleted in|have been allocated from}0 non-ARC code">, - InGroup, DefaultIgnore; def err_arc_autoreleasing_var : Error< - "%select{__block variables|global variables|fields|ivars}0 cannot have " + "%select{__block variables|global variables|fields|instance variables}0 cannot have " "__autoreleasing ownership">; def err_arc_autoreleasing_capture : Error< "cannot capture __autoreleasing variable in a " @@ -3632,10 +3713,10 @@ def warn_arc_object_memaccess : Warning< let CategoryName = "ARC and @properties" in { def err_arc_strong_property_ownership : Error< - "existing ivar %1 for strong property %0 may not be " + "existing instance variable %1 for strong property %0 may not be " "%select{|__unsafe_unretained||__weak}2">; def err_arc_assign_property_ownership : Error< - "existing ivar %1 for property %0 with %select{unsafe_unretained| assign}2 " + "existing instance variable %1 for property %0 with %select{unsafe_unretained| assign}2 " "attribute must be __unsafe_unretained">; def err_arc_inconsistent_property_ownership : Error< "%select{|unsafe_unretained|strong|weak}1 property %0 may not also be " @@ -3766,16 +3847,14 @@ def warn_precedence_bitwise_rel : Warning< InGroup; def note_precedence_bitwise_first : Note< "place parentheses around the %0 expression to evaluate it first">; -def note_precedence_bitwise_silence : Note< - "place parentheses around the %0 expression to silence this warning">; +def note_precedence_silence : Note< + "place parentheses around the '%0' expression to silence this warning">; def warn_precedence_conditional : Warning< "operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">, InGroup; def note_precedence_conditional_first : Note< "place parentheses around the '?:' expression to evaluate it first">; -def note_precedence_conditional_silence : Note< - "place parentheses around the '%0' expression to silence this warning">; def warn_logical_instead_of_bitwise : Warning< "use of logical '%0' with constant operand">, @@ -3787,13 +3866,13 @@ def note_logical_instead_of_bitwise_remove_constant : Note< def warn_bitwise_and_in_bitwise_or : Warning< "'&' within '|'">, InGroup; -def note_bitwise_and_in_bitwise_or_silence : Note< - "place parentheses around the '&' expression to silence this warning">; def warn_logical_and_in_logical_or : Warning< "'&&' within '||'">, InGroup; -def note_logical_and_in_logical_or_silence : Note< - "place parentheses around the '&&' expression to silence this warning">; + +def warn_addition_in_bitshift : Warning< + "operator '%0' has lower precedence than '%1'; " + "'%1' will be evaluated first">, InGroup; def warn_self_assignment : Warning< "explicitly assigning a variable of type %0 to itself">, @@ -3896,6 +3975,8 @@ def ext_out_of_line_declaration : ExtWarn< "out-of-line declaration of a member must be a definition">, InGroup, DefaultError; def warn_member_extra_qualification : Warning< + "extra qualification on member %0">, InGroup; +def err_member_extra_qualification : Error< "extra qualification on member %0">; def err_member_qualification : Error< "non-friend class member %0 cannot have a qualified name">; @@ -4013,7 +4094,8 @@ def ext_typecheck_comparison_of_pointer_integer : ExtWarn< def err_typecheck_comparison_of_pointer_integer : Error< "comparison between pointer and integer (%0 and %1)">; def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< - "comparison of distinct pointer types%diff{ ($ and $)|}0,1">; + "comparison of distinct pointer types%diff{ ($ and $)|}0,1">, + InGroup; def ext_typecheck_cond_incompatible_operands : ExtWarn< "incompatible operand types (%0 and %1)">; def err_cond_voidptr_arc : Error < @@ -4023,7 +4105,7 @@ def err_typecheck_comparison_of_distinct_pointers : Error< "comparison of distinct pointer types%diff{ ($ and $)|}0,1">; def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn< "comparison of distinct pointer types (%0 and %1) uses non-standard " - "composite pointer type %2">; + "composite pointer type %2">, InGroup; def err_typecheck_assign_const : Error<"read-only variable is not assignable">; def err_stmtexpr_file_scope : Error< "statement expression not allowed at file scope">; @@ -4033,6 +4115,9 @@ def warn_mixed_sign_comparison : Warning< def warn_lunsigned_always_true_comparison : Warning< "comparison of unsigned%select{| enum}2 expression %0 is always %1">, InGroup; +def warn_out_of_range_compare : Warning< + "comparison of constant %0 with expression of type %1 is always " + "%select{false|true}2">, InGroup; def warn_runsigned_always_true_comparison : Warning< "comparison of %0 unsigned%select{| enum}2 expression is always %1">, InGroup; @@ -4166,7 +4251,7 @@ def err_nogetter_property_incdec : Error< def error_no_subobject_property_setting : Error< "expression is not assignable">; def err_qualified_objc_access : Error< - "%select{property|ivar}0 access cannot be qualified with '%1'">; + "%select{property|instance variable}0 access cannot be qualified with '%1'">; def ext_freestanding_complex : Extension< "complex numbers are an extension in a freestanding C99 implementation">; @@ -4562,7 +4647,7 @@ def err_invalid_declarator_global_scope : Error< def err_invalid_declarator_in_function : Error< "definition or redeclaration of %0 not allowed inside a function">; def err_not_tag_in_scope : Error< - "no %select{struct|union|class|enum}0 named %1 in %2">; + "no %select{struct|interface|union|class|enum}0 named %1 in %2">; def err_no_typeid_with_fno_rtti : Error< "cannot use typeid with -fno-rtti">; @@ -4885,6 +4970,8 @@ def note_callee_decl : Note< "%0 declared here">; def note_defined_here : Note<"%0 defined here">; +def err_builtin_fn_use : Error<"builtin functions must be directly called">; + def warn_call_wrong_number_of_arguments : Warning< "too %select{few|many}0 arguments in call to %1">; def err_atomic_builtin_must_be_pointer : Error< @@ -4898,6 +4985,9 @@ def err_atomic_builtin_pointer_size : Error< def err_atomic_op_needs_atomic : Error< "first argument to atomic operation must be a pointer to _Atomic " "type (%0 invalid)">; +def err_atomic_op_needs_non_const_atomic : Error< + "first argument to atomic operation must be a pointer to non-const _Atomic " + "type (%0 invalid)">; def err_atomic_op_needs_trivial_copy : Error< "first argument to atomic operation must be a pointer to a trivially-copyable" " type (%0 invalid)">; @@ -4960,7 +5050,9 @@ def err_typecheck_cast_to_incomplete : Error< "cast to incomplete type %0">; def ext_typecheck_cast_nonscalar : Extension< "C99 forbids casting nonscalar type %0 to the same type">; -def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">; +def ext_typecheck_cast_to_union : Extension< + "cast to union type is a GNU extension">, + InGroup; def err_typecheck_cast_to_union_no_type : Error< "cast to union type from type %0 not present in union">; def err_cast_pointer_from_non_pointer_int : Error< @@ -4968,6 +5060,9 @@ def err_cast_pointer_from_non_pointer_int : Error< def warn_cast_pointer_from_sel : Warning< "cast of type %0 to %1 is deprecated; use sel_getName instead">, InGroup; +def warn_bad_function_cast : Warning< + "cast from function call of type %0 to non-matching type %1">, + InGroup, DefaultIgnore; def err_cast_pointer_to_non_pointer_int : Error< "pointer cannot be cast to type %0">; def err_typecheck_expect_scalar_operand : Error< @@ -5045,19 +5140,21 @@ let CategoryName = "Inline Assembly Issue" in { "unsupported inline asm: input with type " "%diff{$ matching output with type $|}0,1">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; - def warn_asm_label_on_auto_decl : Warning< - "ignored asm label '%0' on automatic variable">; + def err_asm_empty : Error<"__asm used with no assembly instructions">; def err_invalid_asm_cast_lvalue : Error< "invalid use of a cast in a inline asm context requiring an l-value: " "remove the cast or build with -fheinous-gnu-extensions">; + def err_inline_ms_asm_parsing : Error<"%0">; + def warn_asm_label_on_auto_decl : Warning< + "ignored asm label '%0' on automatic variable">; def warn_invalid_asm_cast_lvalue : Warning< - "invalid use of a cast in a inline asm context requiring an l-value: " + "invalid use of a cast in an inline asm context requiring an l-value: " "accepted due to -fheinous-gnu-extensions, but clang may remove support " "for this in the future">; - - def warn_unsupported_msasm : ExtWarn< - "MS-style inline assembly is not supported">, InGroup; + def warn_asm_mismatched_size_modifier : Warning< + "the size being stored is truncated, use a modifier to specify the size">, + InGroup; } let CategoryName = "Semantic Issue" in { @@ -5122,7 +5219,7 @@ def err_in_class_initializer_references_def_ctor : Error< def ext_in_class_initializer_non_constant : Extension< "in-class initializer for static data member is not a constant expression; " - "folding it to a constant is a GNU extension">; + "folding it to a constant is a GNU extension">, InGroup; // C++ anonymous unions and GNU anonymous structs/unions def ext_anonymous_union : Extension< @@ -5178,6 +5275,8 @@ def err_static_data_member_not_allowed_in_local_class : Error< def err_base_clause_on_union : Error<"unions cannot have base classes">; def err_base_must_be_class : Error<"base specifier must name a class">; def err_union_as_base_class : Error<"unions cannot be base classes">; +def err_circular_inheritance : Error< + "circular inheritance between %0 and %1">; def err_incomplete_base_class : Error<"base class has incomplete type">; def err_duplicate_base_class : Error< "base class %0 specified more than once as a direct base class">; @@ -5340,6 +5439,10 @@ def err_out_of_line_default_deletes : Error< "defaulting this %select{default constructor|copy constructor|move " "constructor|copy assignment operator|move assignment operator|destructor}0 " "would delete it after its first declaration">; +def ext_implicit_exception_spec_mismatch : ExtWarn< + "function previously declared with an %select{explicit|implicit}0 exception " + "specification redeclared with an %select{implicit|explicit}0 exception " + "specification">, InGroup>; def warn_ptr_arith_precedes_bounds : Warning< "the pointer decremented by %0 refers before the beginning of the array">, @@ -5373,6 +5476,10 @@ def warn_scanf_nonzero_width : Warning< def warn_printf_conversion_argument_type_mismatch : Warning< "format specifies type %0 but the argument has type %1">, InGroup; +def warn_format_argument_needs_cast : Warning< + "values of type '%0' should not be used as format arguments; add an explicit " + "cast to %1 instead">, + InGroup; def warn_printf_positional_arg_exceeds_data_args : Warning < "data argument position '%0' exceeds the number of data arguments (%1)">, InGroup; @@ -5397,7 +5504,8 @@ def warn_format_string_is_wide_literal : Warning< def warn_printf_format_string_contains_null_char : Warning< "format string contains '\\0' within the string body">, InGroup; def warn_printf_asterisk_missing_arg : Warning< - "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">; + "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">, + InGroup; def warn_printf_asterisk_wrong_type : Warning< "field %select{width|precision}0 should have type %1, but argument has type %2">, InGroup; @@ -5425,6 +5533,7 @@ def warn_scanf_scanlist_incomplete : Warning< "no closing ']' for '%%[' in scanf format string">, InGroup; def note_format_string_defined : Note<"format string is defined here">; +def note_format_fix_specifier : Note<"did you mean to use '%0'?">; def note_printf_c_str: Note<"did you mean to call the %0 method?">; def warn_null_arg : Warning< @@ -5588,7 +5697,7 @@ def warn_unannotated_fallthrough_per_function : Warning< "unannotated fall-through between switch labels in partly-annotated " "function">, InGroup, DefaultIgnore; def note_insert_fallthrough_fixit : Note< - "insert '[[clang::fallthrough]];' to silence this warning">; + "insert '%0;' to silence this warning">; def note_insert_break_fixit : Note< "insert 'break;' to avoid fall-through">; def err_fallthrough_attr_wrong_target : Error< @@ -5824,7 +5933,7 @@ def err_typecheck_member_reference_ivar_suggest : Error< def err_property_not_found_suggest : Error< "property %0 not found on object of type %1; did you mean %2?">; def err_ivar_access_using_property_syntax_suggest : Error< - "property %0 not found on object of type %1; did you mean to access ivar %2?">; + "property %0 not found on object of type %1; did you mean to access instance variable %2?">; def err_property_found_suggest : Error< "property %0 found on object of type %1; did you mean to access " "it with the \".\" operator?">; @@ -5911,7 +6020,7 @@ def err_module_private_local : Error< "%select{local variable|parameter|typedef}0 %1 cannot be declared " "__module_private__">; def err_module_private_local_class : Error< - "local %select{struct|union|class|enum}0 cannot be declared " + "local %select{struct|interface|union|class|enum}0 cannot be declared " "__module_private__">; def err_module_private_definition : Error< "definition of %0 must be imported before it is required">; diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index a440e806d735..e9df09d114db 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -25,9 +25,13 @@ def err_fe_pch_file_modified : Error< def err_fe_pch_file_overridden : Error< "file '%0' from the precompiled header has been overridden">; -def warn_pch_target_triple : Error< - "PCH file was compiled for the target '%0' but the current translation " - "unit is being compiled for target '%1'">; +def err_pch_targetopt_mismatch : Error< + "PCH file was compiled for the %0 '%1' but the current translation " + "unit is being compiled for target '%2'">; +def err_pch_targetopt_feature_mismatch : Error< + "%select{AST file|current translation unit}0 was compiled with the target " + "feature'%1' but the %select{current translation unit is|AST file was}0 " + "not">; def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " "PCH file but is currently %select{disabled|enabled}2">; def err_pch_langopt_value_mismatch : Error< @@ -41,21 +45,24 @@ def warn_pch_different_branch : Error< "PCH file built from a different branch (%0) than the compiler (%1)">; def err_pch_with_compiler_errors : Error< "PCH file contains compiler errors">; -def warn_cmdline_conflicting_macro_def : Error< - "definition of the macro '%0' conflicts with the definition used to " - "build the precompiled header">; -def note_pch_macro_defined_as : Note< - "definition of macro '%0' in the precompiled header">; -def warn_cmdline_missing_macro_defs : Warning< - "macro definitions used to build the precompiled header are missing">; -def note_using_macro_def_from_pch : Note< - "using this macro definition from precompiled header">; -def warn_macro_name_used_in_pch : Error< - "definition of macro %0 conflicts with an identifier used in the " - "precompiled header">; -def warn_pch_compiler_options_mismatch : Error< - "compiler options used when building the precompiled header differ from " - "the options used when using the precompiled header">; + + +def err_pch_macro_def_undef : Error< + "macro '%0' was %select{defined|undef'd}1 in the precompiled header but " + "%select{undef'd|defined}1 on the command line">; +def err_pch_macro_def_conflict : Error< + "definition of macro '%0' differs between the precompiled header ('%1') " + "and the command line ('%2')">; +def err_pch_include_opt_missing : Error< + "precompiled header depends on '%select{-include|-imacros}0 %1' option " + "that is missing from the command line">; +def err_pch_include_opt_conflict : Error< + "precompiled header option '%select{-include|-imacros}0 %1' conflicts with " + "corresponding option '%select{-include|-imacros}0 %2' on command line">; +def err_pch_undef : Error< + "%select{command line contains|precompiled header was built with}0 " + "'-undef' but %select{precompiled header was not built with it|" + "it is not present on the command line}0">; def err_not_a_pch_file : Error< "'%0' does not appear to be a precompiled header file">, DefaultFatal; diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index b00f2b782709..b2f578da7b49 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -103,6 +103,10 @@ public: bool operator<(const FileEntry &RHS) const { return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode); } + + /// \brief Check whether the file is a named pipe (and thus can't be opened by + /// the native FileManager methods). + bool isNamedPipe() const; }; /// \brief Implements support for file system lookup, file system caching, diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index dc6acdaa91ae..76242ec0a56d 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -21,7 +21,6 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include #include @@ -54,6 +53,7 @@ class IdentifierInfo { // are for builtins. unsigned ObjCOrBuiltinID :11; bool HasMacro : 1; // True if there is a #define for this. + bool HadMacro : 1; // True if there was a #define for this. bool IsExtension : 1; // True if identifier is a lang extension. bool IsCXX11CompatKeyword : 1; // True if identifier is a keyword in C++11. bool IsPoisoned : 1; // True if identifier is poisoned. @@ -70,13 +70,13 @@ class IdentifierInfo { // stored externally. bool IsModulesImport : 1; // True if this is the 'import' contextual // keyword. - // 1 bit left in 32-bit word. - + // 32-bit word is filled. + void *FETokenInfo; // Managed by the language front-end. llvm::StringMapEntry *Entry; - IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE. - void operator=(const IdentifierInfo&); // NONASSIGNABLE. + IdentifierInfo(const IdentifierInfo&) LLVM_DELETED_FUNCTION; + void operator=(const IdentifierInfo&) LLVM_DELETED_FUNCTION; friend class IdentifierTable; @@ -133,10 +133,21 @@ public: if (HasMacro == Val) return; HasMacro = Val; - if (Val) + if (Val) { NeedsHandleIdentifier = 1; - else + HadMacro = true; + } else { RecomputeNeedsHandleIdentifier(); + } + } + /// \brief Returns true if this identifier was \#defined to some value at any + /// moment. In this case there should be an entry for the identifier in the + /// macro history table in Preprocessor. + bool hadMacroDefinition() const { + return HadMacro; + } + void setHadMacroDefinition(bool Val) { + HadMacro = Val; } /// getTokenID - If this is a source-language token (e.g. 'for'), this API @@ -346,8 +357,8 @@ public: /// actual functionality. class IdentifierIterator { private: - IdentifierIterator(const IdentifierIterator&); // Do not implement - IdentifierIterator &operator=(const IdentifierIterator&); // Do not implement + IdentifierIterator(const IdentifierIterator &) LLVM_DELETED_FUNCTION; + void operator=(const IdentifierIterator &) LLVM_DELETED_FUNCTION; protected: IdentifierIterator() { } @@ -695,8 +706,8 @@ public: /// multi-keyword caching. class SelectorTable { void *Impl; // Actually a SelectorTableImpl - SelectorTable(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT - void operator=(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT + SelectorTable(const SelectorTable &) LLVM_DELETED_FUNCTION; + void operator=(const SelectorTable &) LLVM_DELETED_FUNCTION; public: SelectorTable(); ~SelectorTable(); diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index fab17a2fe56e..dbc08c7dca1f 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -48,15 +48,19 @@ LANGOPT(MicrosoftMode , 1, 0, "Microsoft compatibility mode") LANGOPT(Borland , 1, 0, "Borland extensions") LANGOPT(CPlusPlus , 1, 0, "C++") LANGOPT(CPlusPlus0x , 1, 0, "C++0x") +LANGOPT(CPlusPlus1y , 1, 0, "C++1y") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, "Objective-C auto-synthesized properties") +BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0, + "Encoding extended block type signature") BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1, "Objective-C related result type inference") LANGOPT(Trigraphs , 1, 0,"trigraphs") -LANGOPT(BCPLComment , 1, 0, "BCPL-style '//' comments") +LANGOPT(LineComment , 1, 0, "'//' comments") LANGOPT(Bool , 1, 0, "bool, true, and false keywords") +LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword") BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers") BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode") BENIGN_LANGOPT(GNUMode , 1, 1, "GNU extensions") @@ -115,7 +119,6 @@ LANGOPT(CUDA , 1, 0, "CUDA") LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators") BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision") -BENIGN_LANGOPT(CatchUndefined , 1, 0, "catching undefined behavior at run time") BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records") BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form") BENIGN_LANGOPT(DumpVTableLayouts , 1, 0, "dumping the layouts of emitted vtables") @@ -125,8 +128,6 @@ BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type") BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and subscripting support") -BENIGN_LANGOPT(AddressSanitizer , 1, 0, "AddressSanitizer enabled") -BENIGN_LANGOPT(ThreadSanitizer , 1, 0, "ThreadSanitizer enabled") BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants") @@ -135,7 +136,7 @@ LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") -LANGOPT(ObjCRuntimeHasWeak , 1, 0, "__weak support in the ARC runtime") +LANGOPT(ObjCARCWeak , 1, 0, "__weak support in the ARC runtime") LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map") LANGOPT(MRTD , 1, 0, "-mrtd calling convention") @@ -162,6 +163,17 @@ VALUE_LANGOPT(MSCVersion, 32, 0, LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling") +BENIGN_LANGOPT(EmitMicrosoftInlineAsm , 1, 0, + "Enable emission of MS-style inline assembly.") + + +BENIGN_LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST") + +/// Runtime sanitizers. +#define SANITIZER(NAME, ID) \ +BENIGN_LANGOPT(Sanitize##ID, 1, 0, NAME " sanitizer") +#include "clang/Basic/Sanitizers.def" + #undef LANGOPT #undef VALUE_LANGOPT #undef BENIGN_LANGOPT diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index c8027f47028f..b6b088c1f701 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -21,6 +21,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SetVector.h" #include #include #include @@ -63,11 +64,21 @@ private: /// \brief A mapping from the submodule name to the index into the /// \c SubModules vector at which that submodule resides. llvm::StringMap SubModuleIndex; + + /// \brief The AST file if this is a top-level module which has a + /// corresponding serialized AST file, or null otherwise. + const FileEntry *ASTFile; public: /// \brief The headers that are part of this module. llvm::SmallVector Headers; + /// \brief The headers that are explicitly excluded from this module. + llvm::SmallVector ExcludedHeaders; + + /// \brief The top-level headers associated with this module. + llvm::SmallSetVector TopHeaders; + /// \brief The set of language features required to use this module. /// /// If any of these features is not present, the \c IsAvailable bit @@ -158,7 +169,7 @@ public: /// \brief Construct a top-level module. explicit Module(StringRef Name, SourceLocation DefinitionLoc, bool IsFramework) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), Umbrella(), + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0),Umbrella(),ASTFile(0), IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(false), IsSystem(false), InferSubmodules(false), InferExplicitSubmodules(false), @@ -227,7 +238,18 @@ public: StringRef getTopLevelModuleName() const { return getTopLevelModule()->Name; } - + + /// \brief The serialized AST file for this module, if one was created. + const FileEntry *getASTFile() const { + return getTopLevelModule()->ASTFile; + } + + /// \brief Set the serialized AST file for the top-level module of this module. + void setASTFile(const FileEntry *File) { + assert((getASTFile() == 0 || getASTFile() == File) && "file path changed"); + getTopLevelModule()->ASTFile = File; + } + /// \brief Retrieve the directory for which this module serves as the /// umbrella. const DirectoryEntry *getUmbrellaDir() const; @@ -271,6 +293,10 @@ public: submodule_iterator submodule_end() { return SubModules.end(); } submodule_const_iterator submodule_end() const { return SubModules.end(); } + static StringRef getModuleInputBufferName() { + return ""; + } + /// \brief Print the module map for this module to the given stream. /// void print(llvm::raw_ostream &OS, unsigned Indent = 0) const; diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index b24fe7cd9159..d543b7671549 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -126,12 +126,25 @@ public: return !isGNUFamily(); } + /// \brief Does this runtime allow ARC at all? + bool allowsARC() const { + switch (getKind()) { + case FragileMacOSX: return false; + case MacOSX: return true; + case iOS: return true; + case GCC: return false; + case GNUstep: return true; + case ObjFW: return true; + } + llvm_unreachable("bad kind"); + } + /// \brief Does this runtime natively provide the ARC entrypoints? /// /// ARC cannot be directly supported on a platform that does not provide /// these entrypoints, although it may be supportable via a stub /// library. - bool hasARC() const { + bool hasNativeARC() const { switch (getKind()) { case FragileMacOSX: return false; case MacOSX: return getVersion() >= VersionTuple(10, 7); @@ -139,16 +152,35 @@ public: case GCC: return false; case GNUstep: return getVersion() >= VersionTuple(1, 6); - case ObjFW: return false; // XXX: this will change soon + case ObjFW: return true; } llvm_unreachable("bad kind"); } + /// \brief Does this runtime supports optimized setter entrypoints? + bool hasOptimizedSetter() const { + switch (getKind()) { + case MacOSX: + return getVersion() >= VersionTuple(10, 8); + case iOS: + return (getVersion() >= VersionTuple(6)); + + default: + return false; + } + } + + /// Does this runtime allow the use of __weak? + bool allowsWeak() const { + return hasNativeWeak(); + } + /// \brief Does this runtime natively provide ARC-compliant 'weak' /// entrypoints? - bool hasWeak() const { - // Right now, this is always equivalent to the ARC decision. - return hasARC(); + bool hasNativeWeak() const { + // Right now, this is always equivalent to whether the runtime + // natively supports ARC decision. + return hasNativeARC(); } /// \brief Does this runtime directly support the subscripting methods? @@ -158,7 +190,7 @@ public: switch (getKind()) { case FragileMacOSX: return false; case MacOSX: return getVersion() >= VersionTuple(10, 8); - case iOS: return false; + case iOS: return getVersion() >= VersionTuple(6); // This is really a lie, because some implementations and versions // of the runtime do not support ARC. Probably -fgnu-runtime @@ -226,6 +258,7 @@ public: } llvm_unreachable("bad kind"); } + /// \brief Does this runtime use zero-cost exceptions? bool hasUnwindExceptions() const { switch (getKind()) { diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 79273fcc798d..cc9ca9f2ec37 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -65,8 +65,7 @@ inline void Emit64(raw_ostream& Out, uint64_t V) { inline void Pad(raw_ostream& Out, unsigned A) { Offset off = (Offset) Out.tell(); - uint32_t n = ((uintptr_t)(off+A-1) & ~(uintptr_t)(A-1)) - off; - for (; n ; --n) + for (uint32_t n = llvm::OffsetToAlignment(off, A); n; --n) Emit8(Out, 0); } @@ -102,7 +101,7 @@ inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) { inline uint32_t ReadLE32(const unsigned char *&Data) { // Hosts that directly support little-endian 32-bit loads can just // use them. Big-endian hosts need a bswap. - uint32_t V = *((uint32_t*)Data); + uint32_t V = *((const uint32_t*)Data); if (llvm::sys::isBigEndianHost()) V = llvm::ByteSwap_32(V); Data += 4; diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def new file mode 100644 index 000000000000..085ca16eae1a --- /dev/null +++ b/include/clang/Basic/Sanitizers.def @@ -0,0 +1,69 @@ +//===--- Sanitizers.def - Runtime sanitizer options -------------*- 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 options for specifying which runtime sanitizers to +// enable. Users of this file must define the SANITIZER macro to make use of +// this information. Users of this file can also define the SANITIZER_GROUP +// macro to get information on options which refer to sets of sanitizers. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER +#error "Define SANITIZER prior to including this file!" +#endif + +// SANITIZER(NAME, ID) + +// The first value is the name of the sanitizer as a string. The sanitizer can +// be enabled by specifying -fsanitize=NAME. + +// The second value is an identifier which can be used to refer to the +// sanitizer. + + +// SANITIZER_GROUP(NAME, ID, ALIAS) + +// The first two values have the same semantics as the corresponding SANITIZER +// values. The third value is an expression ORing together the IDs of individual +// sanitizers in this group. + +#ifndef SANITIZER_GROUP +#define SANITIZER_GROUP(NAME, ID, ALIAS) +#endif + + +// AddressSanitizer +SANITIZER("address", Address) + +// ThreadSanitizer +SANITIZER("thread", Thread) + +// UndefinedBehaviorSanitizer +SANITIZER("signed-integer-overflow", SignedIntegerOverflow) +SANITIZER("divide-by-zero", DivideByZero) +SANITIZER("shift", Shift) +SANITIZER("unreachable", Unreachable) +SANITIZER("return", Return) +SANITIZER("vla-bound", VLABound) +SANITIZER("alignment", Alignment) +SANITIZER("null", Null) +SANITIZER("vptr", Vptr) +SANITIZER("object-size", ObjectSize) +SANITIZER("float-cast-overflow", FloatCastOverflow) + +// -fsanitize=undefined (and its alias -fcatch-undefined-behavior). This should +// include all the sanitizers which have low overhead, no ABI or address space +// layout implications, and only catch undefined behavior. +SANITIZER_GROUP("undefined", Undefined, + SignedIntegerOverflow | DivideByZero | Shift | Unreachable | + Return | VLABound | Alignment | Null | Vptr | ObjectSize | + FloatCastOverflow) + +#undef SANITIZER +#undef SANITIZER_GROUP diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index d6bba385633d..cfcf468772ef 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace llvm { class MemoryBuffer; @@ -171,6 +172,7 @@ public: } void print(raw_ostream &OS, const SourceManager &SM) const; + LLVM_ATTRIBUTE_USED std::string printToString(const SourceManager &SM) const; void dump(const SourceManager &SM) const; }; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 32268d789d14..db6bfd2ad3dd 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -62,7 +62,6 @@ class LangOptions; class ASTWriter; class ASTReader; -/// \namespace /// \brief Public enums and private classes that are part of the /// SourceManager implementation. /// @@ -221,7 +220,7 @@ namespace SrcMgr { private: // Disable assignments. - ContentCache &operator=(const ContentCache& RHS); + ContentCache &operator=(const ContentCache& RHS) LLVM_DELETED_FUNCTION; }; /// \brief Information about a FileID, basically just the logical file @@ -647,8 +646,8 @@ class SourceManager : public RefCountedBase { mutable llvm::DenseMap MacroArgsCacheMap; // SourceManager doesn't support copy construction. - explicit SourceManager(const SourceManager&); - void operator=(const SourceManager&); + explicit SourceManager(const SourceManager&) LLVM_DELETED_FUNCTION; + void operator=(const SourceManager&) LLVM_DELETED_FUNCTION; public: SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile = false); @@ -675,9 +674,10 @@ public: /// /// One example of when this would be used is when the main source is read /// from STDIN. - FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) { + FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer, + SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) { assert(MainFileID.isInvalid() && "MainFileID already set!"); - MainFileID = createFileIDForMemBuffer(Buffer); + MainFileID = createFileIDForMemBuffer(Buffer, Kind); return MainFileID; } @@ -734,10 +734,11 @@ public: /// This does no caching of the buffer and takes ownership of the /// MemoryBuffer, so only pass a MemoryBuffer to this once. FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer, + SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, int LoadedID = 0, unsigned LoadedOffset = 0, SourceLocation IncludeLoc = SourceLocation()) { return createFileID(createMemBufferContentCache(Buffer), IncludeLoc, - SrcMgr::C_User, LoadedID, LoadedOffset); + FileCharacter, LoadedID, LoadedOffset); } /// \brief Return a new SourceLocation that encodes the @@ -1557,7 +1558,11 @@ private: getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, unsigned Offset) const; void computeMacroArgsCache(MacroArgsMap *&MacroArgsCache, FileID FID) const; - + void associateFileChunkWithMacroArgExp(MacroArgsMap &MacroArgsCache, + FileID FID, + SourceLocation SpellLoc, + SourceLocation ExpansionLoc, + unsigned ExpansionLength) const; friend class ASTReader; friend class ASTWriter; }; diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 96cada10571e..c82b8cb91887 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -53,6 +53,7 @@ namespace clang { TST_union, TST_struct, TST_class, // C++ class type + TST_interface, // C++ (Microsoft-specific) __interface type TST_typename, // Typedef, C++ class-name or enum name, etc. TST_typeofType, TST_typeofExpr, @@ -174,6 +175,20 @@ namespace clang { ICIS_CopyInit, ///< Copy initialization. ICIS_ListInit ///< Direct list-initialization. }; + + /// \brief CallingConv - Specifies the calling convention that a function uses. + enum CallingConv { + CC_Default, + CC_C, // __attribute__((cdecl)) + CC_X86StdCall, // __attribute__((stdcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall, // __attribute__((thiscall)) + CC_X86Pascal, // __attribute__((pascal)) + CC_AAPCS, // __attribute__((pcs("aapcs"))) + CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) + CC_PnaclCall // __attribute__((pnaclcall)) + }; + } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 47738af2907f..8f6a1c9f9890 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -28,11 +28,10 @@ def SwitchCase : Stmt<1>; def CaseStmt : DStmt; def DefaultStmt : DStmt; -// GNU Extensions -def AsmStmt : Stmt; - -// MS Extensions -def MSAsmStmt : Stmt; +// Asm statements +def AsmStmt : Stmt<1>; +def GCCAsmStmt : DStmt; +def MSAsmStmt : DStmt; // Obj-C statements def ObjCAtTryStmt : Stmt; @@ -132,6 +131,7 @@ def PackExpansionExpr : DStmt; def SizeOfPackExpr : DStmt; def SubstNonTypeTemplateParmExpr : DStmt; def SubstNonTypeTemplateParmPackExpr : DStmt; +def FunctionParmPackExpr : DStmt; def MaterializeTemporaryExpr : DStmt; def LambdaExpr : DStmt; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 54d49e6fa559..2d26783e3875 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -23,7 +23,9 @@ #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/TargetOptions.h" #include "clang/Basic/VersionTuple.h" +#include "clang/Basic/Specifiers.h" #include #include #include @@ -38,7 +40,6 @@ class LangOptions; class MacroBuilder; class SourceLocation; class SourceManager; -class TargetOptions; namespace Builtin { struct Info; } @@ -61,6 +62,7 @@ enum TargetCXXABI { /// \brief Exposes information about the current target. /// class TargetInfo : public RefCountedBase { + llvm::IntrusiveRefCntPtr TargetOpts; llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default @@ -111,6 +113,16 @@ public: virtual ~TargetInfo(); + /// \brief Retrieve the target options. + TargetOptions &getTargetOpts() const { + assert(TargetOpts && "Missing target options"); + return *TargetOpts; + } + + void setTargetOpts(TargetOptions &TargetOpts) { + this->TargetOpts = &TargetOpts; + } + ///===---- Target Data Type Query Methods -------------------------------===// enum IntType { NoInt = 0, @@ -150,12 +162,18 @@ public: /// __builtin_va_list as defined by the x86-64 ABI: /// http://www.x86-64.org/documentation/abi.pdf - X86_64ABIBuiltinVaList + X86_64ABIBuiltinVaList, + + /// __builtin_va_list as defined by ARM AAPCS ABI + /// http://infocenter.arm.com + // /help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf + AAPCSABIBuiltinVaList }; protected: IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, - WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType; + WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType, + ProcessIDType; /// \brief Whether Objective-C's built-in boolean type should be signed char. /// @@ -196,7 +214,7 @@ public: IntType getChar32Type() const { return Char32Type; } IntType getInt64Type() const { return Int64Type; } IntType getSigAtomicType() const { return SigAtomicType; } - + IntType getProcessIDType() const { return ProcessIDType; } /// \brief Return the width (in bits) of the specified integer type enum. /// @@ -500,6 +518,11 @@ public: bool validateInputConstraint(ConstraintInfo *OutputConstraints, unsigned NumOutputs, ConstraintInfo &info) const; + virtual bool validateConstraintModifier(StringRef /*Constraint*/, + const char /*Modifier*/, + unsigned /*Size*/) const { + return true; + } bool resolveSymbolicName(const char *&Name, ConstraintInfo *OutputConstraints, unsigned NumOutputs, unsigned &Index) const; @@ -712,6 +735,34 @@ public: bool isBigEndian() const { return BigEndian; } + /// \brief Gets the default calling convention for the given target and + /// declaration context. + virtual CallingConv getDefaultCallingConv() const { + // Not all targets will specify an explicit calling convention that we can + // express. This will always do the right thing, even though it's not + // an explicit calling convention. + return CC_Default; + } + + enum CallingConvCheckResult { + CCCR_OK, + CCCR_Warning + }; + + /// \brief Determines whether a given calling convention is valid for the + /// target. A calling convention can either be accepted, produce a warning + /// and be substituted with the default calling convention, or (someday) + /// produce an error (such as using thiscall on a non-instance function). + virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_Default: + return CCCR_OK; + } + } + protected: virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return PointerWidth; diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 15ececd1df5d..d6deb0244d9f 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -15,13 +15,14 @@ #ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H #define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include #include namespace clang { /// \brief Options for controlling the target. -class TargetOptions { +class TargetOptions : public RefCountedBase { public: /// If given, the name of the target triple to compile for. If not given the /// target will be selected to match the host. @@ -40,6 +41,9 @@ public: /// If given, the version string of the linker in use. std::string LinkerVersion; + /// \brief The list of target specific features to enable or disable, as written on the command line. + std::vector FeaturesAsWritten; + /// The list of target specific features to enable or disable -- this should /// be a list of strings starting with by '+' or '-'. std::vector Features; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index fc031914a8d0..25e8d5a635c7 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -217,6 +217,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // KEYALTIVEC - This is a keyword in AltiVec // KEYBORLAND - This is a keyword if Borland extensions are enabled // BOOLSUPPORT - This is a keyword if 'bool' is a built-in type +// WCHARSUPPORT - This is a keyword if 'wchar_t' is a built-in type // KEYWORD(auto , KEYALL) KEYWORD(break , KEYALL) @@ -295,7 +296,7 @@ KEYWORD(typename , KEYCXX) KEYWORD(typeid , KEYCXX) KEYWORD(using , KEYCXX) KEYWORD(virtual , KEYCXX) -KEYWORD(wchar_t , KEYCXX) +KEYWORD(wchar_t , WCHARSUPPORT) // C++ 2.5p2: Alternative Representations. CXX_KEYWORD_OPERATOR(and , ampamp) @@ -364,6 +365,7 @@ KEYWORD(__is_convertible_to , KEYCXX) KEYWORD(__is_empty , KEYCXX) KEYWORD(__is_enum , KEYCXX) KEYWORD(__is_final , KEYCXX) +KEYWORD(__is_interface_class , KEYCXX) // Tentative name - there's no implementation of std::is_literal_type yet. KEYWORD(__is_literal , KEYCXX) // Name for GCC 4.6 compatibility - people have already written libraries using @@ -505,6 +507,7 @@ KEYWORD(__if_not_exists , KEYMS) KEYWORD(__single_inheritance , KEYMS) KEYWORD(__multiple_inheritance , KEYMS) KEYWORD(__virtual_inheritance , KEYMS) +KEYWORD(__interface , KEYMS) ALIAS("__int8" , char , KEYMS) ALIAS("__int16" , short , KEYMS) ALIAS("__int32" , int , KEYMS) @@ -518,7 +521,6 @@ ALIAS("_thiscall" , __thiscall , KEYMS) ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) ALIAS("_inline" , inline , KEYMS) ALIAS("_declspec" , __declspec , KEYMS) -ALIAS("__interface" , struct , KEYMS) // Borland Extensions which should be disabled in strict conformance mode. ALIAS("_pascal" , __pascal , KEYBORLAND) @@ -600,6 +602,41 @@ ANNOTATION(pragma_pack) // handles them. ANNOTATION(pragma_parser_crash) +// Annotation for #pragma ms_struct... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_msstruct) + +// Annotation for #pragma align... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_align) + +// Annotation for #pragma weak id +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_weak) + +// Annotation for #pragma weak id = id +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_weakalias) + +// Annotation for #pragma redefine_extname... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_redefine_extname) + +// Annotation for #pragma STDC FP_CONTRACT... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_fp_contract) + +// Annotation for #pragma OPENCL EXTENSION... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_opencl_extension) + #undef ANNOTATION #undef TESTING_KEYWORD #undef OBJC2_AT_KEYWORD diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h index 478add8db5db..e850971e34fa 100644 --- a/include/clang/Basic/TokenKinds.h +++ b/include/clang/Basic/TokenKinds.h @@ -63,6 +63,31 @@ const char *getTokenName(enum TokenKind Kind); /// Preprocessor::getSpelling(). const char *getTokenSimpleSpelling(enum TokenKind Kind); +/// \brief Return true if this is a raw identifier or an identifier kind. +inline bool isAnyIdentifier(TokenKind K) { + return (K == tok::identifier) || (K == tok::raw_identifier); +} + +/// \brief Return true if this is a "literal" kind, like a numeric +/// constant, string, etc. +inline bool isLiteral(TokenKind K) { + return (K == tok::numeric_constant) || (K == tok::char_constant) || + (K == tok::wide_char_constant) || (K == tok::utf16_char_constant) || + (K == tok::utf32_char_constant) || (K == tok::string_literal) || + (K == tok::wide_string_literal) || (K == tok::utf8_string_literal) || + (K == tok::utf16_string_literal) || (K == tok::utf32_string_literal) || + (K == tok::angle_string_literal); +} + +/// \brief Return true if this is any of tok::annot_* kinds. +inline bool isAnnotation(TokenKind K) { +#define ANNOTATION(NAME) \ + if (K == tok::annot_##NAME) \ + return true; +#include "clang/Basic/TokenKinds.def" + return false; +} + } // end namespace tok } // end namespace clang diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 0a5a8643a36e..882b52d489ec 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -41,6 +41,7 @@ namespace clang { UTT_IsFunction, UTT_IsFundamental, UTT_IsIntegral, + UTT_IsInterfaceClass, UTT_IsLiteral, UTT_IsLvalueReference, UTT_IsMemberFunctionPointer, diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 451d56292363..3373e017decb 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -379,8 +379,8 @@ def VORR : Inst<"vorr", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_OR>; def VEOR : Inst<"veor", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_XOR>; def VBIC : Inst<"vbic", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ANDN>; def VORN : Inst<"vorn", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ORN>; -def VBSL : Inst<"vbsl", "dudd", - "csilUcUsUiUlfPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPs", OP_SEL>; +def VBSL : SInst<"vbsl", "dudd", + "csilUcUsUiUlfPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPs">; //////////////////////////////////////////////////////////////////////////////// // E.3.30 Transposition operations @@ -394,3 +394,7 @@ def VREINTERPRET : Inst<"vreinterpret", "dd", "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT>; +//////////////////////////////////////////////////////////////////////////////// +// Vector fused multiply-add operations + +def VFMA : SInst<"vfma", "dddd", "fQf">; diff --git a/include/clang/CodeGen/CodeGenAction.h b/include/clang/CodeGen/CodeGenAction.h index 7fa589feebf8..912ef01a018c 100644 --- a/include/clang/CodeGen/CodeGenAction.h +++ b/include/clang/CodeGen/CodeGenAction.h @@ -30,7 +30,7 @@ private: bool OwnsVMContext; protected: - /// Create a new code generation action. If the optional \arg _VMContext + /// Create a new code generation action. If the optional \p _VMContext /// parameter is supplied, the action uses it without taking ownership, /// otherwise it creates a fresh LLVM context and takes ownership. CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext = 0); diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index 6e317a0726b5..4057e48f69a4 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -90,8 +90,6 @@ public: iterator end() { return Inputs.end(); } const_iterator begin() const { return Inputs.begin(); } const_iterator end() const { return Inputs.end(); } - - static bool classof(const Action *) { return true; } }; class InputAction : public Action { @@ -105,7 +103,6 @@ public: static bool classof(const Action *A) { return A->getKind() == InputClass; } - static bool classof(const InputAction *) { return true; } }; class BindArchAction : public Action { @@ -122,7 +119,6 @@ public: static bool classof(const Action *A) { return A->getKind() == BindArchClass; } - static bool classof(const BindArchAction *) { return true; } }; class JobAction : public Action { @@ -136,7 +132,6 @@ public: return (A->getKind() >= JobClassFirst && A->getKind() <= JobClassLast); } - static bool classof(const JobAction *) { return true; } }; class PreprocessJobAction : public JobAction { @@ -147,7 +142,6 @@ public: static bool classof(const Action *A) { return A->getKind() == PreprocessJobClass; } - static bool classof(const PreprocessJobAction *) { return true; } }; class PrecompileJobAction : public JobAction { @@ -158,7 +152,6 @@ public: static bool classof(const Action *A) { return A->getKind() == PrecompileJobClass; } - static bool classof(const PrecompileJobAction *) { return true; } }; class AnalyzeJobAction : public JobAction { @@ -169,7 +162,6 @@ public: static bool classof(const Action *A) { return A->getKind() == AnalyzeJobClass; } - static bool classof(const AnalyzeJobAction *) { return true; } }; class MigrateJobAction : public JobAction { @@ -180,7 +172,6 @@ public: static bool classof(const Action *A) { return A->getKind() == MigrateJobClass; } - static bool classof(const MigrateJobAction *) { return true; } }; class CompileJobAction : public JobAction { @@ -191,7 +182,6 @@ public: static bool classof(const Action *A) { return A->getKind() == CompileJobClass; } - static bool classof(const CompileJobAction *) { return true; } }; class AssembleJobAction : public JobAction { @@ -202,7 +192,6 @@ public: static bool classof(const Action *A) { return A->getKind() == AssembleJobClass; } - static bool classof(const AssembleJobAction *) { return true; } }; class LinkJobAction : public JobAction { @@ -213,7 +202,6 @@ public: static bool classof(const Action *A) { return A->getKind() == LinkJobClass; } - static bool classof(const LinkJobAction *) { return true; } }; class LipoJobAction : public JobAction { @@ -224,7 +212,6 @@ public: static bool classof(const Action *A) { return A->getKind() == LipoJobClass; } - static bool classof(const LipoJobAction *) { return true; } }; class DsymutilJobAction : public JobAction { @@ -235,7 +222,6 @@ public: static bool classof(const Action *A) { return A->getKind() == DsymutilJobClass; } - static bool classof(const DsymutilJobAction *) { return true; } }; class VerifyJobAction : public JobAction { @@ -245,7 +231,6 @@ public: static bool classof(const Action *A) { return A->getKind() == VerifyJobClass; } - static bool classof(const VerifyJobAction *) { return true; } }; } // end namespace driver diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h index e466cc323173..3b3829a634a0 100644 --- a/include/clang/Driver/Arg.h +++ b/include/clang/Driver/Arg.h @@ -15,6 +15,8 @@ #ifndef CLANG_DRIVER_ARG_H_ #define CLANG_DRIVER_ARG_H_ +#include "clang/Driver/Option.h" + #include "Util.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -23,7 +25,6 @@ namespace clang { namespace driver { class ArgList; - class Option; /// \brief A concrete instance of a particular driver option. /// @@ -33,17 +34,20 @@ namespace driver { /// ArgList to provide efficient iteration over all instances of a /// particular option. class Arg { - Arg(const Arg &); // DO NOT IMPLEMENT - void operator=(const Arg &); // DO NOT IMPLEMENT + Arg(const Arg &) LLVM_DELETED_FUNCTION; + void operator=(const Arg &) LLVM_DELETED_FUNCTION; private: /// \brief The option this argument is an instance of. - const Option *Opt; + const Option Opt; /// \brief The argument this argument was derived from (during tool chain /// argument translation), if any. const Arg *BaseArg; + /// \brief How this instance of the option was spelled. + StringRef Spelling; + /// \brief The index at which this argument appears in the containing /// ArgList. unsigned Index; @@ -60,14 +64,16 @@ namespace driver { SmallVector Values; public: - Arg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); - Arg(const Option *Opt, unsigned Index, + Arg(const Option Opt, StringRef Spelling, unsigned Index, + const Arg *BaseArg = 0); + Arg(const Option Opt, StringRef Spelling, unsigned Index, const char *Value0, const Arg *BaseArg = 0); - Arg(const Option *Opt, unsigned Index, + Arg(const Option Opt, StringRef Spelling, unsigned Index, const char *Value0, const char *Value1, const Arg *BaseArg = 0); ~Arg(); - const Option &getOption() const { return *Opt; } + const Option getOption() const { return Opt; } + StringRef getSpelling() const { return Spelling; } unsigned getIndex() const { return Index; } /// \brief Return the base argument which generated this arg. @@ -90,7 +96,7 @@ namespace driver { void claim() const { getBaseArg().Claimed = true; } unsigned getNumValues() const { return Values.size(); } - const char *getValue(const ArgList &Args, unsigned N=0) const { + const char *getValue(unsigned N = 0) const { return Values[N]; } @@ -115,8 +121,6 @@ namespace driver { /// when rendered as a input (e.g., Xlinker). void renderAsInput(const ArgList &Args, ArgStringList &Output) const; - static bool classof(const Arg *) { return true; } - void dump() const; /// \brief Return a formatted version of the argument and diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index b7e490ccf7ca..72ed7bf58604 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -11,6 +11,7 @@ #define CLANG_DRIVER_ARGLIST_H_ #include "clang/Basic/LLVM.h" +#include "clang/Driver/Option.h" #include "clang/Driver/OptSpecifier.h" #include "clang/Driver/Util.h" #include "llvm/ADT/SmallVector.h" @@ -94,8 +95,8 @@ namespace driver { /// and to iterate over groups of arguments. class ArgList { private: - ArgList(const ArgList &); // DO NOT IMPLEMENT - void operator=(const ArgList &); // DO NOT IMPLEMENT + ArgList(const ArgList &) LLVM_DELETED_FUNCTION; + void operator=(const ArgList &) LLVM_DELETED_FUNCTION; public: typedef SmallVector arglist_type; @@ -117,7 +118,7 @@ namespace driver { /// @name Arg Access /// @{ - /// append - Append \arg A to the arg list. + /// append - Append \p A to the arg list. void append(Arg *A); arglist_type &getArgs() { return Args; } @@ -153,16 +154,16 @@ namespace driver { /// @name Arg Removal /// @{ - /// eraseArg - Remove any option matching \arg Id. + /// eraseArg - Remove any option matching \p Id. void eraseArg(OptSpecifier Id); /// @} /// @name Arg Access /// @{ - /// hasArg - Does the arg list contain any option matching \arg Id. + /// hasArg - Does the arg list contain any option matching \p Id. /// - /// \arg Claim Whether the argument should be claimed, if it exists. + /// \p Claim Whether the argument should be claimed, if it exists. bool hasArgNoClaim(OptSpecifier Id) const { return getLastArgNoClaim(Id) != 0; } @@ -176,9 +177,9 @@ namespace driver { return getLastArg(Id0, Id1, Id2) != 0; } - /// getLastArg - Return the last argument matching \arg Id, or null. + /// getLastArg - Return the last argument matching \p Id, or null. /// - /// \arg Claim Whether the argument should be claimed, if it exists. + /// \p Claim Whether the argument should be claimed, if it exists. Arg *getLastArgNoClaim(OptSpecifier Id) const; Arg *getLastArg(OptSpecifier Id) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; @@ -196,7 +197,7 @@ namespace driver { OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5, OptSpecifier Id6, OptSpecifier Id7) const; - /// getArgString - Return the input argument string at \arg Index. + /// getArgString - Return the input argument string at \p Index. virtual const char *getArgString(unsigned Index) const = 0; /// getNumInputArgStrings - Return the number of original argument strings, @@ -233,15 +234,13 @@ namespace driver { /// @name Translation Utilities /// @{ - /// hasFlag - Given an option \arg Pos and its negative form \arg - /// Neg, return true if the option is present, false if the - /// negation is present, and \arg Default if neither option is - /// given. If both the option and its negation are present, the - /// last one wins. + /// hasFlag - Given an option \p Pos and its negative form \p Neg, return + /// true if the option is present, false if the negation is present, and + /// \p Default if neither option is given. If both the option and its + /// negation are present, the last one wins. bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; - /// AddLastArg - Render only the last argument match \arg Id0, if - /// present. + /// AddLastArg - Render only the last argument match \p Id0, if present. void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; /// AddAllArgs - Render all arguments matching the given ids. @@ -286,8 +285,8 @@ namespace driver { } const char *MakeArgString(const Twine &Str) const; - /// \brief Create an arg string for (\arg LHS + \arg RHS), reusing the - /// string at \arg Index if possible. + /// \brief Create an arg string for (\p LHS + \p RHS), reusing the + /// string at \p Index if possible. const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS, StringRef RHS) const; @@ -347,7 +346,7 @@ namespace driver { mutable arglist_type SynthesizedArgs; public: - /// Construct a new derived arg list from \arg BaseArgs. + /// Construct a new derived arg list from \p BaseArgs. DerivedArgList(const InputArgList &BaseArgs); ~DerivedArgList(); @@ -374,55 +373,54 @@ namespace driver { virtual const char *MakeArgString(StringRef Str) const; - /// AddFlagArg - Construct a new FlagArg for the given option \arg Id and + /// AddFlagArg - Construct a new FlagArg for the given option \p Id and /// append it to the argument list. - void AddFlagArg(const Arg *BaseArg, const Option *Opt) { + void AddFlagArg(const Arg *BaseArg, const Option Opt) { append(MakeFlagArg(BaseArg, Opt)); } /// AddPositionalArg - Construct a new Positional arg for the given option - /// \arg Id, with the provided \arg Value and append it to the argument + /// \p Id, with the provided \p Value and append it to the argument /// list. - void AddPositionalArg(const Arg *BaseArg, const Option *Opt, + void AddPositionalArg(const Arg *BaseArg, const Option Opt, StringRef Value) { append(MakePositionalArg(BaseArg, Opt, Value)); } /// AddSeparateArg - Construct a new Positional arg for the given option - /// \arg Id, with the provided \arg Value and append it to the argument + /// \p Id, with the provided \p Value and append it to the argument /// list. - void AddSeparateArg(const Arg *BaseArg, const Option *Opt, + void AddSeparateArg(const Arg *BaseArg, const Option Opt, StringRef Value) { append(MakeSeparateArg(BaseArg, Opt, Value)); } - /// AddJoinedArg - Construct a new Positional arg for the given option \arg - /// Id, with the provided \arg Value and append it to the argument list. - void AddJoinedArg(const Arg *BaseArg, const Option *Opt, + /// AddJoinedArg - Construct a new Positional arg for the given option + /// \p Id, with the provided \p Value and append it to the argument list. + void AddJoinedArg(const Arg *BaseArg, const Option Opt, StringRef Value) { append(MakeJoinedArg(BaseArg, Opt, Value)); } - /// MakeFlagArg - Construct a new FlagArg for the given option - /// \arg Id. - Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const; + /// MakeFlagArg - Construct a new FlagArg for the given option \p Id. + Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const; /// MakePositionalArg - Construct a new Positional arg for the - /// given option \arg Id, with the provided \arg Value. - Arg *MakePositionalArg(const Arg *BaseArg, const Option *Opt, + /// given option \p Id, with the provided \p Value. + Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt, StringRef Value) const; /// MakeSeparateArg - Construct a new Positional arg for the - /// given option \arg Id, with the provided \arg Value. - Arg *MakeSeparateArg(const Arg *BaseArg, const Option *Opt, + /// given option \p Id, with the provided \p Value. + Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt, StringRef Value) const; /// MakeJoinedArg - Construct a new Positional arg for the - /// given option \arg Id, with the provided \arg Value. - Arg *MakeJoinedArg(const Arg *BaseArg, const Option *Opt, + /// given option \p Id, with the provided \p Value. + Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt, StringRef Value) const; /// @} diff --git a/include/clang/Driver/CC1AsOptions.h b/include/clang/Driver/CC1AsOptions.h index 05082132cee4..420a10138cba 100644 --- a/include/clang/Driver/CC1AsOptions.h +++ b/include/clang/Driver/CC1AsOptions.h @@ -17,11 +17,13 @@ namespace driver { namespace cc1asoptions { enum ID { OPT_INVALID = 0, // This is not an option ID. -#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ +#define PREFIX(NAME, VALUE) +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) OPT_##ID, #include "clang/Driver/CC1AsOptions.inc" LastOption #undef OPTION +#undef PREFIX }; } diff --git a/include/clang/Driver/CC1AsOptions.td b/include/clang/Driver/CC1AsOptions.td index 37ba6027e207..9fd855a9ce9f 100644 --- a/include/clang/Driver/CC1AsOptions.td +++ b/include/clang/Driver/CC1AsOptions.td @@ -18,22 +18,22 @@ include "OptParser.td" // Target Options //===----------------------------------------------------------------------===// -def triple : Separate<"-triple">, +def triple : Separate<["-"], "triple">, HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">; -def target_cpu : Separate<"-target-cpu">, +def target_cpu : Separate<["-"], "target-cpu">, HelpText<"Target a specific cpu type">; -def target_feature : Separate<"-target-feature">, +def target_feature : Separate<["-"], "target-feature">, HelpText<"Target specific attributes">; //===----------------------------------------------------------------------===// // Language Options //===----------------------------------------------------------------------===// -def I : JoinedOrSeparate<"-I">, MetaVarName<"">, +def I : JoinedOrSeparate<["-"], "I">, MetaVarName<"">, HelpText<"Add directory to include search path">; -def n : Flag<"-n">, +def n : Flag<["-"], "n">, HelpText<"Don't automatically start assembly file with a text section">; -def L : Flag<"-L">, +def L : Flag<["-"], "L">, HelpText<"Save temporary labels in the symbol table. " "Note this may change .s semantics, it should almost never be used " "on compiler generated code!">; @@ -42,50 +42,49 @@ def L : Flag<"-L">, // Frontend Options //===----------------------------------------------------------------------===// -def o : Separate<"-o">, MetaVarName<"">, HelpText<"Specify output file">; +def o : Separate<["-"], "o">, MetaVarName<"">, + HelpText<"Specify output file">; -def filetype : Separate<"-filetype">, +def filetype : Separate<["-"], "filetype">, HelpText<"Specify the output file type ('asm', 'null', or 'obj')">; -def help : Flag<"-help">, +def help : Flag<["-", "--"], "help">, HelpText<"Print this help text">; -def _help : Flag<"--help">, Alias; -def version : Flag<"-version">, +def version : Flag<["-", "--"], "version">, HelpText<"Print the assembler version">; -def _version : Flag<"--version">, Alias; -def v : Flag<"-v">, Alias; +def v : Flag<["-"], "v">, Alias; // Generic forwarding to LLVM options. This should only be used for debugging // and experimental features. -def mllvm : Separate<"-mllvm">, +def mllvm : Separate<["-"], "mllvm">, HelpText<"Additional arguments to forward to LLVM's option processing">; //===----------------------------------------------------------------------===// // Transliterate Options //===----------------------------------------------------------------------===// -def output_asm_variant : Separate<"-output-asm-variant">, +def output_asm_variant : Separate<["-"], "output-asm-variant">, HelpText<"Select the asm variant index to use for output">; -def show_encoding : Flag<"-show-encoding">, +def show_encoding : Flag<["-"], "show-encoding">, HelpText<"Show instruction encoding information in transliterate mode">; -def show_inst : Flag<"-show-inst">, +def show_inst : Flag<["-"], "show-inst">, HelpText<"Show internal instruction representation in transliterate mode">; //===----------------------------------------------------------------------===// // Assemble Options //===----------------------------------------------------------------------===// -def relax_all : Flag<"-relax-all">, +def relax_all : Flag<["-"], "relax-all">, HelpText<"Relax all fixups (for performance testing)">; -def no_exec_stack : Flag<"--noexecstack">, +def no_exec_stack : Flag<["--"], "noexecstack">, HelpText<"Mark the file as not needing an executable stack">; -def fatal_warnings : Flag<"--fatal-warnings">, +def fatal_warnings : Flag<["--"], "fatal-warnings">, HelpText<"Consider warnings as errors">; -def g : Flag<"-g">, HelpText<"Generate source level debug information">; +def g : Flag<["-"], "g">, HelpText<"Generate source level debug information">; -def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, +def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 6e4d7f2d31d5..3ff25494ff53 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -11,235 +11,238 @@ // //===----------------------------------------------------------------------===// -let Flags = [CC1Option] in { +let Flags = [CC1Option, NoDriverOption] in { //===----------------------------------------------------------------------===// // Target Options //===----------------------------------------------------------------------===// -def cxx_abi : Separate<"-cxx-abi">, +def cxx_abi : Separate<["-"], "cxx-abi">, HelpText<"Target a particular C++ ABI type">; -def target_abi : Separate<"-target-abi">, +def target_abi : Separate<["-"], "target-abi">, HelpText<"Target a particular ABI type">; -def target_cpu : Separate<"-target-cpu">, +def target_cpu : Separate<["-"], "target-cpu">, HelpText<"Target a specific cpu type">; -def target_feature : Separate<"-target-feature">, +def target_feature : Separate<["-"], "target-feature">, HelpText<"Target specific attributes">; -def target_linker_version : Separate<"-target-linker-version">, +def target_linker_version : Separate<["-"], "target-linker-version">, HelpText<"Target linker version">; -def triple : Separate<"-triple">, +def triple : Separate<["-"], "triple">, HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; -def triple_EQ : Joined<"-triple=">, Alias; +def triple_EQ : Joined<["-"], "triple=">, Alias; //===----------------------------------------------------------------------===// // Analyzer Options //===----------------------------------------------------------------------===// -def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">, +def analysis_UnoptimizedCFG : Flag<["-"], "unoptimized-cfg">, HelpText<"Generate unoptimized CFGs for all analyses">; -def analysis_CFGAddImplicitDtors : Flag<"-cfg-add-implicit-dtors">, +def analysis_CFGAddImplicitDtors : Flag<["-"], "cfg-add-implicit-dtors">, HelpText<"Add C++ implicit destructors to CFGs for all analyses">; -def analyzer_store : Separate<"-analyzer-store">, +def analyzer_store : Separate<["-"], "analyzer-store">, HelpText<"Source Code Analysis - Abstract Memory Store Models">; -def analyzer_store_EQ : Joined<"-analyzer-store=">, Alias; +def analyzer_store_EQ : Joined<["-"], "analyzer-store=">, Alias; -def analyzer_constraints : Separate<"-analyzer-constraints">, +def analyzer_constraints : Separate<["-"], "analyzer-constraints">, HelpText<"Source Code Analysis - Symbolic Constraint Engines">; -def analyzer_constraints_EQ : Joined<"-analyzer-constraints=">, +def analyzer_constraints_EQ : Joined<["-"], "analyzer-constraints=">, Alias; -def analyzer_output : Separate<"-analyzer-output">, +def analyzer_output : Separate<["-"], "analyzer-output">, HelpText<"Source Code Analysis - Output Options">; -def analyzer_output_EQ : Joined<"-analyzer-output=">, +def analyzer_output_EQ : Joined<["-"], "analyzer-output=">, Alias; -def analyzer_purge : Separate<"-analyzer-purge">, +def analyzer_purge : Separate<["-"], "analyzer-purge">, HelpText<"Source Code Analysis - Dead Symbol Removal Frequency">; -def analyzer_purge_EQ : Joined<"-analyzer-purge=">, Alias; +def analyzer_purge_EQ : Joined<["-"], "analyzer-purge=">, Alias; -def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">, +def analyzer_opt_analyze_headers : Flag<["-"], "analyzer-opt-analyze-headers">, HelpText<"Force the static analyzer to analyze functions defined in header files">; -def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">, +def analyzer_opt_analyze_nested_blocks : Flag<["-"], "analyzer-opt-analyze-nested-blocks">, HelpText<"Analyze the definitions of blocks in addition to functions">; -def analyzer_display_progress : Flag<"-analyzer-display-progress">, +def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; -def analyze_function : Separate<"-analyze-function">, +def analyze_function : Separate<["-"], "analyze-function">, HelpText<"Run analysis on specific function">; -def analyze_function_EQ : Joined<"-analyze-function=">, Alias; -def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">, +def analyze_function_EQ : Joined<["-"], "analyze-function=">, Alias; +def analyzer_eagerly_assume : Flag<["-"], "analyzer-eagerly-assume">, HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">; -def analyzer_no_eagerly_trim_egraph : Flag<"-analyzer-no-eagerly-trim-egraph">, - HelpText<"Don't eagerly remove uninteresting ExplodedNodes from the ExplodedGraph">; -def trim_egraph : Flag<"-trim-egraph">, +def trim_egraph : Flag<["-"], "trim-egraph">, HelpText<"Only show error-related paths in the analysis graph">; -def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">, +def analyzer_viz_egraph_graphviz : Flag<["-"], "analyzer-viz-egraph-graphviz">, HelpText<"Display exploded graph using GraphViz">; -def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">, +def analyzer_viz_egraph_ubigraph : Flag<["-"], "analyzer-viz-egraph-ubigraph">, HelpText<"Display exploded graph using Ubigraph">; -def analyzer_inline_max_stack_depth : Separate<"-analyzer-inline-max-stack-depth">, +def analyzer_inline_max_stack_depth : Separate<["-"], "analyzer-inline-max-stack-depth">, HelpText<"Bound on stack depth while inlining (4 by default)">; -def analyzer_inline_max_stack_depth_EQ : Joined<"-analyzer-inline-max-stack-depth=">, +def analyzer_inline_max_stack_depth_EQ : Joined<["-"], "analyzer-inline-max-stack-depth=">, Alias; -def analyzer_inline_max_function_size : Separate<"-analyzer-inline-max-function-size">, +def analyzer_inline_max_function_size : Separate<["-"], "analyzer-inline-max-function-size">, HelpText<"Bound on the number of basic blocks in an inlined function (200 by default)">; -def analyzer_inline_max_function_size_EQ : Joined<"-analyzer-inline-max-function-size=">, +def analyzer_inline_max_function_size_EQ : Joined<["-"], "analyzer-inline-max-function-size=">, Alias; -def analyzer_ipa : Separate<"-analyzer-ipa">, +def analyzer_ipa : Separate<["-"], "analyzer-ipa">, HelpText<"Specify the inter-procedural analysis mode">; -def analyzer_ipa_EQ : Joined<"-analyzer-ipa=">, Alias; +def analyzer_ipa_EQ : Joined<["-"], "analyzer-ipa=">, Alias; -def analyzer_inlining_mode : Separate<"-analyzer-inlining-mode">, +def analyzer_inlining_mode : Separate<["-"], "analyzer-inlining-mode">, HelpText<"Specify the function selection heuristic used during inlining">; -def analyzer_inlining_mode_EQ : Joined<"-analyzer-inlining-mode=">, Alias; +def analyzer_inlining_mode_EQ : Joined<["-"], "analyzer-inlining-mode=">, Alias; -def analyzer_disable_retry_exhausted : Flag<"-analyzer-disable-retry-exhausted">, +def analyzer_disable_retry_exhausted : Flag<["-"], "analyzer-disable-retry-exhausted">, HelpText<"Do not re-analyze paths leading to exhausted nodes with a different strategy (may decrease code coverage)">; -def analyzer_max_nodes : Separate<"-analyzer-max-nodes">, +def analyzer_max_nodes : Separate<["-"], "analyzer-max-nodes">, HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">; -def analyzer_max_loop : Separate<"-analyzer-max-loop">, +def analyzer_max_loop : Separate<["-"], "analyzer-max-loop">, HelpText<"The maximum number of times the analyzer will go through a loop">; -def analyzer_stats : Flag<"-analyzer-stats">, +def analyzer_stats : Flag<["-"], "analyzer-stats">, HelpText<"Print internal analyzer statistics.">; -def analyzer_checker : Separate<"-analyzer-checker">, +def analyzer_checker : Separate<["-"], "analyzer-checker">, HelpText<"Choose analyzer checkers to enable">; -def analyzer_checker_EQ : Joined<"-analyzer-checker=">, +def analyzer_checker_EQ : Joined<["-"], "analyzer-checker=">, Alias; -def analyzer_disable_checker : Separate<"-analyzer-disable-checker">, +def analyzer_disable_checker : Separate<["-"], "analyzer-disable-checker">, HelpText<"Choose analyzer checkers to disable">; -def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">, +def analyzer_disable_checker_EQ : Joined<["-"], "analyzer-disable-checker=">, Alias; -def analyzer_checker_help : Flag<"-analyzer-checker-help">, +def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; +def analyzer_config : Separate<["-"], "analyzer-config">, + HelpText<"Choose analyzer options to enable">; + //===----------------------------------------------------------------------===// // Migrator Options //===----------------------------------------------------------------------===// -def migrator_no_nsalloc_error : Flag<"-no-ns-alloc-error">, +def migrator_no_nsalloc_error : Flag<["-"], "no-ns-alloc-error">, HelpText<"Do not error on use of NSAllocateCollectable/NSReallocateCollectable">; -def migrator_no_finalize_removal : Flag<"-no-finalize-removal">, +def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">, HelpText<"Do not remove finalize method in gc mode">; //===----------------------------------------------------------------------===// // CodeGen Options //===----------------------------------------------------------------------===// -def disable_llvm_optzns : Flag<"-disable-llvm-optzns">, +def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">, HelpText<"Don't run LLVM optimization passes">; -def disable_llvm_verifier : Flag<"-disable-llvm-verifier">, +def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">, HelpText<"Don't run the LLVM IR verifier pass">; -def disable_red_zone : Flag<"-disable-red-zone">, +def disable_red_zone : Flag<["-"], "disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; -def fdebug_compilation_dir : Separate<"-fdebug-compilation-dir">, +def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">, HelpText<"The compilation directory to embed in the debug info.">; -def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, +def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; -def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, +def dwarf_column_info : Flag<["-"], "dwarf-column-info">, + HelpText<"Turn on column location information.">; +def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; -def no_implicit_float : Flag<"-no-implicit-float">, +def no_implicit_float : Flag<["-"], "no-implicit-float">, HelpText<"Don't generate implicit floating point instructions">; -def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, +def fdump_vtable_layouts : Flag<["-"], "fdump-vtable-layouts">, HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; -def femit_coverage_notes : Flag<"-femit-coverage-notes">, +def femit_coverage_notes : Flag<["-"], "femit-coverage-notes">, HelpText<"Emit a gcov coverage notes file when compiling.">; -def femit_coverage_data: Flag<"-femit-coverage-data">, +def femit_coverage_data: Flag<["-"], "femit-coverage-data">, HelpText<"Instrument the program to emit gcov coverage data when run.">; -def coverage_file : Separate<"-coverage-file">, +def coverage_file : Separate<["-"], "coverage-file">, HelpText<"Emit coverage data to this filename. The extension will be replaced.">; -def coverage_file_EQ : Joined<"-coverage-file=">, Alias; -def fuse_register_sized_bitfield_access: Flag<"-fuse-register-sized-bitfield-access">, +def coverage_file_EQ : Joined<["-"], "coverage-file=">, Alias; +def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfield-access">, HelpText<"Use register sized accesses to bit-fields, when possible.">; -def relaxed_aliasing : Flag<"-relaxed-aliasing">, +def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; -def masm_verbose : Flag<"-masm-verbose">, +def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; -def mcode_model : Separate<"-mcode-model">, +def mcode_model : Separate<["-"], "mcode-model">, HelpText<"The code model to use">; -def mdebug_pass : Separate<"-mdebug-pass">, +def mdebug_pass : Separate<["-"], "mdebug-pass">, HelpText<"Enable additional debug output">; -def mdisable_fp_elim : Flag<"-mdisable-fp-elim">, +def mdisable_fp_elim : Flag<["-"], "mdisable-fp-elim">, HelpText<"Disable frame pointer elimination optimization">; -def mdisable_tail_calls : Flag<"-mdisable-tail-calls">, +def mdisable_tail_calls : Flag<["-"], "mdisable-tail-calls">, HelpText<"Disable tail call optimization, keeping the call stack accurate">; -def menable_no_infinities : Flag<"-menable-no-infs">, +def menable_no_infinities : Flag<["-"], "menable-no-infs">, HelpText<"Allow optimization to assume there are no infinities.">; -def menable_no_nans : Flag<"-menable-no-nans">, +def menable_no_nans : Flag<["-"], "menable-no-nans">, HelpText<"Allow optimization to assume there are no NaNs.">; -def menable_unsafe_fp_math : Flag<"-menable-unsafe-fp-math">, +def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, HelpText<"Allow unsafe floating-point math optimizations which may decrease " "precision">; -def mfloat_abi : Separate<"-mfloat-abi">, +def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; -def mlimit_float_precision : Separate<"-mlimit-float-precision">, +def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">, HelpText<"Limit float precision to the given value">; -def mno_exec_stack : Flag<"-mnoexecstack">, +def mno_exec_stack : Flag<["-"], "mnoexecstack">, HelpText<"Mark the file as not needing an executable stack">; -def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, +def mno_zero_initialized_in_bss : Flag<["-"], "mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; -def backend_option : Separate<"-backend-option">, +def backend_option : Separate<["-"], "backend-option">, HelpText<"Additional arguments to forward to LLVM backend (during code gen)">; -def mregparm : Separate<"-mregparm">, +def mregparm : Separate<["-"], "mregparm">, HelpText<"Limit the number of registers available for integer arguments">; -def msave_temp_labels : Flag<"-msave-temp-labels">, +def msave_temp_labels : Flag<["-"], "msave-temp-labels">, HelpText<"(integrated-as) Save temporary labels">; -def mrelocation_model : Separate<"-mrelocation-model">, +def mrelocation_model : Separate<["-"], "mrelocation-model">, HelpText<"The relocation model to use">; -def munwind_tables : Flag<"-munwind-tables">, +def munwind_tables : Flag<["-"], "munwind-tables">, HelpText<"Generate unwinding tables for all functions">; -def fuse_init_array : Flag<"-fuse-init-array">, +def fuse_init_array : Flag<["-"], "fuse-init-array">, HelpText<"Use .init_array instead of .ctors">; -def mconstructor_aliases : Flag<"-mconstructor-aliases">, +def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">, HelpText<"Emit complete constructors and destructors as aliases when possible">; -def mlink_bitcode_file : Separate<"-mlink-bitcode-file">, +def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">, HelpText<"Link the given bitcode file before performing optimizations.">; //===----------------------------------------------------------------------===// // Dependency Output Options //===----------------------------------------------------------------------===// -def sys_header_deps : Flag<"-sys-header-deps">, +def sys_header_deps : Flag<["-"], "sys-header-deps">, HelpText<"Include system headers in dependency output">; -def header_include_file : Separate<"-header-include-file">, +def header_include_file : Separate<["-"], "header-include-file">, HelpText<"Filename (or -) to write header include output to">; //===----------------------------------------------------------------------===// // Diagnostic Options //===----------------------------------------------------------------------===// -def dump_build_information : Separate<"-dump-build-information">, +def dump_build_information : Separate<["-"], "dump-build-information">, MetaVarName<"">, HelpText<"output a dump of some build information to a file">; -def diagnostic_log_file : Separate<"-diagnostic-log-file">, +def diagnostic_log_file : Separate<["-"], "diagnostic-log-file">, HelpText<"Filename (or -) to log diagnostics to">; -def diagnostic_serialized_file : Separate<"-serialize-diagnostic-file">, +def diagnostic_serialized_file : Separate<["-"], "serialize-diagnostic-file">, MetaVarName<"">, HelpText<"File for serializing diagnostics in a binary format">; -def fdiagnostics_format : Separate<"-fdiagnostics-format">, +def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">, HelpText<"Change diagnostic formatting to match IDE and command line tools">; -def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">, +def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">, HelpText<"Print diagnostic category">; -def ftabstop : Separate<"-ftabstop">, MetaVarName<"">, +def ftabstop : Separate<["-"], "ftabstop">, MetaVarName<"">, HelpText<"Set the tab stop distance.">; -def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"">, +def ferror_limit : Separate<["-"], "ferror-limit">, MetaVarName<"">, HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">; -def fmacro_backtrace_limit : Separate<"-fmacro-backtrace-limit">, MetaVarName<"">, +def fmacro_backtrace_limit : Separate<["-"], "fmacro-backtrace-limit">, MetaVarName<"">, HelpText<"Set the maximum number of entries to print in a macro expansion backtrace (0 = no limit).">; -def ftemplate_backtrace_limit : Separate<"-ftemplate-backtrace-limit">, MetaVarName<"">, +def ftemplate_backtrace_limit : Separate<["-"], "ftemplate-backtrace-limit">, MetaVarName<"">, HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">; -def fconstexpr_backtrace_limit : Separate<"-fconstexpr-backtrace-limit">, MetaVarName<"">, +def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">, MetaVarName<"">, HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">; -def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"">, +def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; -def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">, +def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; //===----------------------------------------------------------------------===// @@ -248,43 +251,43 @@ def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">, // This isn't normally used, it is just here so we can parse a // CompilerInvocation out of a driver-derived argument vector. -def cc1 : Flag<"-cc1">; +def cc1 : Flag<["-"], "cc1">; -def ast_merge : Separate<"-ast-merge">, +def ast_merge : Separate<["-"], "ast-merge">, MetaVarName<"">, HelpText<"Merge the given AST file into the translation unit being compiled.">; -def code_completion_at : Separate<"-code-completion-at">, +def code_completion_at : Separate<["-"], "code-completion-at">, MetaVarName<"::">, HelpText<"Dump code-completion information at a location">; -def remap_file : Separate<"-remap-file">, +def remap_file : Separate<["-"], "remap-file">, MetaVarName<";">, HelpText<"Replace the contents of the file with the contents of the file">; -def code_completion_at_EQ : Joined<"-code-completion-at=">, +def code_completion_at_EQ : Joined<["-"], "code-completion-at=">, Alias; -def code_completion_macros : Flag<"-code-completion-macros">, +def code_completion_macros : Flag<["-"], "code-completion-macros">, HelpText<"Include macros in code-completion results">; -def code_completion_patterns : Flag<"-code-completion-patterns">, +def code_completion_patterns : Flag<["-"], "code-completion-patterns">, HelpText<"Include code patterns in code-completion results">; -def no_code_completion_globals : Flag<"-no-code-completion-globals">, +def no_code_completion_globals : Flag<["-"], "no-code-completion-globals">, HelpText<"Do not include global declarations in code-completion results.">; -def code_completion_brief_comments : Flag<"-code-completion-brief-comments">, +def code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">, HelpText<"Include brief documentation comments in code-completion results.">; -def disable_free : Flag<"-disable-free">, +def disable_free : Flag<["-"], "disable-free">, HelpText<"Disable freeing of memory on exit">; -def load : Separate<"-load">, MetaVarName<"">, +def load : Separate<["-"], "load">, MetaVarName<"">, HelpText<"Load the named plugin (dynamic shared object)">; -def plugin : Separate<"-plugin">, MetaVarName<"">, +def plugin : Separate<["-"], "plugin">, MetaVarName<"">, HelpText<"Use the named plugin action instead of the default action (use \"help\" to list available options)">; -def plugin_arg : JoinedAndSeparate<"-plugin-arg-">, +def plugin_arg : JoinedAndSeparate<["-"], "plugin-arg-">, MetaVarName<" ">, HelpText<"Pass to plugin ">; -def add_plugin : Separate<"-add-plugin">, MetaVarName<"">, +def add_plugin : Separate<["-"], "add-plugin">, MetaVarName<"">, HelpText<"Use the named plugin action in addition to the default action">; -def resource_dir : Separate<"-resource-dir">, +def resource_dir : Separate<["-"], "resource-dir">, HelpText<"The directory which holds the compiler resource files">; -def version : Flag<"-version">, +def version : Flag<["-"], "version">, HelpText<"Print the compiler version">; -def ast_dump_filter : Separate<"-ast-dump-filter">, +def ast_dump_filter : Separate<["-"], "ast-dump-filter">, MetaVarName<"">, HelpText<"Use with -ast-dump or -ast-print to dump/print only AST declaration" " nodes having a certain substring in a qualified name. Use" @@ -292,191 +295,197 @@ def ast_dump_filter : Separate<"-ast-dump-filter">, let Group = Action_Group in { -def Eonly : Flag<"-Eonly">, +def Eonly : Flag<["-"], "Eonly">, HelpText<"Just run preprocessor, no output (for timings)">; -def dump_raw_tokens : Flag<"-dump-raw-tokens">, +def dump_raw_tokens : Flag<["-"], "dump-raw-tokens">, HelpText<"Lex file in raw mode and dump raw tokens">; -def analyze : Flag<"-analyze">, +def analyze : Flag<["-"], "analyze">, HelpText<"Run static analysis engine">; -def dump_tokens : Flag<"-dump-tokens">, +def dump_tokens : Flag<["-"], "dump-tokens">, HelpText<"Run preprocessor, dump internal rep of tokens">; -def init_only : Flag<"-init-only">, +def init_only : Flag<["-"], "init-only">, HelpText<"Only execute frontend initialization">; -def fixit : Flag<"-fixit">, +def fixit : Flag<["-"], "fixit">, HelpText<"Apply fix-it advice to the input source">; -def fixit_EQ : Joined<"-fixit=">, +def fixit_EQ : Joined<["-"], "fixit=">, HelpText<"Apply fix-it advice creating a file with the given suffix">; -def print_preamble : Flag<"-print-preamble">, +def print_preamble : Flag<["-"], "print-preamble">, HelpText<"Print the \"preamble\" of a file, which is a candidate for implicit" " precompiled headers.">; -def emit_html : Flag<"-emit-html">, +def emit_html : Flag<["-"], "emit-html">, HelpText<"Output input source as HTML">; -def ast_print : Flag<"-ast-print">, +def ast_print : Flag<["-"], "ast-print">, HelpText<"Build ASTs and then pretty-print them">; -def ast_list : Flag<"-ast-list">, +def ast_list : Flag<["-"], "ast-list">, HelpText<"Build ASTs and print the list of declaration node qualified names">; -def ast_dump : Flag<"-ast-dump">, +def ast_dump : Flag<["-"], "ast-dump">, HelpText<"Build ASTs and then debug dump them">; -def ast_dump_xml : Flag<"-ast-dump-xml">, +def ast_dump_xml : Flag<["-"], "ast-dump-xml">, HelpText<"Build ASTs and then debug dump them in a verbose XML format">; -def ast_view : Flag<"-ast-view">, +def ast_view : Flag<["-"], "ast-view">, HelpText<"Build ASTs and view them with GraphViz">; -def print_decl_contexts : Flag<"-print-decl-contexts">, +def print_decl_contexts : Flag<["-"], "print-decl-contexts">, HelpText<"Print DeclContexts and their Decls">; -def emit_module : Flag<"-emit-module">, +def emit_module : Flag<["-"], "emit-module">, HelpText<"Generate pre-compiled module file from a module map">; -def emit_pth : Flag<"-emit-pth">, +def emit_pth : Flag<["-"], "emit-pth">, HelpText<"Generate pre-tokenized header file">; -def emit_pch : Flag<"-emit-pch">, +def emit_pch : Flag<["-"], "emit-pch">, HelpText<"Generate pre-compiled header file">; -def emit_llvm_bc : Flag<"-emit-llvm-bc">, +def emit_llvm_bc : Flag<["-"], "emit-llvm-bc">, HelpText<"Build ASTs then convert to LLVM, emit .bc file">; -def emit_llvm_only : Flag<"-emit-llvm-only">, +def emit_llvm_only : Flag<["-"], "emit-llvm-only">, HelpText<"Build ASTs and convert to LLVM, discarding output">; -def emit_codegen_only : Flag<"-emit-codegen-only">, +def emit_codegen_only : Flag<["-"], "emit-codegen-only">, HelpText<"Generate machine code, but discard output">; -def emit_obj : Flag<"-emit-obj">, +def emit_obj : Flag<["-"], "emit-obj">, HelpText<"Emit native object files">; -def rewrite_test : Flag<"-rewrite-test">, +def rewrite_test : Flag<["-"], "rewrite-test">, HelpText<"Rewriter playground">; -def rewrite_macros : Flag<"-rewrite-macros">, +def rewrite_macros : Flag<["-"], "rewrite-macros">, HelpText<"Expand macros without full preprocessing">; -def migrate : Flag<"-migrate">, +def migrate : Flag<["-"], "migrate">, HelpText<"Migrate source code">; } -def mt_migrate_directory : Separate<"-mt-migrate-directory">, +def mt_migrate_directory : Separate<["-"], "mt-migrate-directory">, HelpText<"Directory for temporary files produced during ARC or ObjC migration">; -def arcmt_check : Flag<"-arcmt-check">, +def arcmt_check : Flag<["-"], "arcmt-check">, HelpText<"Check for ARC migration issues that need manual handling">; -def arcmt_modify : Flag<"-arcmt-modify">, +def arcmt_modify : Flag<["-"], "arcmt-modify">, HelpText<"Apply modifications to files to conform to ARC">; -def arcmt_migrate : Flag<"-arcmt-migrate">, +def arcmt_migrate : Flag<["-"], "arcmt-migrate">, HelpText<"Apply modifications and produces temporary files that conform to ARC">; -def relocatable_pch : Flag<"-relocatable-pch">, +def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, HelpText<"Whether to build a relocatable precompiled header">; -def print_stats : Flag<"-print-stats">, +def print_stats : Flag<["-"], "print-stats">, HelpText<"Print performance metrics and statistics">; -def fdump_record_layouts : Flag<"-fdump-record-layouts">, +def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">, HelpText<"Dump record layout information">; -def fdump_record_layouts_simple : Flag<"-fdump-record-layouts-simple">, +def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">, HelpText<"Dump record layout information in a simple form used for testing">; -def fix_what_you_can : Flag<"-fix-what-you-can">, +def fix_what_you_can : Flag<["-"], "fix-what-you-can">, HelpText<"Apply fix-it advice even in the presence of unfixable errors">; -def fix_only_warnings : Flag<"-fix-only-warnings">, +def fix_only_warnings : Flag<["-"], "fix-only-warnings">, HelpText<"Apply fix-it advice only for warnings, not errors">; -def fixit_recompile : Flag<"-fixit-recompile">, +def fixit_recompile : Flag<["-"], "fixit-recompile">, HelpText<"Apply fix-it changes and recompile">; -def fixit_to_temp : Flag<"-fixit-to-temporary">, +def fixit_to_temp : Flag<["-"], "fixit-to-temporary">, HelpText<"Apply fix-it changes to temporary files">; -def foverride_record_layout_EQ : Joined<"-foverride-record-layout=">, +def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">, HelpText<"Override record layouts with those in the given file">; //===----------------------------------------------------------------------===// // Language Options //===----------------------------------------------------------------------===// -def fblocks_runtime_optional : Flag<"-fblocks-runtime-optional">, +def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">, HelpText<"Weakly link in the blocks runtime">; -def fsjlj_exceptions : Flag<"-fsjlj-exceptions">, +def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; -def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">, +def fhidden_weak_vtables : Flag<["-"], "fhidden-weak-vtables">, HelpText<"Generate weak vtables and RTTI with hidden visibility">; -def main_file_name : Separate<"-main-file-name">, +def main_file_name : Separate<["-"], "main-file-name">, HelpText<"Main file name to use for debug info">; -def fno_signed_char : Flag<"-fno-signed-char">, +def fno_signed_char : Flag<["-"], "fno-signed-char">, HelpText<"Char is unsigned">; -def fconstant_string_class : Separate<"-fconstant-string-class">, +def fno_wchar : Flag<["-"], "fno-wchar">, + HelpText<"Disable C++ builtin type wchar_t">; +def fconstant_string_class : Separate<["-"], "fconstant-string-class">, MetaVarName<"">, HelpText<"Specify the class to use for constant Objective-C string objects.">; -def fobjc_arc_cxxlib_EQ : Joined<"-fobjc-arc-cxxlib=">, +def fobjc_arc_cxxlib_EQ : Joined<["-"], "fobjc-arc-cxxlib=">, HelpText<"Objective-C++ Automatic Reference Counting standard library kind">; -def fobjc_runtime_has_weak : Flag<"-fobjc-runtime-has-weak">, +def fobjc_runtime_has_weak : Flag<["-"], "fobjc-runtime-has-weak">, HelpText<"The target Objective-C runtime supports ARC weak operations">; -def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">, +def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">, HelpText<"Objective-C dispatch method to use">; -def fobjc_default_synthesize_properties : Flag<"-fobjc-default-synthesize-properties">, +def fobjc_default_synthesize_properties : Flag<["-"], "fobjc-default-synthesize-properties">, HelpText<"enable the default synthesis of Objective-C properties">; -def pic_level : Separate<"-pic-level">, +def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">, + HelpText<"enable extended encoding of block type signature">; +def pic_level : Separate<["-"], "pic-level">, HelpText<"Value for __PIC__">; -def pie_level : Separate<"-pie-level">, +def pie_level : Separate<["-"], "pie-level">, HelpText<"Value for __PIE__">; -def fno_validate_pch : Flag<"-fno-validate-pch">, +def fno_validate_pch : Flag<["-"], "fno-validate-pch">, HelpText<"Disable validation of precompiled headers">; -def dump_deserialized_pch_decls : Flag<"-dump-deserialized-decls">, +def dump_deserialized_pch_decls : Flag<["-"], "dump-deserialized-decls">, HelpText<"Dump declarations that are deserialized from PCH, for testing">; -def error_on_deserialized_pch_decl : Separate<"-error-on-deserialized-decl">, +def error_on_deserialized_pch_decl : Separate<["-"], "error-on-deserialized-decl">, HelpText<"Emit error if a specific declaration is deserialized from PCH, for testing">; -def error_on_deserialized_pch_decl_EQ : Joined<"-error-on-deserialized-decl=">, +def error_on_deserialized_pch_decl_EQ : Joined<["-"], "error-on-deserialized-decl=">, Alias; -def static_define : Flag<"-static-define">, +def static_define : Flag<["-"], "static-define">, HelpText<"Should __STATIC__ be defined">; -def stack_protector : Separate<"-stack-protector">, +def stack_protector : Separate<["-"], "stack-protector">, HelpText<"Enable stack protectors">; -def fvisibility : Separate<"-fvisibility">, +def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">, + HelpText<"Lower bound for a buffer to be considered for stack protection">; +def fvisibility : Separate<["-"], "fvisibility">, HelpText<"Default symbol visibility">; -def ftemplate_depth : Separate<"-ftemplate-depth">, +def ftemplate_depth : Separate<["-"], "ftemplate-depth">, HelpText<"Maximum depth of recursive template instantiation">; -def fconstexpr_depth : Separate<"-fconstexpr-depth">, +def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">, HelpText<"Maximum depth of recursive constexpr function calls">; -def fconst_strings : Flag<"-fconst-strings">, +def fconst_strings : Flag<["-"], "fconst-strings">, HelpText<"Use a const qualified type for string literals in C and ObjC">; -def fno_const_strings : Flag<"-fno-const-strings">, +def fno_const_strings : Flag<["-"], "fno-const-strings">, HelpText<"Don't use a const qualified type for string literals in C and ObjC">; -def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">, +def fno_bitfield_type_align : Flag<["-"], "fno-bitfield-type-align">, HelpText<"Ignore bit-field types when aligning structures">; -def ffake_address_space_map : Flag<"-ffake-address-space-map">, +def ffake_address_space_map : Flag<["-"], "ffake-address-space-map">, HelpText<"Use a fake address space map; OpenCL testing purposes only">; -def funknown_anytype : Flag<"-funknown-anytype">, +def funknown_anytype : Flag<["-"], "funknown-anytype">, HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">; -def fdebugger_support : Flag<"-fdebugger-support">, +def fdebugger_support : Flag<["-"], "fdebugger-support">, HelpText<"Enable special debugger support behavior">; -def fdebugger_cast_result_to_id : Flag<"-fdebugger-cast-result-to-id">, +def fdebugger_cast_result_to_id : Flag<["-"], "fdebugger-cast-result-to-id">, HelpText<"Enable casting unknown expression results to id">; -def fdebugger_objc_literal : Flag<"-fdebugger-objc-literal">, +def fdebugger_objc_literal : Flag<["-"], "fdebugger-objc-literal">, HelpText<"Enable special debugger support for Objective-C subscripting and literals">; -def fdeprecated_macro : Flag<"-fdeprecated-macro">, +def fdeprecated_macro : Flag<["-"], "fdeprecated-macro">, HelpText<"Defines the __DEPRECATED macro">; -def fno_deprecated_macro : Flag<"-fno-deprecated-macro">, +def fno_deprecated_macro : Flag<["-"], "fno-deprecated-macro">, HelpText<"Undefines the __DEPRECATED macro">; //===----------------------------------------------------------------------===// // Header Search Options //===----------------------------------------------------------------------===// -def nostdsysteminc : Flag<"-nostdsysteminc">, +def nostdsysteminc : Flag<["-"], "nostdsysteminc">, HelpText<"Disable standard system #include directories">; -def fmodule_name : Joined<"-fmodule-name=">, +def fmodule_name : Joined<["-"], "fmodule-name=">, MetaVarName<"">, HelpText<"Specify the name of the module to build">; -def fdisable_module_hash : Flag<"-fdisable-module-hash">, +def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">, HelpText<"Disable the module hash">; -def c_isystem : JoinedOrSeparate<"-c-isystem">, MetaVarName<"">, +def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"">, HelpText<"Add directory to the C SYSTEM include search path">; -def objc_isystem : JoinedOrSeparate<"-objc-isystem">, +def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">, MetaVarName<"">, HelpText<"Add directory to the ObjC SYSTEM include search path">; -def objcxx_isystem : JoinedOrSeparate<"-objcxx-isystem">, +def objcxx_isystem : JoinedOrSeparate<["-"], "objcxx-isystem">, MetaVarName<"">, HelpText<"Add directory to the ObjC++ SYSTEM include search path">; -def internal_isystem : JoinedOrSeparate<"-internal-isystem">, +def internal_isystem : JoinedOrSeparate<["-"], "internal-isystem">, MetaVarName<"">, HelpText<"Add directory to the internal system include search path; these " "are assumed to not be user-provided and are used to model system " "and standard headers' paths.">; -def internal_externc_isystem : JoinedOrSeparate<"-internal-externc-isystem">, +def internal_externc_isystem : JoinedOrSeparate<["-"], "internal-externc-isystem">, MetaVarName<"">, HelpText<"Add directory to the internal system include search path with " "implicit extern \"C\" semantics; these are assumed to not be " "user-provided and are used to model system and standard headers' " "paths.">; -def isystem_prefix : JoinedOrSeparate<"-isystem-prefix">, +def isystem_prefix : JoinedOrSeparate<["-"], "isystem-prefix">, MetaVarName<"">, HelpText<"Treat all #include paths starting with as including a " "system header.">; -def ino_system_prefix : JoinedOrSeparate<"-ino-system-prefix">, +def ino_system_prefix : JoinedOrSeparate<["-"], "ino-system-prefix">, MetaVarName<"">, HelpText<"Treat all #include paths starting with as not including a " "system header.">; @@ -485,42 +494,42 @@ def ino_system_prefix : JoinedOrSeparate<"-ino-system-prefix">, // Preprocessor Options //===----------------------------------------------------------------------===// -def include_pth : Separate<"-include-pth">, MetaVarName<"">, +def include_pth : Separate<["-"], "include-pth">, MetaVarName<"">, HelpText<"Include file before parsing">; -def chain_include : Separate<"-chain-include">, MetaVarName<"">, +def chain_include : Separate<["-"], "chain-include">, MetaVarName<"">, HelpText<"Include and chain a header file after turning it into PCH">; -def preamble_bytes_EQ : Joined<"-preamble-bytes=">, +def preamble_bytes_EQ : Joined<["-"], "preamble-bytes=">, HelpText<"Assume that the precompiled header is a precompiled preamble " "covering the first N bytes of the main file">; -def token_cache : Separate<"-token-cache">, MetaVarName<"">, +def token_cache : Separate<["-"], "token-cache">, MetaVarName<"">, HelpText<"Use specified token cache file">; -def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">, +def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">, HelpText<"include a detailed record of preprocessing actions">; //===----------------------------------------------------------------------===// // OpenCL Options //===----------------------------------------------------------------------===// -def cl_opt_disable : Flag<"-cl-opt-disable">, +def cl_opt_disable : Flag<["-"], "cl-opt-disable">, HelpText<"OpenCL only. This option disables all optimizations. The default is optimizations are enabled.">; -def cl_single_precision_constant : Flag<"-cl-single-precision-constant">, +def cl_single_precision_constant : Flag<["-"], "cl-single-precision-constant">, HelpText<"OpenCL only. Treat double precision floating-point constant as single precision constant.">; -def cl_finite_math_only : Flag<"-cl-finite-math-only">, +def cl_finite_math_only : Flag<["-"], "cl-finite-math-only">, HelpText<"OpenCL only. Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf.">; -def cl_unsafe_math_optimizations : Flag<"-cl-unsafe-math-optimizations">, +def cl_unsafe_math_optimizations : Flag<["-"], "cl-unsafe-math-optimizations">, HelpText<"OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable">; -def cl_fast_relaxed_math : Flag<"-cl-fast-relaxed-math">, +def cl_fast_relaxed_math : Flag<["-"], "cl-fast-relaxed-math">, HelpText<"OpenCL only. Sets -cl-finite-math-only and -cl-unsafe-math-optimizations, and defines __FAST_RELAXED_MATH__">; -def cl_mad_enable : Flag<"-cl-mad-enable">, +def cl_mad_enable : Flag<["-"], "cl-mad-enable">, HelpText<"OpenCL only. Enable less precise MAD instructions to be generated.">; -def cl_std_EQ : Joined<"-cl-std=">, +def cl_std_EQ : Joined<["-"], "cl-std=">, HelpText<"OpenCL language standard to compile for">; //===----------------------------------------------------------------------===// // CUDA Options //===----------------------------------------------------------------------===// -def fcuda_is_device : Flag<"-fcuda-is-device">, +def fcuda_is_device : Flag<["-"], "fcuda-is-device">, HelpText<"Generate code for CUDA device">; } // let Flags = [CC1Option] diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 7a10d567354b..5f63aa768857 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -98,8 +98,7 @@ public: StringRef getSysRoot() const; /// getArgsForToolChain - Return the derived argument list for the - /// tool chain \arg TC (or the default tool chain, if TC is not - /// specified). + /// tool chain \p TC (or the default tool chain, if TC is not specified). /// /// \param BoundArch - The bound architecture name, or 0. const DerivedArgList &getArgsForToolChain(const ToolChain *TC, @@ -142,6 +141,14 @@ public: void PrintJob(raw_ostream &OS, const Job &J, const char *Terminator, bool Quote) const; + /// PrintDiagnosticJob - Print one job in -### format, but with the + /// superfluous options removed, which are not necessary for + /// reproducing the crash. + /// + /// \param OS - The stream to print on. + /// \param J - The job to print. + void PrintDiagnosticJob(raw_ostream &OS, const Job &J) const; + /// ExecuteCommand - Execute an actual command. /// /// \param FailingCommand - For non-zero results, this will be set to the diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 609505597a70..b752ce6a349a 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -146,28 +146,11 @@ private: /// jobs. unsigned CheckInputsExist : 1; - /// Use the clang compiler where possible. - unsigned CCCUseClang : 1; - - /// Use clang for handling C++ and Objective-C++ inputs. - unsigned CCCUseClangCXX : 1; - - /// Use clang as a preprocessor (clang's preprocessor will still be - /// used where an integrated CPP would). - unsigned CCCUseClangCPP : 1; - - /// \brief Force use of clang frontend. - unsigned ForcedClangUse : 1; - public: /// Use lazy precompiled headers for PCH support. unsigned CCCUsePCH : 1; private: - /// Only use clang for the given architectures (only used when - /// non-empty). - std::set CCCClangArchs; - /// Certain options suppress the 'no input files' warning. bool SuppressMissingInputWarning : 1; @@ -232,9 +215,6 @@ public: InstalledDir = Value; } - bool shouldForceClangUse() const { return ForcedClangUse; } - void setForcedClangUse(bool V = true) { ForcedClangUse = V; } - /// @} /// @name Primary Functionality /// @{ @@ -287,7 +267,7 @@ public: /// BuildJobs - Bind actions to concrete tools and translate /// arguments to form the list of jobs to run. /// - /// \arg C - The compilation that is being built. + /// \param C - The compilation that is being built. void BuildJobs(Compilation &C) const; /// ExecuteCompilation - Execute the compilation according to the command line @@ -323,26 +303,21 @@ public: /// PrintVersion - Print the driver version. void PrintVersion(const Compilation &C, raw_ostream &OS) const; - /// GetFilePath - Lookup \arg Name in the list of file search paths. + /// GetFilePath - Lookup \p Name in the list of file search paths. /// - /// \arg TC - The tool chain for additional information on + /// \param TC - The tool chain for additional information on /// directories to search. // // FIXME: This should be in CompilationInfo. std::string GetFilePath(const char *Name, const ToolChain &TC) const; - /// GetProgramPath - Lookup \arg Name in the list of program search - /// paths. + /// GetProgramPath - Lookup \p Name in the list of program search paths. /// - /// \arg TC - The provided tool chain for additional information on + /// \param TC - The provided tool chain for additional information on /// directories to search. - /// - /// \arg WantFile - False when searching for an executable file, otherwise - /// true. Defaults to false. // // FIXME: This should be in CompilationInfo. - std::string GetProgramPath(const char *Name, const ToolChain &TC, - bool WantFile = false) const; + std::string GetProgramPath(const char *Name, const ToolChain &TC) const; /// HandleImmediateArgs - Handle any arguments which should be /// treated before building actions or binding tools. @@ -352,14 +327,14 @@ public: bool HandleImmediateArgs(const Compilation &C); /// ConstructAction - Construct the appropriate action to do for - /// \arg Phase on the \arg Input, taking in to account arguments + /// \p Phase on the \p Input, taking in to account arguments /// like -fsyntax-only or --analyze. Action *ConstructPhaseAction(const ArgList &Args, phases::ID Phase, Action *Input) const; /// BuildJobsForAction - Construct the jobs to perform for the - /// action \arg A. + /// action \p A. void BuildJobsForAction(Compilation &C, const Action *A, const ToolChain *TC, @@ -369,7 +344,7 @@ public: InputInfo &Result) const; /// GetNamedOutputPath - Return the name to use for the output of - /// the action \arg JA. The result is appended to the compilation's + /// the action \p JA. The result is appended to the compilation's /// list of temporary or result files, as appropriate. /// /// \param C - The compilation. diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index c94886dc26c1..84f5ee19173d 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -39,8 +39,6 @@ public: /// addCommand - Append a command to the current job, which must be /// either a piped job or a job list. void addCommand(Command *C); - - static bool classof(const Job *) { return true; } }; /// Command - An executable path/name and argument vector to @@ -78,7 +76,6 @@ public: static bool classof(const Job *J) { return J->getKind() == CommandClass; } - static bool classof(const Command *) { return true; } }; /// JobList - A sequence of jobs to perform. @@ -113,7 +110,6 @@ public: static bool classof(const Job *J) { return J->getKind() == JobListClass; } - static bool classof(const JobList *) { return true; } }; } // end namespace driver diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td index 9e6d5b9118e8..d16a2a779324 100644 --- a/include/clang/Driver/OptParser.td +++ b/include/clang/Driver/OptParser.td @@ -88,6 +88,9 @@ def NoForward : OptionFlag; // CC1Option - This option should be accepted by clang -cc1. def CC1Option : OptionFlag; +// NoDriverOption - This option should not be accepted by the driver. +def NoDriverOption : OptionFlag; + // Define the option group class. class OptionGroup { @@ -99,8 +102,9 @@ class OptionGroup { // Define the option class. -class Option { +class Option prefixes, string name, OptionKind kind> { string EnumName = ?; // Uses the def name if undefined. + list Prefixes = prefixes; string Name = name; OptionKind Kind = kind; // Used by MultiArg option kind. @@ -114,15 +118,22 @@ class Option { // Helpers for defining options. -class Flag : Option; -class Joined : Option; -class Separate : Option; -class CommaJoined : Option; -class MultiArg : Option { +class Flag prefixes, string name> + : Option; +class Joined prefixes, string name> + : Option; +class Separate prefixes, string name> + : Option; +class CommaJoined prefixes, string name> + : Option; +class MultiArg prefixes, string name, int numargs> + : Option { int NumArgs = numargs; } -class JoinedOrSeparate : Option; -class JoinedAndSeparate : Option; +class JoinedOrSeparate prefixes, string name> + : Option; +class JoinedAndSeparate prefixes, string name> + : Option; // Mix-ins for adding optional attributes. @@ -137,5 +148,5 @@ class MetaVarName { string MetaVarName = name; } // FIXME: Have generator validate that these appear in correct position (and // aren't duplicated). -def INPUT : Option<"", KIND_INPUT>, Flags<[DriverOption,CC1Option]>; -def UNKNOWN : Option<"", KIND_UNKNOWN>; +def INPUT : Option<[], "", KIND_INPUT>, Flags<[DriverOption,CC1Option]>; +def UNKNOWN : Option<[], "", KIND_UNKNOWN>; diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h index 27bd11985a67..53d83a0f38aa 100644 --- a/include/clang/Driver/OptTable.h +++ b/include/clang/Driver/OptTable.h @@ -12,24 +12,10 @@ #include "clang/Basic/LLVM.h" #include "clang/Driver/OptSpecifier.h" +#include "llvm/ADT/StringSet.h" namespace clang { namespace driver { -namespace options { - enum DriverFlag { - DriverOption = (1 << 0), - HelpHidden = (1 << 1), - LinkerInput = (1 << 2), - NoArgumentUnused = (1 << 3), - NoForward = (1 << 4), - RenderAsInput = (1 << 5), - RenderJoined = (1 << 6), - RenderSeparate = (1 << 7), - Unsupported = (1 << 8), - CC1Option = (1 << 9) - }; -} - class Arg; class ArgList; class InputArgList; @@ -46,9 +32,13 @@ namespace options { public: /// \brief Entry for a single option instance in the option data table. struct Info { + /// A null terminated array of prefix strings to apply to name while + /// matching. + const char *const *Prefixes; const char *Name; const char *HelpText; const char *MetaVar; + unsigned ID; unsigned char Kind; unsigned char Param; unsigned short Flags; @@ -61,19 +51,18 @@ namespace options { const Info *OptionInfos; unsigned NumOptionInfos; - /// \brief The lazily constructed options table, indexed by option::ID - 1. - mutable Option **Options; - - /// \brief Prebound input option instance. - const Option *TheInputOption; - - /// \brief Prebound unknown option instance. - const Option *TheUnknownOption; + unsigned TheInputOptionID; + unsigned TheUnknownOptionID; /// The index of the first option which can be parsed (i.e., is not a /// special option like 'input' or 'unknown', and is not an option group). unsigned FirstSearchableIndex; + /// The union of all option prefixes. If an argument does not begin with + /// one of these, it is an input. + llvm::StringSet<> PrefixesUnion; + std::string PrefixChars; + private: const Info &getInfo(OptSpecifier Opt) const { unsigned id = Opt.getID(); @@ -81,8 +70,6 @@ namespace options { return OptionInfos[id - 1]; } - Option *CreateOption(unsigned id) const; - protected: OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos); public: @@ -95,17 +82,7 @@ namespace options { /// if necessary. /// /// \return The option, or null for the INVALID option id. - const Option *getOption(OptSpecifier Opt) const { - unsigned id = Opt.getID(); - if (id == 0) - return 0; - - assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); - Option *&Entry = Options[id - 1]; - if (!Entry) - Entry = CreateOption(id); - return Entry; - } + const Option getOption(OptSpecifier Opt) const; /// \brief Lookup the name of the given option. const char *getOptionName(OptSpecifier id) const { @@ -122,11 +99,6 @@ namespace options { return getInfo(id).GroupID; } - /// \brief Should the help for the given option be hidden by default. - bool isOptionHelpHidden(OptSpecifier id) const { - return getInfo(id).Flags & options::HelpHidden; - } - /// \brief Get the help text to use to describe this option. const char *getOptionHelpText(OptSpecifier id) const { return getInfo(id).HelpText; @@ -176,9 +148,12 @@ namespace options { /// \param OS - The stream to write the help text to. /// \param Name - The name to use in the usage line. /// \param Title - The title to use in the usage line. - /// \param ShowHidden - Whether help-hidden arguments should be shown. + /// \param FlagsToInclude - If non-zero, only include options with any + /// of these flags set. + /// \param FlagsToExclude - Exclude options with any of these flags set. void PrintHelp(raw_ostream &OS, const char *Name, - const char *Title, bool ShowHidden = false) const; + const char *Title, unsigned short FlagsToInclude = 0, + unsigned short FlagsToExclude = 0) const; }; } } diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h index e6c4e12e0d1b..c3db773cd922 100644 --- a/include/clang/Driver/Option.h +++ b/include/clang/Driver/Option.h @@ -10,15 +10,36 @@ #ifndef CLANG_DRIVER_OPTION_H_ #define CLANG_DRIVER_OPTION_H_ -#include "clang/Driver/OptSpecifier.h" +#include "clang/Driver/OptTable.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" #include "clang/Basic/LLVM.h" namespace clang { namespace driver { class Arg; class ArgList; - class OptionGroup; + +namespace options { + /// Base flags for all options. Custom flags may be added after. + enum DriverFlag { + HelpHidden = (1 << 0), + RenderAsInput = (1 << 1), + RenderJoined = (1 << 2), + RenderSeparate = (1 << 3) + }; + + /// Flags specifically for clang options. + enum ClangFlags { + DriverOption = (1 << 4), + LinkerInput = (1 << 5), + NoArgumentUnused = (1 << 6), + NoForward = (1 << 7), + Unsupported = (1 << 8), + CC1Option = (1 << 9), + NoDriverOption = (1 << 10) + }; +} /// Option - Abstract representation for a single form of driver /// argument. @@ -53,100 +74,104 @@ namespace driver { RenderValuesStyle }; - private: - OptionClass Kind; - - /// The option ID. - OptSpecifier ID; - - /// The option name. - StringRef Name; - - /// Group this option is a member of, if any. - const OptionGroup *Group; - - /// Option that this is an alias for, if any. - const Option *Alias; - - /// Unsupported options will be rejected. - bool Unsupported : 1; - - /// Treat this option like a linker input? - bool LinkerInput : 1; - - /// When rendering as an input, don't render the option. + protected: + const OptTable::Info *Info; + const OptTable *Owner; - // FIXME: We should ditch the render/renderAsInput distinction. - bool NoOptAsInput : 1; + public: + Option(const OptTable::Info *Info, const OptTable *Owner); + ~Option(); - /// The style to using when rendering arguments parsed by this option. - unsigned RenderStyle : 2; + bool isValid() const { + return Info != 0; + } - /// This option is only consumed by the driver. - bool DriverOption : 1; + unsigned getID() const { + assert(Info && "Must have a valid info!"); + return Info->ID; + } - /// This option should not report argument unused errors. - bool NoArgumentUnused : 1; + OptionClass getKind() const { + assert(Info && "Must have a valid info!"); + return OptionClass(Info->Kind); + } - /// This option should not be implicitly forwarded. - bool NoForward : 1; + /// \brief Get the name of this option without any prefix. + StringRef getName() const { + assert(Info && "Must have a valid info!"); + return Info->Name; + } - /// CC1Option - This option should be accepted by clang -cc1. - bool CC1Option : 1; + const Option getGroup() const { + assert(Info && "Must have a valid info!"); + assert(Owner && "Must have a valid owner!"); + return Owner->getOption(Info->GroupID); + } - protected: - Option(OptionClass Kind, OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias); - public: - virtual ~Option(); + const Option getAlias() const { + assert(Info && "Must have a valid info!"); + assert(Owner && "Must have a valid owner!"); + return Owner->getOption(Info->AliasID); + } - unsigned getID() const { return ID.getID(); } - OptionClass getKind() const { return Kind; } - StringRef getName() const { return Name; } - const OptionGroup *getGroup() const { return Group; } - const Option *getAlias() const { return Alias; } + /// \brief Get the default prefix for this option. + StringRef getPrefix() const { + const char *Prefix = *Info->Prefixes; + return Prefix ? Prefix : StringRef(); + } - bool isUnsupported() const { return Unsupported; } - void setUnsupported(bool Value) { Unsupported = Value; } + /// \brief Get the name of this option with the default prefix. + std::string getPrefixedName() const { + std::string Ret = getPrefix(); + Ret += getName(); + return Ret; + } - bool isLinkerInput() const { return LinkerInput; } - void setLinkerInput(bool Value) { LinkerInput = Value; } + unsigned getNumArgs() const { return Info->Param; } - bool hasNoOptAsInput() const { return NoOptAsInput; } - void setNoOptAsInput(bool Value) { NoOptAsInput = Value; } + bool hasNoOptAsInput() const { return Info->Flags & options::RenderAsInput;} RenderStyleKind getRenderStyle() const { - return RenderStyleKind(RenderStyle); + if (Info->Flags & options::RenderJoined) + return RenderJoinedStyle; + if (Info->Flags & options::RenderSeparate) + return RenderSeparateStyle; + switch (getKind()) { + case GroupClass: + case InputClass: + case UnknownClass: + return RenderValuesStyle; + case JoinedClass: + case JoinedAndSeparateClass: + return RenderJoinedStyle; + case CommaJoinedClass: + return RenderCommaJoinedStyle; + case FlagClass: + case SeparateClass: + case MultiArgClass: + case JoinedOrSeparateClass: + return RenderSeparateStyle; + } + llvm_unreachable("Unexpected kind!"); } - void setRenderStyle(RenderStyleKind Value) { RenderStyle = Value; } - - bool isDriverOption() const { return DriverOption; } - void setDriverOption(bool Value) { DriverOption = Value; } - bool hasNoArgumentUnused() const { return NoArgumentUnused; } - void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; } - - bool hasNoForward() const { return NoForward; } - void setNoForward(bool Value) { NoForward = Value; } - - bool isCC1Option() const { return CC1Option; } - void setIsCC1Option(bool Value) { CC1Option = Value; } - - bool hasForwardToGCC() const { - return !NoForward && !DriverOption && !LinkerInput; + /// Test if this option has the flag \a Val. + bool hasFlag(unsigned Val) const { + return Info->Flags & Val; } /// getUnaliasedOption - Return the final option this option /// aliases (itself, if the option has no alias). - const Option *getUnaliasedOption() const { - if (Alias) return Alias->getUnaliasedOption(); - return this; + const Option getUnaliasedOption() const { + const Option Alias = getAlias(); + if (Alias.isValid()) return Alias.getUnaliasedOption(); + return *this; } /// getRenderName - Return the name to use when rendering this /// option. StringRef getRenderName() const { - return getUnaliasedOption()->getName(); + return getUnaliasedOption().getName(); } /// matches - Predicate for whether this option is part of the @@ -164,158 +189,13 @@ namespace driver { /// If the option accepts the current argument, accept() sets /// Index to the position where argument parsing should resume /// (even if the argument is missing values). - virtual Arg *accept(const ArgList &Args, unsigned &Index) const = 0; + /// + /// \parm ArgSize The number of bytes taken up by the matched Option prefix + /// and name. This is used to determine where joined values + /// start. + Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const; void dump() const; - - static bool classof(const Option *) { return true; } - }; - - /// OptionGroup - A set of options which are can be handled uniformly - /// by the driver. - class OptionGroup : public Option { - public: - OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::GroupClass; - } - static bool classof(const OptionGroup *) { return true; } - }; - - // Dummy option classes. - - /// InputOption - Dummy option class for representing driver inputs. - class InputOption : public Option { - public: - InputOption(OptSpecifier ID); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::InputClass; - } - static bool classof(const InputOption *) { return true; } - }; - - /// UnknownOption - Dummy option class for represent unknown arguments. - class UnknownOption : public Option { - public: - UnknownOption(OptSpecifier ID); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::UnknownClass; - } - static bool classof(const UnknownOption *) { return true; } - }; - - // Normal options. - - class FlagOption : public Option { - public: - FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, - const Option *Alias); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::FlagClass; - } - static bool classof(const FlagOption *) { return true; } - }; - - class JoinedOption : public Option { - public: - JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, - const Option *Alias); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::JoinedClass; - } - static bool classof(const JoinedOption *) { return true; } - }; - - class SeparateOption : public Option { - public: - SeparateOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::SeparateClass; - } - static bool classof(const SeparateOption *) { return true; } - }; - - class CommaJoinedOption : public Option { - public: - CommaJoinedOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::CommaJoinedClass; - } - static bool classof(const CommaJoinedOption *) { return true; } - }; - - // FIXME: Fold MultiArgOption into SeparateOption? - - /// MultiArgOption - An option which takes multiple arguments (these - /// are always separate arguments). - class MultiArgOption : public Option { - unsigned NumArgs; - - public: - MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, - const Option *Alias, unsigned NumArgs); - - unsigned getNumArgs() const { return NumArgs; } - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::MultiArgClass; - } - static bool classof(const MultiArgOption *) { return true; } - }; - - /// JoinedOrSeparateOption - An option which either literally - /// prefixes its (non-empty) value, or is follwed by a value. - class JoinedOrSeparateOption : public Option { - public: - JoinedOrSeparateOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::JoinedOrSeparateClass; - } - static bool classof(const JoinedOrSeparateOption *) { return true; } - }; - - /// JoinedAndSeparateOption - An option which literally prefixes its - /// value and is followed by another value. - class JoinedAndSeparateOption : public Option { - public: - JoinedAndSeparateOption(OptSpecifier ID, const char *Name, - const OptionGroup *Group, const Option *Alias); - - virtual Arg *accept(const ArgList &Args, unsigned &Index) const; - - static bool classof(const Option *O) { - return O->getKind() == Option::JoinedAndSeparateClass; - } - static bool classof(const JoinedAndSeparateOption *) { return true; } }; } // end namespace driver diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h index ac312cdfd4d2..6c114e252d3c 100644 --- a/include/clang/Driver/Options.h +++ b/include/clang/Driver/Options.h @@ -17,11 +17,13 @@ namespace driver { namespace options { enum ID { OPT_INVALID = 0, // This is not an option ID. -#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ +#define PREFIX(NAME, VALUE) +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) OPT_##ID, #include "clang/Driver/Options.inc" LastOption #undef OPTION +#undef PREFIX }; } diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index c7698a28f910..77ba17a2b4c7 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1,4 +1,4 @@ -//===--- DriverOptions.td - Options for clang -----------------------------===// +//===--- Options.td - Options for clang -----------------------------------===// // // The LLVM Compiler Infrastructure // @@ -41,6 +41,8 @@ def m_x86_Features_Group : OptionGroup<"">, Group">, Group; def opencl_Group : OptionGroup<"">; def u_Group : OptionGroup<"">; +def mips_CPUs_Group : OptionGroup<"">, + Group; def pedantic_Group : OptionGroup<"">, Group; @@ -82,1092 +84,1071 @@ def ccc_debug_Group : OptionGroup<"">, Group, HelpText<"DEBUG/DEVELOPMENT OPTIONS">; class CCCDriverOpt : Group, Flags<[DriverOption, HelpHidden]>; -def ccc_cxx : Flag<"-ccc-cxx">, CCCDriverOpt, +def ccc_cxx : Flag<["-"], "ccc-cxx">, CCCDriverOpt, HelpText<"Act as a C++ driver">; -def ccc_echo : Flag<"-ccc-echo">, CCCDriverOpt, +def ccc_echo : Flag<["-"], "ccc-echo">, CCCDriverOpt, HelpText<"Echo commands before running them">; -def ccc_gcc_name : Separate<"-ccc-gcc-name">, CCCDriverOpt, +def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, CCCDriverOpt, HelpText<"Name for native GCC compiler">, MetaVarName<"">; -def ccc_clang_cxx : Flag<"-ccc-clang-cxx">, CCCDriverOpt, - HelpText<"Enable the clang compiler for C++">; -def ccc_no_clang_cxx : Flag<"-ccc-no-clang-cxx">, CCCDriverOpt, - HelpText<"Disable the clang compiler for C++">; -def ccc_no_clang : Flag<"-ccc-no-clang">, CCCDriverOpt, - HelpText<"Disable the clang compiler">; -def ccc_no_clang_cpp : Flag<"-ccc-no-clang-cpp">, CCCDriverOpt, - HelpText<"Disable the clang preprocessor">; -def ccc_clang_archs : Separate<"-ccc-clang-archs">, CCCDriverOpt, +def ccc_clang_archs : Separate<["-"], "ccc-clang-archs">, CCCDriverOpt, HelpText<"Comma separate list of architectures to use the clang compiler for">, MetaVarName<"">; -def ccc_pch_is_pch : Flag<"-ccc-pch-is-pch">, CCCDriverOpt, +def ccc_pch_is_pch : Flag<["-"], "ccc-pch-is-pch">, CCCDriverOpt, HelpText<"Use lazy PCH for precompiled headers">; -def ccc_pch_is_pth : Flag<"-ccc-pch-is-pth">, CCCDriverOpt, +def ccc_pch_is_pth : Flag<["-"], "ccc-pch-is-pth">, CCCDriverOpt, HelpText<"Use pretokenized headers for precompiled headers">; class CCCDebugOpt : Group, Flags<[DriverOption, HelpHidden]>; -def ccc_install_dir : Separate<"-ccc-install-dir">, CCCDebugOpt, +def ccc_install_dir : Separate<["-"], "ccc-install-dir">, CCCDebugOpt, HelpText<"Simulate installation in the given directory">; -def ccc_print_options : Flag<"-ccc-print-options">, CCCDebugOpt, +def ccc_print_options : Flag<["-"], "ccc-print-options">, CCCDebugOpt, HelpText<"Dump parsed command line arguments">; -def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt, +def ccc_print_phases : Flag<["-"], "ccc-print-phases">, CCCDebugOpt, HelpText<"Dump list of actions to perform">; -def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt, +def ccc_print_bindings : Flag<["-"], "ccc-print-bindings">, CCCDebugOpt, HelpText<"Show bindings of tools to actions">; -def ccc_arcmt_check : Flag<"-ccc-arcmt-check">, CCCDriverOpt, +def ccc_arcmt_check : Flag<["-"], "ccc-arcmt-check">, CCCDriverOpt, HelpText<"Check for ARC migration issues that need manual handling">; -def ccc_arcmt_modify : Flag<"-ccc-arcmt-modify">, CCCDriverOpt, +def ccc_arcmt_modify : Flag<["-"], "ccc-arcmt-modify">, CCCDriverOpt, HelpText<"Apply modifications to files to conform to ARC">; -def ccc_arrmt_check : Flag<"-ccc-arrmt-check">, Alias; -def ccc_arrmt_modify : Flag<"-ccc-arrmt-modify">, Alias; -def ccc_arcmt_migrate : Separate<"-ccc-arcmt-migrate">, CCCDriverOpt, +def ccc_arrmt_check : Flag<["-"], "ccc-arrmt-check">, Alias; +def ccc_arrmt_modify : Flag<["-"], "ccc-arrmt-modify">, Alias; +def ccc_arcmt_migrate : Separate<["-"], "ccc-arcmt-migrate">, CCCDriverOpt, HelpText<"Apply modifications and produces temporary files that conform to ARC">; -def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">, +def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output">, HelpText<"Output path for the plist report">, Flags<[CC1Option]>; -def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">, +def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">, HelpText<"Emit ARC errors even if the migrator can fix them">, Flags<[CC1Option]>; -def _migrate : Flag<"--migrate">, Flags<[DriverOption]>, +def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>, HelpText<"Run the migrator">; -def ccc_objcmt_migrate : Separate<"-ccc-objcmt-migrate">, CCCDriverOpt, +def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">, CCCDriverOpt, HelpText<"Apply modifications and produces temporary files to migrate to " "modern ObjC syntax">; -def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">, Flags<[CC1Option]>, +def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC literals">; -def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">, Flags<[CC1Option]>, +def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC subscripting">; // Make sure all other -ccc- options are rejected. -def ccc_ : Joined<"-ccc-">, Group, Flags<[Unsupported]>; +def ccc_ : Joined<["-"], "ccc-">, Group, Flags<[Unsupported]>; // Standard Options -def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>, +def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption]>, HelpText<"Print the commands to run for this compilation">; // The '--' option is here for the sake of compatibility with gcc, but is // being ignored by the driver. -def _DASH_DASH : Flag<"--">, Flags<[DriverOption]>; -def A : JoinedOrSeparate<"-A">; -def B : JoinedOrSeparate<"-B">; -def CC : Flag<"-CC">, Flags<[CC1Option]>; -def C : Flag<"-C">, Flags<[CC1Option]>; -def D : JoinedOrSeparate<"-D">, Group, Flags<[CC1Option]>; -def E : Flag<"-E">, Flags<[DriverOption,CC1Option]>, Group, +def _DASH_DASH : Flag<["--"], "">, Flags<[DriverOption]>; +def A : JoinedOrSeparate<["-"], "A">; +def B : JoinedOrSeparate<["-"], "B">; +def CC : Flag<["-"], "CC">, Flags<[CC1Option]>; +def C : Flag<["-"], "C">, Flags<[CC1Option]>; +def D : JoinedOrSeparate<["-"], "D">, Group, Flags<[CC1Option]>; +def E : Flag<["-"], "E">, Flags<[DriverOption,CC1Option]>, Group, HelpText<"Only run the preprocessor">; -def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined,CC1Option]>, +def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>, HelpText<"Add directory to framework include search path">; -def G : Separate<"-G">, Flags<[DriverOption]>; -def H : Flag<"-H">, Flags<[CC1Option]>, +def G : Separate<["-"], "G">, Flags<[DriverOption]>; +def H : Flag<["-"], "H">, Flags<[CC1Option]>, HelpText<"Show header includes and nesting depth">; -def I_ : Flag<"-I-">, Group; -def I : JoinedOrSeparate<"-I">, Group, Flags<[CC1Option]>, +def I_ : Flag<["-"], "I-">, Group; +def I : JoinedOrSeparate<["-"], "I">, Group, Flags<[CC1Option]>, HelpText<"Add directory to include search path">; -def L : JoinedOrSeparate<"-L">, Flags<[RenderJoined]>; -def MD : Flag<"-MD">, Group; -def MF : JoinedOrSeparate<"-MF">, Group; -def MG : Flag<"-MG">, Group, Flags<[CC1Option]>, +def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>; +def MD : Flag<["-"], "MD">, Group; +def MF : JoinedOrSeparate<["-"], "MF">, Group; +def MG : Flag<["-"], "MG">, Group, Flags<[CC1Option]>, HelpText<"Add missing headers to dependency list">; -def MMD : Flag<"-MMD">, Group; -def MM : Flag<"-MM">, Group; -def MP : Flag<"-MP">, Group, Flags<[CC1Option]>, +def MMD : Flag<["-"], "MMD">, Group; +def MM : Flag<["-"], "MM">, Group; +def MP : Flag<["-"], "MP">, Group, Flags<[CC1Option]>, HelpText<"Create phony target for each dependency (other than main file)">; -def MQ : JoinedOrSeparate<"-MQ">, Group, Flags<[CC1Option]>, +def MQ : JoinedOrSeparate<["-"], "MQ">, Group, Flags<[CC1Option]>, HelpText<"Specify target to quote for dependency">; -def MT : JoinedOrSeparate<"-MT">, Group, Flags<[CC1Option]>, +def MT : JoinedOrSeparate<["-"], "MT">, Group, Flags<[CC1Option]>, HelpText<"Specify target for dependency">; -def Mach : Flag<"-Mach">; -def M : Flag<"-M">, Group; -def O0 : Joined<"-O0">, Group, Flags<[CC1Option]>; -def O4 : Joined<"-O4">, Group, Flags<[CC1Option]>; -def ObjCXX : Flag<"-ObjC++">, Flags<[DriverOption]>, +def Mach : Flag<["-"], "Mach">; +def M : Flag<["-"], "M">, Group; +def O0 : Joined<["-"], "O0">, Group, Flags<[CC1Option]>; +def O4 : Joined<["-"], "O4">, Group, Flags<[CC1Option]>; +def ObjCXX : Flag<["-"], "ObjC++">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C++ inputs">; -def ObjC : Flag<"-ObjC">, Flags<[DriverOption]>, +def ObjC : Flag<["-"], "ObjC">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C inputs">; -def O : Joined<"-O">, Group, Flags<[CC1Option]>; -def P : Flag<"-P">, Flags<[CC1Option]>, +def O : Joined<["-"], "O">, Group, Flags<[CC1Option]>; +def P : Flag<["-"], "P">, Flags<[CC1Option]>, HelpText<"Disable linemarker output in -E mode">; -def Qn : Flag<"-Qn">; -def Qunused_arguments : Flag<"-Qunused-arguments">, Flags<[DriverOption]>, +def Qn : Flag<["-"], "Qn">; +def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption]>, HelpText<"Don't emit warning for unused driver arguments">; -def Q : Flag<"-Q">; -def R : Flag<"-R">; -def S : Flag<"-S">, Flags<[DriverOption,CC1Option]>, Group, +def Q : Flag<["-"], "Q">; +def R : Flag<["-"], "R">; +def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group, HelpText<"Only run preprocess and compilation steps">; -def Tbss : JoinedOrSeparate<"-Tbss">, Group; -def Tdata : JoinedOrSeparate<"-Tdata">, Group; -def Ttext : JoinedOrSeparate<"-Ttext">, Group; -def T : JoinedOrSeparate<"-T">, Group; -def U : JoinedOrSeparate<"-U">, Group, Flags<[CC1Option]>; -def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>; -def Wa_COMMA : CommaJoined<"-Wa,">, +def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group; +def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group; +def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group; +def T : JoinedOrSeparate<["-"], "T">, Group; +def U : JoinedOrSeparate<["-"], "U">, Group, Flags<[CC1Option]>; +def V : JoinedOrSeparate<["-"], "V">, Flags<[DriverOption, Unsupported]>; +def Wa_COMMA : CommaJoined<["-"], "Wa,">, HelpText<"Pass the comma separated arguments in to the assembler">, MetaVarName<"">; -def Wall : Flag<"-Wall">, Group, Flags<[CC1Option]>; -def Wdeprecated : Flag<"-Wdeprecated">, Group, Flags<[CC1Option]>; -def Wno_deprecated : Flag<"-Wno-deprecated">, Group, Flags<[CC1Option]>; -def Wextra : Flag<"-Wextra">, Group, Flags<[CC1Option]>; -def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>, +def Wall : Flag<["-"], "Wall">, Group, Flags<[CC1Option]>; +def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, Flags<[CC1Option]>; +def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group, Flags<[CC1Option]>; +def Wextra : Flag<["-"], "Wextra">, Group, Flags<[CC1Option]>; +def Wl_COMMA : CommaJoined<["-"], "Wl,">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass the comma separated arguments in to the linker">, MetaVarName<"">; -def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group, +def Wno_nonportable_cfstrings : Joined<["-"], "Wno-nonportable-cfstrings">, Group, Flags<[CC1Option]>; -def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group, +def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group, Flags<[CC1Option]>; -def Wp_COMMA : CommaJoined<"-Wp,">, +def Wp_COMMA : CommaJoined<["-"], "Wp,">, HelpText<"Pass the comma separated arguments in to the preprocessor">, MetaVarName<"">; -def Wwrite_strings : Flag<"-Wwrite-strings">, Group, Flags<[CC1Option]>; -def Wno_write_strings : Flag<"-Wno-write-strings">, Group, Flags<[CC1Option]>; -def W_Joined : Joined<"-W">, Group, Flags<[CC1Option]>; -def Xanalyzer : Separate<"-Xanalyzer">, +def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group, Flags<[CC1Option]>; +def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group, Flags<[CC1Option]>; +def W_Joined : Joined<["-"], "W">, Group, Flags<[CC1Option]>, + MetaVarName<"">, HelpText<"Enable the specified warning">; +def Xanalyzer : Separate<["-"], "Xanalyzer">, HelpText<"Pass to the static analyzer">, MetaVarName<"">; -def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>; -def Xassembler : Separate<"-Xassembler">, +def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[DriverOption]>; +def Xassembler : Separate<["-"], "Xassembler">, HelpText<"Pass to the assembler">, MetaVarName<"">; -def Xclang : Separate<"-Xclang">, +def Xclang : Separate<["-"], "Xclang">, HelpText<"Pass to the clang compiler">, MetaVarName<"">, Flags<[NoForward]>; -def Xlinker : Separate<"-Xlinker">, Flags<[LinkerInput, RenderAsInput]>, +def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass to the linker">, MetaVarName<"">; -def Xpreprocessor : Separate<"-Xpreprocessor">, +def Xpreprocessor : Separate<["-"], "Xpreprocessor">, HelpText<"Pass to the preprocessor">, MetaVarName<"">; -def X_Flag : Flag<"-X">; -def X_Joined : Joined<"-X">; -def Z_Flag : Flag<"-Z">; -def Z_Joined : Joined<"-Z">; -def all__load : Flag<"-all_load">; -def allowable__client : Separate<"-allowable_client">; -def ansi : Flag<"-ansi">, Group; -def arch__errors__fatal : Flag<"-arch_errors_fatal">; -def arch : Separate<"-arch">, Flags<[DriverOption]>; -def arch__only : Separate<"-arch_only">; -def a : Joined<"-a">, Group; -def bind__at__load : Flag<"-bind_at_load">; -def bundle__loader : Separate<"-bundle_loader">; -def bundle : Flag<"-bundle">; -def b : JoinedOrSeparate<"-b">, Flags<[Unsupported]>; -def cl_kernel_arg_info : Flag<"-cl-kernel-arg-info">, Flags<[CC1Option]>, Group, +def X_Flag : Flag<["-"], "X">; +def X_Joined : Joined<["-"], "X">; +def Z_Flag : Flag<["-"], "Z">; +def Z_Joined : Joined<["-"], "Z">; +def all__load : Flag<["-"], "all_load">; +def allowable__client : Separate<["-"], "allowable_client">; +def ansi : Flag<["-", "--"], "ansi">, Group; +def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">; +def arch : Separate<["-"], "arch">, Flags<[DriverOption]>; +def arch__only : Separate<["-"], "arch_only">; +def a : Joined<["-"], "a">, Group; +def bind__at__load : Flag<["-"], "bind_at_load">; +def bundle__loader : Separate<["-"], "bundle_loader">; +def bundle : Flag<["-"], "bundle">; +def b : JoinedOrSeparate<["-"], "b">, Flags<[Unsupported]>; +def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, Flags<[CC1Option]>, Group, HelpText<"OpenCL only. This option allows the compiler to store information about the arguments of a kernel(s)"> ; -def client__name : JoinedOrSeparate<"-client_name">; -def combine : Flag<"-combine">, Flags<[DriverOption, Unsupported]>; -def compatibility__version : JoinedOrSeparate<"-compatibility_version">; -def coverage : Flag<"-coverage">; -def cpp_precomp : Flag<"-cpp-precomp">, Group; -def current__version : JoinedOrSeparate<"-current_version">; -def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group, +def client__name : JoinedOrSeparate<["-"], "client_name">; +def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>; +def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">; +def coverage : Flag<["-", "--"], "coverage">; +def cpp_precomp : Flag<["-"], "cpp-precomp">, Group; +def current__version : JoinedOrSeparate<["-"], "current_version">; +def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group, HelpText<"Add directory to the C++ SYSTEM include search path">, Flags<[CC1Option]>, MetaVarName<"">; -def c : Flag<"-c">, Flags<[DriverOption]>, +def c : Flag<["-"], "c">, Flags<[DriverOption]>, HelpText<"Only run preprocess, compile, and assemble steps">; -def dA : Flag<"-dA">, Group; -def dD : Flag<"-dD">, Group, Flags<[CC1Option]>, +def dA : Flag<["-"], "dA">, Group; +def dD : Flag<["-"], "dD">, Group, Flags<[CC1Option]>, HelpText<"Print macro definitions in -E mode in addition to normal output">; -def dM : Flag<"-dM">, Group, Flags<[CC1Option]>, +def dM : Flag<["-"], "dM">, Group, Flags<[CC1Option]>, HelpText<"Print macro definitions in -E mode instead of normal output">; -def dead__strip : Flag<"-dead_strip">; -def dependency_file : Separate<"-dependency-file">, Flags<[CC1Option]>, +def dead__strip : Flag<["-"], "dead_strip">; +def dependency_file : Separate<["-"], "dependency-file">, Flags<[CC1Option]>, HelpText<"Filename (or -) to write dependency output to">; -def dependency_dot : Separate<"-dependency-dot">, Flags<[CC1Option]>, +def dependency_dot : Separate<["-"], "dependency-dot">, Flags<[CC1Option]>, HelpText<"Filename to write DOT-formatted header dependencies to">; -def dumpmachine : Flag<"-dumpmachine">; -def dumpspecs : Flag<"-dumpspecs">, Flags<[Unsupported]>; -def dumpversion : Flag<"-dumpversion">; -def dylib__file : Separate<"-dylib_file">; -def dylinker__install__name : JoinedOrSeparate<"-dylinker_install_name">; -def dylinker : Flag<"-dylinker">; -def dynamiclib : Flag<"-dynamiclib">; -def dynamic : Flag<"-dynamic">, Flags<[NoArgumentUnused]>; -def d_Flag : Flag<"-d">, Group; -def d_Joined : Joined<"-d">, Group; -def emit_ast : Flag<"-emit-ast">, +def dumpmachine : Flag<["-"], "dumpmachine">; +def dumpspecs : Flag<["-"], "dumpspecs">, Flags<[Unsupported]>; +def dumpversion : Flag<["-"], "dumpversion">; +def dylib__file : Separate<["-"], "dylib_file">; +def dylinker__install__name : JoinedOrSeparate<["-"], "dylinker_install_name">; +def dylinker : Flag<["-"], "dylinker">; +def dynamiclib : Flag<["-"], "dynamiclib">; +def dynamic : Flag<["-"], "dynamic">, Flags<[NoArgumentUnused]>; +def d_Flag : Flag<["-"], "d">, Group; +def d_Joined : Joined<["-"], "d">, Group; +def emit_ast : Flag<["-"], "emit-ast">, HelpText<"Emit Clang AST files for source inputs">; -def emit_llvm : Flag<"-emit-llvm">, Flags<[CC1Option]>, Group, +def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group, HelpText<"Use the LLVM representation for assembler and object files">; -def exported__symbols__list : Separate<"-exported_symbols_list">; -def e : JoinedOrSeparate<"-e">; -def fPIC : Flag<"-fPIC">, Group; -def fno_PIC : Flag<"-fno-PIC">, Group; -def fPIE : Flag<"-fPIE">, Group; -def fno_PIE : Flag<"-fno-PIE">, Group; -def faccess_control : Flag<"-faccess-control">, Group; -def fallow_unsupported : Flag<"-fallow-unsupported">, Group; -def faltivec : Flag<"-faltivec">, Group, Flags<[CC1Option]>, +def exported__symbols__list : Separate<["-"], "exported_symbols_list">; +def e : JoinedOrSeparate<["-"], "e">; +def fPIC : Flag<["-"], "fPIC">, Group; +def fno_PIC : Flag<["-"], "fno-PIC">, Group; +def fPIE : Flag<["-"], "fPIE">, Group; +def fno_PIE : Flag<["-"], "fno-PIE">, Group; +def faccess_control : Flag<["-"], "faccess-control">, Group; +def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group; +def faltivec : Flag<["-"], "faltivec">, Group, Flags<[CC1Option]>, HelpText<"Enable AltiVec vector initializer syntax">; -def fapple_kext : Flag<"-fapple-kext">, Group, Flags<[CC1Option]>, +def fapple_kext : Flag<["-"], "fapple-kext">, Group, Flags<[CC1Option]>, HelpText<"Use Apple's kernel extensions ABI">; -def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, Group, Flags<[CC1Option]>, +def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group, Flags<[CC1Option]>, HelpText<"Enable Apple gcc-compatible #pragma pack handling">; -def faddress_sanitizer : Flag<"-faddress-sanitizer">, Group, Flags<[CC1Option]>, - HelpText<"Enable AddressSanitizer instrumentation (memory error detection)">; -def fno_address_sanitizer : Flag<"-fno-address-sanitizer">, Group, Flags<[CC1Option]>; -def fthread_sanitizer : Flag<"-fthread-sanitizer">, Group, Flags<[CC1Option]>, - HelpText<"Enable ThreadSanitizer instrumentation (race detection)">; -def fno_thread_sanitizer : Flag<"-fno-thread-sanitizer">, Group, Flags<[CC1Option]>; -def fasm : Flag<"-fasm">, Group; +def faddress_sanitizer : Flag<["-"], "faddress-sanitizer">, Group; +def fno_address_sanitizer : Flag<["-"], "fno-address-sanitizer">, Group; +def fthread_sanitizer : Flag<["-"], "fthread-sanitizer">, Group; +def fno_thread_sanitizer : Flag<["-"], "fno-thread-sanitizer">, Group; +def fasm : Flag<["-"], "fasm">, Group; -def fasm_blocks : Flag<"-fasm-blocks">, Group; -def fno_asm_blocks : Flag<"-fno-asm-blocks">, Group; +def fasm_blocks : Flag<["-"], "fasm-blocks">, Group; +def fno_asm_blocks : Flag<["-"], "fno-asm-blocks">, Group; -def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group; -def fastcp : Flag<"-fastcp">, Group; -def fastf : Flag<"-fastf">, Group; -def fast : Flag<"-fast">, Group; -def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group; -def fblocks : Flag<"-fblocks">, Group, Flags<[CC1Option]>, +def fassume_sane_operator_new : Flag<["-"], "fassume-sane-operator-new">, Group; +def fastcp : Flag<["-"], "fastcp">, Group; +def fastf : Flag<["-"], "fastf">, Group; +def fast : Flag<["-"], "fast">, Group; +def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group; +def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>, HelpText<"Enable the 'blocks' language feature">; -def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group; -def fborland_extensions : Flag<"-fborland-extensions">, Group, Flags<[CC1Option]>, +def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group; +def fborland_extensions : Flag<["-"], "fborland-extensions">, Group, Flags<[CC1Option]>, HelpText<"Accept non-standard constructs supported by the Borland compiler">; -def fbounds_checking : Flag<"-fbounds-checking">, Group, - HelpText<"Enable run-time bounds checks.">; -def fbounds_checking_EQ : Joined<"-fbounds-checking=">, Flags<[CC1Option]>, +def fbounds_checking : Flag<["-"], "fbounds-checking">, Group, + HelpText<"Enable run-time bounds checks">; +def fbounds_checking_EQ : Joined<["-"], "fbounds-checking=">, Flags<[CC1Option]>, Group; -def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group; -def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group; -def fbuiltin : Flag<"-fbuiltin">, Group; -def fcaret_diagnostics : Flag<"-fcaret-diagnostics">, Group; -def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, Flags<[CC1Option]>, - Group, HelpText<"Generate runtime checks for undefined behavior.">; -def fclasspath_EQ : Joined<"-fclasspath=">, Group; -def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group, Flags<[CC1Option]>, +def fbuiltin_strcat : Flag<["-"], "fbuiltin-strcat">, Group; +def fbuiltin_strcpy : Flag<["-"], "fbuiltin-strcpy">, Group; +def fbuiltin : Flag<["-"], "fbuiltin">, Group; +def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group; +def fcatch_undefined_behavior : Flag<["-"], "fcatch-undefined-behavior">, Group; +def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group; +def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group, Flags<[CC1Option]>, HelpText<"Use colors in diagnostics">; -def fcommon : Flag<"-fcommon">, Group; -def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group; -def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group; -def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group; -def fconstexpr_depth_EQ : Joined<"-fconstexpr-depth=">, Group; -def fconstexpr_backtrace_limit_EQ : Joined<"-fconstexpr-backtrace-limit=">, +def fcommon : Flag<["-"], "fcommon">, Group; +def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group; +def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group; +def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group; +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 fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>; +def fcreate_profile : Flag<["-"], "fcreate-profile">, Group; +def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group, HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>; -def fcxx_modules : Flag <"-fcxx-modules">, Group, Flags<[NoForward]>; -def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group; -def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group; -def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group; -def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group, +def fcxx_modules : Flag <["-"], "fcxx-modules">, Group, Flags<[NoForward]>; +def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group; +def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group; +def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group; +def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">, Group, Flags<[CC1Option]>, HelpText<"Print fix-its in machine parseable form">; -def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, +def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">, Group, Flags<[CC1Option]>, HelpText<"Print source range spans in numeric form">; -def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group, +def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group, Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">; -def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, Group, +def fdiagnostics_show_name : Flag<["-"], "fdiagnostics-show-name">, Group, Flags<[CC1Option]>, HelpText<"Print diagnostic name">; -def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, +def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">, Group, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">; -def fdiagnostics_format_EQ : Joined<"-fdiagnostics-format=">, Group; -def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group; -def fdiagnostics_show_template_tree : Flag<"-fdiagnostics-show-template-tree">, +def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group; +def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group; +def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">, Group, Flags<[CC1Option]>, HelpText<"Print a template comparison tree for differing templates">; -def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group, +def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group, HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>; -def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group; -def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group, Flags<[CC1Option]>; -def fdwarf_directory_asm : Flag<"-fdwarf-directory-asm">, Group; -def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, Group, Flags<[CC1Option]>; -def felide_constructors : Flag<"-felide-constructors">, Group; -def fno_elide_type : Flag<"-fno-elide-type">, Group, +def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group; +def fno_dwarf2_cfi_asm : Flag<["-"], "fno-dwarf2-cfi-asm">, Group, Flags<[CC1Option]>; +def fdwarf_directory_asm : Flag<["-"], "fdwarf-directory-asm">, Group; +def fno_dwarf_directory_asm : Flag<["-"], "fno-dwarf-directory-asm">, Group, Flags<[CC1Option]>; +def felide_constructors : Flag<["-"], "felide-constructors">, Group; +def fno_elide_type : Flag<["-"], "fno-elide-type">, Group, Flags<[CC1Option]>, HelpText<"Do not elide types when printing diagnostics">; -def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group; -def femit_all_decls : Flag<"-femit-all-decls">, Group, Flags<[CC1Option]>, +def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbols">, Group; +def femit_all_decls : Flag<["-"], "femit-all-decls">, Group, Flags<[CC1Option]>, HelpText<"Emit all declarations, even if unused">; -def fencoding_EQ : Joined<"-fencoding=">, Group; -def ferror_limit_EQ : Joined<"-ferror-limit=">, Group; -def fexceptions : Flag<"-fexceptions">, Group, Flags<[CC1Option]>, +def fencoding_EQ : Joined<["-"], "fencoding=">, Group; +def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group; +def fexceptions : Flag<["-"], "fexceptions">, Group, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; -def fextdirs_EQ : Joined<"-fextdirs=">, Group; -def fhosted : Flag<"-fhosted">, Group; -def ffast_math : Flag<"-ffast-math">, Group, Flags<[CC1Option]>, +def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group; +def fhosted : Flag<["-"], "fhosted">, Group; +def ffast_math : Flag<["-"], "ffast-math">, Group, Flags<[CC1Option]>, HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on " "optimizations, but provides a preprocessor macro __FAST_MATH__ the " - "same as GCC's -ffast-math flag.">; -def fmath_errno : Flag<"-fmath-errno">, Group, Flags<[CC1Option]>, + "same as GCC's -ffast-math flag">; +def fno_fast_math : Flag<["-"], "fno-fast-math">, Group; +def fmath_errno : Flag<["-"], "fmath-errno">, Group, Flags<[CC1Option]>, HelpText<"Require math functions to indicate errors by setting errno">; -def fno_math_errno : Flag<"-fno-math-errno">, Group; -def fsignaling_math : Flag<"-fsignaling-math">, Group; -def fno_signaling_math : Flag<"-fno-signaling-math">, Group; -def funsafe_math_optimizations : Flag<"-funsafe-math-optimizations">, +def fno_math_errno : Flag<["-"], "fno-math-errno">, Group; +def fsignaling_math : Flag<["-"], "fsignaling-math">, Group; +def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group; +def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group, + Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Enable runtime instrumentation for bug detection: " + "address (memory errors) | thread (race detection) | " + "undefined (miscellaneous undefined behavior)">; +def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group; +def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group; -def fno_unsafe_math_optimizations : Flag<"-fno-unsafe-math-optimizations">, +def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, Group; -def fassociative_math : Flag<"-fassociative-math">, Group; -def fno_associative_math : Flag<"-fno-associative-math">, Group; -def freciprocal_math : Flag<"-freciprocal-math">, Group; -def fno_reciprocal_math : Flag<"-fno-reciprocal-math">, Group; -def ffinite_math_only : Flag<"-ffinite-math-only">, Group, Flags<[CC1Option]>; -def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group; -def fsigned_zeros : Flag<"-fsigned-zeros">, Group; -def fno_signed_zeros : Flag<"-fno-signed-zeros">, Group; -def fhonor_nans : Flag<"-fhonor-nans">, Group; -def fno_honor_nans : Flag<"-fno-honor-nans">, Group; -def fhonor_infinities : Flag<"-fhonor-infinities">, Group; -def fno_honor_infinities : Flag<"-fno-honor-infinities">, Group; +def fassociative_math : Flag<["-"], "fassociative-math">, Group; +def fno_associative_math : Flag<["-"], "fno-associative-math">, Group; +def freciprocal_math : Flag<["-"], "freciprocal-math">, Group; +def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group; +def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group, Flags<[CC1Option]>; +def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group; +def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group; +def fno_signed_zeros : Flag<["-"], "fno-signed-zeros">, Group; +def fhonor_nans : Flag<["-"], "fhonor-nans">, Group; +def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group; +def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group; +def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group; // Sic. This option was misspelled originally. -def fhonor_infinites : Flag<"-fhonor-infinites">, Alias; -def fno_honor_infinites : Flag<"-fno-honor-infinites">, Alias; -def ftrapping_math : Flag<"-ftrapping-math">, Group; -def fno_trapping_math : Flag<"-fno-trapping-math">, Group; -def ffp_contract : Joined<"-ffp-contract=">, Group, +def fhonor_infinites : Flag<["-"], "fhonor-infinites">, Alias; +def fno_honor_infinites : Flag<["-"], "fno-honor-infinites">, Alias; +def ftrapping_math : Flag<["-"], "ftrapping-math">, Group; +def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group; +def ffp_contract : Joined<["-"], "ffp-contract=">, Group, Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">; -def ffor_scope : Flag<"-ffor-scope">, Group; -def fno_for_scope : Flag<"-fno-for-scope">, Group; +def ffor_scope : Flag<["-"], "ffor-scope">, Group; +def fno_for_scope : Flag<["-"], "fno-for-scope">, Group; -def frewrite_includes : Flag<"-frewrite-includes">, Group, +def frewrite_includes : Flag<["-"], "frewrite-includes">, Group, Flags<[CC1Option]>; -def fno_rewrite_includes : Flag<"-fno-rewrite-includes">, Group; +def fno_rewrite_includes : Flag<["-"], "fno-rewrite-includes">, Group; -def ffreestanding : Flag<"-ffreestanding">, Group, Flags<[CC1Option]>, +def ffreestanding : Flag<["-"], "ffreestanding">, Group, Flags<[CC1Option]>, HelpText<"Assert that the compilation takes place in a freestanding environment">; -def fgnu_keywords : Flag<"-fgnu-keywords">, Group, Flags<[CC1Option]>, +def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group, Flags<[CC1Option]>, HelpText<"Allow GNU-extension keywords regardless of language standard">; -def fgnu89_inline : Flag<"-fgnu89-inline">, Group, Flags<[CC1Option]>, +def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group, Flags<[CC1Option]>, HelpText<"Use the gnu89 inline semantics">; -def fno_gnu89_inline : Flag<"-fno-gnu89-inline">, Group; -def fgnu_runtime : Flag<"-fgnu-runtime">, Group, +def fno_gnu89_inline : Flag<["-"], "fno-gnu89-inline">, Group; +def fgnu_runtime : Flag<["-"], "fgnu-runtime">, Group, HelpText<"Generate output compatible with the standard GNU Objective-C runtime">; -def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">, Flags<[CC1Option]>; -def filelist : Separate<"-filelist">, Flags<[LinkerInput]>; -def findirect_virtual_calls : Flag<"-findirect-virtual-calls">, Alias; -def finline_functions : Flag<"-finline-functions">, Group; -def finline : Flag<"-finline">, Group; -def finstrument_functions : Flag<"-finstrument-functions">, Group, Flags<[CC1Option]>, +def fheinous_gnu_extensions : Flag<["-"], "fheinous-gnu-extensions">, Flags<[CC1Option]>; +def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>; +def findirect_virtual_calls : Flag<["-"], "findirect-virtual-calls">, Alias; +def finline_functions : Flag<["-"], "finline-functions">, Group; +def finline : Flag<["-"], "finline">, Group; +def finstrument_functions : Flag<["-"], "finstrument-functions">, Group, Flags<[CC1Option]>, HelpText<"Generate calls to instrument function entry and exit">; -def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group; -def flat__namespace : Flag<"-flat_namespace">; -def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group; -def flimit_debug_info : Flag<"-flimit-debug-info">, Group, Flags<[CC1Option]>, +def fkeep_inline_functions : Flag<["-"], "fkeep-inline-functions">, Group; +def flat__namespace : Flag<["-"], "flat_namespace">; +def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group; +def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Group, Flags<[CC1Option]>, HelpText<"Limit debug information produced to reduce size of debug binary">; -def flimited_precision_EQ : Joined<"-flimited-precision=">, Group; -def flto : Flag<"-flto">, Group; -def fno_lto : Flag<"-fno-lto">, Group; -def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">, +def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group; +def flto : Flag<["-"], "flto">, Group; +def fno_lto : Flag<["-"], "fno-lto">, Group; +def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, Group; -def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group; -def fmessage_length_EQ : Joined<"-fmessage-length=">, Group; -def fms_extensions : Flag<"-fms-extensions">, Group, Flags<[CC1Option]>, +def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group; +def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group; +def fms_extensions : Flag<["-"], "fms-extensions">, Group, Flags<[CC1Option]>, HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; -def fenable_experimental_ms_inline_asm : Flag<"-fenable-experimental-ms-inline-asm">, Group, Flags<[CC1Option]>, +def fenable_experimental_ms_inline_asm : Flag<["-"], "fenable-experimental-ms-inline-asm">, Group, Flags<[CC1Option]>, HelpText<"Enable support for Microsoft style inine assembly">; -def fms_compatibility : Flag<"-fms-compatibility">, Group, Flags<[CC1Option]>, +def fms_compatibility : Flag<["-"], "fms-compatibility">, Group, Flags<[CC1Option]>, HelpText<"Enable Microsoft compatibility mode">; -def fmsc_version : Joined<"-fmsc-version=">, Group, Flags<[CC1Option]>, +def fmsc_version : Joined<["-"], "fmsc-version=">, Group, Flags<[CC1Option]>, HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">; -def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group, +def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group, HelpText<"Parse templated function definitions at the end of the " "translation unit ">, Flags<[CC1Option]>; -def fmodule_cache_path : Separate<"-fmodule-cache-path">, Group, +def fmodule_cache_path : Separate<["-"], "fmodule-cache-path">, Group, Flags<[NoForward,CC1Option]>, MetaVarName<"">, HelpText<"Specify the module cache path">; -def fmodules : Flag <"-fmodules">, Group, Flags<[NoForward,CC1Option]>, +def fmodules : Flag <["-"], "fmodules">, Group, Flags<[NoForward,CC1Option]>, HelpText<"Enable the 'modules' language feature">; - -def fmudflapth : Flag<"-fmudflapth">, Group; -def fmudflap : Flag<"-fmudflap">, Group; -def fnested_functions : Flag<"-fnested-functions">, Group; -def fnext_runtime : Flag<"-fnext-runtime">, Group; -def fno_access_control : Flag<"-fno-access-control">, Group, Flags<[CC1Option]>, +def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group, Flags<[CC1Option]>; + +def fmudflapth : Flag<["-"], "fmudflapth">, Group; +def fmudflap : Flag<["-"], "fmudflap">, Group; +def fnested_functions : Flag<["-"], "fnested-functions">, Group; +def fnext_runtime : Flag<["-"], "fnext-runtime">, Group; +def fno_access_control : Flag<["-"], "fno-access-control">, Group, Flags<[CC1Option]>, HelpText<"Disable C++ access control">; -def fno_apple_pragma_pack : Flag<"-fno-apple-pragma-pack">, Group; -def fno_asm : Flag<"-fno-asm">, Group; -def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group; -def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group, +def fno_apple_pragma_pack : Flag<["-"], "fno-apple-pragma-pack">, Group; +def fno_asm : Flag<["-"], "fno-asm">, Group; +def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables">, Group; +def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group, HelpText<"Don't assume that C++'s global operator new can't alias any pointer">, Flags<[CC1Option]>; -def fno_blocks : Flag<"-fno-blocks">, Group; -def fno_borland_extensions : Flag<"-fno-borland-extensions">, Group; -def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group; -def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group; -def fno_builtin : Flag<"-fno-builtin">, Group, Flags<[CC1Option]>, +def fno_blocks : Flag<["-"], "fno-blocks">, Group; +def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group; +def fno_builtin_strcat : Flag<["-"], "fno-builtin-strcat">, Group; +def fno_builtin_strcpy : Flag<["-"], "fno-builtin-strcpy">, Group; +def fno_builtin : Flag<["-"], "fno-builtin">, Group, Flags<[CC1Option]>, HelpText<"Disable implicit builtin knowledge of functions">; -def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group, +def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group, Flags<[CC1Option]>; -def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group; -def fno_common : Flag<"-fno-common">, Group, Flags<[CC1Option]>, +def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group; +def fno_common : Flag<["-"], "fno-common">, Group, Flags<[CC1Option]>, HelpText<"Compile common globals like normal definitions">; -def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group, +def fno_constant_cfstrings : Flag<["-"], "fno-constant-cfstrings">, Group, Flags<[CC1Option]>, HelpText<"Disable creation of CodeFoundation-type constant strings">; -def fno_cxx_exceptions: Flag<"-fno-cxx-exceptions">, Group; -def fno_cxx_modules : Flag <"-fno-cxx-modules">, Group, Flags<[NoForward]>; -def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group, +def fno_cxx_exceptions: Flag<["-"], "fno-cxx-exceptions">, Group; +def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group, Flags<[NoForward]>; +def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group, Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">; -def fno_diagnostics_show_name : Flag<"-fno-diagnostics-show-name">, Group; -def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group; -def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">, +def fno_diagnostics_show_name : Flag<["-"], "fno-diagnostics-show-name">, Group; +def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group; +def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">, Flags<[CC1Option]>, Group, HelpText<"Display include stacks for diagnostic notes">; -def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group, +def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group, HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>; -def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group, +def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group, HelpText<"Disable C++ copy constructor elision">, Flags<[CC1Option]>; -def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group; -def fno_exceptions : Flag<"-fno-exceptions">, Group; -def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group, Flags<[CC1Option]>; -def fno_inline_functions : Flag<"-fno-inline-functions">, Group, Flags<[CC1Option]>; -def fno_inline : Flag<"-fno-inline">, Group, Flags<[CC1Option]>; -def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group; -def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group, +def fno_eliminate_unused_debug_symbols : Flag<["-"], "fno-eliminate-unused-debug-symbols">, Group; +def fno_exceptions : Flag<["-"], "fno-exceptions">, Group; +def fno_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group, Flags<[CC1Option]>; +def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group, Flags<[CC1Option]>; +def fno_inline : Flag<["-"], "fno-inline">, Group, Flags<[CC1Option]>; +def fno_keep_inline_functions : Flag<["-"], "fno-keep-inline-functions">, Group; +def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>; -def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, Group, Flags<[CC1Option]>, +def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Group, Flags<[CC1Option]>, HelpText<"Do not limit debug information produced to reduce size of debug binary">; -def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group, - Flags<[CC1Option]>, HelpText<"Disallow merging of constants.">; -def fno_modules : Flag <"-fno-modules">, Group, Flags<[NoForward]>; -def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group; -def fno_ms_compatibility : Flag<"-fno-ms-compatibility">, Group; -def fno_delayed_template_parsing : Flag<"-fno-delayed-template-parsing">, Group; -def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group; -def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group; -def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group; -def fno_operator_names : Flag<"-fno-operator-names">, Group, +def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group, + Flags<[CC1Option]>, HelpText<"Disallow merging of constants">; +def fno_modules : Flag <["-"], "fno-modules">, Group, Flags<[NoForward]>; +def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group; +def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group; +def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group; +def fno_objc_exceptions: Flag<["-"], "fno-objc-exceptions">, Group; +def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group; +def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group; +def fno_operator_names : Flag<["-"], "fno-operator-names">, Group, HelpText<"Do not treat C++ operator name keywords as synonyms for operators">, Flags<[CC1Option]>; -def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group; -def fno_rtti : Flag<"-fno-rtti">, Group, Flags<[CC1Option]>, +def fno_pascal_strings : Flag<["-"], "fno-pascal-strings">, Group; +def fno_rtti : Flag<["-"], "fno-rtti">, Group, Flags<[CC1Option]>, HelpText<"Disable generation of rtti information">; -def fno_short_enums : Flag<"-fno-short-enums">, Group; -def fno_show_column : Flag<"-fno-show-column">, Group, Flags<[CC1Option]>, +def fno_short_enums : Flag<["-"], "fno-short-enums">, Group; +def fno_show_column : Flag<["-"], "fno-show-column">, Group, Flags<[CC1Option]>, HelpText<"Do not include column number on diagnostics">; -def fno_show_source_location : Flag<"-fno-show-source-location">, Group, +def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group, Flags<[CC1Option]>, HelpText<"Do not include source location information with diagnostics">; -def fno_spell_checking : Flag<"-fno-spell-checking">, Group, +def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group, Flags<[CC1Option]>, HelpText<"Disable spell-checking">; -def fno_stack_protector : Flag<"-fno-stack-protector">, Group; -def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group; -def fno_strict_enums : Flag<"-fno-strict-enums">, Group; -def fno_strict_overflow : Flag<"-fno-strict-overflow">, Group; -def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group, +def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group; +def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group; +def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group; +def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; +def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">; -def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group, Flags<[CC1Option]>, +def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group, Flags<[CC1Option]>, HelpText<"Don't use __cxa_atexit for calling destructors">; -def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group; -def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group; -def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group; -def fno_working_directory : Flag<"-fno-working-directory">, Group; -def fno_wrapv : Flag<"-fno-wrapv">, Group; -def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group; -def fobjc_arc : Flag<"-fobjc-arc">, Group, Flags<[CC1Option]>, +def fno_unit_at_a_time : Flag<["-"], "fno-unit-at-a-time">, Group; +def fno_unwind_tables : Flag<["-"], "fno-unwind-tables">, Group; +def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, Group; +def fno_working_directory : Flag<["-"], "fno-working-directory">, Group; +def fno_wrapv : Flag<["-"], "fno-wrapv">, Group; +def fno_zero_initialized_in_bss : Flag<["-"], "fno-zero-initialized-in-bss">, Group; +def fobjc_arc : Flag<["-"], "fobjc-arc">, Group, Flags<[CC1Option]>, HelpText<"Synthesize retain and release calls for Objective-C pointers">; -def fno_objc_arc : Flag<"-fno-objc-arc">, Group; -def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group, Flags<[CC1Option]>, +def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group; +def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group, Flags<[CC1Option]>, HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">; -def fno_objc_arc_exceptions : Flag<"-fno-objc-arc-exceptions">, Group; -def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group; -def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group; -def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group, +def fno_objc_arc_exceptions : Flag<["-"], "fno-objc-arc-exceptions">, Group; +def fobjc_atdefs : Flag<["-"], "fobjc-atdefs">, Group; +def fobjc_call_cxx_cdtors : Flag<["-"], "fobjc-call-cxx-cdtors">, Group; +def fobjc_exceptions: Flag<["-"], "fobjc-exceptions">, Group, HelpText<"Enable Objective-C exceptions">, Flags<[CC1Option]>; -def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group, Flags<[CC1Option]>, +def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group, Flags<[CC1Option]>, HelpText<"Use GC exclusively for Objective-C related memory management">; -def fobjc_gc : Flag<"-fobjc-gc">, Group, Flags<[CC1Option]>, +def fobjc_gc : Flag<["-"], "fobjc-gc">, Group, Flags<[CC1Option]>, HelpText<"Enable Objective-C garbage collection">; -def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group; -def fobjc_new_property : Flag<"-fobjc-new-property">, Group; -def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">, +def fobjc_legacy_dispatch : Flag<["-"], "fobjc-legacy-dispatch">, Group; +def fobjc_new_property : Flag<["-"], "fobjc-new-property">, Group; +def fobjc_infer_related_result_type : Flag<["-"], "fobjc-infer-related-result-type">, Group; -def fno_objc_infer_related_result_type : Flag< - "-fno-objc-infer-related-result-type">, Group, +def fno_objc_infer_related_result_type : Flag<["-"], + "fno-objc-infer-related-result-type">, Group, HelpText< "do not infer Objective-C related result type based on method family">, Flags<[CC1Option]>; -def fobjc_link_runtime: Flag<"-fobjc-link-runtime">, Group; +def fobjc_link_runtime: Flag<["-"], "fobjc-link-runtime">, Group; // Objective-C ABI options. -def fobjc_runtime_EQ : Joined<"-fobjc-runtime=">, Group, Flags<[CC1Option]>, +def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group, Flags<[CC1Option]>, HelpText<"Specify the target Objective-C runtime kind and version">; -def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group; -def fobjc_nonfragile_abi_version_EQ : Joined<"-fobjc-nonfragile-abi-version=">, Group; -def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group; -def fno_objc_nonfragile_abi : Flag<"-fno-objc-nonfragile-abi">, Group; +def fobjc_abi_version_EQ : Joined<["-"], "fobjc-abi-version=">, Group; +def fobjc_nonfragile_abi_version_EQ : Joined<["-"], "fobjc-nonfragile-abi-version=">, Group; +def fobjc_nonfragile_abi : Flag<["-"], "fobjc-nonfragile-abi">, Group; +def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group; -def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, Group; -def fobjc : Flag<"-fobjc">, Group; -def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group; -def fopenmp : Flag<"-fopenmp">, Group; -def fno_optimize_sibling_calls : Flag<"-fno-optimize-sibling-calls">, Group; -def foptimize_sibling_calls : Flag<"-foptimize-sibling-calls">, Group; -def force__cpusubtype__ALL : Flag<"-force_cpusubtype_ALL">; -def force__flat__namespace : Flag<"-force_flat_namespace">; -def force__load : Separate<"-force_load">; -def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, Group; -def fpack_struct : Flag<"-fpack-struct">, Group; -def fno_pack_struct : Flag<"-fno-pack-struct">, Group; -def fpack_struct_EQ : Joined<"-fpack-struct=">, Group, Flags<[CC1Option]>, +def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group; +def fobjc : Flag<["-"], "fobjc">, Group; +def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group; +def fopenmp : Flag<["-"], "fopenmp">, Group; +def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group; +def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group; +def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">; +def force__flat__namespace : Flag<["-"], "force_flat_namespace">; +def force__load : Separate<["-"], "force_load">; +def foutput_class_dir_EQ : Joined<["-"], "foutput-class-dir=">, Group; +def fpack_struct : Flag<["-"], "fpack-struct">, Group; +def fno_pack_struct : Flag<["-"], "fno-pack-struct">, Group; +def fpack_struct_EQ : Joined<["-"], "fpack-struct=">, Group, Flags<[CC1Option]>, HelpText<"Specify the default maximum struct packing alignment">; -def fpascal_strings : Flag<"-fpascal-strings">, Group, Flags<[CC1Option]>, +def fpascal_strings : Flag<["-"], "fpascal-strings">, Group, Flags<[CC1Option]>, HelpText<"Recognize and construct Pascal-style string literals">; -def fpch_preprocess : Flag<"-fpch-preprocess">, Group; -def fpic : Flag<"-fpic">, Group; -def fno_pic : Flag<"-fno-pic">, Group; -def fpie : Flag<"-fpie">, Group; -def fno_pie : Flag<"-fno-pie">, Group; -def fprofile_arcs : Flag<"-fprofile-arcs">, Group; -def fprofile_generate : Flag<"-fprofile-generate">, Group; -def framework : Separate<"-framework">, Flags<[LinkerInput]>; -def frandom_seed_EQ : Joined<"-frandom-seed=">, Group; -def frtti : Flag<"-frtti">, Group; -def fsched_interblock : Flag<"-fsched-interblock">, Group; -def fshort_enums : Flag<"-fshort-enums">, Group, Flags<[CC1Option]>, +def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group; +def fpic : Flag<["-"], "fpic">, Group; +def fno_pic : Flag<["-"], "fno-pic">, Group; +def fpie : Flag<["-"], "fpie">, Group; +def fno_pie : Flag<["-"], "fno-pie">, Group; +def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group; +def fprofile_generate : Flag<["-"], "fprofile-generate">, Group; +def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>; +def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group; +def frtti : Flag<["-"], "frtti">, Group; +def fsched_interblock : Flag<["-"], "fsched-interblock">, Group; +def fshort_enums : Flag<["-"], "fshort-enums">, Group, Flags<[CC1Option]>, HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; -def freorder_blocks : Flag<"-freorder-blocks">, Group; -def fshort_wchar : Flag<"-fshort-wchar">, Group, Flags<[CC1Option]>, +def freorder_blocks : Flag<["-"], "freorder-blocks">, Group; +def fshort_wchar : Flag<["-"], "fshort-wchar">, Group, Flags<[CC1Option]>, HelpText<"Force wchar_t to be a short unsigned int">; -def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group, Flags<[CC1Option]>, +def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group, Flags<[CC1Option]>, HelpText<"Which overload candidates to show when overload resolution fails: " "best|all; defaults to all">; -def fshow_column : Flag<"-fshow-column">, Group, Flags<[CC1Option]>; -def fshow_source_location : Flag<"-fshow-source-location">, Group; -def fspell_checking : Flag<"-fspell-checking">, Group; -def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group; -def fsigned_char : Flag<"-fsigned-char">, Group; -def fstack_protector_all : Flag<"-fstack-protector-all">, Group; -def fstack_protector : Flag<"-fstack-protector">, Group; -def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group; -def fstrict_enums : Flag<"-fstrict-enums">, Group, Flags<[CC1Option]>, +def fshow_column : Flag<["-"], "fshow-column">, Group, Flags<[CC1Option]>; +def fshow_source_location : Flag<["-"], "fshow-source-location">, Group; +def fspell_checking : Flag<["-"], "fspell-checking">, Group; +def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group; +def fsigned_char : Flag<["-"], "fsigned-char">, Group; +def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group; +def fstack_protector : Flag<["-"], "fstack-protector">, Group; +def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group; +def fstrict_enums : Flag<["-"], "fstrict-enums">, Group, Flags<[CC1Option]>, HelpText<"Enable optimizations based on the strict definition of an enum's " - "value range.">; -def fstrict_overflow : Flag<"-fstrict-overflow">, Group; -def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption,CC1Option]>, Group; -def ftabstop_EQ : Joined<"-ftabstop=">, Group; -def ftemplate_depth_EQ : Joined<"-ftemplate-depth=">, Group; -def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group; -def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, + "value range">; +def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group; +def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[DriverOption,CC1Option]>, Group; +def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group; +def ftemplate_depth_EQ : Joined<["-"], "ftemplate-depth=">, Group; +def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">, Group; +def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">, Group; -def ftest_coverage : Flag<"-ftest-coverage">, Group; -def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">, +def ftest_coverage : Flag<["-"], "ftest-coverage">, Group; +def Wlarge_by_value_copy_def : Flag<["-"], "Wlarge-by-value-copy">, HelpText<"Warn if a function definition returns or accepts an object larger " - "in bytes that a given value">; -def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">, Flags<[CC1Option]>; + "in bytes than a given value">, Flags<[HelpHidden]>; +def Wlarge_by_value_copy_EQ : Joined<["-"], "Wlarge-by-value-copy=">, Flags<[CC1Option]>; // Just silence warnings about -Wlarger-than, -Wframe-larger-than for now. -def Wlarger_than : Separate<"-Wlarger-than">, Group; -def Wlarger_than_EQ : Joined<"-Wlarger-than=">, Alias; -def Wlarger_than_ : Joined<"-Wlarger-than-">, Alias; -def Wframe_larger_than : Separate<"-Wframe-larger-than">, Group; -def Wframe_larger_than_EQ : Joined<"-Wframe-larger-than=">, Alias; +def Wlarger_than : Separate<["-"], "Wlarger-than">, Group; +def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Alias; +def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias; +def Wframe_larger_than : Separate<["-"], "Wframe-larger-than">, Group; +def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Alias; -def fterminated_vtables : Flag<"-fterminated-vtables">, Alias; -def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group; -def ftime_report : Flag<"-ftime-report">, Group, Flags<[CC1Option]>; -def ftlsmodel_EQ : Joined<"-ftls-model=">, Group, Flags<[CC1Option]>; -def ftrapv : Flag<"-ftrapv">, Group, Flags<[CC1Option]>, +def fterminated_vtables : Flag<["-"], "fterminated-vtables">, Alias; +def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group; +def ftime_report : Flag<["-"], "ftime-report">, Group, Flags<[CC1Option]>; +def ftlsmodel_EQ : Joined<["-"], "ftls-model=">, Group, Flags<[CC1Option]>; +def ftrapv : Flag<["-"], "ftrapv">, Group, Flags<[CC1Option]>, HelpText<"Trap on integer overflow">; -def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group, +def ftrapv_handler_EQ : Joined<["-"], "ftrapv-handler=">, Group, MetaVarName<"">, - HelpText<"Specify the function to be called on overflow.">; -def ftrapv_handler : Separate<"-ftrapv-handler">, Group, Flags<[CC1Option]>; -def ftrap_function_EQ : Joined<"-ftrap-function=">, Group, Flags<[CC1Option]>, + HelpText<"Specify the function to be called on overflow">; +def ftrapv_handler : Separate<["-"], "ftrapv-handler">, Group, Flags<[CC1Option]>; +def ftrap_function_EQ : Joined<["-"], "ftrap-function=">, Group, Flags<[CC1Option]>, HelpText<"Issue call to specified function rather than a trap instruction">; -def funit_at_a_time : Flag<"-funit-at-a-time">, Group; -def funroll_loops : Flag<"-funroll-loops">, Group, +def funit_at_a_time : Flag<["-"], "funit-at-a-time">, Group; +def funroll_loops : Flag<["-"], "funroll-loops">, Group, HelpText<"Turn on loop unroller">, Flags<[CC1Option]>; -def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group; -def funsigned_char : Flag<"-funsigned-char">, Group; -def funwind_tables : Flag<"-funwind-tables">, Group; -def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group; -def fverbose_asm : Flag<"-fverbose-asm">, Group; -def fvisibility_EQ : Joined<"-fvisibility=">, Group; -def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group, +def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group; +def funsigned_char : Flag<["-"], "funsigned-char">, Group; +def funwind_tables : Flag<["-"], "funwind-tables">, Group; +def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group; +def fverbose_asm : Flag<["-"], "fverbose-asm">, Group; +def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group; +def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group, HelpText<"Give inline C++ member functions default visibility by default">, Flags<[CC1Option]>; -def fwrapv : Flag<"-fwrapv">, Group, Flags<[CC1Option]>, +def fwrapv : Flag<["-"], "fwrapv">, Group, Flags<[CC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; -def fwritable_strings : Flag<"-fwritable-strings">, Group, Flags<[CC1Option]>, +def fwritable_strings : Flag<["-"], "fwritable-strings">, Group, Flags<[CC1Option]>, HelpText<"Store string literals as writable data">; -def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group; -def ffunction_sections: Flag <"-ffunction-sections">, Group, +def fzero_initialized_in_bss : Flag<["-"], "fzero-initialized-in-bss">, Group; +def ffunction_sections: Flag <["-"], "ffunction-sections">, Group, Flags<[CC1Option]>, HelpText<"Place each function in its own section (ELF Only)">; -def fdata_sections : Flag <"-fdata-sections">, Group, Flags<[CC1Option]>, +def fdata_sections : Flag <["-"], "fdata-sections">, Group, Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">; -def f : Joined<"-f">, Group; -def g_Flag : Flag<"-g">, Group, +def f : Joined<["-"], "f">, Group; +def g_Flag : Flag<["-"], "g">, Group, HelpText<"Generate source level debug information">, Flags<[CC1Option]>; -def gline_tables_only : Flag<"-gline-tables-only">, Group, +def gline_tables_only : Flag<["-"], "gline-tables-only">, Group, HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>; -def g0 : Flag<"-g0">, Group; -def g1 : Flag<"-g1">, Group; -def g2 : Flag<"-g2">, Group; -def g3 : Flag<"-g3">, Group; -def ggdb : Flag<"-ggdb">, Group; -def ggdb0 : Flag<"-ggdb0">, Group; -def ggdb1 : Flag<"-ggdb1">, Group; -def ggdb2 : Flag<"-ggdb2">, Group; -def ggdb3 : Flag<"-ggdb3">, Group; -def gdwarf_2 : Flag<"-gdwarf-2">, Group; -def gdwarf_3 : Flag<"-gdwarf-3">, Group; -def gdwarf_4 : Flag<"-gdwarf-4">, Group; -def gfull : Flag<"-gfull">, Group; -def gused : Flag<"-gused">, Group; -def gstabs : Joined<"-gstabs">, Group, Flags<[Unsupported]>; -def gcoff : Joined<"-gcoff">, Group, Flags<[Unsupported]>; -def gxcoff : Joined<"-gxcoff">, Group, Flags<[Unsupported]>; -def gvms : Joined<"-gvms">, Group, Flags<[Unsupported]>; -def gtoggle : Flag<"-gtoggle">, Group, Flags<[Unsupported]>; -def grecord_gcc_switches : Flag<"-grecord-gcc-switches">, Group; -def gno_record_gcc_switches : Flag<"-gno-record-gcc-switches">, +def g0 : Flag<["-"], "g0">, Group; +def g1 : Flag<["-"], "g1">, Group; +def g2 : Flag<["-"], "g2">, Group; +def g3 : Flag<["-"], "g3">, Group; +def ggdb : Flag<["-"], "ggdb">, Group; +def ggdb0 : Flag<["-"], "ggdb0">, Group; +def ggdb1 : Flag<["-"], "ggdb1">, Group; +def ggdb2 : Flag<["-"], "ggdb2">, Group; +def ggdb3 : Flag<["-"], "ggdb3">, Group; +def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group; +def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group; +def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group; +def gfull : Flag<["-"], "gfull">, Group; +def gused : Flag<["-"], "gused">, Group; +def gstabs : Joined<["-"], "gstabs">, Group, Flags<[Unsupported]>; +def gcoff : Joined<["-"], "gcoff">, Group, Flags<[Unsupported]>; +def gxcoff : Joined<["-"], "gxcoff">, Group, Flags<[Unsupported]>; +def gvms : Joined<["-"], "gvms">, Group, Flags<[Unsupported]>; +def gtoggle : Flag<["-"], "gtoggle">, Group, Flags<[Unsupported]>; +def grecord_gcc_switches : Flag<["-"], "grecord-gcc-switches">, Group; +def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">, Group; -def gstrict_dwarf : Flag<"-gstrict-dwarf">, Group; -def gno_strict_dwarf : Flag<"-gno-strict-dwarf">, Group; -def headerpad__max__install__names : Joined<"-headerpad_max_install_names">; -def help : Flag<"-help">, Flags<[CC1Option]>, +def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group; +def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group; +def gcolumn_info : Flag<["-"], "gcolumn-info">, Group; +def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; +def help : Flag<["-", "--"], "help">, Flags<[CC1Option]>, HelpText<"Display available options">; -def index_header_map : Flag<"-index-header-map">, Flags<[CC1Option]>, +def index_header_map : Flag<["-"], "index-header-map">, Flags<[CC1Option]>, HelpText<"Make the next included directory (-I or -F) an indexer header map">; -def idirafter : JoinedOrSeparate<"-idirafter">, Group, Flags<[CC1Option]>, +def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group, Flags<[CC1Option]>, HelpText<"Add directory to AFTER include search path">; -def iframework : Joined<"-iframework">, Group, Flags<[CC1Option]>, +def iframework : JoinedOrSeparate<["-"], "iframework">, Group, Flags<[CC1Option]>, HelpText<"Add directory to SYSTEM framework search path">; -def imacros : JoinedOrSeparate<"-imacros">, Group, Flags<[CC1Option]>, +def imacros : JoinedOrSeparate<["-", "--"], "imacros">, Group, Flags<[CC1Option]>, HelpText<"Include macros from file before parsing">, MetaVarName<"">; -def image__base : Separate<"-image_base">; -def include_ : JoinedOrSeparate<"-include">, Group, EnumName<"include">, +def image__base : Separate<["-"], "image_base">; +def include_ : JoinedOrSeparate<["-", "--"], "include">, Group, EnumName<"include">, MetaVarName<"">, HelpText<"Include file before parsing">, Flags<[CC1Option]>; -def include_pch : Separate<"-include-pch">, Group, Flags<[CC1Option]>, +def include_pch : Separate<["-"], "include-pch">, Group, Flags<[CC1Option]>, HelpText<"Include precompiled header file">, MetaVarName<"">; -def init : Separate<"-init">; -def install__name : Separate<"-install_name">; -def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>; -def iprefix : JoinedOrSeparate<"-iprefix">, Group, Flags<[CC1Option]>, +def init : Separate<["-"], "init">; +def install__name : Separate<["-"], "install_name">; +def integrated_as : Flag<["-"], "integrated-as">, Flags<[DriverOption]>; +def iprefix : JoinedOrSeparate<["-"], "iprefix">, Group, Flags<[CC1Option]>, HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"">; -def iquote : JoinedOrSeparate<"-iquote">, Group, Flags<[CC1Option]>, +def iquote : JoinedOrSeparate<["-"], "iquote">, Group, Flags<[CC1Option]>, HelpText<"Add directory to QUOTE include search path">, MetaVarName<"">; -def isysroot : JoinedOrSeparate<"-isysroot">, Group, Flags<[CC1Option]>, +def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group, Flags<[CC1Option]>, HelpText<"Set the system root directory (usually /)">, MetaVarName<"">; -def isystem : JoinedOrSeparate<"-isystem">, Group, Flags<[CC1Option]>, +def isystem : JoinedOrSeparate<["-"], "isystem">, Group, Flags<[CC1Option]>, HelpText<"Add directory to SYSTEM include search path">, MetaVarName<"">; -def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group, +def iwithprefixbefore : JoinedOrSeparate<["-"], "iwithprefixbefore">, Group, HelpText<"Set directory to include search path with prefix">, MetaVarName<"">, Flags<[CC1Option]>; -def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group, Flags<[CC1Option]>, +def iwithprefix : JoinedOrSeparate<["-"], "iwithprefix">, Group, Flags<[CC1Option]>, HelpText<"Set directory to SYSTEM include search path with prefix">, MetaVarName<"">; -def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group, +def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group, HelpText<"Add directory to SYSTEM include search path, " "absolute paths are relative to -isysroot">, MetaVarName<"">, Flags<[CC1Option]>; -def i : Joined<"-i">, Group; -def keep__private__externs : Flag<"-keep_private_externs">; -def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>; -def lazy__framework : Separate<"-lazy_framework">, Flags<[LinkerInput]>; -def lazy__library : Separate<"-lazy_library">, Flags<[LinkerInput]>; -def m32 : Flag<"-m32">, Group, Flags<[DriverOption]>; -def mqdsp6_compat : Flag<"-mqdsp6-compat">, Group, Flags<[DriverOption,CC1Option]>, +def i : Joined<["-"], "i">, Group; +def keep__private__externs : Flag<["-"], "keep_private_externs">; +def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>; +def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>; +def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>; +def m32 : Flag<["-"], "m32">, Group, Flags<[DriverOption]>; +def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group, Flags<[DriverOption,CC1Option]>, HelpText<"Enable hexagon-qdsp6 backward compatibility">; -def m3dnowa : Flag<"-m3dnowa">, Group; -def m3dnow : Flag<"-m3dnow">, Group; -def m64 : Flag<"-m64">, Group, Flags<[DriverOption]>; -def mabi_EQ : Joined<"-mabi=">, Group; -def march_EQ : Joined<"-march=">, Group; -def maltivec : Flag<"-maltivec">, Alias; -def mcmodel_EQ : Joined<"-mcmodel=">, Group; -def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group; -def mcpu_EQ : Joined<"-mcpu=">, Group; -def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group; -def mfix_and_continue : Flag<"-mfix-and-continue">, Group; -def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group; -def mfpmath_EQ : Joined<"-mfpmath=">, Group; -def mfpu_EQ : Joined<"-mfpu=">, Group; -def mglobal_merge : Flag<"-mglobal-merge">, Group; -def mhard_float : Flag<"-mhard-float">, Group; -def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group; -def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias; -def mios_simulator_version_min_EQ : Joined<"-mios-simulator-version-min=">, Group; -def mkernel : Flag<"-mkernel">, Group; -def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>; -def mllvm : Separate<"-mllvm">, Flags<[CC1Option]>, +def m3dnowa : Flag<["-"], "m3dnowa">, Group; +def m3dnow : Flag<["-"], "m3dnow">, Group; +def m64 : Flag<["-"], "m64">, Group, Flags<[DriverOption]>; +def mabi_EQ : Joined<["-"], "mabi=">, Group; +def march_EQ : Joined<["-"], "march=">, Group; +def maltivec : Flag<["-"], "maltivec">, Alias; +def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group; +def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group; +def mcpu_EQ : Joined<["-"], "mcpu=">, Group; +def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group; +def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group; +def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group; +def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group; +def mfpu_EQ : Joined<["-"], "mfpu=">, Group; +def mglobal_merge : Flag<["-"], "mglobal-merge">, Group; +def mhard_float : Flag<["-"], "mhard-float">, Group; +def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group; +def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, Alias; +def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Group; +def mkernel : Flag<["-"], "mkernel">, Group; +def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Flags<[NoForward]>; +def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option]>, HelpText<"Additional arguments to forward to LLVM's option processing">; -def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group; -def mms_bitfields : Flag<"-mms-bitfields">, Group, Flags<[CC1Option]>, - HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">; -def mstackrealign : Flag<"-mstackrealign">, Group, Flags<[CC1Option]>, - HelpText<"Force realign the stack at entry to every function.">; -def mstack_alignment : Joined<"-mstack-alignment=">, Group, Flags<[CC1Option]>, +def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">, Group; +def mms_bitfields : Flag<["-"], "mms-bitfields">, Group, Flags<[CC1Option]>, + HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">; +def mstackrealign : Flag<["-"], "mstackrealign">, Group, Flags<[CC1Option]>, + HelpText<"Force realign the stack at entry to every function">; +def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group, Flags<[CC1Option]>, HelpText<"Set the stack alignment">; -def mmmx : Flag<"-mmmx">, Group; -def mno_3dnowa : Flag<"-mno-3dnowa">, Group; -def mno_3dnow : Flag<"-mno-3dnow">, Group; -def mno_constant_cfstrings : Flag<"-mno-constant-cfstrings">, Group; -def mno_global_merge : Flag<"-mno-global-merge">, Group, Flags<[CC1Option]>, +def mstrict_align : Flag<["-"], "mstrict-align">, Group, Flags<[CC1Option]>, + HelpText<"Force all memory accesses to be aligned (ARM only)">; +def mmmx : Flag<["-"], "mmmx">, Group; +def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group; +def mno_3dnow : Flag<["-"], "mno-3dnow">, Group; +def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group; +def mno_global_merge : Flag<["-"], "mno-global-merge">, Group, Flags<[CC1Option]>, HelpText<"Disable merging of globals">; -def mno_mmx : Flag<"-mno-mmx">, Group; -def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group; -def mno_red_zone : Flag<"-mno-red-zone">, Group; -def mno_relax_all : Flag<"-mno-relax-all">, Group; -def mno_rtd: Flag<"-mno-rtd">, Group; -def mno_soft_float : Flag<"-mno-soft-float">, Group; -def mno_stackrealign : Flag<"-mno-stackrealign">, Group; -def mno_sse2 : Flag<"-mno-sse2">, Group; -def mno_sse3 : Flag<"-mno-sse3">, Group; -def mno_sse4a : Flag<"-mno-sse4a">, Group; -def mno_sse4 : Flag<"-mno-sse4">, Group; -def mno_sse4_1 : Flag<"-mno-sse4.1">, Group; -def mno_sse4_2 : Flag<"-mno-sse4.2">, Group; -def mno_sse : Flag<"-mno-sse">, Group; -def mno_ssse3 : Flag<"-mno-ssse3">, Group; -def mno_aes : Flag<"-mno-aes">, Group; -def mno_avx : Flag<"-mno-avx">, Group; -def mno_avx2 : Flag<"-mno-avx2">, Group; -def mno_pclmul : Flag<"-mno-pclmul">, Group; -def mno_lzcnt : Flag<"-mno-lzcnt">, Group; -def mno_rdrnd : Flag<"-mno-rdrnd">, Group; -def mno_bmi : Flag<"-mno-bmi">, Group; -def mno_bmi2 : Flag<"-mno-bmi2">, Group; -def mno_popcnt : Flag<"-mno-popcnt">, Group; -def mno_fma4 : Flag<"-mno-fma4">, Group; -def mno_fma : Flag<"-mno-fma">, Group; -def mno_xop : Flag<"-mno-xop">, Group; +def mno_mmx : Flag<["-"], "mno-mmx">, Group; +def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">, Group; +def mno_red_zone : Flag<["-"], "mno-red-zone">, Group; +def mno_relax_all : Flag<["-"], "mno-relax-all">, Group; +def mno_rtd: Flag<["-"], "mno-rtd">, Group; +def mno_soft_float : Flag<["-"], "mno-soft-float">, Group; +def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group; +def mno_sse2 : Flag<["-"], "mno-sse2">, Group; +def mno_sse3 : Flag<["-"], "mno-sse3">, Group; +def mno_sse4a : Flag<["-"], "mno-sse4a">, Group; +def mno_sse4 : Flag<["-"], "mno-sse4">, Group; +def mno_sse4_1 : Flag<["-"], "mno-sse4.1">, Group; +def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group; +def mno_sse : Flag<["-"], "mno-sse">, Group; +def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group; +def mno_aes : Flag<["-"], "mno-aes">, Group; +def mno_avx : Flag<["-"], "mno-avx">, Group; +def mno_avx2 : Flag<["-"], "mno-avx2">, Group; +def mno_pclmul : Flag<["-"], "mno-pclmul">, Group; +def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group; +def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group; +def mno_bmi : Flag<["-"], "mno-bmi">, Group; +def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group; +def mno_popcnt : Flag<["-"], "mno-popcnt">, Group; +def mno_fma4 : Flag<["-"], "mno-fma4">, Group; +def mno_fma : Flag<["-"], "mno-fma">, Group; +def mno_xop : Flag<["-"], "mno-xop">, Group; +def mno_f16c : Flag<["-"], "mno-f16c">, Group; +def mno_rtm : Flag<["-"], "mno-rtm">, Group; -def mno_thumb : Flag<"-mno-thumb">, Group; -def marm : Flag<"-marm">, Alias; +def mno_thumb : Flag<["-"], "mno-thumb">, Group; +def marm : Flag<["-"], "marm">, Alias; -def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group; -def mno_omit_leaf_frame_pointer : Flag<"-mno-omit-leaf-frame-pointer">, Group; -def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group, - HelpText<"Omit frame pointer setup for leaf functions.">, Flags<[CC1Option]>; -def mpascal_strings : Flag<"-mpascal-strings">, Group; -def mred_zone : Flag<"-mred-zone">, Group; -def mregparm_EQ : Joined<"-mregparm=">, Group; -def mrelax_all : Flag<"-mrelax-all">, Group, Flags<[CC1Option]>, +def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings">, Group; +def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group; +def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group, + HelpText<"Omit frame pointer setup for leaf functions">, Flags<[CC1Option]>; +def mpascal_strings : Flag<["-"], "mpascal-strings">, Group; +def mred_zone : Flag<["-"], "mred-zone">, Group; +def mregparm_EQ : Joined<["-"], "mregparm=">, Group; +def mrelax_all : Flag<["-"], "mrelax-all">, Group, Flags<[CC1Option]>, HelpText<"(integrated-as) Relax all machine instructions">; -def mrtd : Flag<"-mrtd">, Group, Flags<[CC1Option]>, +def mrtd : Flag<["-"], "mrtd">, Group, Flags<[CC1Option]>, HelpText<"Make StdCall calling convention the default">; -def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group; -def msoft_float : Flag<"-msoft-float">, Group, Flags<[CC1Option]>, +def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">, Group; +def msoft_float : Flag<["-"], "msoft-float">, Group, Flags<[CC1Option]>, HelpText<"Use software floating point">; -def mno_implicit_float : Flag<"-mno-implicit-float">, Group, +def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group, HelpText<"Don't generate implicit floating point instructions">; -def msse2 : Flag<"-msse2">, Group; -def msse3 : Flag<"-msse3">, Group; -def msse4a : Flag<"-msse4a">, Group; -def msse4 : Flag<"-msse4">, Group; -def msse4_1 : Flag<"-msse4.1">, Group; -def msse4_2 : Flag<"-msse4.2">, Group; -def msse : Flag<"-msse">, Group; -def mssse3 : Flag<"-mssse3">, Group; -def maes : Flag<"-maes">, Group; -def mavx : Flag<"-mavx">, Group; -def mavx2 : Flag<"-mavx2">, Group; -def mpclmul : Flag<"-mpclmul">, Group; -def mlzcnt : Flag<"-mlzcnt">, Group; -def mrdrnd : Flag<"-mrdrnd">, Group; -def mbmi : Flag<"-mbmi">, Group; -def mbmi2 : Flag<"-mbmi2">, Group; -def mpopcnt : Flag<"-mpopcnt">, Group; -def mfma4 : Flag<"-mfma4">, Group; -def mfma : Flag<"-mfma">, Group; -def mxop : Flag<"-mxop">, Group; -def mips16 : Flag<"-mips16">, Group; -def mno_mips16 : Flag<"-mno-mips16">, Group; -def mdsp : Flag<"-mdsp">, Group; -def mno_dsp : Flag<"-mno-dsp">, Group; -def mdspr2 : Flag<"-mdspr2">, Group; -def mno_dspr2 : Flag<"-mno-dspr2">, Group; -def mthumb : Flag<"-mthumb">, Group; -def mtune_EQ : Joined<"-mtune=">, Group; -def multi__module : Flag<"-multi_module">; -def multiply__defined__unused : Separate<"-multiply_defined_unused">; -def multiply__defined : Separate<"-multiply_defined">; -def mwarn_nonportable_cfstrings : Flag<"-mwarn-nonportable-cfstrings">, Group; -def m_Separate : Separate<"-m">, Group; -def m_Joined : Joined<"-m">, Group; -def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[HelpHidden]>, +def msse2 : Flag<["-"], "msse2">, Group; +def msse3 : Flag<["-"], "msse3">, Group; +def msse4a : Flag<["-"], "msse4a">, Group; +def msse4 : Flag<["-"], "msse4">, Group; +def msse4_1 : Flag<["-"], "msse4.1">, Group; +def msse4_2 : Flag<["-"], "msse4.2">, Group; +def msse : Flag<["-"], "msse">, Group; +def mssse3 : Flag<["-"], "mssse3">, Group; +def maes : Flag<["-"], "maes">, Group; +def mavx : Flag<["-"], "mavx">, Group; +def mavx2 : Flag<["-"], "mavx2">, Group; +def mpclmul : Flag<["-"], "mpclmul">, Group; +def mlzcnt : Flag<["-"], "mlzcnt">, Group; +def mrdrnd : Flag<["-"], "mrdrnd">, Group; +def mbmi : Flag<["-"], "mbmi">, Group; +def mbmi2 : Flag<["-"], "mbmi2">, Group; +def mpopcnt : Flag<["-"], "mpopcnt">, Group; +def mfma4 : Flag<["-"], "mfma4">, Group; +def mfma : Flag<["-"], "mfma">, Group; +def mxop : Flag<["-"], "mxop">, Group; +def mf16c : Flag<["-"], "mf16c">, Group; +def mrtm : Flag<["-"], "mrtm">, Group; +def mips16 : Flag<["-"], "mips16">, Group; +def mno_mips16 : Flag<["-"], "mno-mips16">, Group; +def mdsp : Flag<["-"], "mdsp">, Group; +def mno_dsp : Flag<["-"], "mno-dsp">, Group; +def mdspr2 : Flag<["-"], "mdspr2">, Group; +def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group; +def mips32 : Flag<["-"], "mips32">, Group, + HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>; +def mips32r2 : Flag<["-"], "mips32r2">, Group, + HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>; +def mips64 : Flag<["-"], "mips64">, Group, + HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>; +def mips64r2 : Flag<["-"], "mips64r2">, Group, + HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>; +def mthumb : Flag<["-"], "mthumb">, Group; +def mtune_EQ : Joined<["-"], "mtune=">, Group; +def multi__module : Flag<["-"], "multi_module">; +def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">; +def multiply__defined : Separate<["-"], "multiply_defined">; +def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Group; +def m_Separate : Separate<["-"], "m">, Group; +def m_Joined : Joined<["-"], "m">, Group; +def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden]>, HelpText<"Use relative instead of canonical paths">; -def no_cpp_precomp : Flag<"-no-cpp-precomp">, Group; -def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>; -def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>; -def no_pedantic : Flag<"-no-pedantic">, Group; -def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">; -def nobuiltininc : Flag<"-nobuiltininc">, Flags<[CC1Option]>, +def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group; +def no_integrated_as : Flag<["-"], "no-integrated-as">, Flags<[DriverOption]>; +def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>; +def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group; +def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">; +def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option]>, HelpText<"Disable builtin #include directories">; -def nodefaultlibs : Flag<"-nodefaultlibs">; -def nofixprebinding : Flag<"-nofixprebinding">; -def nolibc : Flag<"-nolibc">; -def nomultidefs : Flag<"-nomultidefs">; -def noprebind : Flag<"-noprebind">; -def noseglinkedit : Flag<"-noseglinkedit">; -def nostartfiles : Flag<"-nostartfiles">; -def nostdinc : Flag<"-nostdinc">; -def nostdlibinc : Flag<"-nostdlibinc">; -def nostdincxx : Flag<"-nostdinc++">, Flags<[CC1Option]>, +def nodefaultlibs : Flag<["-"], "nodefaultlibs">; +def nofixprebinding : Flag<["-"], "nofixprebinding">; +def nolibc : Flag<["-"], "nolibc">; +def nomultidefs : Flag<["-"], "nomultidefs">; +def noprebind : Flag<["-"], "noprebind">; +def noseglinkedit : Flag<["-"], "noseglinkedit">; +def nostartfiles : Flag<["-"], "nostartfiles">; +def nostdinc : Flag<["-"], "nostdinc">; +def nostdlibinc : Flag<["-"], "nostdlibinc">; +def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>, HelpText<"Disable standard #include directories for the C++ standard library">; -def nostdlib : Flag<"-nostdlib">; -def object : Flag<"-object">; -def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput, CC1Option]>, +def nostdlib : Flag<["-"], "nostdlib">; +def object : Flag<["-"], "object">; +def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option]>, HelpText<"Write output to ">, MetaVarName<"">; -def pagezero__size : JoinedOrSeparate<"-pagezero_size">; -def pass_exit_codes : Flag<"-pass-exit-codes">, Flags<[Unsupported]>; -def pedantic_errors : Flag<"-pedantic-errors">, Group, Flags<[CC1Option]>; -def pedantic : Flag<"-pedantic">, Group, Flags<[CC1Option]>; -def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>; -def pipe : Flag<"-pipe">, +def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">; +def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>; +def pedantic_errors : Flag<["-", "--"], "pedantic-errors">, Group, Flags<[CC1Option]>; +def pedantic : Flag<["-", "--"], "pedantic">, Group, Flags<[CC1Option]>; +def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>; +def pipe : Flag<["-", "--"], "pipe">, HelpText<"Use pipes between commands, when possible">; -def prebind__all__twolevel__modules : Flag<"-prebind_all_twolevel_modules">; -def prebind : Flag<"-prebind">; -def preload : Flag<"-preload">; -def print_file_name_EQ : Joined<"-print-file-name=">, +def prebind__all__twolevel__modules : Flag<["-"], "prebind_all_twolevel_modules">; +def prebind : Flag<["-"], "prebind">; +def preload : Flag<["-"], "preload">; +def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">, HelpText<"Print the full library path of ">, MetaVarName<"">; -def print_ivar_layout : Flag<"-print-ivar-layout">, Flags<[CC1Option]>, +def print_ivar_layout : Flag<["-"], "print-ivar-layout">, Flags<[CC1Option]>, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; -def print_libgcc_file_name : Flag<"-print-libgcc-file-name">, +def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">, HelpText<"Print the library path for \"libgcc.a\"">; -def print_multi_directory : Flag<"-print-multi-directory">; -def print_multi_lib : Flag<"-print-multi-lib">; -def print_multi_os_directory : Flag<"-print-multi-os-directory">; -def print_prog_name_EQ : Joined<"-print-prog-name=">, +def print_multi_directory : Flag<["-", "--"], "print-multi-directory">; +def print_multi_lib : Flag<["-", "--"], "print-multi-lib">; +def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">; +def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">, HelpText<"Print the full program path of ">, MetaVarName<"">; -def print_search_dirs : Flag<"-print-search-dirs">, +def print_search_dirs : Flag<["-", "--"], "print-search-dirs">, HelpText<"Print the paths used for finding libraries and programs">; -def private__bundle : Flag<"-private_bundle">; -def pthreads : Flag<"-pthreads">; -def pthread : Flag<"-pthread">, Flags<[CC1Option]>, +def private__bundle : Flag<["-"], "private_bundle">; +def pthreads : Flag<["-"], "pthreads">; +def pthread : Flag<["-"], "pthread">, Flags<[CC1Option]>, HelpText<"Support POSIX threads in generated code">; -def p : Flag<"-p">; -def pie : Flag<"-pie">; -def read__only__relocs : Separate<"-read_only_relocs">; -def remap : Flag<"-remap">; -def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption,CC1Option]>, +def p : Flag<["-"], "p">; +def pie : Flag<["-"], "pie">; +def read__only__relocs : Separate<["-"], "read_only_relocs">; +def remap : Flag<["-"], "remap">; +def rewrite_objc : Flag<["-"], "rewrite-objc">, Flags<[DriverOption,CC1Option]>, HelpText<"Rewrite Objective-C source to C++">, Group; -def rewrite_legacy_objc : Flag<"-rewrite-legacy-objc">, Flags<[DriverOption]>, +def rewrite_legacy_objc : Flag<["-"], "rewrite-legacy-objc">, Flags<[DriverOption]>, HelpText<"Rewrite Legacy Objective-C source to C++">; -def rdynamic : Flag<"-rdynamic">; -def rpath : Separate<"-rpath">, Flags<[LinkerInput]>; -def rtlib_EQ : Joined<"-rtlib=">; -def r : Flag<"-r">; -def save_temps : Flag<"-save-temps">, Flags<[DriverOption]>, +def rdynamic : Flag<["-"], "rdynamic">; +def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>; +def rtlib_EQ : Joined<["-", "--"], "rtlib=">; +def r : Flag<["-"], "r">; +def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>, HelpText<"Save intermediate compilation results">; -def sectalign : MultiArg<"-sectalign", 3>; -def sectcreate : MultiArg<"-sectcreate", 3>; -def sectobjectsymbols : MultiArg<"-sectobjectsymbols", 2>; -def sectorder : MultiArg<"-sectorder", 3>; -def seg1addr : JoinedOrSeparate<"-seg1addr">; -def seg__addr__table__filename : Separate<"-seg_addr_table_filename">; -def seg__addr__table : Separate<"-seg_addr_table">; -def segaddr : MultiArg<"-segaddr", 2>; -def segcreate : MultiArg<"-segcreate", 3>; -def seglinkedit : Flag<"-seglinkedit">; -def segprot : MultiArg<"-segprot", 3>; -def segs__read__only__addr : Separate<"-segs_read_only_addr">; -def segs__read__write__addr : Separate<"-segs_read_write_addr">; -def segs__read__ : Joined<"-segs_read_">; -def shared_libgcc : Flag<"-shared-libgcc">; -def shared : Flag<"-shared">; -def single__module : Flag<"-single_module">; -def specs_EQ : Joined<"-specs=">; -def specs : Separate<"-specs">, Flags<[Unsupported]>; -def static_libgcc : Flag<"-static-libgcc">; -def static_libstdcxx : Flag<"-static-libstdc++">; -def static : Flag<"-static">, Flags<[NoArgumentUnused]>; -def std_default_EQ : Joined<"-std-default=">; -def std_EQ : Joined<"-std=">, Flags<[CC1Option]>, Group, +def sectalign : MultiArg<["-"], "sectalign", 3>; +def sectcreate : MultiArg<["-"], "sectcreate", 3>; +def sectobjectsymbols : MultiArg<["-"], "sectobjectsymbols", 2>; +def sectorder : MultiArg<["-"], "sectorder", 3>; +def seg1addr : JoinedOrSeparate<["-"], "seg1addr">; +def seg__addr__table__filename : Separate<["-"], "seg_addr_table_filename">; +def seg__addr__table : Separate<["-"], "seg_addr_table">; +def segaddr : MultiArg<["-"], "segaddr", 2>; +def segcreate : MultiArg<["-"], "segcreate", 3>; +def seglinkedit : Flag<["-"], "seglinkedit">; +def segprot : MultiArg<["-"], "segprot", 3>; +def segs__read__only__addr : Separate<["-"], "segs_read_only_addr">; +def segs__read__write__addr : Separate<["-"], "segs_read_write_addr">; +def segs__read__ : Joined<["-"], "segs_read_">; +def shared_libgcc : Flag<["-"], "shared-libgcc">; +def shared : Flag<["-", "--"], "shared">; +def single__module : Flag<["-"], "single_module">; +def specs_EQ : Joined<["-", "--"], "specs=">; +def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>; +def static_libgcc : Flag<["-"], "static-libgcc">; +def static_libstdcxx : Flag<["-"], "static-libstdc++">; +def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>; +def std_default_EQ : Joined<["-"], "std-default=">; +def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, Group, HelpText<"Language standard to compile for">; -def stdlib_EQ : Joined<"-stdlib=">, Flags<[CC1Option]>, +def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>, HelpText<"C++ standard library to use">; -def sub__library : JoinedOrSeparate<"-sub_library">; -def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">; -def s : Flag<"-s">; -def target : Separate<"-target">, Flags<[DriverOption]>, +def sub__library : JoinedOrSeparate<["-"], "sub_library">; +def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">; +def s : Flag<["-"], "s">; +def target : Separate<["-"], "target">, Flags<[DriverOption]>, HelpText<"Generate code for the given target">; -def gcc_toolchain : Separate<"-gcc-toolchain">, Flags<[DriverOption]>, +def gcc_toolchain : Separate<["-"], "gcc-toolchain">, Flags<[DriverOption]>, HelpText<"Use the gcc toolchain at the given directory">; -// We should deprecate the use of -ccc-host-triple, and then remove. -def ccc_host_triple : Separate<"-ccc-host-triple">, Alias; -def time : Flag<"-time">, +def time : Flag<["-"], "time">, HelpText<"Time individual commands">; -def traditional_cpp : Flag<"-traditional-cpp">, Flags<[CC1Option]>, +def traditional_cpp : Flag<["-", "--"], "traditional-cpp">, Flags<[CC1Option]>, HelpText<"Enable some traditional CPP emulation">; -def traditional : Flag<"-traditional">; -def trigraphs : Flag<"-trigraphs">, Flags<[CC1Option]>, +def traditional : Flag<["-", "--"], "traditional">; +def trigraphs : Flag<["-", "--"], "trigraphs">, Flags<[CC1Option]>, HelpText<"Process trigraph sequences">; -def twolevel__namespace__hints : Flag<"-twolevel_namespace_hints">; -def twolevel__namespace : Flag<"-twolevel_namespace">; -def t : Flag<"-t">; -def umbrella : Separate<"-umbrella">; -def undefined : JoinedOrSeparate<"-undefined">, Group; -def undef : Flag<"-undef">, Group, Flags<[CC1Option]>, +def twolevel__namespace__hints : Flag<["-"], "twolevel_namespace_hints">; +def twolevel__namespace : Flag<["-"], "twolevel_namespace">; +def t : Flag<["-"], "t">; +def umbrella : Separate<["-"], "umbrella">; +def undefined : JoinedOrSeparate<["-"], "undefined">, Group; +def undef : Flag<["-"], "undef">, Group, Flags<[CC1Option]>, HelpText<"undef all system defines">; -def unexported__symbols__list : Separate<"-unexported_symbols_list">; -def u : JoinedOrSeparate<"-u">, Group; -def use_gold_plugin : Flag<"-use-gold-plugin">; -def v : Flag<"-v">, Flags<[CC1Option]>, +def unexported__symbols__list : Separate<["-"], "unexported_symbols_list">; +def u : JoinedOrSeparate<["-"], "u">, Group; +def use_gold_plugin : Flag<["-"], "use-gold-plugin">; +def v : Flag<["-"], "v">, Flags<[CC1Option]>, HelpText<"Show commands to run and use verbose output">; -def verify : Flag<"-verify">, Flags<[DriverOption,CC1Option]>, - HelpText<"Verify output using a verifier.">; -def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>; -def weak__framework : Separate<"-weak_framework">, Flags<[LinkerInput]>; -def weak__library : Separate<"-weak_library">, Flags<[LinkerInput]>; -def weak__reference__mismatches : Separate<"-weak_reference_mismatches">; -def whatsloaded : Flag<"-whatsloaded">; -def whyload : Flag<"-whyload">; -def w : Flag<"-w">, HelpText<"Suppress all warnings.">, Flags<[CC1Option]>; -def x : JoinedOrSeparate<"-x">, Flags<[DriverOption,CC1Option]>, +def verify : Flag<["-"], "verify">, Flags<[DriverOption,CC1Option]>, + HelpText<"Verify output using a verifier">; +def weak_l : Joined<["-"], "weak-l">, Flags<[LinkerInput]>; +def weak__framework : Separate<["-"], "weak_framework">, Flags<[LinkerInput]>; +def weak__library : Separate<["-"], "weak_library">, Flags<[LinkerInput]>; +def weak__reference__mismatches : Separate<["-"], "weak_reference_mismatches">; +def whatsloaded : Flag<["-"], "whatsloaded">; +def whyload : Flag<["-"], "whyload">; +def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>; +def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>, HelpText<"Treat subsequent input files as having type ">, MetaVarName<"">; -def y : Joined<"-y">; +def y : Joined<["-"], "y">; -def working_directory : JoinedOrSeparate<"-working-directory">, Flags<[CC1Option]>, +def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>, HelpText<"Resolve file paths relative to the specified directory">; -def working_directory_EQ : Joined<"-working-directory=">, Flags<[CC1Option]>, +def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>, Alias; // Double dash options, which are usually an alias for one of the previous // options. -def _CLASSPATH_EQ : Joined<"--CLASSPATH=">, Alias; -def _CLASSPATH : Separate<"--CLASSPATH">, Alias; -def _all_warnings : Flag<"--all-warnings">, Alias; -def _analyze_auto : Flag<"--analyze-auto">, Flags<[DriverOption]>; -def _analyzer_no_default_checks : Flag<"--analyzer-no-default-checks">, Flags<[DriverOption]>; -def _analyzer_output : JoinedOrSeparate<"--analyzer-output">, Flags<[DriverOption]>; -def _analyze : Flag<"--analyze">, Flags<[DriverOption]>, +def _CLASSPATH_EQ : Joined<["--"], "CLASSPATH=">, Alias; +def _CLASSPATH : Separate<["--"], "CLASSPATH">, Alias; +def _all_warnings : Flag<["--"], "all-warnings">, Alias; +def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>; +def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>; +def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>; +def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption]>, HelpText<"Run the static analyzer">; -def _ansi : Flag<"--ansi">, Alias; -def _assemble : Flag<"--assemble">, Alias; -def _assert_EQ : Joined<"--assert=">, Alias; -def _assert : Separate<"--assert">, Alias; -def _bootclasspath_EQ : Joined<"--bootclasspath=">, Alias; -def _bootclasspath : Separate<"--bootclasspath">, Alias; -def _classpath_EQ : Joined<"--classpath=">, Alias; -def _classpath : Separate<"--classpath">, Alias; -def _combine : Flag<"--combine">, Alias; -def _comments_in_macros : Flag<"--comments-in-macros">, Alias; -def _comments : Flag<"--comments">, Alias; -def _compile : Flag<"--compile">, Alias; -def _constant_cfstrings : Flag<"--constant-cfstrings">; -def _coverage : Flag<"--coverage">, Alias; -def _debug_EQ : Joined<"--debug=">, Alias; -def _debug : Flag<"--debug">, Alias; -def _define_macro_EQ : Joined<"--define-macro=">, Alias; -def _define_macro : Separate<"--define-macro">, Alias; -def _dependencies : Flag<"--dependencies">, Alias; -def _encoding_EQ : Joined<"--encoding=">, Alias; -def _encoding : Separate<"--encoding">, Alias; -def _entry : Flag<"--entry">, Alias; -def _extdirs_EQ : Joined<"--extdirs=">, Alias; -def _extdirs : Separate<"--extdirs">, Alias; -def _extra_warnings : Flag<"--extra-warnings">, Alias; -def _for_linker_EQ : Joined<"--for-linker=">, Alias; -def _for_linker : Separate<"--for-linker">, Alias; -def _force_link_EQ : Joined<"--force-link=">, Alias; -def _force_link : Separate<"--force-link">, Alias; -def _help_hidden : Flag<"--help-hidden">; -def _help : Flag<"--help">, Alias; -def _imacros_EQ : Joined<"--imacros=">, Alias; -def _imacros : Separate<"--imacros">, Alias; -def _include_barrier : Flag<"--include-barrier">, Alias; -def _include_directory_after_EQ : Joined<"--include-directory-after=">, Alias; -def _include_directory_after : Separate<"--include-directory-after">, Alias; -def _include_directory_EQ : Joined<"--include-directory=">, Alias; -def _include_directory : Separate<"--include-directory">, Alias; -def _include_prefix_EQ : Joined<"--include-prefix=">, Alias; -def _include_prefix : Separate<"--include-prefix">, Alias; -def _include_with_prefix_after_EQ : Joined<"--include-with-prefix-after=">, Alias; -def _include_with_prefix_after : Separate<"--include-with-prefix-after">, Alias; -def _include_with_prefix_before_EQ : Joined<"--include-with-prefix-before=">, Alias; -def _include_with_prefix_before : Separate<"--include-with-prefix-before">, Alias; -def _include_with_prefix_EQ : Joined<"--include-with-prefix=">, Alias; -def _include_with_prefix : Separate<"--include-with-prefix">, Alias; -def _include_EQ : Joined<"--include=">, Alias; -def _include : Separate<"--include">, Alias; -def _language_EQ : Joined<"--language=">, Alias; -def _language : Separate<"--language">, Alias; -def _library_directory_EQ : Joined<"--library-directory=">, Alias; -def _library_directory : Separate<"--library-directory">, Alias; -def _machine__EQ : Joined<"--machine-=">, Alias; -def _machine_ : Joined<"--machine-">, Alias; -def _machine_EQ : Joined<"--machine=">, Alias; -def _machine : Separate<"--machine">, Alias; -def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias; -def _no_line_commands : Flag<"--no-line-commands">, Alias

; -def _relocatable_pch : Flag<"--relocatable-pch">, - HelpText<"Build a relocatable precompiled header">; -def _resource_EQ : Joined<"--resource=">, Alias; -def _resource : Separate<"--resource">, Alias; -def _rtlib_EQ : Joined<"--rtlib=">, Alias; -def _rtlib : Separate<"--rtlib">, Alias; -def _save_temps : Flag<"--save-temps">, Alias; -def _serialize_diags : Separate<"--serialize-diagnostics">, Flags<[DriverOption]>, +def _assemble : Flag<["--"], "assemble">, Alias; +def _assert_EQ : Joined<["--"], "assert=">, Alias; +def _assert : Separate<["--"], "assert">, Alias; +def _bootclasspath_EQ : Joined<["--"], "bootclasspath=">, Alias; +def _bootclasspath : Separate<["--"], "bootclasspath">, Alias; +def _classpath_EQ : Joined<["--"], "classpath=">, Alias; +def _classpath : Separate<["--"], "classpath">, Alias; +def _comments_in_macros : Flag<["--"], "comments-in-macros">, Alias; +def _comments : Flag<["--"], "comments">, Alias; +def _compile : Flag<["--"], "compile">, Alias; +def _constant_cfstrings : Flag<["--"], "constant-cfstrings">; +def _debug_EQ : Joined<["--"], "debug=">, Alias; +def _debug : Flag<["--"], "debug">, Alias; +def _define_macro_EQ : Joined<["--"], "define-macro=">, Alias; +def _define_macro : Separate<["--"], "define-macro">, Alias; +def _dependencies : Flag<["--"], "dependencies">, Alias; +def _encoding_EQ : Joined<["--"], "encoding=">, Alias; +def _encoding : Separate<["--"], "encoding">, Alias; +def _entry : Flag<["--"], "entry">, Alias; +def _extdirs_EQ : Joined<["--"], "extdirs=">, Alias; +def _extdirs : Separate<["--"], "extdirs">, Alias; +def _extra_warnings : Flag<["--"], "extra-warnings">, Alias; +def _for_linker_EQ : Joined<["--"], "for-linker=">, Alias; +def _for_linker : Separate<["--"], "for-linker">, Alias; +def _force_link_EQ : Joined<["--"], "force-link=">, Alias; +def _force_link : Separate<["--"], "force-link">, Alias; +def _help_hidden : Flag<["--"], "help-hidden">; +def _imacros_EQ : Joined<["--"], "imacros=">, Alias; +def _include_barrier : Flag<["--"], "include-barrier">, Alias; +def _include_directory_after_EQ : Joined<["--"], "include-directory-after=">, Alias; +def _include_directory_after : Separate<["--"], "include-directory-after">, Alias; +def _include_directory_EQ : Joined<["--"], "include-directory=">, Alias; +def _include_directory : Separate<["--"], "include-directory">, Alias; +def _include_prefix_EQ : Joined<["--"], "include-prefix=">, Alias; +def _include_prefix : Separate<["--"], "include-prefix">, Alias; +def _include_with_prefix_after_EQ : Joined<["--"], "include-with-prefix-after=">, Alias; +def _include_with_prefix_after : Separate<["--"], "include-with-prefix-after">, Alias; +def _include_with_prefix_before_EQ : Joined<["--"], "include-with-prefix-before=">, Alias; +def _include_with_prefix_before : Separate<["--"], "include-with-prefix-before">, Alias; +def _include_with_prefix_EQ : Joined<["--"], "include-with-prefix=">, Alias; +def _include_with_prefix : Separate<["--"], "include-with-prefix">, Alias; +def _include_EQ : Joined<["--"], "include=">, Alias; +def _language_EQ : Joined<["--"], "language=">, Alias; +def _language : Separate<["--"], "language">, Alias; +def _library_directory_EQ : Joined<["--"], "library-directory=">, Alias; +def _library_directory : Separate<["--"], "library-directory">, Alias; +def _machine__EQ : Joined<["--"], "machine-=">, Alias; +def _machine_ : Joined<["--"], "machine-">, Alias; +def _machine_EQ : Joined<["--"], "machine=">, Alias; +def _machine : Separate<["--"], "machine">, Alias; +def _no_line_commands : Flag<["--"], "no-line-commands">, Alias

; +def _no_standard_includes : Flag<["--"], "no-standard-includes">, Alias; +def _no_standard_libraries : Flag<["--"], "no-standard-libraries">, Alias; +def _no_undefined : Flag<["--"], "no-undefined">, Flags<[LinkerInput]>; +def _no_warnings : Flag<["--"], "no-warnings">, Alias; +def _optimize_EQ : Joined<["--"], "optimize=">, Alias; +def _optimize : Flag<["--"], "optimize">, Alias; +def _output_class_directory_EQ : Joined<["--"], "output-class-directory=">, Alias; +def _output_class_directory : Separate<["--"], "output-class-directory">, Alias; +def _output_EQ : Joined<["--"], "output=">, Alias; +def _output : Separate<["--"], "output">, Alias; +def _param : Separate<["--"], "param">; +def _param_EQ : Joined<["--"], "param=">, Alias<_param>; +def _prefix_EQ : Joined<["--"], "prefix=">, Alias; +def _prefix : Separate<["--"], "prefix">, Alias; +def _preprocess : Flag<["--"], "preprocess">, Alias; +def _print_diagnostic_categories : Flag<["--"], "print-diagnostic-categories">; +def _print_file_name : Separate<["--"], "print-file-name">, Alias; +def _print_missing_file_dependencies : Flag<["--"], "print-missing-file-dependencies">, Alias; +def _print_prog_name : Separate<["--"], "print-prog-name">, Alias; +def _profile_blocks : Flag<["--"], "profile-blocks">, Alias; +def _profile : Flag<["--"], "profile">, Alias

; +def _resource_EQ : Joined<["--"], "resource=">, Alias; +def _resource : Separate<["--"], "resource">, Alias; +def _rtlib : Separate<["--"], "rtlib">, Alias; +def _serialize_diags : Separate<["-", "--"], "serialize-diagnostics">, Flags<[DriverOption]>, HelpText<"Serialize compiler diagnostics to a file">; -def _shared : Flag<"--shared">, Alias; -def _signed_char : Flag<"--signed-char">, Alias; -def _specs_EQ : Joined<"--specs=">, Alias; -def _specs : Separate<"--specs">, Alias; -def _static : Flag<"--static">, Alias; -def _std_EQ : Joined<"--std=">, Alias; -def _std : Separate<"--std">, Alias; -def _stdlib_EQ : Joined<"--stdlib=">, Alias; -def _stdlib : Separate<"--stdlib">, Alias; -def _sysroot_EQ : Joined<"--sysroot=">; -def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>; -def _target_help : Flag<"--target-help">; -def _trace_includes : Flag<"--trace-includes">, Alias; -def _traditional_cpp : Flag<"--traditional-cpp">, Alias; -def _traditional : Flag<"--traditional">, Alias; -def _trigraphs : Flag<"--trigraphs">, Alias; -def _undefine_macro_EQ : Joined<"--undefine-macro=">, Alias; -def _undefine_macro : Separate<"--undefine-macro">, Alias; -def _unsigned_char : Flag<"--unsigned-char">, Alias; -def _user_dependencies : Flag<"--user-dependencies">, Alias; -def _verbose : Flag<"--verbose">, Alias; -def _version : Flag<"--version">, Flags<[CC1Option]>; -def _warn__EQ : Joined<"--warn-=">, Alias; -def _warn_ : Joined<"--warn-">, Alias; -def _write_dependencies : Flag<"--write-dependencies">, Alias; -def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias; -def _ : Joined<"--">, Flags<[Unsupported]>; -def mieee_rnd_near : Flag<"-mieee-rnd-near">, Group; -def serialize_diags : Separate<"-serialize-diagnostics">, Alias<_serialize_diags>; +// We give --version different semantics from -version. +def _version : Flag<["--"], "version">, Flags<[CC1Option]>; +def _signed_char : Flag<["--"], "signed-char">, Alias; +def _std : Separate<["--"], "std">, Alias; +def _stdlib : Separate<["--"], "stdlib">, Alias; +def _sysroot_EQ : Joined<["--"], "sysroot=">; +def _sysroot : Separate<["--"], "sysroot">, Alias<_sysroot_EQ>; +def _target_help : Flag<["--"], "target-help">; +def _trace_includes : Flag<["--"], "trace-includes">, Alias; +def _undefine_macro_EQ : Joined<["--"], "undefine-macro=">, Alias; +def _undefine_macro : Separate<["--"], "undefine-macro">, Alias; +def _unsigned_char : Flag<["--"], "unsigned-char">, Alias; +def _user_dependencies : Flag<["--"], "user-dependencies">, Alias; +def _verbose : Flag<["--"], "verbose">, Alias; +def _warn__EQ : Joined<["--"], "warn-=">, Alias; +def _warn_ : Joined<["--"], "warn-">, Alias; +def _write_dependencies : Flag<["--"], "write-dependencies">, Alias; +def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias; +def _ : Joined<["--"], "">, Flags<[Unsupported]>; +def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group; // Special internal option to handle -Xlinker --no-demangle. -def Z_Xlinker__no_demangle : Flag<"-Z-Xlinker-no-demangle">, +def Z_Xlinker__no_demangle : Flag<["-"], "Z-Xlinker-no-demangle">, Flags<[Unsupported, NoArgumentUnused]>; // Special internal option to allow forwarding arbitrary arguments to linker. -def Zlinker_input : Separate<"-Zlinker-input">, +def Zlinker_input : Separate<["-"], "Zlinker-input">, Flags<[Unsupported, NoArgumentUnused]>; // Reserved library options. -def Z_reserved_lib_stdcxx : Flag<"-Z-reserved-lib-stdc++">, +def Z_reserved_lib_stdcxx : Flag<["-"], "Z-reserved-lib-stdc++">, Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group; -def Z_reserved_lib_cckext : Flag<"-Z-reserved-lib-cckext">, +def Z_reserved_lib_cckext : Flag<["-"], "Z-reserved-lib-cckext">, Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group; include "CC1Options.td" diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index 8822d7b3fe24..c62e7567ea3e 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -55,8 +55,8 @@ public: /// driver add an additional "command failed" diagnostic on failures. virtual bool hasGoodDiagnostics() const { return false; } - /// ConstructJob - Construct jobs to perform the action \arg JA, - /// writing to \arg Output and with \arg Inputs. + /// ConstructJob - Construct jobs to perform the action \p JA, + /// writing to \p Output and with \p Inputs. /// /// \param TCArgs - The argument list for this toolchain, with any /// tool chain specific translations applied. diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index ab417bb577cb..509e08d67efc 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -85,6 +85,10 @@ public: StringRef getPlatform() const { return Triple.getVendorName(); } StringRef getOS() const { return Triple.getOSName(); } + /// \brief Provide the default architecture name (as expected by -arch) for + /// this toolchain. Note t + std::string getDefaultUniversalArchName() const; + std::string getTripleString() const { return Triple.getTriple(); } @@ -107,15 +111,15 @@ public: return 0; } - /// SelectTool - Choose a tool to use to handle the action \arg JA with the - /// given \arg Inputs. + /// SelectTool - Choose a tool to use to handle the action \p JA with the + /// given \p Inputs. virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const = 0; // Helper methods std::string GetFilePath(const char *Name) const; - std::string GetProgramPath(const char *Name, bool WantFile = false) const; + std::string GetProgramPath(const char *Name) const; // Platform defaults information @@ -144,6 +148,10 @@ public: /// IsObjCDefaultSynthPropertiesDefault - Does this tool chain enable /// -fobjc-default-synthesize-properties by default. virtual bool IsObjCDefaultSynthPropertiesDefault() const { return false; } + + /// IsEncodeExtendedBlockSignatureDefault - Does this tool chain enable + /// -fencode-extended-block-signature by default. + virtual bool IsEncodeExtendedBlockSignatureDefault() const { return false; } /// IsObjCNonFragileABIDefault - Does this tool chain set /// -fobjc-nonfragile-abi by default. @@ -166,16 +174,15 @@ public: /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables /// by default. - virtual bool IsUnwindTablesDefault() const = 0; + virtual bool IsUnwindTablesDefault() const; - /// GetDefaultRelocationModel - Return the LLVM name of the default - /// relocation model for this tool chain. - virtual const char *GetDefaultRelocationModel() const = 0; + /// \brief Test whether this toolchain defaults to PIC. + virtual bool isPICDefault() const = 0; - /// GetForcedPicModel - Return the LLVM name of the forced PIC model - /// for this tool chain, or 0 if this tool chain does not force a - /// particular PIC mode. - virtual const char *GetForcedPicModel() const = 0; + /// \brief Tests whether this toolchain forces its default for PIC or non-PIC. + /// If this returns true, any PIC related flags should be ignored and instead + /// the result of \c isPICDefault() is used exclusively. + virtual bool isPICDefaultForced() const = 0; /// SupportsProfiling - Does this tool chain support -pg. virtual bool SupportsProfiling() const { return true; } @@ -183,8 +190,8 @@ public: /// Does this tool chain support Objective-C garbage collection. virtual bool SupportsObjCGC() const { return true; } - /// Does this tool chain support Objective-C ARC. - virtual bool SupportsObjCARC() const { return true; } + /// Complain if this tool chain doesn't support Objective-C ARC. + virtual void CheckObjCARC() const {} /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf /// compile unit information. @@ -252,6 +259,13 @@ public: /// for kernel extensions (Darwin-specific). virtual void AddCCKextLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + + /// AddFastMathRuntimeIfAvailable - If a runtime library exists that sets + /// global flags for unsafe floating point math, add it and return true. + /// + /// This checks for presence of the -ffast-math or -funsafe-math flags. + virtual bool AddFastMathRuntimeIfAvailable(const ArgList &Args, + ArgStringList &CmdArgs) const; }; } // end namespace driver diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index 3dea471cca42..d28ca888d302 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -59,10 +59,6 @@ namespace types { /// isAcceptedByClang - Can clang handle this input type. bool isAcceptedByClang(ID Id); - /// isOnlyAcceptedByClang - Is clang the only compiler that can handle this - /// input type. - bool isOnlyAcceptedByClang(ID Id); - /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers). bool isCXX(ID Id); diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 144b79642d5c..5e409bd7ed83 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -19,11 +19,13 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Lex/ModuleLoader.h" #include "clang/Lex/PreprocessingRecord.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/TargetOptions.h" #include "clang-c/Index.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" @@ -56,21 +58,27 @@ class Preprocessor; class SourceManager; class TargetInfo; class ASTFrontendAction; +class ASTDeserializationListener; /// \brief Utility class for loading a ASTContext from an AST file. /// class ASTUnit : public ModuleLoader { private: - IntrusiveRefCntPtr LangOpts; - IntrusiveRefCntPtr Diagnostics; - IntrusiveRefCntPtr FileMgr; - IntrusiveRefCntPtr SourceMgr; - OwningPtr HeaderInfo; - IntrusiveRefCntPtr Target; - IntrusiveRefCntPtr PP; - IntrusiveRefCntPtr Ctx; + IntrusiveRefCntPtr LangOpts; + IntrusiveRefCntPtr Diagnostics; + IntrusiveRefCntPtr FileMgr; + IntrusiveRefCntPtr SourceMgr; + OwningPtr HeaderInfo; + IntrusiveRefCntPtr Target; + IntrusiveRefCntPtr PP; + IntrusiveRefCntPtr Ctx; + IntrusiveRefCntPtr TargetOpts; + IntrusiveRefCntPtr HSOpts; ASTReader *Reader; + struct ASTWriterData; + OwningPtr WriterData; + FileSystemOptions FileSystemOpts; /// \brief The AST consumer that received information about the translation @@ -85,13 +93,6 @@ private: /// LoadFromCommandLine available. IntrusiveRefCntPtr Invocation; - /// \brief The set of target features. - /// - /// FIXME: each time we reparse, we need to restore the set of target - /// features from this vector, because TargetInfo::CreateTargetInfo() - /// mangles the target options in place. Yuck! - std::vector TargetFeatures; - // OnlyLocalDecls - when true, walking this AST should only visit declarations // that come from the AST itself, not from included precompiled headers. // FIXME: This is temporary; eventually, CIndex will always do this. @@ -374,8 +375,8 @@ private: /// \brief Clear out and deallocate void ClearCachedCompletionResults(); - ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT - ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT + ASTUnit(const ASTUnit &) LLVM_DELETED_FUNCTION; + void operator=(const ASTUnit &) LLVM_DELETED_FUNCTION; explicit ASTUnit(bool MainFileIsAST); @@ -466,7 +467,11 @@ public: const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } - const std::string &getOriginalSourceFileName(); + StringRef getOriginalSourceFileName() { + return OriginalSourceFile; + } + + ASTDeserializationListener *getDeserializationListener(); /// \brief Add a temporary file that the ASTUnit depends on. /// @@ -515,7 +520,7 @@ public: void addFileLevelDecl(Decl *D); /// \brief Get the decls that are contained in a file in the Offset/Length - /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of + /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. void findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, SmallVectorImpl &Decls); @@ -542,14 +547,14 @@ public: /// \brief Get the source location for the given file:offset pair. SourceLocation getLocation(const FileEntry *File, unsigned Offset) const; - /// \brief If \arg Loc is a loaded location from the preamble, returns + /// \brief If \p Loc is a loaded location from the preamble, returns /// the corresponding local location of the main file, otherwise it returns - /// \arg Loc. + /// \p Loc. SourceLocation mapLocationFromPreamble(SourceLocation Loc); - /// \brief If \arg Loc is a local location of the main file but inside the + /// \brief If \p Loc is a local location of the main file but inside the /// preamble chunk, returns the corresponding loaded location from the - /// preamble, otherwise it returns \arg Loc. + /// preamble, otherwise it returns \p Loc. SourceLocation mapLocationToPreamble(SourceLocation Loc); bool isInPreambleFileID(SourceLocation Loc); @@ -557,13 +562,13 @@ public: SourceLocation getStartOfMainFileID(); SourceLocation getEndOfPreambleFileID(); - /// \brief \see mapLocationFromPreamble. + /// \see mapLocationFromPreamble. SourceRange mapRangeFromPreamble(SourceRange R) { return SourceRange(mapLocationFromPreamble(R.getBegin()), mapLocationFromPreamble(R.getEnd())); } - /// \brief \see mapLocationToPreamble. + /// \see mapLocationToPreamble. SourceRange mapRangeToPreamble(SourceRange R) { return SourceRange(mapLocationToPreamble(R.getBegin()), mapLocationToPreamble(R.getEnd())); @@ -607,6 +612,29 @@ public: return CachedCompletionResults.size(); } + /// \brief Returns an iterator range for the local preprocessing entities + /// of the local Preprocessor, if this is a parsed source file, or the loaded + /// preprocessing entities of the primary module if this is an AST file. + std::pair + getLocalPreprocessingEntities() const; + + /// \brief Type for a function iterating over a number of declarations. + /// \returns true to continue iteration and false to abort. + typedef bool (*DeclVisitorFn)(void *context, const Decl *D); + + /// \brief Iterate over local declarations (locally parsed if this is a parsed + /// source file or the loaded declarations of the primary module if this is an + /// AST file). + /// \returns true if the iteration was complete or false if it was aborted. + bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn); + + /// \brief Get the PCH file if one was included. + const FileEntry *getPCHFile(); + + /// \brief Returns true if the ASTUnit was constructed from a serialized + /// module file. + bool isModuleFile(); + llvm::MemoryBuffer *getBufferForFile(StringRef Filename, std::string *ErrorStr = 0); @@ -679,7 +707,7 @@ public: /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit /// mainly to allow the caller to see the diagnostics. /// This will only receive an ASTUnit if a new one was created. If an already - /// created ASTUnit was passed in \param Unit then the caller can check that. + /// created ASTUnit was passed in \p Unit then the caller can check that. /// static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI, IntrusiveRefCntPtr Diags, @@ -750,6 +778,7 @@ public: bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false, bool UserFilesAreVolatile = false, + bool ForSerialization = false, OwningPtr *ErrAST = 0); /// \brief Reparse the source files using the same command-line options that @@ -792,8 +821,9 @@ public: /// \brief Save this translation unit to a file with the given name. /// - /// \returns An indication of whether the save was successful or not. - CXSaveError Save(StringRef File); + /// \returns true if there was a file error or false if the save was + /// successful. + bool Save(StringRef File); /// \brief Serialize this translation unit with the given output stream. /// diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def deleted file mode 100644 index 29ddc9e176b4..000000000000 --- a/include/clang/Frontend/Analyses.def +++ /dev/null @@ -1,67 +0,0 @@ -//===-- Analyses.def - Metadata about Static Analyses -----------*- 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 set of static analyses used by AnalysisConsumer. -// -//===----------------------------------------------------------------------===// - -#ifndef ANALYSIS_STORE -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) -#endif - -ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager) - -#ifndef ANALYSIS_CONSTRAINTS -#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) -#endif - -ANALYSIS_CONSTRAINTS(BasicConstraints, "basic", "Use basic constraint tracking", CreateBasicConstraintManager) -ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager) - -#ifndef ANALYSIS_DIAGNOSTICS -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) -#endif - -ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer, false) -ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer, true) -ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer, true) -ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true) -ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true) - -#ifndef ANALYSIS_PURGE -#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) -#endif - -ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraints before every statement") -ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block") -ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints") - -#ifndef ANALYSIS_IPA -#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) -#endif - -ANALYSIS_IPA(None, "none", "Perform only intra-procedural analysis") -ANALYSIS_IPA(Inlining, "inlining", "Inline callees when their definitions are available") -ANALYSIS_IPA(DynamicDispatch, "dynamic", "Experimental: Enable inlining of dynamically dispatched methods") -ANALYSIS_IPA(DynamicDispatchBifurcate, "dynamic-bifurcate", "Experimental: Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailable") - -#ifndef ANALYSIS_INLINING_MODE -#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) -#endif - -ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions in the order defined in the TU") -ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined, use call graph to order") - -#undef ANALYSIS_STORE -#undef ANALYSIS_CONSTRAINTS -#undef ANALYSIS_DIAGNOSTICS -#undef ANALYSIS_PURGE -#undef ANALYSIS_INLINING_MODE -#undef ANALYSIS_IPA - diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h deleted file mode 100644 index 4e489fea7423..000000000000 --- a/include/clang/Frontend/AnalyzerOptions.h +++ /dev/null @@ -1,135 +0,0 @@ -//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header contains the structures necessary for a front-end to specify -// various analyses. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_ANALYZEROPTIONS_H -#define LLVM_CLANG_FRONTEND_ANALYZEROPTIONS_H - -#include -#include - -namespace clang { -class ASTConsumer; -class DiagnosticsEngine; -class Preprocessor; -class LangOptions; - -/// Analysis - Set of available source code analyses. -enum Analyses { -#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME, -#include "clang/Frontend/Analyses.def" -NumAnalyses -}; - -/// AnalysisStores - Set of available analysis store models. -enum AnalysisStores { -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, -#include "clang/Frontend/Analyses.def" -NumStores -}; - -/// AnalysisConstraints - Set of available constraint models. -enum AnalysisConstraints { -#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, -#include "clang/Frontend/Analyses.def" -NumConstraints -}; - -/// AnalysisDiagClients - Set of available diagnostic clients for rendering -/// analysis results. -enum AnalysisDiagClients { -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME, -#include "clang/Frontend/Analyses.def" -NUM_ANALYSIS_DIAG_CLIENTS -}; - -/// AnalysisPurgeModes - Set of available strategies for dead symbol removal. -enum AnalysisPurgeMode { -#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME, -#include "clang/Frontend/Analyses.def" -NumPurgeModes -}; - -/// AnalysisIPAMode - Set of inter-procedural modes. -enum AnalysisIPAMode { -#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) NAME, -#include "clang/Frontend/Analyses.def" -NumIPAModes -}; - -/// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. -enum AnalysisInliningMode { -#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, -#include "clang/Frontend/Analyses.def" -NumInliningModes -}; - -class AnalyzerOptions { -public: - /// \brief Pair of checker name and enable/disable. - std::vector > CheckersControlList; - AnalysisStores AnalysisStoreOpt; - AnalysisConstraints AnalysisConstraintsOpt; - AnalysisDiagClients AnalysisDiagOpt; - AnalysisPurgeMode AnalysisPurgeOpt; - AnalysisIPAMode IPAMode; - std::string AnalyzeSpecificFunction; - unsigned MaxNodes; - unsigned MaxLoop; - unsigned ShowCheckerHelp : 1; - unsigned AnalyzeAll : 1; - unsigned AnalyzerDisplayProgress : 1; - unsigned AnalyzeNestedBlocks : 1; - unsigned EagerlyAssume : 1; - unsigned TrimGraph : 1; - unsigned VisualizeEGDot : 1; - unsigned VisualizeEGUbi : 1; - unsigned UnoptimizedCFG : 1; - unsigned CFGAddImplicitDtors : 1; - unsigned EagerlyTrimEGraph : 1; - unsigned PrintStats : 1; - unsigned NoRetryExhausted : 1; - unsigned InlineMaxStackDepth; - unsigned InlineMaxFunctionSize; - AnalysisInliningMode InliningMode; - -public: - AnalyzerOptions() { - AnalysisStoreOpt = RegionStoreModel; - AnalysisConstraintsOpt = RangeConstraintsModel; - AnalysisDiagOpt = PD_HTML; - AnalysisPurgeOpt = PurgeStmt; - IPAMode = Inlining; - ShowCheckerHelp = 0; - AnalyzeAll = 0; - AnalyzerDisplayProgress = 0; - AnalyzeNestedBlocks = 0; - EagerlyAssume = 0; - TrimGraph = 0; - VisualizeEGDot = 0; - VisualizeEGUbi = 0; - UnoptimizedCFG = 0; - CFGAddImplicitDtors = 0; - EagerlyTrimEGraph = 0; - PrintStats = 0; - NoRetryExhausted = 0; - // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). - InlineMaxStackDepth = 5; - InlineMaxFunctionSize = 200; - InliningMode = NoRedundancy; - } -}; - -} - -#endif diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def new file mode 100644 index 000000000000..558e6f11113b --- /dev/null +++ b/include/clang/Frontend/CodeGenOptions.def @@ -0,0 +1,132 @@ +//===--- CodeGenOptions.def - Code generation option database ------ 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 code generation options. Users of this file +// must define the CODEGENOPT macro to make use of this information. +// Optionally, the user may also define ENUM_CODEGENOPT (for options +// that have enumeration type and VALUE_CODEGENOPT is a code +// generation option that describes a value rather than a flag. +// +//===----------------------------------------------------------------------===// +#ifndef CODEGENOPT +# error Define the CODEGENOPT macro to handle language options +#endif + +#ifndef VALUE_CODEGENOPT +# define VALUE_CODEGENOPT(Name, Bits, Default) \ +CODEGENOPT(Name, Bits, Default) +#endif + +#ifndef ENUM_CODEGENOPT +# define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ +CODEGENOPT(Name, Bits, Default) +#endif + +CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. +CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. +CODEGENOPT(CUDAIsDevice , 1, 0) ///< Set when compiling for CUDA device. +CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors. +CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker + ///< aliases to base ctors when possible. +CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled. +CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled. +CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use in + ///< getting .bc files that correspond to the + ///< internal state before optimizations are + ///< done. +CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. +CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. +CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what + ///< Decl* various IR entities came from. + ///< Only useful when running CodeGen as a + ///< subroutine. +CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA. +CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO. +CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata. +CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables + ///< are required. +CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. +CODEGENOPT(HiddenWeakVTables , 1, 0) ///< Emit weak vtables, RTTI, and thunks with + ///< hidden visibility. +CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is + ///< enabled. +CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. +CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to + ///< be generated. +CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. +CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled. +CODEGENOPT(NoDwarf2CFIAsm , 1, 0) ///< Set when -fno-dwarf2-cfi-asm is enabled. +CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is + ///< enabled. +CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled. +CODEGENOPT(NoGlobalMerge , 1, 0) ///< Set when -mno-global-merge is enabled. +CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. +CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. +CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled. + ///< Disables use of the inline keyword. +CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. +CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss. +/// \brief Method of Objective-C dispatch to use. +ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy) +CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is + ///< enabled. +VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. +VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. +CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. +CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. +CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. +CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. +CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. +CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. +CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. +CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization + ///< selection. +CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled. +CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns. +CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables. + + /// Attempt to use register sized accesses to bit-fields in structures, when + /// possible. +CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0) + +CODEGENOPT(VerifyModule , 1, 1) ///< Control whether the module should be run + ///< through the LLVM Verifier. + +CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to permit stack + ///< realignment. +CODEGENOPT(UseInitArray , 1, 0) ///< Control whether to use .init_array or + ///< .ctors. +VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack + ///< alignment, if not 0. +CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information + ///< in debug info. + +/// The user specified number of registers to be used for integral arguments, +/// or 0 if unspecified. +VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) + +/// The run-time penalty for bounds checking, or 0 to disable. +VALUE_CODEGENOPT(BoundsChecking, 8, 0) + +/// The lower bound for a buffer to be considered for stack protection. +VALUE_CODEGENOPT(SSPBufferSize, 32, 0) + +/// The kind of generated debug info. +ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 2, NoDebugInfo) + +/// The kind of inlining to perform. +ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining) + +/// The default TLS model to use. +ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) + +#undef CODEGENOPT +#undef ENUM_CODEGENOPT +#undef VALUE_CODEGENOPT + diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 3e3409335208..35671870f441 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -19,9 +19,23 @@ namespace clang { +/// \brief Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure +/// that this large collection of bitfields is a trivial class type. +class CodeGenOptionsBase { +public: +#define CODEGENOPT(Name, Bits, Default) unsigned Name : Bits; +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) +#include "clang/Frontend/CodeGenOptions.def" + +protected: +#define CODEGENOPT(Name, Bits, Default) +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) unsigned Name : Bits; +#include "clang/Frontend/CodeGenOptions.def" +}; + /// CodeGenOptions - Track various options which control how the code /// is optimized and passed to the backend. -class CodeGenOptions { +class CodeGenOptions : public CodeGenOptionsBase { public: enum InliningMethod { NoInlining, // Perform no inlining whatsoever. @@ -51,86 +65,6 @@ public: LocalExecTLSModel }; - unsigned AsmVerbose : 1; ///< -dA, -fverbose-asm. - unsigned ObjCAutoRefCountExceptions : 1; ///< Whether ARC should be EH-safe. - unsigned CUDAIsDevice : 1; ///< Set when compiling for CUDA device. - unsigned CXAAtExit : 1; ///< Use __cxa_atexit for calling destructors. - unsigned CXXCtorDtorAliases: 1; ///< Emit complete ctors/dtors as linker - ///< aliases to base ctors when possible. - unsigned DataSections : 1; ///< Set when -fdata-sections is enabled. - unsigned DisableFPElim : 1; ///< Set when -fomit-frame-pointer is enabled. - unsigned DisableLLVMOpts : 1; ///< Don't run any optimizations, for use in - ///< getting .bc files that correspond to the - ///< internal state before optimizations are - ///< done. - unsigned DisableRedZone : 1; ///< Set when -mno-red-zone is enabled. - unsigned DisableTailCalls : 1; ///< Do not emit tail calls. - unsigned EmitDeclMetadata : 1; ///< Emit special metadata indicating what - ///< Decl* various IR entities came from. Only - ///< useful when running CodeGen as a - ///< subroutine. - unsigned EmitGcovArcs : 1; ///< Emit coverage data files, aka. GCDA. - unsigned EmitGcovNotes : 1; ///< Emit coverage "notes" files, aka GCNO. - unsigned EmitOpenCLArgMetadata : 1; ///< Emit OpenCL kernel arg metadata. - unsigned EmitMicrosoftInlineAsm : 1; ///< Enable emission of MS-style inline - ///< assembly. - unsigned ForbidGuardVariables : 1; ///< Issue errors if C++ guard variables - ///< are required. - unsigned FunctionSections : 1; ///< Set when -ffunction-sections is enabled. - unsigned HiddenWeakTemplateVTables : 1; ///< Emit weak vtables and RTTI for - ///< template classes with hidden visibility - unsigned HiddenWeakVTables : 1; ///< Emit weak vtables, RTTI, and thunks with - ///< hidden visibility. - unsigned InstrumentFunctions : 1; ///< Set when -finstrument-functions is - ///< enabled. - unsigned InstrumentForProfiling : 1; ///< Set when -pg is enabled. - unsigned LessPreciseFPMAD : 1; ///< Enable less precise MAD instructions to - ///< be generated. - unsigned MergeAllConstants : 1; ///< Merge identical constants. - unsigned NoCommon : 1; ///< Set when -fno-common or C++ is enabled. - unsigned NoDwarf2CFIAsm : 1; ///< Set when -fno-dwarf2-cfi-asm is enabled. - unsigned NoDwarfDirectoryAsm : 1; ///< Set when -fno-dwarf-directory-asm is - ///< enabled. - unsigned NoExecStack : 1; ///< Set when -Wa,--noexecstack is enabled. - unsigned NoGlobalMerge : 1; ///< Set when -mno-global-merge is enabled. - unsigned NoImplicitFloat : 1; ///< Set when -mno-implicit-float is enabled. - unsigned NoInfsFPMath : 1; ///< Assume FP arguments, results not +-Inf. - unsigned NoInline : 1; ///< Set when -fno-inline is enabled. Disables - ///< use of the inline keyword. - unsigned NoNaNsFPMath : 1; ///< Assume FP arguments, results not NaN. - unsigned NoZeroInitializedInBSS : 1; ///< -fno-zero-initialized-in-bss. - unsigned ObjCDispatchMethod : 2; ///< Method of Objective-C dispatch to use. - unsigned OmitLeafFramePointer : 1; ///< Set when -momit-leaf-frame-pointer is - ///< enabled. - unsigned OptimizationLevel : 3; ///< The -O[0-4] option specified. - unsigned OptimizeSize : 2; ///< If -Os (==1) or -Oz (==2) is specified. - unsigned RelaxAll : 1; ///< Relax all machine code instructions. - unsigned RelaxedAliasing : 1; ///< Set when -fno-strict-aliasing is enabled. - unsigned SaveTempLabels : 1; ///< Save temporary labels. - unsigned SimplifyLibCalls : 1; ///< Set when -fbuiltin is enabled. - unsigned SoftFloat : 1; ///< -soft-float. - unsigned StrictEnums : 1; ///< Optimize based on strict enum definition. - unsigned TimePasses : 1; ///< Set when -ftime-report is enabled. - unsigned UnitAtATime : 1; ///< Unused. For mirroring GCC optimization - ///< selection. - unsigned UnrollLoops : 1; ///< Control whether loops are unrolled. - unsigned UnsafeFPMath : 1; ///< Allow unsafe floating point optzns. - unsigned UnwindTables : 1; ///< Emit unwind tables. - - /// Attempt to use register sized accesses to bit-fields in structures, when - /// possible. - unsigned UseRegisterSizedBitfieldAccess : 1; - - unsigned VerifyModule : 1; ///< Control whether the module should be run - ///< through the LLVM Verifier. - - unsigned StackRealignment : 1; ///< Control whether to permit stack - ///< realignment. - unsigned UseInitArray : 1; ///< Control whether to use .init_array or - ///< .ctors. - unsigned StackAlignment; ///< Overrides default stack alignment, - ///< if not 0. - /// The code model to use (-mcmodel). std::string CodeModel; @@ -144,9 +78,6 @@ public: /// The string to embed in debug information as the current working directory. std::string DebugCompilationDir; - /// The kind of generated debug info. - DebugInfoKind DebugInfo; - /// The string to embed in the debug information for the compile unit, if /// non-empty. std::string DwarfDebugFlags; @@ -160,9 +91,6 @@ public: /// The name of the bitcode file to link before optzns. std::string LinkBitcodeFile; - /// The kind of inlining to perform. - InliningMethod Inlining; - /// The user provided name for the "main file", if non-empty. This is useful /// in situations where the input file name does not match the original input /// file, for example with -save-temps. @@ -178,79 +106,21 @@ public: /// A list of command-line options to forward to the LLVM backend. std::vector BackendOptions; - /// The user specified number of registers to be used for integral arguments, - /// or 0 if unspecified. - unsigned NumRegisterParameters; - - /// The run-time penalty for bounds checking, or 0 to disable. - unsigned char BoundsChecking; - - /// The default TLS model to use. - TLSModel DefaultTLSModel; - public: + // Define accessors/mutators for code generation options of enumeration type. +#define CODEGENOPT(Name, Bits, Default) +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ + Type get##Name() const { return static_cast(Name); } \ + void set##Name(Type Value) { Name = static_cast(Value); } +#include "clang/Frontend/CodeGenOptions.def" + CodeGenOptions() { - AsmVerbose = 0; - CUDAIsDevice = 0; - CXAAtExit = 1; - CXXCtorDtorAliases = 0; - DataSections = 0; - DisableFPElim = 0; - DisableLLVMOpts = 0; - DisableRedZone = 0; - DisableTailCalls = 0; - EmitDeclMetadata = 0; - EmitGcovArcs = 0; - EmitGcovNotes = 0; - EmitOpenCLArgMetadata = 0; - EmitMicrosoftInlineAsm = 0; - ForbidGuardVariables = 0; - FunctionSections = 0; - HiddenWeakTemplateVTables = 0; - HiddenWeakVTables = 0; - InstrumentFunctions = 0; - InstrumentForProfiling = 0; - LessPreciseFPMAD = 0; - MergeAllConstants = 1; - NoCommon = 0; - NoDwarf2CFIAsm = 0; - NoImplicitFloat = 0; - NoInfsFPMath = 0; - NoInline = 0; - NoNaNsFPMath = 0; - NoZeroInitializedInBSS = 0; - NumRegisterParameters = 0; - ObjCAutoRefCountExceptions = 0; - ObjCDispatchMethod = Legacy; - OmitLeafFramePointer = 0; - OptimizationLevel = 0; - OptimizeSize = 0; - RelaxAll = 0; - RelaxedAliasing = 0; - SaveTempLabels = 0; - SimplifyLibCalls = 1; - SoftFloat = 0; - StrictEnums = 0; - TimePasses = 0; - UnitAtATime = 1; - UnrollLoops = 0; - UnsafeFPMath = 0; - UnwindTables = 0; - UseRegisterSizedBitfieldAccess = 0; - VerifyModule = 1; - StackRealignment = 0; - StackAlignment = 0; - BoundsChecking = 0; - UseInitArray = 0; +#define CODEGENOPT(Name, Bits, Default) Name = Default; +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ + set##Name(Default); +#include "clang/Frontend/CodeGenOptions.def" - DebugInfo = NoDebugInfo; - Inlining = NoInlining; RelocationModel = "pic"; - DefaultTLSModel = GeneralDynamicTLSModel; - } - - ObjCDispatchMethodKind getObjCDispatchMethod() const { - return ObjCDispatchMethodKind(ObjCDispatchMethod); } }; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index b28e1031b835..2f3dc3f80847 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/ModuleLoader.h" #include "llvm/ADT/ArrayRef.h" @@ -130,8 +131,8 @@ class CompilerInstance : public ModuleLoader { /// The list of active output files. std::list OutputFiles; - void operator=(const CompilerInstance &); // DO NOT IMPLEMENT - CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT + CompilerInstance(const CompilerInstance &) LLVM_DELETED_FUNCTION; + void operator=(const CompilerInstance &) LLVM_DELETED_FUNCTION; public: CompilerInstance(); ~CompilerInstance(); @@ -189,10 +190,7 @@ public: /// @name Forwarding Methods /// { - AnalyzerOptions &getAnalyzerOpts() { - return Invocation->getAnalyzerOpts(); - } - const AnalyzerOptions &getAnalyzerOpts() const { + AnalyzerOptionsRef getAnalyzerOpts() { return Invocation->getAnalyzerOpts(); } @@ -393,7 +391,7 @@ public: ASTConsumer *takeASTConsumer() { return Consumer.take(); } /// setASTConsumer - Replace the current AST consumer; the compiler instance - /// takes ownership of \arg Value. + /// takes ownership of \p Value. void setASTConsumer(ASTConsumer *Value); /// } @@ -433,7 +431,7 @@ public: } /// setCodeCompletionConsumer - Replace the current code completion consumer; - /// the compiler instance takes ownership of \arg Value. + /// the compiler instance takes ownership of \p Value. void setCodeCompletionConsumer(CodeCompleteConsumer *Value); /// } @@ -488,7 +486,7 @@ public: /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. /// - /// The \arg Argc and \arg Argv arguments are used only for logging purposes, + /// The \p Argc and \p Argv arguments are used only for logging purposes, /// when the diagnostic options indicate that the compiler should output /// logging information. /// @@ -498,8 +496,7 @@ public: /// releasing the returned DiagnosticsEngine's client eventually. /// /// \param Opts - The diagnostic options; note that the created text - /// diagnostic object contains a reference to these options and its lifetime - /// must extend past that of the diagnostic engine. + /// diagnostic object contains a reference to these options. /// /// \param Client If non-NULL, a diagnostic client that will be /// attached to (and, then, owned by) the returned DiagnosticsEngine @@ -510,7 +507,7 @@ public: /// /// \return The new object on success, or null on failure. static IntrusiveRefCntPtr - createDiagnostics(const DiagnosticOptions &Opts, int Argc, + createDiagnostics(DiagnosticOptions *Opts, int Argc, const char* const *Argv, DiagnosticConsumer *Client = 0, bool ShouldOwnClient = true, @@ -534,7 +531,6 @@ public: /// context. void createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation, - bool DisableStatCache, bool AllowPCHWithCompilerErrors, void *DeserializationListener); @@ -544,7 +540,6 @@ public: static ExternalASTSource * createPCHExternalASTSource(StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, - bool DisableStatCache, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, void *DeserializationListener, bool Preamble); @@ -555,8 +550,7 @@ public: void createCodeCompletionConsumer(); /// Create a code completion consumer to print code completion results, at - /// \arg Filename, \arg Line, and \arg Column, to the given output stream \arg - /// OS. + /// \p Filename, \p Line, and \p Column, to the given output stream \p OS. static CodeCompleteConsumer * createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, unsigned Line, unsigned Column, @@ -596,15 +590,15 @@ public: /// Create a new output file, optionally deriving the output path name. /// - /// If \arg OutputPath is empty, then createOutputFile will derive an output - /// path location as \arg BaseInput, with any suffix removed, and \arg - /// Extension appended. If OutputPath is not stdout and \arg UseTemporary + /// If \p OutputPath is empty, then createOutputFile will derive an output + /// path location as \p BaseInput, with any suffix removed, and \p Extension + /// appended. If \p OutputPath is not stdout and \p UseTemporary /// is true, createOutputFile will create a new temporary file that must be - /// renamed to OutputPath in the end. + /// renamed to \p OutputPath in the end. /// /// \param OutputPath - If given, the path to the output file. /// \param Error [out] - On failure, the error message. - /// \param BaseInput - If \arg OutputPath is empty, the input path name to use + /// \param BaseInput - If \p OutputPath is empty, the input path name to use /// for deriving the output path. /// \param Extension - The extension to use for derived output names. /// \param Binary - The mode to open the file in. @@ -613,7 +607,7 @@ public: /// multithreaded use, as the underlying signal mechanism is not reentrant /// \param UseTemporary - Create a new temporary file that must be renamed to /// OutputPath in the end. - /// \param CreateMissingDirectories - When \arg UseTemporary is true, create + /// \param CreateMissingDirectories - When \p UseTemporary is true, create /// missing directories in the output path. /// \param ResultPathName [out] - If given, the result path name will be /// stored here on success. @@ -637,15 +631,13 @@ public: /// as the main file. /// /// \return True on success. - bool InitializeSourceManager(StringRef InputFile, - SrcMgr::CharacteristicKind Kind = SrcMgr::C_User); + bool InitializeSourceManager(const FrontendInputFile &Input); /// InitializeSourceManager - Initialize the source manager to set InputFile /// as the main file. /// /// \return True on success. - static bool InitializeSourceManager(StringRef InputFile, - SrcMgr::CharacteristicKind Kind, + static bool InitializeSourceManager(const FrontendInputFile &Input, DiagnosticsEngine &Diags, FileManager &FileMgr, SourceManager &SourceMgr, diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index d6fe003da0fd..1314956c3f47 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -13,15 +13,15 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/FileSystemOptions.h" -#include "clang/Frontend/AnalyzerOptions.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/Frontend/MigratorOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/DependencyOutputOptions.h" -#include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/FrontendOptions.h" -#include "clang/Frontend/HeaderSearchOptions.h" #include "clang/Frontend/LangStandard.h" -#include "clang/Frontend/PreprocessorOptions.h" #include "clang/Frontend/PreprocessorOutputOptions.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" @@ -52,6 +52,19 @@ class CompilerInvocationBase : public RefCountedBase { protected: /// Options controlling the language variant. IntrusiveRefCntPtr LangOpts; + + /// Options controlling the target. + IntrusiveRefCntPtr TargetOpts; + + /// Options controlling the diagnostic engine. + IntrusiveRefCntPtr DiagnosticOpts; + + /// Options controlling the \#include directive. + IntrusiveRefCntPtr HeaderSearchOpts; + + /// Options controlling the preprocessor (aside from \#include handling). + IntrusiveRefCntPtr PreprocessorOpts; + public: CompilerInvocationBase(); @@ -59,6 +72,23 @@ public: LangOptions *getLangOpts() { return LangOpts.getPtr(); } const LangOptions *getLangOpts() const { return LangOpts.getPtr(); } + + TargetOptions &getTargetOpts() { return *TargetOpts.getPtr(); } + const TargetOptions &getTargetOpts() const { + return *TargetOpts.getPtr(); + } + + DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; } + + HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; } + const HeaderSearchOptions &getHeaderSearchOpts() const { + return *HeaderSearchOpts; + } + + PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; } + const PreprocessorOptions &getPreprocessorOpts() const { + return *PreprocessorOpts; + } }; /// \brief Helper class for holding the data necessary to invoke the compiler. @@ -68,7 +98,7 @@ public: /// options, the warning flags, and so on. class CompilerInvocation : public CompilerInvocationBase { /// Options controlling the static analyzer. - AnalyzerOptions AnalyzerOpts; + AnalyzerOptionsRef AnalyzerOpts; MigratorOptions MigratorOpts; @@ -78,29 +108,17 @@ class CompilerInvocation : public CompilerInvocationBase { /// Options controlling dependency output. DependencyOutputOptions DependencyOutputOpts; - /// Options controlling the diagnostic engine. - DiagnosticOptions DiagnosticOpts; - /// Options controlling file system operations. FileSystemOptions FileSystemOpts; /// Options controlling the frontend itself. FrontendOptions FrontendOpts; - /// Options controlling the \#include directive. - HeaderSearchOptions HeaderSearchOpts; - - /// Options controlling the preprocessor (aside from \#include handling). - PreprocessorOptions PreprocessorOpts; - /// Options controlling preprocessed output. PreprocessorOutputOptions PreprocessorOutputOpts; - /// Options controlling the target. - TargetOptions TargetOpts; - public: - CompilerInvocation() {} + CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {} /// @name Utility Methods /// @{ @@ -127,10 +145,6 @@ public: /// executable), for finding the builtin compiler path. static std::string GetResourcesPath(const char *Argv0, void *MainAddr); - /// \brief Convert the CompilerInvocation to a list of strings suitable for - /// passing to CreateFromArgs. - void toArgs(std::vector &Res) const; - /// \brief Set language defaults for the given input language and /// language standard in the given LangOptions object. /// @@ -148,8 +162,7 @@ public: /// @name Option Subgroups /// @{ - AnalyzerOptions &getAnalyzerOpts() { return AnalyzerOpts; } - const AnalyzerOptions &getAnalyzerOpts() const { + AnalyzerOptionsRef getAnalyzerOpts() const { return AnalyzerOpts; } @@ -170,29 +183,16 @@ public: return DependencyOutputOpts; } - DiagnosticOptions &getDiagnosticOpts() { return DiagnosticOpts; } - const DiagnosticOptions &getDiagnosticOpts() const { return DiagnosticOpts; } - FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; } const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } - HeaderSearchOptions &getHeaderSearchOpts() { return HeaderSearchOpts; } - const HeaderSearchOptions &getHeaderSearchOpts() const { - return HeaderSearchOpts; - } - FrontendOptions &getFrontendOpts() { return FrontendOpts; } const FrontendOptions &getFrontendOpts() const { return FrontendOpts; } - PreprocessorOptions &getPreprocessorOpts() { return PreprocessorOpts; } - const PreprocessorOptions &getPreprocessorOpts() const { - return PreprocessorOpts; - } - PreprocessorOutputOptions &getPreprocessorOutputOpts() { return PreprocessorOutputOpts; } @@ -200,11 +200,6 @@ public: return PreprocessorOutputOpts; } - TargetOptions &getTargetOpts() { return TargetOpts; } - const TargetOptions &getTargetOpts() const { - return TargetOpts; - } - /// @} }; diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h deleted file mode 100644 index 8dec37ca0311..000000000000 --- a/include/clang/Frontend/DiagnosticOptions.h +++ /dev/null @@ -1,111 +0,0 @@ -//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H -#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H - -#include "clang/Basic/Diagnostic.h" - -#include -#include - -namespace clang { - -/// DiagnosticOptions - Options for controlling the compiler diagnostics -/// engine. -class DiagnosticOptions { -public: - unsigned IgnoreWarnings : 1; /// -w - unsigned NoRewriteMacros : 1; /// -Wno-rewrite-macros - unsigned Pedantic : 1; /// -pedantic - unsigned PedanticErrors : 1; /// -pedantic-errors - unsigned ShowColumn : 1; /// Show column number on diagnostics. - unsigned ShowLocation : 1; /// Show source location information. - unsigned ShowCarets : 1; /// Show carets in diagnostics. - unsigned ShowFixits : 1; /// Show fixit information. - unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. - unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its. - unsigned ShowOptionNames : 1; /// Show the option name for mappable - /// diagnostics. - unsigned ShowNoteIncludeStack : 1; /// Show include stacks for notes. - unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, - /// 2 -> Full Name. - - unsigned Format : 2; /// Format for diagnostics: - enum TextDiagnosticFormat { Clang, Msvc, Vi }; - - unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. - unsigned ShowOverloads : 1; /// Overload candidates to show. Values from - /// DiagnosticsEngine::OverloadsShown - unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected - /// diagnostics, indicated by markers in the - /// input source file. - - unsigned ElideType: 1; /// Elide identical types in template diffing - unsigned ShowTemplateTree: 1; /// Print a template tree when diffing - - unsigned ErrorLimit; /// Limit # errors emitted. - unsigned MacroBacktraceLimit; /// Limit depth of macro expansion backtrace. - unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace. - unsigned ConstexprBacktraceLimit; /// Limit depth of constexpr backtrace. - - /// The distance between tab stops. - unsigned TabStop; - enum { DefaultTabStop = 8, MaxTabStop = 100, - DefaultMacroBacktraceLimit = 6, - DefaultTemplateBacktraceLimit = 10, - DefaultConstexprBacktraceLimit = 10 }; - - /// Column limit for formatting message diagnostics, or 0 if unused. - unsigned MessageLength; - - /// If non-empty, a file to log extended build information to, for development - /// testing and analysis. - std::string DumpBuildInformation; - - /// The file to log diagnostic output to. - std::string DiagnosticLogFile; - - /// The file to serialize diagnostics to (non-appending). - std::string DiagnosticSerializationFile; - - /// The list of -W... options used to alter the diagnostic mappings, with the - /// prefixes removed. - std::vector Warnings; - -public: - DiagnosticOptions() { - IgnoreWarnings = 0; - TabStop = DefaultTabStop; - MessageLength = 0; - NoRewriteMacros = 0; - Pedantic = 0; - PedanticErrors = 0; - ShowCarets = 1; - ShowColors = 0; - ShowOverloads = DiagnosticsEngine::Ovl_All; - ShowColumn = 1; - ShowFixits = 1; - ShowLocation = 1; - ShowOptionNames = 0; - ShowCategories = 0; - Format = Clang; - ShowSourceRanges = 0; - ShowParseableFixits = 0; - VerifyDiagnostics = 0; - ErrorLimit = 0; - TemplateBacktraceLimit = DefaultTemplateBacktraceLimit; - MacroBacktraceLimit = DefaultMacroBacktraceLimit; - ConstexprBacktraceLimit = DefaultConstexprBacktraceLimit; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h index 09d7ecb51d80..086bb137d46f 100644 --- a/include/clang/Frontend/DiagnosticRenderer.h +++ b/include/clang/Frontend/DiagnosticRenderer.h @@ -44,7 +44,7 @@ typedef llvm::PointerUnion DiagOpts; /// \brief The location of the previous diagnostic if known. /// @@ -66,7 +66,7 @@ protected: DiagnosticsEngine::Level LastLevel; DiagnosticRenderer(const LangOptions &LangOpts, - const DiagnosticOptions &DiagOpts); + DiagnosticOptions *DiagOpts); virtual ~DiagnosticRenderer(); @@ -124,7 +124,7 @@ public: /// \param Ranges The underlined ranges for this code snippet. /// \param FixItHints The FixIt hints active for this diagnostic. /// \param SM The SourceManager; will be null if the diagnostic came from the - /// frontend, thus \param Loc will be invalid. + /// frontend, thus \p Loc will be invalid. void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, ArrayRef FixItHints, @@ -139,7 +139,7 @@ public: class DiagnosticNoteRenderer : public DiagnosticRenderer { public: DiagnosticNoteRenderer(const LangOptions &LangOpts, - const DiagnosticOptions &DiagOpts) + DiagnosticOptions *DiagOpts) : DiagnosticRenderer(LangOpts, DiagOpts) {} virtual ~DiagnosticNoteRenderer(); diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index c0056de5cae3..328344425c38 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -109,7 +109,7 @@ public: /// @{ bool isCurrentFileAST() const { - assert(!CurrentInput.File.empty() && "No current file!"); + assert(!CurrentInput.isEmpty() && "No current file!"); return CurrentASTUnit != 0; } @@ -117,14 +117,14 @@ public: return CurrentInput; } - const std::string &getCurrentFile() const { - assert(!CurrentInput.File.empty() && "No current file!"); - return CurrentInput.File; + const StringRef getCurrentFile() const { + assert(!CurrentInput.isEmpty() && "No current file!"); + return CurrentInput.getFile(); } InputKind getCurrentFileKind() const { - assert(!CurrentInput.File.empty() && "No current file!"); - return CurrentInput.Kind; + assert(!CurrentInput.isEmpty() && "No current file!"); + return CurrentInput.getKind(); } ASTUnit &getCurrentASTUnit() const { @@ -167,8 +167,8 @@ public: /// @name Public Action Interface /// @{ - /// BeginSourceFile - Prepare the action for processing the input file \arg - /// Filename; this is run after the options and frontend have been + /// BeginSourceFile - Prepare the action for processing the input file + /// \p Input; this is run after the options and frontend have been /// initialized, but prior to executing any per-file processing. /// /// \param CI - The compiler instance this action is being run from. The diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index ce1cd9b2d3bc..db2f5a5e7159 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -16,6 +16,10 @@ #include #include +namespace llvm { +class MemoryBuffer; +} + namespace clang { namespace frontend { @@ -72,19 +76,41 @@ enum InputKind { /// \brief An input file for the front end. -struct FrontendInputFile { +class FrontendInputFile { /// \brief The file name, or "-" to read from standard input. std::string File; + llvm::MemoryBuffer *Buffer; + /// \brief The kind of input, e.g., C source, AST file, LLVM IR. InputKind Kind; /// \brief Whether we're dealing with a 'system' input (vs. a 'user' input). bool IsSystem; - - FrontendInputFile() : Kind(IK_None) { } + +public: + FrontendInputFile() : Buffer(0), Kind(IK_None) { } FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) - : File(File.str()), Kind(Kind), IsSystem(IsSystem) { } + : File(File.str()), Buffer(0), Kind(Kind), IsSystem(IsSystem) { } + FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind, + bool IsSystem = false) + : Buffer(buffer), Kind(Kind), IsSystem(IsSystem) { } + + InputKind getKind() const { return Kind; } + bool isSystem() const { return IsSystem; } + + bool isEmpty() const { return File.empty() && Buffer == 0; } + bool isFile() const { return !isBuffer(); } + bool isBuffer() const { return Buffer != 0; } + + StringRef getFile() const { + assert(isFile()); + return File; + } + llvm::MemoryBuffer *getBuffer() const { + assert(isBuffer()); + return Buffer; + } }; /// FrontendOptions - Options for controlling the behavior of the frontend. diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h deleted file mode 100644 index ebc8f264b2a2..000000000000 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ /dev/null @@ -1,146 +0,0 @@ -//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H -#define LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H - -#include "llvm/ADT/StringRef.h" -#include - -namespace clang { - -namespace frontend { - /// IncludeDirGroup - Identifiers the group a include entry belongs to, which - /// represents its relative positive in the search list. A \#include of a "" - /// path starts at the -iquote group, then searches the Angled group, then - /// searches the system group, etc. - enum IncludeDirGroup { - Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'. - Angled, ///< Paths for '\#include <>' added by '-I'. - IndexHeaderMap, ///< Like Angled, but marks header maps used when - /// building frameworks. - System, ///< Like Angled, but marks system directories. - CSystem, ///< Like System, but only used for C. - CXXSystem, ///< Like System, but only used for C++. - ObjCSystem, ///< Like System, but only used for ObjC. - ObjCXXSystem, ///< Like System, but only used for ObjC++. - After ///< Like System, but searched after the system directories. - }; -} - -/// HeaderSearchOptions - Helper class for storing options related to the -/// initialization of the HeaderSearch object. -class HeaderSearchOptions { -public: - struct Entry { - std::string Path; - frontend::IncludeDirGroup Group; - unsigned IsUserSupplied : 1; - unsigned IsFramework : 1; - - /// IgnoreSysRoot - This is false if an absolute path should be treated - /// relative to the sysroot, or true if it should always be the absolute - /// path. - unsigned IgnoreSysRoot : 1; - - /// \brief True if this entry is an internal search path. - /// - /// This typically indicates that users didn't directly provide it, but - /// instead it was provided by a compatibility layer for a particular - /// system. This isn't redundant with IsUserSupplied (even though perhaps - /// it should be) because that is false for user provided '-iwithprefix' - /// header search entries. - unsigned IsInternal : 1; - - /// \brief True if this entry's headers should be wrapped in extern "C". - unsigned ImplicitExternC : 1; - - Entry(StringRef path, frontend::IncludeDirGroup group, - bool isUserSupplied, bool isFramework, bool ignoreSysRoot, - bool isInternal, bool implicitExternC) - : Path(path), Group(group), IsUserSupplied(isUserSupplied), - IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot), - IsInternal(isInternal), ImplicitExternC(implicitExternC) {} - }; - - struct SystemHeaderPrefix { - /// A prefix to be matched against paths in \#include directives. - std::string Prefix; - - /// True if paths beginning with this prefix should be treated as system - /// headers. - bool IsSystemHeader; - - SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) - : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} - }; - - /// If non-empty, the directory to use as a "virtual system root" for include - /// paths. - std::string Sysroot; - - /// User specified include entries. - std::vector UserEntries; - - /// User-specified system header prefixes. - std::vector SystemHeaderPrefixes; - - /// The directory which holds the compiler resource files (builtin includes, - /// etc.). - std::string ResourceDir; - - /// \brief The directory used for the module cache. - std::string ModuleCachePath; - - /// \brief Whether we should disable the use of the hash string within the - /// module cache. - /// - /// Note: Only used for testing! - unsigned DisableModuleHash : 1; - - /// Include the compiler builtin includes. - unsigned UseBuiltinIncludes : 1; - - /// Include the system standard include search directories. - unsigned UseStandardSystemIncludes : 1; - - /// Include the system standard C++ library include search directories. - unsigned UseStandardCXXIncludes : 1; - - /// Use libc++ instead of the default libstdc++. - unsigned UseLibcxx : 1; - - /// Whether header search information should be output as for -v. - unsigned Verbose : 1; - -public: - HeaderSearchOptions(StringRef _Sysroot = "/") - : Sysroot(_Sysroot), DisableModuleHash(0), UseBuiltinIncludes(true), - UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), - UseLibcxx(false), Verbose(false) {} - - /// AddPath - Add the \arg Path path to the specified \arg Group list. - void AddPath(StringRef Path, frontend::IncludeDirGroup Group, - bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot, - bool IsInternal = false, bool ImplicitExternC = false) { - UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, - IgnoreSysRoot, IsInternal, ImplicitExternC)); - } - - /// AddSystemHeaderPrefix - Override whether \#include directives naming a - /// path starting with \arg Prefix should be considered as naming a system - /// header. - void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { - SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader)); - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h index e6f44032ac95..f07cb0234bdb 100644 --- a/include/clang/Frontend/LangStandard.h +++ b/include/clang/Frontend/LangStandard.h @@ -18,16 +18,17 @@ namespace clang { namespace frontend { enum LangFeatures { - BCPLComment = (1 << 0), + LineComment = (1 << 0), C89 = (1 << 1), C99 = (1 << 2), C11 = (1 << 3), CPlusPlus = (1 << 4), CPlusPlus0x = (1 << 5), - Digraphs = (1 << 6), - GNUMode = (1 << 7), - HexFloat = (1 << 8), - ImplicitInt = (1 << 9) + CPlusPlus1y = (1 << 6), + Digraphs = (1 << 7), + GNUMode = (1 << 8), + HexFloat = (1 << 9), + ImplicitInt = (1 << 10) }; } @@ -53,8 +54,8 @@ public: /// getDescription - Get the description of this standard. const char *getDescription() const { return Description; } - /// hasBCPLComments - Language supports '//' comments. - bool hasBCPLComments() const { return Flags & frontend::BCPLComment; } + /// Language supports '//' comments. + bool hasLineComments() const { return Flags & frontend::LineComment; } /// isC89 - Language is a superset of C89. bool isC89() const { return Flags & frontend::C89; } @@ -71,6 +72,9 @@ public: /// isCPlusPlus0x - Language is a C++0x variant. bool isCPlusPlus0x() const { return Flags & frontend::CPlusPlus0x; } + /// isCPlusPlus1y - Language is a C++1y variant. + bool isCPlusPlus1y() const { return Flags & frontend::CPlusPlus1y; } + /// hasDigraphs - Language supports digraphs. bool hasDigraphs() const { return Flags & frontend::Digraphs; } diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index a604d4bff658..10807b7804b3 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -36,91 +36,99 @@ LANGSTANDARD(c94, "iso9899:199409", LANGSTANDARD(gnu89, "gnu89", "ISO C 1990 with GNU extensions", - BCPLComment | C89 | Digraphs | GNUMode | ImplicitInt) + LineComment | C89 | Digraphs | GNUMode | ImplicitInt) LANGSTANDARD(gnu90, "gnu90", "ISO C 1990 with GNU extensions", - BCPLComment | C89 | Digraphs | GNUMode | ImplicitInt) + LineComment | C89 | Digraphs | GNUMode | ImplicitInt) // C99-ish modes LANGSTANDARD(c99, "c99", "ISO C 1999", - BCPLComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat) LANGSTANDARD(c9x, "c9x", "ISO C 1999", - BCPLComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat) LANGSTANDARD(iso9899_1999, "iso9899:1999", "ISO C 1999", - BCPLComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat) LANGSTANDARD(iso9899_199x, "iso9899:199x", "ISO C 1999", - BCPLComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat) LANGSTANDARD(gnu99, "gnu99", "ISO C 1999 with GNU extensions", - BCPLComment | C99 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | Digraphs | GNUMode | HexFloat) LANGSTANDARD(gnu9x, "gnu9x", "ISO C 1999 with GNU extensions", - BCPLComment | C99 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | Digraphs | GNUMode | HexFloat) // C11 modes LANGSTANDARD(c11, "c11", "ISO C 2011", - BCPLComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat) LANGSTANDARD(c1x, "c1x", "ISO C 2011", - BCPLComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat) LANGSTANDARD(iso9899_2011, "iso9899:2011", "ISO C 2011", - BCPLComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat) LANGSTANDARD(iso9899_201x, "iso9899:2011", "ISO C 2011", - BCPLComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat) LANGSTANDARD(gnu11, "gnu11", "ISO C 2011 with GNU extensions", - BCPLComment | C99 | C11 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat) LANGSTANDARD(gnu1x, "gnu1x", "ISO C 2011 with GNU extensions", - BCPLComment | C99 | C11 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat) // C++ modes LANGSTANDARD(cxx98, "c++98", "ISO C++ 1998 with amendments", - BCPLComment | CPlusPlus | Digraphs) + LineComment | CPlusPlus | Digraphs) LANGSTANDARD(cxx03, "c++03", "ISO C++ 1998 with amendments", - BCPLComment | CPlusPlus | Digraphs) + LineComment | CPlusPlus | Digraphs) LANGSTANDARD(gnucxx98, "gnu++98", "ISO C++ 1998 with amendments and GNU extensions", - BCPLComment | CPlusPlus | Digraphs | GNUMode) + LineComment | CPlusPlus | Digraphs | GNUMode) LANGSTANDARD(cxx0x, "c++0x", "ISO C++ 2011 with amendments", - BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs) + LineComment | CPlusPlus | CPlusPlus0x | Digraphs) LANGSTANDARD(cxx11, "c++11", "ISO C++ 2011 with amendments", - BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs) + LineComment | CPlusPlus | CPlusPlus0x | Digraphs) LANGSTANDARD(gnucxx0x, "gnu++0x", "ISO C++ 2011 with amendments and GNU extensions", - BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) + LineComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) LANGSTANDARD(gnucxx11, "gnu++11", "ISO C++ 2011 with amendments and GNU extensions", - BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) + LineComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) + +LANGSTANDARD(cxx1y, "c++1y", + "Working draft for ISO C++ 2014", + LineComment | CPlusPlus | CPlusPlus0x | CPlusPlus1y | Digraphs) +LANGSTANDARD(gnucxx1y, "gnu++1y", + "Working draft for ISO C++ 2014 with GNU extensions", + LineComment | CPlusPlus | CPlusPlus0x | CPlusPlus1y | Digraphs | + GNUMode) // OpenCL LANGSTANDARD(opencl, "cl", "OpenCL 1.0", - BCPLComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat) LANGSTANDARD(opencl11, "CL1.1", "OpenCL 1.1", - BCPLComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat) LANGSTANDARD(opencl12, "CL1.2", "OpenCL 1.2", - BCPLComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat) // CUDA LANGSTANDARD(cuda, "cuda", "NVIDIA CUDA(tm)", - BCPLComment | CPlusPlus | Digraphs) + LineComment | CPlusPlus | Digraphs) #undef LANGSTANDARD diff --git a/include/clang/Frontend/LogDiagnosticPrinter.h b/include/clang/Frontend/LogDiagnosticPrinter.h index 4de15f2aed5f..f4fa876ae392 100644 --- a/include/clang/Frontend/LogDiagnosticPrinter.h +++ b/include/clang/Frontend/LogDiagnosticPrinter.h @@ -42,7 +42,7 @@ class LogDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; const LangOptions *LangOpts; - const DiagnosticOptions *DiagOpts; + llvm::IntrusiveRefCntPtr DiagOpts; SourceLocation LastWarningLoc; FullSourceLoc LastLoc; @@ -54,7 +54,7 @@ class LogDiagnosticPrinter : public DiagnosticConsumer { std::string DwarfDebugFlags; public: - LogDiagnosticPrinter(raw_ostream &OS, const DiagnosticOptions &Diags, + LogDiagnosticPrinter(raw_ostream &OS, DiagnosticOptions *Diags, bool OwnsOutputStream = false); virtual ~LogDiagnosticPrinter(); diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h index ffa7b4a9dc6b..539f2c5c4df8 100644 --- a/include/clang/Frontend/MultiplexConsumer.h +++ b/include/clang/Frontend/MultiplexConsumer.h @@ -52,7 +52,6 @@ public: virtual void InitializeSema(Sema &S); virtual void ForgetSema(); - static bool classof(const MultiplexConsumer *) { return true; } private: std::vector Consumers; // Owns these. OwningPtr MutationListener; diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h deleted file mode 100644 index d86a923d4307..000000000000 --- a/include/clang/Frontend/PreprocessorOptions.h +++ /dev/null @@ -1,224 +0,0 @@ -//===--- PreprocessorOptions.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ -#define LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include -#include -#include -#include -#include - -namespace llvm { - class MemoryBuffer; -} - -namespace clang { - -class Preprocessor; -class LangOptions; - -/// \brief Enumerate the kinds of standard library that -enum ObjCXXARCStandardLibraryKind { - ARCXX_nolib, - /// \brief libc++ - ARCXX_libcxx, - /// \brief libstdc++ - ARCXX_libstdcxx -}; - -/// PreprocessorOptions - This class is used for passing the various options -/// used in preprocessor initialization to InitializePreprocessor(). -class PreprocessorOptions { -public: - std::vector > Macros; - std::vector Includes; - std::vector MacroIncludes; - - unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler - /// and target specific predefines. - - unsigned DetailedRecord : 1; /// Whether we should maintain a detailed - /// record of all macro definitions and - /// expansions. - unsigned DetailedRecordConditionalDirectives : 1; /// Whether in the - /// preprocessing record we should also keep - /// track of locations of conditional directives - /// in non-system files. - - /// The implicit PCH included at the start of the translation unit, or empty. - std::string ImplicitPCHInclude; - - /// \brief Headers that will be converted to chained PCHs in memory. - std::vector ChainedIncludes; - - /// \brief When true, disables most of the normal validation performed on - /// precompiled headers. - bool DisablePCHValidation; - - /// \brief When true, disables the use of the stat cache within a - /// precompiled header or AST file. - bool DisableStatCache; - - /// \brief When true, a PCH with compiler errors will not be rejected. - bool AllowPCHWithCompilerErrors; - - /// \brief Dump declarations that are deserialized from PCH, for testing. - bool DumpDeserializedPCHDecls; - - /// \brief This is a set of names for decls that we do not want to be - /// deserialized, and we emit an error if they are; for testing purposes. - std::set DeserializedPCHDeclsToErrorOn; - - /// \brief If non-zero, the implicit PCH include is actually a precompiled - /// preamble that covers this number of bytes in the main source file. - /// - /// The boolean indicates whether the preamble ends at the start of a new - /// line. - std::pair PrecompiledPreambleBytes; - - /// The implicit PTH input included at the start of the translation unit, or - /// empty. - std::string ImplicitPTHInclude; - - /// If given, a PTH cache file to use for speeding up header parsing. - std::string TokenCache; - - /// \brief True if the SourceManager should report the original file name for - /// contents of files that were remapped to other files. Defaults to true. - bool RemappedFilesKeepOriginalName; - - /// \brief The set of file remappings, which take existing files on - /// the system (the first part of each pair) and gives them the - /// contents of other files on the system (the second part of each - /// pair). - std::vector > RemappedFiles; - - /// \brief The set of file-to-buffer remappings, which take existing files - /// on the system (the first part of each pair) and gives them the contents - /// of the specified memory buffer (the second part of each pair). - std::vector > - RemappedFileBuffers; - - /// \brief Whether the compiler instance should retain (i.e., not free) - /// the buffers associated with remapped files. - /// - /// This flag defaults to false; it can be set true only through direct - /// manipulation of the compiler invocation object, in cases where the - /// compiler invocation and its buffers will be reused. - bool RetainRemappedFileBuffers; - - /// \brief The Objective-C++ ARC standard library that we should support, - /// by providing appropriate definitions to retrofit the standard library - /// with support for lifetime-qualified pointers. - ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary; - - /// \brief The path of modules being build, which is used to detect - /// cycles in the module dependency graph as modules are being built. - /// - /// There is no way to set this value from the command line. If we ever need - /// to do so (e.g., if on-demand module construction moves out-of-process), - /// we can add a cc1-level option to do so. - SmallVector ModuleBuildPath; - - typedef std::vector >::iterator - remapped_file_iterator; - typedef std::vector >::const_iterator - const_remapped_file_iterator; - remapped_file_iterator remapped_file_begin() { - return RemappedFiles.begin(); - } - const_remapped_file_iterator remapped_file_begin() const { - return RemappedFiles.begin(); - } - remapped_file_iterator remapped_file_end() { - return RemappedFiles.end(); - } - const_remapped_file_iterator remapped_file_end() const { - return RemappedFiles.end(); - } - - typedef std::vector >:: - iterator remapped_file_buffer_iterator; - typedef std::vector >:: - const_iterator const_remapped_file_buffer_iterator; - remapped_file_buffer_iterator remapped_file_buffer_begin() { - return RemappedFileBuffers.begin(); - } - const_remapped_file_buffer_iterator remapped_file_buffer_begin() const { - return RemappedFileBuffers.begin(); - } - remapped_file_buffer_iterator remapped_file_buffer_end() { - return RemappedFileBuffers.end(); - } - const_remapped_file_buffer_iterator remapped_file_buffer_end() const { - return RemappedFileBuffers.end(); - } - -public: - PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DetailedRecordConditionalDirectives(false), - DisablePCHValidation(false), DisableStatCache(false), - AllowPCHWithCompilerErrors(false), - DumpDeserializedPCHDecls(false), - PrecompiledPreambleBytes(0, true), - RemappedFilesKeepOriginalName(true), - RetainRemappedFileBuffers(false), - ObjCXXARCStandardLibrary(ARCXX_nolib) { } - - void addMacroDef(StringRef Name) { - Macros.push_back(std::make_pair(Name, false)); - } - void addMacroUndef(StringRef Name) { - Macros.push_back(std::make_pair(Name, true)); - } - void addRemappedFile(StringRef From, StringRef To) { - RemappedFiles.push_back(std::make_pair(From, To)); - } - - remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) { - return RemappedFiles.erase(Remapped); - } - - void addRemappedFile(StringRef From, const llvm::MemoryBuffer * To) { - RemappedFileBuffers.push_back(std::make_pair(From, To)); - } - - remapped_file_buffer_iterator - eraseRemappedFile(remapped_file_buffer_iterator Remapped) { - return RemappedFileBuffers.erase(Remapped); - } - - void clearRemappedFiles() { - RemappedFiles.clear(); - RemappedFileBuffers.clear(); - } - - /// \brief Reset any options that are not considered when building a - /// module. - void resetNonModularOptions() { - Includes.clear(); - MacroIncludes.clear(); - ChainedIncludes.clear(); - DumpDeserializedPCHDecls = false; - ImplicitPCHInclude.clear(); - ImplicitPTHInclude.clear(); - TokenCache.clear(); - RetainRemappedFileBuffers = true; - PrecompiledPreambleBytes.first = 0; - PrecompiledPreambleBytes.second = 0; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h index aa0695fe24b6..ab70afd21fc6 100644 --- a/include/clang/Frontend/SerializedDiagnosticPrinter.h +++ b/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -54,7 +54,7 @@ enum RecordIDs { /// (via libclang) without needing to parse Clang's command line output. /// DiagnosticConsumer *create(llvm::raw_ostream *OS, - const DiagnosticOptions &diags); + DiagnosticOptions *diags); } // end serialized_diags namespace } // end clang namespace diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h index c869c08c0fc2..51f841ddd3c5 100644 --- a/include/clang/Frontend/TextDiagnostic.h +++ b/include/clang/Frontend/TextDiagnostic.h @@ -40,7 +40,7 @@ class TextDiagnostic : public DiagnosticRenderer { public: TextDiagnostic(raw_ostream &OS, const LangOptions &LangOpts, - const DiagnosticOptions &DiagOpts); + DiagnosticOptions *DiagOpts); virtual ~TextDiagnostic(); diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 23cf5211cd01..91ac3c833942 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -18,6 +18,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" namespace clang { class DiagnosticOptions; @@ -26,7 +27,7 @@ class TextDiagnostic; class TextDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; - const DiagnosticOptions *DiagOpts; + llvm::IntrusiveRefCntPtr DiagOpts; /// \brief Handle to the currently active text diagnostic emitter. OwningPtr TextDiag; @@ -37,7 +38,7 @@ class TextDiagnosticPrinter : public DiagnosticConsumer { unsigned OwnsOutputStream : 1; public: - TextDiagnosticPrinter(raw_ostream &os, const DiagnosticOptions &diags, + TextDiagnosticPrinter(raw_ostream &os, DiagnosticOptions *diags, bool OwnsOutputStream = false); virtual ~TextDiagnosticPrinter(); diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h index a74589edc94a..06a3b24f3a3f 100644 --- a/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -12,9 +12,9 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include @@ -33,7 +33,9 @@ class FileEntry; /// Indicating that a line expects an error or a warning is simple. Put a /// comment on the line that has the diagnostic, use: /// -/// expected-{error,warning,note} +/// \code +/// expected-{error,warning,note} +/// \endcode /// /// to tag if it's an expected error or warning, and place the expected text /// between {{ and }} markers. The full text doesn't have to be included, only @@ -94,12 +96,15 @@ class FileEntry; /// /// In this example, the diagnostic may appear only once, if at all. /// -/// Regex matching mode may be selected by appending '-re' to type. Example: +/// Regex matching mode may be selected by appending '-re' to type, such as: /// +/// \code /// expected-error-re +/// \endcode /// /// Examples matching error: "variable has incomplete type 'struct s'" /// +/// \code /// // expected-error {{variable has incomplete type 'struct s'}} /// // expected-error {{variable has incomplete type}} /// @@ -107,6 +112,15 @@ class FileEntry; /// // expected-error-re {{variable has has type 'struct .*'}} /// // expected-error-re {{variable has has type 'struct (.*)'}} /// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}} +/// \endcode +/// +/// VerifyDiagnosticConsumer expects at least one expected-* directive to +/// be found inside the source code. If no diagnostics are expected the +/// following directive can be used to indicate this: +/// +/// \code +/// // expected-no-diagnostics +/// \endcode /// class VerifyDiagnosticConsumer: public DiagnosticConsumer, public CommentHandler { @@ -146,8 +160,8 @@ public: } private: - Directive(const Directive&); // DO NOT IMPLEMENT - void operator=(const Directive&); // DO NOT IMPLEMENT + Directive(const Directive &) LLVM_DELETED_FUNCTION; + void operator=(const Directive &) LLVM_DELETED_FUNCTION; }; typedef std::vector DirectiveList; @@ -166,10 +180,12 @@ public: } }; -#ifndef NDEBUG - typedef llvm::DenseSet FilesWithDiagnosticsSet; - typedef llvm::SmallPtrSet FilesParsedForDirectivesSet; -#endif + enum DirectiveStatus { + HasNoDirectives, + HasNoDirectivesReported, + HasExpectedNoDiagnostics, + HasOtherExpectedDirectives + }; private: DiagnosticsEngine &Diags; @@ -177,13 +193,36 @@ private: bool OwnsPrimaryClient; OwningPtr Buffer; const Preprocessor *CurrentPreprocessor; + const LangOptions *LangOpts; + SourceManager *SrcManager; unsigned ActiveSourceFiles; -#ifndef NDEBUG - FilesWithDiagnosticsSet FilesWithDiagnostics; - FilesParsedForDirectivesSet FilesParsedForDirectives; -#endif + DirectiveStatus Status; ExpectedData ED; + void CheckDiagnostics(); + void setSourceManager(SourceManager &SM) { + assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!"); + SrcManager = &SM; + } + +#ifndef NDEBUG + class UnparsedFileStatus { + llvm::PointerIntPair Data; + + public: + UnparsedFileStatus(const FileEntry *File, bool FoundDirectives) + : Data(File, FoundDirectives) {} + + const FileEntry *getFile() const { return Data.getPointer(); } + bool foundDirectives() const { return Data.getInt(); } + }; + + typedef llvm::DenseMap ParsedFilesMap; + typedef llvm::DenseMap UnparsedFilesMap; + + ParsedFilesMap ParsedFiles; + UnparsedFilesMap UnparsedFiles; +#endif public: /// Create a new verifying diagnostic client, which will issue errors to @@ -197,12 +236,19 @@ public: virtual void EndSourceFile(); - /// \brief Manually register a file as parsed. - inline void appendParsedFile(const FileEntry *File) { -#ifndef NDEBUG - FilesParsedForDirectives.insert(File); -#endif - } + enum ParsedStatus { + /// File has been processed via HandleComment. + IsParsed, + + /// File has diagnostics and may have directives. + IsUnparsed, + + /// File has diagnostics but guaranteed no directives. + IsUnparsedNoDirectives + }; + + /// \brief Update lists of parsed and unparsed files. + void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS); virtual bool HandleComment(Preprocessor &PP, SourceRange Comment); diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index f172b5c8d22d..d2e2412192ed 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -28,9 +28,6 @@ public: /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros() = 0; - /// \brief Read the definition for the given macro. - virtual void LoadMacroDefinition(IdentifierInfo *II) = 0; - /// \brief Update an out-of-date identifier. virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0; }; diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h index 107408dced10..8473a6a4e752 100644 --- a/include/clang/Lex/HeaderMap.h +++ b/include/clang/Lex/HeaderMap.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_LEX_HEADERMAP_H #include "clang/Basic/LLVM.h" +#include "llvm/Support/Compiler.h" namespace llvm { class MemoryBuffer; @@ -30,8 +31,8 @@ namespace clang { /// symlinks to files. Its advantages are that it is dense and more efficient /// to create and process than a directory of symlinks. class HeaderMap { - HeaderMap(const HeaderMap&); // DO NOT IMPLEMENT - void operator=(const HeaderMap&); // DO NOT IMPLEMENT + HeaderMap(const HeaderMap &) LLVM_DELETED_FUNCTION; + void operator=(const HeaderMap &) LLVM_DELETED_FUNCTION; const llvm::MemoryBuffer *FileBuffer; bool NeedsBSwap; diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 8e9491fdc339..4334db771c85 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -17,6 +17,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" @@ -29,6 +30,7 @@ class DiagnosticsEngine; class ExternalIdentifierLookup; class FileEntry; class FileManager; +class HeaderSearchOptions; class IdentifierInfo; /// \brief The preprocessor keeps track of this information for each @@ -131,8 +133,10 @@ class HeaderSearch { bool IsUserSpecifiedSystemFramework; }; + /// \brief Header-search options used to initialize this header search. + llvm::IntrusiveRefCntPtr HSOpts; + FileManager &FileMgr; - DiagnosticsEngine &Diags; /// \#include search path information. Requests for \#include "x" search the /// directory of the \#including file first, then each directory in SearchDirs /// consecutively. Requests for search the current dir first, then each @@ -207,17 +211,21 @@ class HeaderSearch { unsigned NumFrameworkLookups, NumSubFrameworkLookups; // HeaderSearch doesn't support default or copy construction. - explicit HeaderSearch(); - explicit HeaderSearch(const HeaderSearch&); - void operator=(const HeaderSearch&); - + HeaderSearch(const HeaderSearch&) LLVM_DELETED_FUNCTION; + void operator=(const HeaderSearch&) LLVM_DELETED_FUNCTION; + friend class DirectoryLookup; public: - HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags, + HeaderSearch(llvm::IntrusiveRefCntPtr HSOpts, + FileManager &FM, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target); ~HeaderSearch(); + /// \brief Retrieve the header-search options with which this header search + /// was initialized. + HeaderSearchOptions &getHeaderSearchOpts() const { return *HSOpts; } + FileManager &getFileMgr() const { return FileMgr; } /// \brief Interface for setting the file search paths. @@ -283,6 +291,11 @@ public: /// \brief Retrieve the path to the module cache. StringRef getModuleCachePath() const { return ModuleCachePath; } + + /// \brief Consider modules when including files from this directory. + void setDirectoryHasModuleMap(const DirectoryEntry* Dir) { + DirectoryHasModuleMap[Dir] = true; + } /// \brief Forget everything we know about headers so far. void ClearFileInfo() { diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h new file mode 100644 index 000000000000..468fefa4aba3 --- /dev/null +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -0,0 +1,147 @@ +//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H +#define LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace clang { + +namespace frontend { + /// IncludeDirGroup - Identifiers the group a include entry belongs to, which + /// represents its relative positive in the search list. A \#include of a "" + /// path starts at the -iquote group, then searches the Angled group, then + /// searches the system group, etc. + enum IncludeDirGroup { + Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'. + Angled, ///< Paths for '\#include <>' added by '-I'. + IndexHeaderMap, ///< Like Angled, but marks header maps used when + /// building frameworks. + System, ///< Like Angled, but marks system directories. + CSystem, ///< Like System, but only used for C. + CXXSystem, ///< Like System, but only used for C++. + ObjCSystem, ///< Like System, but only used for ObjC. + ObjCXXSystem, ///< Like System, but only used for ObjC++. + After ///< Like System, but searched after the system directories. + }; +} + +/// HeaderSearchOptions - Helper class for storing options related to the +/// initialization of the HeaderSearch object. +class HeaderSearchOptions : public llvm::RefCountedBase { +public: + struct Entry { + std::string Path; + frontend::IncludeDirGroup Group; + unsigned IsUserSupplied : 1; + unsigned IsFramework : 1; + + /// IgnoreSysRoot - This is false if an absolute path should be treated + /// relative to the sysroot, or true if it should always be the absolute + /// path. + unsigned IgnoreSysRoot : 1; + + /// \brief True if this entry is an internal search path. + /// + /// This typically indicates that users didn't directly provide it, but + /// instead it was provided by a compatibility layer for a particular + /// system. This isn't redundant with IsUserSupplied (even though perhaps + /// it should be) because that is false for user provided '-iwithprefix' + /// header search entries. + unsigned IsInternal : 1; + + /// \brief True if this entry's headers should be wrapped in extern "C". + unsigned ImplicitExternC : 1; + + Entry(StringRef path, frontend::IncludeDirGroup group, + bool isUserSupplied, bool isFramework, bool ignoreSysRoot, + bool isInternal, bool implicitExternC) + : Path(path), Group(group), IsUserSupplied(isUserSupplied), + IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot), + IsInternal(isInternal), ImplicitExternC(implicitExternC) {} + }; + + struct SystemHeaderPrefix { + /// A prefix to be matched against paths in \#include directives. + std::string Prefix; + + /// True if paths beginning with this prefix should be treated as system + /// headers. + bool IsSystemHeader; + + SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) + : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} + }; + + /// If non-empty, the directory to use as a "virtual system root" for include + /// paths. + std::string Sysroot; + + /// User specified include entries. + std::vector UserEntries; + + /// User-specified system header prefixes. + std::vector SystemHeaderPrefixes; + + /// The directory which holds the compiler resource files (builtin includes, + /// etc.). + std::string ResourceDir; + + /// \brief The directory used for the module cache. + std::string ModuleCachePath; + + /// \brief Whether we should disable the use of the hash string within the + /// module cache. + /// + /// Note: Only used for testing! + unsigned DisableModuleHash : 1; + + /// Include the compiler builtin includes. + unsigned UseBuiltinIncludes : 1; + + /// Include the system standard include search directories. + unsigned UseStandardSystemIncludes : 1; + + /// Include the system standard C++ library include search directories. + unsigned UseStandardCXXIncludes : 1; + + /// Use libc++ instead of the default libstdc++. + unsigned UseLibcxx : 1; + + /// Whether header search information should be output as for -v. + unsigned Verbose : 1; + +public: + HeaderSearchOptions(StringRef _Sysroot = "/") + : Sysroot(_Sysroot), DisableModuleHash(0), UseBuiltinIncludes(true), + UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), + UseLibcxx(false), Verbose(false) {} + + /// AddPath - Add the \p Path path to the specified \p Group list. + void AddPath(StringRef Path, frontend::IncludeDirGroup Group, + bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot, + bool IsInternal = false, bool ImplicitExternC = false) { + UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, + IgnoreSysRoot, IsInternal, ImplicitExternC)); + } + + /// AddSystemHeaderPrefix - Override whether \#include directives naming a + /// path starting with \p Prefix should be considered as naming a system + /// header. + void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { + SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader)); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index ca233de71c39..407b644fd74c 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -31,11 +31,11 @@ class DiagnosticBuilder; enum ConflictMarkerKind { /// Not within a conflict marker. CMK_None, - /// A normal or diff3 conflict marker, initiated by at least 7 s. + /// A normal or diff3 conflict marker, initiated by at least 7 "<"s, + /// separated by at least 7 "="s or "|"s, and terminated by at least 7 ">"s. CMK_Normal, - /// A Perforce-style conflict marker, initiated by 4 >s, separated by 4 =s, - /// and terminated by 4 "s, + /// separated by 4 "="s, and terminated by 4 "<"s. CMK_Perforce }; @@ -83,8 +83,8 @@ class Lexer : public PreprocessorLexer { // CurrentConflictMarkerState - The kind of conflict marker we are handling. ConflictMarkerKind CurrentConflictMarkerState; - Lexer(const Lexer&); // DO NOT IMPLEMENT - void operator=(const Lexer&); // DO NOT IMPLEMENT + Lexer(const Lexer &) LLVM_DELETED_FUNCTION; + void operator=(const Lexer &) LLVM_DELETED_FUNCTION; friend class Preprocessor; void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd); @@ -128,9 +128,7 @@ public: SourceLocation getFileLoc() const { return FileLoc; } /// Lex - Return the next token in the file. If this is the end of file, it - /// return the tok::eof token. Return true if an error occurred and - /// compilation should terminate, false if normal. This implicitly involves - /// the preprocessor. + /// return the tok::eof token. This implicitly involves the preprocessor. void Lex(Token &Result) { // Start a new token. Result.startToken(); @@ -278,8 +276,6 @@ public: /// \brief Given a location any where in a source buffer, find the location /// that corresponds to the beginning of the token in which the original /// source location lands. - /// - /// \param Loc static SourceLocation GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts); @@ -324,7 +320,7 @@ public: /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. /// - /// \param MacroBegin If non-null and function returns true, it is set to + /// \param MacroEnd If non-null and function returns true, it is set to /// end location of the macro. static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, @@ -396,7 +392,36 @@ public: static std::pair ComputePreamble(const llvm::MemoryBuffer *Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0); - + + /// \brief Checks that the given token is the first token that occurs after + /// the given location (this excludes comments and whitespace). Returns the + /// location immediately after the specified token. If the token is not found + /// or the location is inside a macro, the returned source location will be + /// invalid. + static SourceLocation findLocationAfterToken(SourceLocation loc, + tok::TokenKind TKind, + const SourceManager &SM, + const LangOptions &LangOpts, + bool SkipTrailingWhitespaceAndNewLine); + + /// \brief Returns true if the given character could appear in an identifier. + static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts); + + /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever + /// emit a warning. + static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, + const LangOptions &LangOpts) { + // If this is not a trigraph and not a UCN or escaped newline, return + // quickly. + if (isObviouslySimpleCharacter(Ptr[0])) { + Size = 1; + return *Ptr; + } + + Size = 0; + return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); + } + //===--------------------------------------------------------------------===// // Internal implementation interfaces. private: @@ -427,7 +452,6 @@ private: //===--------------------------------------------------------------------===// // Lexer character reading interfaces. -public: // This lexer is built on two interfaces for reading characters, both of which // automatically provide phase 1/2 translation. getAndAdvanceChar is used @@ -467,7 +491,6 @@ public: return C; } -private: /// ConsumeChar - When a character (identified by getCharAndSize) is consumed /// and added to a given token, check to see if there are diagnostics that /// need to be emitted or flags that need to be set on the token. If so, do @@ -503,22 +526,6 @@ private: /// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize /// method. char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0); -public: - - /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever - /// emit a warning. - static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, - const LangOptions &LangOpts) { - // If this is not a trigraph and not a UCN or escaped newline, return - // quickly. - if (isObviouslySimpleCharacter(Ptr[0])) { - Size = 1; - return *Ptr; - } - - Size = 0; - return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); - } /// getEscapedNewLineSize - Return the size of the specified escaped newline, /// or 0 if it is not an escaped newline. P[-1] is known to be a "\" on entry @@ -530,22 +537,6 @@ public: /// otherwise return P. static const char *SkipEscapedNewLines(const char *P); - /// \brief Checks that the given token is the first token that occurs after - /// the given location (this excludes comments and whitespace). Returns the - /// location immediately after the specified token. If the token is not found - /// or the location is inside a macro, the returned source location will be - /// invalid. - static SourceLocation findLocationAfterToken(SourceLocation loc, - tok::TokenKind TKind, - const SourceManager &SM, - const LangOptions &LangOpts, - bool SkipTrailingWhitespaceAndNewLine); - - /// \brief Returns true if the given character could appear in an identifier. - static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts); - -private: - /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a /// diagnostic. static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size, @@ -571,15 +562,17 @@ private: bool LexEndOfFile (Token &Result, const char *CurPtr); bool SkipWhitespace (Token &Result, const char *CurPtr); - bool SkipBCPLComment (Token &Result, const char *CurPtr); + bool SkipLineComment (Token &Result, const char *CurPtr); bool SkipBlockComment (Token &Result, const char *CurPtr); - bool SaveBCPLComment (Token &Result, const char *CurPtr); + bool SaveLineComment (Token &Result, const char *CurPtr); bool IsStartOfConflictMarker(const char *CurPtr); bool HandleEndOfConflictMarker(const char *CurPtr); bool isCodeCompletionPoint(const char *CurPtr) const; void cutOffLexing() { BufferPtr = BufferEnd; } + + bool isHexaLiteral(const char *Start, const LangOptions &LangOpts); }; diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index bbce62d1d48a..3b68d1b570f4 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include "clang/Basic/TokenKinds.h" #include @@ -48,8 +49,9 @@ class NumericLiteralParser { bool saw_exponent, saw_period, saw_ud_suffix; public: - NumericLiteralParser(const char *begin, const char *end, - SourceLocation Loc, Preprocessor &PP); + NumericLiteralParser(StringRef TokSpelling, + SourceLocation TokLoc, + Preprocessor &PP); bool hadError; bool isUnsigned; bool isLong; // This is *not* set for long long. @@ -230,8 +232,8 @@ public: private: void init(const Token *StringToks, unsigned NumStringToks); - bool CopyStringFragment(StringRef Fragment); - bool DiagnoseBadString(const Token& Tok); + bool CopyStringFragment(const Token &Tok, const char *TokBegin, + StringRef Fragment); void DiagnoseLexingError(SourceLocation Loc); }; diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index cbd201f849de..aba77d580d9b 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -32,6 +32,12 @@ class MacroInfo { SourceLocation Location; /// EndLocation - The location of the last token in the macro. SourceLocation EndLocation; + /// \brief The location where the macro was #undef'd, or an invalid location + /// for macros that haven't been undefined. + SourceLocation UndefLocation; + /// \brief Previous definition, the identifier of this macro was defined to, + /// or NULL. + MacroInfo *PreviousDefinition; /// Arguments - The list of arguments for a function-like macro. This can be /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this @@ -99,7 +105,16 @@ private: /// \brief Whether the macro has public (when described in a module). bool IsPublic : 1; - + + /// \brief Whether the macro definition is currently "hidden". + /// Note that this is transient state that is never serialized to the AST + /// file. + bool IsHidden : 1; + + /// \brief Whether the definition of this macro is ambiguous, due to + /// multiple definitions coming in from multiple modules. + bool IsAmbiguous : 1; + ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); } @@ -128,10 +143,34 @@ public: /// setDefinitionEndLoc - Set the location of the last token in the macro. /// void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; } + /// getDefinitionEndLoc - Return the location of the last token in the macro. /// SourceLocation getDefinitionEndLoc() const { return EndLocation; } - + + /// \brief Set the location where macro was undefined. Can only be set once. + void setUndefLoc(SourceLocation UndefLoc) { + assert(UndefLocation.isInvalid() && "UndefLocation is already set!"); + assert(UndefLoc.isValid() && "Invalid UndefLoc!"); + UndefLocation = UndefLoc; + } + + /// \brief Get the location where macro was undefined. + SourceLocation getUndefLoc() const { return UndefLocation; } + + /// \brief Set previous definition of the macro with the same name. + void setPreviousDefinition(MacroInfo *PreviousDef) { + PreviousDefinition = PreviousDef; + } + + /// \brief Get previous definition of the macro with the same name. + MacroInfo *getPreviousDefinition() { return PreviousDefinition; } + + /// \brief Find macro definition active in the specified source location. If + /// this macro was not defined there, return NULL. + const MacroInfo *findDefinitionAtLoc(SourceLocation L, + SourceManager &SM) const; + /// \brief Get length in characters of the macro definition. unsigned getDefinitionLength(SourceManager &SM) const { if (IsDefinitionLengthCached) @@ -294,6 +333,23 @@ public: /// \brief Determine the location where this macro was explicitly made /// public or private within its module. SourceLocation getVisibilityLocation() { return VisibilityLocation; } + + /// \brief Determine whether this macro is currently defined (and has not + /// been #undef'd) or has been hidden. + bool isDefined() const { return UndefLocation.isInvalid() && !IsHidden; } + + /// \brief Determine whether this macro definition is hidden. + bool isHidden() const { return IsHidden; } + + /// \brief Set whether this macro definition is hidden. + void setHidden(bool Val) { IsHidden = Val; } + + /// \brief Determine whether this macro definition is ambiguous with + /// other macro definitions. + bool isAmbiguous() const { return IsAmbiguous; } + + /// \brief Set whether this macro definition is ambiguous. + void setAmbiguous(bool Val) { IsAmbiguous = Val; } private: unsigned getDefinitionLengthSlow(SourceManager &SM) const; diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index fe5abdfba7ad..082408d83ce3 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -52,10 +52,37 @@ class ModuleMap { /// \brief The top-level modules that are known. llvm::StringMap Modules; - + + /// \brief A header that is known to reside within a given module, + /// whether it was included or excluded. + class KnownHeader { + llvm::PointerIntPair Storage; + + public: + KnownHeader() : Storage(0, false) { } + KnownHeader(Module *M, bool Excluded) : Storage(M, Excluded) { } + + /// \brief Retrieve the module the header is stored in. + Module *getModule() const { return Storage.getPointer(); } + + /// \brief Whether this header is explicitly excluded from the module. + bool isExcluded() const { return Storage.getInt(); } + + /// \brief Whether this header is available in the module. + bool isAvailable() const { + return !isExcluded() && getModule()->isAvailable(); + } + + // \brief Whether this known header is valid (i.e., it has an + // associated module). + operator bool() const { return Storage.getPointer() != 0; } + }; + + typedef llvm::DenseMap HeadersMap; + /// \brief Mapping from each header to the module that owns the contents of the /// that header. - llvm::DenseMap Headers; + HeadersMap Headers; /// \brief Mapping from directories with umbrella headers to the module /// that is generated from the umbrella header. @@ -64,7 +91,26 @@ class ModuleMap { /// in the module map over to the module that includes them via its umbrella /// header. llvm::DenseMap UmbrellaDirs; - + + /// \brief A directory for which framework modules can be inferred. + struct InferredDirectory { + InferredDirectory() : InferModules(), InferSystemModules() { } + + /// \brief Whether to infer modules from this directory. + unsigned InferModules : 1; + + /// \brief Whether the modules we infer are [system] modules. + unsigned InferSystemModules : 1; + + /// \brief The names of modules that cannot be inferred within this + /// directory. + llvm::SmallVector ExcludedModules; + }; + + /// \brief A mapping from directories to information about inferring + /// framework modules from within those directories. + llvm::DenseMap InferredDirectories; + friend class ModuleMapParser; /// \brief Resolve the given export declaration into an actual export @@ -170,7 +216,23 @@ public: std::pair findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit); - + + /// \brief Determine whether we can infer a framework module a framework + /// with the given name in the given + /// + /// \param ParentDir The directory that is the parent of the framework + /// directory. + /// + /// \param Name The name of the module. + /// + /// \param IsSystem Will be set to 'true' if the inferred module must be a + /// system module. + /// + /// \returns true if we are allowed to infer a framework module, and false + /// otherwise. + bool canInferFrameworkModule(const DirectoryEntry *ParentDir, + StringRef Name, bool &IsSystem); + /// \brief Infer the contents of a framework module map from the given /// framework directory. Module *inferFrameworkModule(StringRef ModuleName, @@ -215,7 +277,9 @@ public: void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir); /// \brief Adds this header to the given module. - void addHeader(Module *Mod, const FileEntry *Header); + /// \param Excluded Whether this header is explicitly excluded from the + /// module; otherwise, it's included in the module. + void addHeader(Module *Mod, const FileEntry *Header, bool Excluded); /// \brief Parse the given module map file, and record any modules we /// encounter. diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 962b4df6c492..8ba02cc4ea23 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_LEX_PPCALLBACKS_H #include "clang/Lex/DirectoryLookup.h" +#include "clang/Lex/ModuleLoader.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/DiagnosticIDs.h" #include "llvm/ADT/StringRef.h" @@ -93,10 +94,10 @@ public: /// \param IsAngled Whether the file name was enclosed in angle brackets; /// otherwise, it was enclosed in quotes. /// - /// \param File The actual file that may be included by this inclusion - /// directive. + /// \param FilenameRange The character range of the quotes or angle brackets + /// for the written file name. /// - /// \param EndLoc The location of the last token within the inclusion + /// \param File The actual file that may be included by this inclusion /// directive. /// /// \param SearchPath Contains the search path which was used to find the file @@ -110,14 +111,34 @@ public: /// /// \param RelativePath The path relative to SearchPath, at which the include /// file was found. This is equal to FileName except for framework includes. + /// + /// \param Imported The module, whenever an inclusion directive was + /// automatically turned into a module import or null otherwise. + /// virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, - SourceLocation EndLoc, StringRef SearchPath, - StringRef RelativePath) { + StringRef RelativePath, + const Module *Imported) { + } + + /// \brief Callback invoked whenever there was an explicit module-import + /// syntax. + /// + /// \param ImportLoc The location of import directive token. + /// + /// \param Path The identifiers (and their locations) of the module + /// "path", e.g., "std.vector" would be split into "std" and "vector". + /// + /// \param Imported The imported module; can be null if importing failed. + /// + virtual void moduleImport(SourceLocation ImportLoc, + ModuleIdPath Path, + const Module *Imported) { } /// \brief Callback invoked when the end of the main file is reached. @@ -266,14 +287,24 @@ public: const Token &IncludeTok, StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, - SourceLocation EndLoc, StringRef SearchPath, - StringRef RelativePath) { - First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc, SearchPath, RelativePath); - Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc, SearchPath, RelativePath); + StringRef RelativePath, + const Module *Imported) { + First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, + FilenameRange, File, SearchPath, RelativePath, + Imported); + Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, + FilenameRange, File, SearchPath, RelativePath, + Imported); + } + + virtual void moduleImport(SourceLocation ImportLoc, + ModuleIdPath Path, + const Module *Imported) { + First->moduleImport(ImportLoc, Path, Imported); + Second->moduleImport(ImportLoc, Path, Imported); } virtual void EndOfMainFile() { diff --git a/include/clang/Lex/PPMutationListener.h b/include/clang/Lex/PPMutationListener.h new file mode 100644 index 000000000000..5319c66fa27d --- /dev/null +++ b/include/clang/Lex/PPMutationListener.h @@ -0,0 +1,43 @@ +//===--- PPMutationListener.h - Preprocessor Mutation Interface -*- 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 PPMutationListener interface. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H +#define LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H + +#include "clang/Basic/SourceLocation.h" + +namespace clang { + +class MacroInfo; + +/// \brief A record that describes an update to a macro that was +/// originally loaded to an AST file and has been modified within the +/// current translation unit. +struct MacroUpdate { + /// \brief The source location at which this macro was #undef'd. + SourceLocation UndefLoc; +}; + +/// \brief An abstract interface that should be implemented by +/// listeners that want to be notified when a preprocessor entity gets +/// modified after its initial creation. +class PPMutationListener { +public: + virtual ~PPMutationListener(); + + /// \brief A macro has been #undef'd. + virtual void UndefinedMacro(MacroInfo *MI) { } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index f6a97a0a90a4..a9276e86b726 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -44,8 +44,8 @@ class PTHLexer : public PreprocessorLexer { /// to process when doing quick skipping of preprocessor blocks. const unsigned char* CurPPCondPtr; - PTHLexer(const PTHLexer&); // DO NOT IMPLEMENT - void operator=(const PTHLexer&); // DO NOT IMPLEMENT + PTHLexer(const PTHLexer &) LLVM_DELETED_FUNCTION; + void operator=(const PTHLexer &) LLVM_DELETED_FUNCTION; /// ReadToken - Used by PTHLexer to read tokens TokBuf. void ReadToken(Token& T); diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index 44f9ab39f321..e64dbd8bbcb0 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -81,9 +81,8 @@ class PTHManager : public IdentifierInfoLookup { void* stringIdLookup, unsigned numIds, const unsigned char* spellingBase, const char *originalSourceFile); - // Do not implement. - PTHManager(); - void operator=(const PTHManager&); + PTHManager(const PTHManager &) LLVM_DELETED_FUNCTION; + void operator=(const PTHManager &) LLVM_DELETED_FUNCTION; /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached /// spelling for a token. diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index fb3e081961bf..57e51b754e42 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -94,9 +94,6 @@ namespace clang { /// entity. bool isInvalid() const { return Kind == InvalidKind; } - // Implement isa/cast/dyncast/etc. - static bool classof(const PreprocessedEntity *) { return true; } - // Only allow allocation of preprocessed entities using the allocator // in PreprocessingRecord or by doing a placement new. void* operator new(size_t bytes, PreprocessingRecord& PR, @@ -133,7 +130,6 @@ namespace clang { return PD->getKind() >= FirstPreprocessingDirective && PD->getKind() <= LastPreprocessingDirective; } - static bool classof(const PreprocessingDirective *) { return true; } }; /// \brief Record the location of a macro definition. @@ -155,7 +151,6 @@ namespace clang { static bool classof(const PreprocessedEntity *PE) { return PE->getKind() == MacroDefinitionKind; } - static bool classof(const MacroDefinition *) { return true; } }; /// \brief Records the location of a macro expansion. @@ -193,7 +188,6 @@ namespace clang { static bool classof(const PreprocessedEntity *PE) { return PE->getKind() == MacroExpansionKind; } - static bool classof(const MacroExpansion *) { return true; } }; /// \brief Record the location of an inclusion directive, such as an @@ -227,13 +221,18 @@ namespace clang { /// This is a value of type InclusionKind. unsigned Kind : 2; + /// \brief Whether the inclusion directive was automatically turned into + /// a module import. + unsigned ImportedModule : 1; + /// \brief The file that was included. const FileEntry *File; public: InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind, StringRef FileName, - bool InQuotes, const FileEntry *File, SourceRange Range); + bool InQuotes, bool ImportedModule, + const FileEntry *File, SourceRange Range); /// \brief Determine what kind of inclusion directive this is. InclusionKind getKind() const { return static_cast(Kind); } @@ -244,6 +243,10 @@ namespace clang { /// \brief Determine whether the included file name was written in quotes; /// otherwise, it was written in angle brackets. bool wasInQuotes() const { return InQuotes; } + + /// \brief Determine whether the inclusion directive was automatically + /// turned into a module import. + bool importedModule() const { return ImportedModule; } /// \brief Retrieve the file entry for the actual file that was included /// by this directive. @@ -253,7 +256,6 @@ namespace clang { static bool classof(const PreprocessedEntity *PE) { return PE->getKind() == InclusionDirectiveKind; } - static bool classof(const InclusionDirective *) { return true; } }; /// \brief An abstract class that should be subclassed by any external source @@ -269,12 +271,12 @@ namespace clang { virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0; /// \brief Returns a pair of [Begin, End) indices of preallocated - /// preprocessed entities that \arg Range encompasses. + /// preprocessed entities that \p Range encompasses. virtual std::pair findPreprocessedEntitiesInRange(SourceRange Range) = 0; /// \brief Optionally returns true or false if the preallocated preprocessed - /// entity with index \arg Index came from file \arg FID. + /// entity with index \p Index came from file \p FID. virtual llvm::Optional isPreprocessedEntityInFileID(unsigned Index, FileID FID) { return llvm::Optional(); @@ -343,14 +345,21 @@ namespace clang { /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to /// indicate preprocessed entities introduced by the current preprocessor. - /// If M is the number of loaded preprocessed entities, value -M - /// corresponds to element 0 in the loaded entities vector, position -M+1 - /// corresponds to element 1 in the loaded entities vector, etc. - typedef int PPEntityID; - - PPEntityID getPPEntityID(unsigned Index, bool isLoaded) const { - return isLoaded ? PPEntityID(Index) - LoadedPreprocessedEntities.size() - : Index; + /// Value -1 corresponds to element 0 in the loaded entities vector, + /// value -2 corresponds to element 1 in the loaded entities vector, etc. + /// Value 0 is an invalid value, the index to local entities is 1-based, + /// value 1 corresponds to element 0 in the local entities vector, + /// value 2 corresponds to element 1 in the local entities vector, etc. + class PPEntityID { + int ID; + explicit PPEntityID(int ID) : ID(ID) {} + friend class PreprocessingRecord; + public: + PPEntityID() : ID(0) {} + }; + + static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) { + return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1); } /// \brief Mapping from MacroInfo structures to their definitions. @@ -372,7 +381,7 @@ namespace clang { } /// \brief Returns a pair of [Begin, End) indices of local preprocessed - /// entities that \arg Range encompasses. + /// entities that \p Range encompasses. std::pair findLocalPreprocessedEntitiesInRange(SourceRange Range) const; unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const; @@ -419,7 +428,7 @@ namespace clang { /// corresponds to element 0 in the loaded entities vector, position -M+1 /// corresponds to element 1 in the loaded entities vector, etc. This /// gives us a reasonably efficient, source-order walk. - PPEntityID Position; + int Position; public: typedef PreprocessedEntity *value_type; @@ -430,11 +439,15 @@ namespace clang { iterator() : Self(0), Position(0) { } - iterator(PreprocessingRecord *Self, PPEntityID Position) + iterator(PreprocessingRecord *Self, int Position) : Self(Self), Position(Position) { } value_type operator*() const { - return Self->getPreprocessedEntity(Position); + bool isLoaded = Position < 0; + unsigned Index = isLoaded ? + Self->LoadedPreprocessedEntities.size() + Position : Position; + PPEntityID ID = Self->getPPEntityID(Index, isLoaded); + return Self->getPreprocessedEntity(ID); } value_type operator[](difference_type D) { @@ -539,15 +552,26 @@ namespace clang { return iterator(this, PreprocessedEntities.size()); } + /// \brief begin/end iterator pair for the given range of loaded + /// preprocessed entities. + std::pair + getIteratorsForLoadedRange(unsigned start, unsigned count) { + unsigned end = start + count; + assert(end <= LoadedPreprocessedEntities.size()); + return std::make_pair( + iterator(this, int(start)-LoadedPreprocessedEntities.size()), + iterator(this, int(end)-LoadedPreprocessedEntities.size())); + } + /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities - /// that source range \arg R encompasses. + /// that source range \p R encompasses. /// /// \param R the range to look for preprocessed entities. /// std::pair getPreprocessedEntitiesInRange(SourceRange R); - /// \brief Returns true if the preprocessed entity that \arg PPEI iterator - /// points to is coming from the file \arg FID. + /// \brief Returns true if the preprocessed entity that \p PPEI iterator + /// points to is coming from the file \p FID. /// /// Can be used to avoid implicit deserializations of preallocated /// preprocessed entities if we only care about entities of a specific file @@ -597,10 +621,11 @@ namespace clang { const Token &IncludeTok, StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, - SourceLocation EndLoc, StringRef SearchPath, - StringRef RelativePath); + StringRef RelativePath, + const Module *Imported); virtual void If(SourceLocation Loc, SourceRange ConditionRange); virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, SourceLocation IfLoc); @@ -613,11 +638,10 @@ namespace clang { /// query. struct { SourceRange Range; - std::pair Result; + std::pair Result; } CachedRangeQuery; - std::pair - getPreprocessedEntitiesInRangeSlow(SourceRange R); + std::pair getPreprocessedEntitiesInRangeSlow(SourceRange R); friend class ASTReader; friend class ASTWriter; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 02e3f1e7e439..e9095fbf44a9 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -18,6 +18,7 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/PTHLexer.h" #include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/PPMutationListener.h" #include "clang/Lex/TokenLexer.h" #include "clang/Lex/PTHManager.h" #include "clang/Basic/Builtins.h" @@ -54,6 +55,28 @@ class CodeCompletionHandler; class DirectoryLookup; class PreprocessingRecord; class ModuleLoader; +class PreprocessorOptions; + +/// \brief Stores token information for comparing actual tokens with +/// predefined values. Only handles simple tokens and identifiers. +class TokenValue { + tok::TokenKind Kind; + IdentifierInfo *II; + +public: + TokenValue(tok::TokenKind Kind) : Kind(Kind), II(0) { + assert(Kind != tok::raw_identifier && "Raw identifiers are not supported."); + assert(Kind != tok::identifier && + "Identifiers should be created by TokenValue(IdentifierInfo *)"); + assert(!tok::isLiteral(Kind) && "Literals are not supported."); + assert(!tok::isAnnotation(Kind) && "Annotations are not supported."); + } + TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {} + bool operator==(const Token &Tok) const { + return Tok.getKind() == Kind && + (!II || II == Tok.getIdentifierInfo()); + } +}; /// Preprocessor - This object engages in a tight little dance with the lexer to /// efficiently preprocess tokens. Lexers know only about tokens within a @@ -61,6 +84,7 @@ class ModuleLoader; /// like the \#include stack, token expansion, etc. /// class Preprocessor : public RefCountedBase { + llvm::IntrusiveRefCntPtr PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; const TargetInfo *Target; @@ -98,6 +122,8 @@ class Preprocessor : public RefCountedBase { IdentifierInfo *Ident__has_include; // __has_include IdentifierInfo *Ident__has_include_next; // __has_include_next IdentifierInfo *Ident__has_warning; // __has_warning + IdentifierInfo *Ident__building_module; // __building_module + IdentifierInfo *Ident__MODULE__; // __MODULE__ SourceLocation DATELoc, TIMELoc; unsigned CounterValue; // Next __COUNTER__ value. @@ -265,6 +291,11 @@ class Preprocessor : public RefCountedBase { /// encountered (e.g. a file is \#included, etc). PPCallbacks *Callbacks; + /// \brief Listener whose actions are invoked when an entity in the + /// preprocessor (e.g., a macro) that was loaded from an AST file is + /// later mutated. + PPMutationListener *Listener; + struct MacroExpandsInfo { Token Tok; MacroInfo *MI; @@ -274,10 +305,12 @@ class Preprocessor : public RefCountedBase { }; SmallVector DelayedMacroExpandsCallbacks; - /// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping - /// to the actual definition of the macro. + /// Macros - For each IdentifierInfo that was associated with a macro, we + /// keep a mapping to the history of all macro definitions and #undefs in + /// the reverse order (the latest one is in the head of the list). llvm::DenseMap Macros; - + friend class ASTReader; + /// \brief Macros that we want to warn because they are not used at the end /// of the translation unit; we store just their SourceLocations instead /// something like MacroInfo*. The benefit of this is that when we are @@ -362,10 +395,9 @@ private: // Cached tokens state. /// allocation. MacroInfoChain *MICache; - MacroInfo *getInfoForMacro(IdentifierInfo *II) const; - public: - Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, + Preprocessor(llvm::IntrusiveRefCntPtr PPOpts, + DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, @@ -382,6 +414,10 @@ public: /// \param Target Information about the target. void Initialize(const TargetInfo &Target); + /// \brief Retrieve the preprocessor options used to initialize this + /// preprocessor. + PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; } + DiagnosticsEngine &getDiagnostics() const { return *Diags; } void setDiagnostics(DiagnosticsEngine &D) { Diags = &D; } @@ -457,37 +493,70 @@ public: Callbacks = C; } + /// \brief Attach an preprocessor mutation listener to the preprocessor. + /// + /// The preprocessor mutation listener provides the ability to track + /// modifications to the preprocessor entities committed after they were + /// initially created. + void setPPMutationListener(PPMutationListener *Listener) { + this->Listener = Listener; + } + + /// \brief Retrieve a pointer to the preprocessor mutation listener + /// associated with this preprocessor, if any. + PPMutationListener *getPPMutationListener() const { return Listener; } + /// \brief Given an identifier, return the MacroInfo it is \#defined to /// or null if it isn't \#define'd. MacroInfo *getMacroInfo(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) return 0; - return getInfoForMacro(II); + MacroInfo *MI = getMacroInfoHistory(II); + assert(MI->getUndefLoc().isInvalid() && "Macro is undefined!"); + return MI; } - /// \brief Specify a macro for this identifier. - void setMacroInfo(IdentifierInfo *II, MacroInfo *MI, - bool LoadedFromAST = false); + /// \brief Given an identifier, return the (probably #undef'd) MacroInfo + /// representing the most recent macro definition. One can iterate over all + /// previous macro definitions from it. This method should only be called for + /// identifiers that hadMacroDefinition(). + MacroInfo *getMacroInfoHistory(IdentifierInfo *II) const; - /// macro_iterator/macro_begin/macro_end - This allows you to walk the current - /// state of the macro table. This visits every currently-defined macro. + /// \brief Specify a macro for this identifier. + void setMacroInfo(IdentifierInfo *II, MacroInfo *MI); + /// \brief Add a MacroInfo that was loaded from an AST file. + void addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI, + MacroInfo *Hint = 0); + /// \brief Make the given MacroInfo, that was loaded from an AST file and + /// previously hidden, visible. + void makeLoadedMacroInfoVisible(IdentifierInfo *II, MacroInfo *MI); + /// \brief Undefine a macro for this identifier. + void clearMacroInfo(IdentifierInfo *II); + + /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro + /// history table. Currently defined macros have + /// IdentifierInfo::hasMacroDefinition() set and an empty + /// MacroInfo::getUndefLoc() at the head of the list. typedef llvm::DenseMap::const_iterator macro_iterator; macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; + /// \brief Return the name of the macro defined before \p Loc that has + /// spelling \p Tokens. If there are multiple macros with same spelling, + /// return the last one defined. + StringRef getLastMacroWithSpelling(SourceLocation Loc, + ArrayRef Tokens) const; + const std::string &getPredefines() const { return Predefines; } /// setPredefines - Set the predefines for this Preprocessor. These /// predefines are automatically injected when parsing the main file. void setPredefines(const char *P) { Predefines = P; } void setPredefines(const std::string &P) { Predefines = P; } - /// getIdentifierInfo - Return information about the specified preprocessor - /// identifier token. The version of this method that takes two character - /// pointers is preferred unless the identifier is already available as a - /// string (this avoids allocation and copying of memory to construct an - /// std::string). + /// Return information about the specified preprocessor + /// identifier token. IdentifierInfo *getIdentifierInfo(StringRef Name) const { return &Identifiers.get(Name); } @@ -501,8 +570,8 @@ public: } /// RemovePragmaHandler - Remove the specific pragma handler from - /// the preprocessor. If \arg Namespace is non-null, then it should - /// be the namespace that \arg Handler was added to. It is an error + /// the preprocessor. If \p Namespace is non-null, then it should + /// be the namespace that \p Handler was added to. It is an error /// to remove a handler that has not been registered. void RemovePragmaHandler(StringRef Namespace, PragmaHandler *Handler); void RemovePragmaHandler(PragmaHandler *Handler) { @@ -564,7 +633,8 @@ public: /// /// ILEnd specifies the location of the ')' for a function-like macro or the /// identifier for an object-like macro. - void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroArgs *Args); + void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroInfo *Macro, + MacroArgs *Args); /// EnterTokenStream - Add a "macro" context to the top of the include stack, /// which will cause the lexer to start returning the specified tokens. @@ -724,6 +794,14 @@ public: CachedTokens[CachedLexPos-1] = Tok; } + /// TypoCorrectToken - Update the current token to represent the provided + /// identifier, in order to cache an action performed by typo correction. + void TypoCorrectToken(const Token &Tok) { + assert(Tok.getIdentifierInfo() && "Expected identifier token"); + if (CachedLexPos != 0 && isBacktrackEnabled()) + CachedTokens[CachedLexPos-1] = Tok; + } + /// \brief Recompute the current lexer kind based on the CurLexer/CurPTHLexer/ /// CurTokenLexer pointers. void recomputeCurLexerKind(); @@ -892,7 +970,7 @@ public: /// CreateString - Plop the specified string into a scratch buffer and set the /// specified token's location and length to it. If specified, the source /// location provides a location of the expansion point of the token. - void CreateString(const char *Buf, unsigned Len, Token &Tok, + void CreateString(StringRef Str, Token &Tok, SourceLocation ExpansionLocStart = SourceLocation(), SourceLocation ExpansionLocEnd = SourceLocation()); @@ -929,7 +1007,7 @@ public: /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. /// - /// \param MacroBegin If non-null and function returns true, it is set to + /// \param MacroEnd If non-null and function returns true, it is set to /// end location of the macro. bool isAtEndOfMacroExpansion(SourceLocation loc, SourceLocation *MacroEnd = 0) const { @@ -1103,10 +1181,10 @@ public: /// from a macro as multiple tokens, which need to be glued together. This /// occurs for code like: /// \code - /// \#define FOO + /// \#define FOO /// \#include FOO /// \endcode - /// because in this case, "" is returned as 7 tokens, not one. + /// because in this case, "" is returned as 7 tokens, not one. /// /// This code concatenates and consumes tokens up to the '>' token. It /// returns false if the > was found, otherwise it returns true if it finds @@ -1289,6 +1367,8 @@ private: // Macro handling. void HandleDefineDirective(Token &Tok); void HandleUndefDirective(Token &Tok); + void UndefineMacro(IdentifierInfo *II, MacroInfo *MI, + SourceLocation UndefLoc); // Conditional Inclusion. void HandleIfdefDirective(Token &Tok, bool isIfndef, diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index 8a0b3cf51acc..20fb8a0c4804 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -69,8 +69,8 @@ protected: /// we are currently in. SmallVector ConditionalStack; - PreprocessorLexer(const PreprocessorLexer&); // DO NOT IMPLEMENT - void operator=(const PreprocessorLexer&); // DO NOT IMPLEMENT + PreprocessorLexer(const PreprocessorLexer &) LLVM_DELETED_FUNCTION; + void operator=(const PreprocessorLexer &) LLVM_DELETED_FUNCTION; friend class Preprocessor; PreprocessorLexer(Preprocessor *pp, FileID fid); diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h new file mode 100644 index 000000000000..e5fe37379355 --- /dev/null +++ b/include/clang/Lex/PreprocessorOptions.h @@ -0,0 +1,221 @@ +//===--- PreprocessorOptions.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ +#define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include +#include +#include +#include +#include + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { + +class Preprocessor; +class LangOptions; + +/// \brief Enumerate the kinds of standard library that +enum ObjCXXARCStandardLibraryKind { + ARCXX_nolib, + /// \brief libc++ + ARCXX_libcxx, + /// \brief libstdc++ + ARCXX_libstdcxx +}; + +/// PreprocessorOptions - This class is used for passing the various options +/// used in preprocessor initialization to InitializePreprocessor(). +class PreprocessorOptions : public llvm::RefCountedBase { +public: + std::vector > Macros; + std::vector Includes; + std::vector MacroIncludes; + + unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler + /// and target specific predefines. + + unsigned DetailedRecord : 1; /// Whether we should maintain a detailed + /// record of all macro definitions and + /// expansions. + unsigned DetailedRecordConditionalDirectives : 1; /// Whether in the + /// preprocessing record we should also keep + /// track of locations of conditional directives + /// in non-system files. + + /// The implicit PCH included at the start of the translation unit, or empty. + std::string ImplicitPCHInclude; + + /// \brief Headers that will be converted to chained PCHs in memory. + std::vector ChainedIncludes; + + /// \brief When true, disables most of the normal validation performed on + /// precompiled headers. + bool DisablePCHValidation; + + /// \brief When true, a PCH with compiler errors will not be rejected. + bool AllowPCHWithCompilerErrors; + + /// \brief Dump declarations that are deserialized from PCH, for testing. + bool DumpDeserializedPCHDecls; + + /// \brief This is a set of names for decls that we do not want to be + /// deserialized, and we emit an error if they are; for testing purposes. + std::set DeserializedPCHDeclsToErrorOn; + + /// \brief If non-zero, the implicit PCH include is actually a precompiled + /// preamble that covers this number of bytes in the main source file. + /// + /// The boolean indicates whether the preamble ends at the start of a new + /// line. + std::pair PrecompiledPreambleBytes; + + /// The implicit PTH input included at the start of the translation unit, or + /// empty. + std::string ImplicitPTHInclude; + + /// If given, a PTH cache file to use for speeding up header parsing. + std::string TokenCache; + + /// \brief True if the SourceManager should report the original file name for + /// contents of files that were remapped to other files. Defaults to true. + bool RemappedFilesKeepOriginalName; + + /// \brief The set of file remappings, which take existing files on + /// the system (the first part of each pair) and gives them the + /// contents of other files on the system (the second part of each + /// pair). + std::vector > RemappedFiles; + + /// \brief The set of file-to-buffer remappings, which take existing files + /// on the system (the first part of each pair) and gives them the contents + /// of the specified memory buffer (the second part of each pair). + std::vector > + RemappedFileBuffers; + + /// \brief Whether the compiler instance should retain (i.e., not free) + /// the buffers associated with remapped files. + /// + /// This flag defaults to false; it can be set true only through direct + /// manipulation of the compiler invocation object, in cases where the + /// compiler invocation and its buffers will be reused. + bool RetainRemappedFileBuffers; + + /// \brief The Objective-C++ ARC standard library that we should support, + /// by providing appropriate definitions to retrofit the standard library + /// with support for lifetime-qualified pointers. + ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary; + + /// \brief The path of modules being build, which is used to detect + /// cycles in the module dependency graph as modules are being built. + /// + /// There is no way to set this value from the command line. If we ever need + /// to do so (e.g., if on-demand module construction moves out-of-process), + /// we can add a cc1-level option to do so. + SmallVector ModuleBuildPath; + + typedef std::vector >::iterator + remapped_file_iterator; + typedef std::vector >::const_iterator + const_remapped_file_iterator; + remapped_file_iterator remapped_file_begin() { + return RemappedFiles.begin(); + } + const_remapped_file_iterator remapped_file_begin() const { + return RemappedFiles.begin(); + } + remapped_file_iterator remapped_file_end() { + return RemappedFiles.end(); + } + const_remapped_file_iterator remapped_file_end() const { + return RemappedFiles.end(); + } + + typedef std::vector >:: + iterator remapped_file_buffer_iterator; + typedef std::vector >:: + const_iterator const_remapped_file_buffer_iterator; + remapped_file_buffer_iterator remapped_file_buffer_begin() { + return RemappedFileBuffers.begin(); + } + const_remapped_file_buffer_iterator remapped_file_buffer_begin() const { + return RemappedFileBuffers.begin(); + } + remapped_file_buffer_iterator remapped_file_buffer_end() { + return RemappedFileBuffers.end(); + } + const_remapped_file_buffer_iterator remapped_file_buffer_end() const { + return RemappedFileBuffers.end(); + } + +public: + PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), + DetailedRecordConditionalDirectives(false), + DisablePCHValidation(false), + AllowPCHWithCompilerErrors(false), + DumpDeserializedPCHDecls(false), + PrecompiledPreambleBytes(0, true), + RemappedFilesKeepOriginalName(true), + RetainRemappedFileBuffers(false), + ObjCXXARCStandardLibrary(ARCXX_nolib) { } + + void addMacroDef(StringRef Name) { + Macros.push_back(std::make_pair(Name, false)); + } + void addMacroUndef(StringRef Name) { + Macros.push_back(std::make_pair(Name, true)); + } + void addRemappedFile(StringRef From, StringRef To) { + RemappedFiles.push_back(std::make_pair(From, To)); + } + + remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) { + return RemappedFiles.erase(Remapped); + } + + void addRemappedFile(StringRef From, const llvm::MemoryBuffer * To) { + RemappedFileBuffers.push_back(std::make_pair(From, To)); + } + + remapped_file_buffer_iterator + eraseRemappedFile(remapped_file_buffer_iterator Remapped) { + return RemappedFileBuffers.erase(Remapped); + } + + void clearRemappedFiles() { + RemappedFiles.clear(); + RemappedFileBuffers.clear(); + } + + /// \brief Reset any options that are not considered when building a + /// module. + void resetNonModularOptions() { + Includes.clear(); + MacroIncludes.clear(); + ChainedIncludes.clear(); + DumpDeserializedPCHDecls = false; + ImplicitPCHInclude.clear(); + ImplicitPTHInclude.clear(); + TokenCache.clear(); + RetainRemappedFileBuffers = true; + PrecompiledPreambleBytes.first = 0; + PrecompiledPreambleBytes.second = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 9c5a023f30d9..50b86c84e571 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -90,26 +90,18 @@ public: /// \brief Return true if this is a raw identifier (when lexing /// in raw mode) or a non-keyword identifier (when lexing in non-raw mode). bool isAnyIdentifier() const { - return is(tok::identifier) || is(tok::raw_identifier); + return tok::isAnyIdentifier(getKind()); } - /// isLiteral - Return true if this is a "literal", like a numeric + /// \brief Return true if this is a "literal", like a numeric /// constant, string, etc. bool isLiteral() const { - return is(tok::numeric_constant) || is(tok::char_constant) || - is(tok::wide_char_constant) || is(tok::utf16_char_constant) || - is(tok::utf32_char_constant) || is(tok::string_literal) || - is(tok::wide_string_literal) || is(tok::utf8_string_literal) || - is(tok::utf16_string_literal) || is(tok::utf32_string_literal) || - is(tok::angle_string_literal); + return tok::isLiteral(getKind()); } + /// \brief Return true if this is any of tok::annot_* kind tokens. bool isAnnotation() const { -#define ANNOTATION(NAME) \ - if (is(tok::annot_##NAME)) \ - return true; -#include "clang/Basic/TokenKinds.def" - return false; + return tok::isAnnotation(getKind()); } /// \brief Return a source location identifier for the specified diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index 1330ad5f3143..090402a811e2 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -22,7 +22,7 @@ namespace clang { class Token; class MacroArgs; -/// TokenLexer - This implements a lexer that returns token from a macro body +/// TokenLexer - This implements a lexer that returns tokens from a macro body /// or token stream instead of lexing from a character buffer. This is used for /// macro expansion and _Pragma handling, for example. /// @@ -91,24 +91,25 @@ class TokenLexer { /// should not be subject to further macro expansion. bool DisableMacroExpansion : 1; - TokenLexer(const TokenLexer&); // DO NOT IMPLEMENT - void operator=(const TokenLexer&); // DO NOT IMPLEMENT + TokenLexer(const TokenLexer &) LLVM_DELETED_FUNCTION; + void operator=(const TokenLexer &) LLVM_DELETED_FUNCTION; public: /// Create a TokenLexer for the specified macro with the specified actual /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. /// ILEnd specifies the location of the ')' for a function-like macro or the /// identifier for an object-like macro. - TokenLexer(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs, - Preprocessor &pp) + TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, + MacroArgs *ActualArgs, Preprocessor &pp) : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) { - Init(Tok, ILEnd, ActualArgs); + Init(Tok, ILEnd, MI, ActualArgs); } /// Init - Initialize this TokenLexer to expand from the specified macro /// with the specified argument information. Note that this ctor takes /// ownership of the ActualArgs pointer. ILEnd specifies the location of the /// ')' for a function-like macro or the identifier for an object-like macro. - void Init(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs); + void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, + MacroArgs *ActualArgs); /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is /// specified, this takes ownership of the tokens and delete[]'s them when @@ -168,7 +169,7 @@ private: /// first token on the next line. void HandleMicrosoftCommentPaste(Token &Tok); - /// \brief If \arg loc is a FileID and points inside the current macro + /// \brief If \p loc is a FileID and points inside the current macro /// definition, returns the appropriate source location pointing at the /// macro expansion source location entry. SourceLocation getExpansionLocForMacroDefLoc(SourceLocation loc) const; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 4ef92f7dbc69..c433344602c6 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -30,6 +30,7 @@ namespace clang { class PragmaHandler; class Scope; class BalancedDelimiterTracker; + class CorrectionCandidateCallback; class DeclGroupRef; class DiagnosticBuilder; class Parser; @@ -163,6 +164,10 @@ class Parser : public CodeCompletionHandler { mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; + // C++ type trait keywords that have can be reverted to identifiers and + // still used as type traits. + llvm::SmallDenseMap RevertableTypeTraits; + OwningPtr AlignHandler; OwningPtr GCCVisibilityHandler; OwningPtr OptionsHandler; @@ -204,6 +209,9 @@ class Parser : public CodeCompletionHandler { /// top-level declaration is finished. SmallVector TemplateIds; + /// \brief Identifiers which have been declared within a tentative parse. + SmallVector TentativelyDeclaredIdentifiers; + IdentifierInfo *getSEHExceptKeyword(); /// True if we are within an Objective-C container while parsing C-like decls. @@ -244,7 +252,7 @@ public: typedef clang::TypeResult TypeResult; typedef Expr *ExprArg; - typedef ASTMultiPtr MultiStmtArg; + typedef llvm::MutableArrayRef MultiStmtArg; typedef Sema::FullExprArg FullExprArg; /// Adorns a ExprResult with Actions to make it an ExprResult @@ -278,6 +286,23 @@ public: /// the EOF was encountered. bool ParseTopLevelDecl(DeclGroupPtrTy &Result); + /// ConsumeToken - Consume the current 'peek token' and lex the next one. + /// This does not work with all kinds of tokens: strings and specific other + /// tokens must be consumed with custom methods below. This returns the + /// location of the consumed token. + SourceLocation ConsumeToken() { + assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && + !isTokenBrace() && + "Should consume special tokens with Consume*Token"); + + if (Tok.is(tok::code_completion)) + return handleUnexpectedCodeCompletionToken(); + + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + private: //===--------------------------------------------------------------------===// // Low-Level token peeking and consumption methods. @@ -310,23 +335,6 @@ private: /// For typos, give a fixit to '=' bool isTokenEqualOrEqualTypo(); - /// ConsumeToken - Consume the current 'peek token' and lex the next one. - /// This does not work with all kinds of tokens: strings and specific other - /// tokens must be consumed with custom methods below. This returns the - /// location of the consumed token. - SourceLocation ConsumeToken() { - assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && - !isTokenBrace() && - "Should consume special tokens with Consume*Token"); - - if (Tok.is(tok::code_completion)) - return handleUnexpectedCodeCompletionToken(); - - PrevTokLocation = Tok.getLocation(); - PP.Lex(Tok); - return PrevTokLocation; - } - /// ConsumeAnyToken - Dispatch to the right Consume* method based on the /// current token type. This should only be used in cases where the type of /// the token really isn't known, e.g. in error recovery. @@ -433,6 +441,34 @@ private: /// #pragma pack... void HandlePragmaPack(); + /// \brief Handle the annotation token produced for + /// #pragma ms_struct... + void HandlePragmaMSStruct(); + + /// \brief Handle the annotation token produced for + /// #pragma align... + void HandlePragmaAlign(); + + /// \brief Handle the annotation token produced for + /// #pragma weak id... + void HandlePragmaWeak(); + + /// \brief Handle the annotation token produced for + /// #pragma weak id = id... + void HandlePragmaWeakAlias(); + + /// \brief Handle the annotation token produced for + /// #pragma redefine_extname... + void HandlePragmaRedefineExtname(); + + /// \brief Handle the annotation token produced for + /// #pragma STDC FP_CONTRACT... + void HandlePragmaFPContract(); + + /// \brief Handle the annotation token produced for + /// #pragma OPENCL EXTENSION... + void HandlePragmaOpenCLExtension(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. @@ -445,6 +481,7 @@ private: return PP.LookAhead(N-1); } +public: /// NextToken - This peeks ahead one token and returns it without /// consuming it. const Token &NextToken() { @@ -456,6 +493,7 @@ private: return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue()); } +private: static void setTypeAnnotation(Token &Tok, ParsedType T) { Tok.setAnnotationValue(T.getAsOpaquePtr()); } @@ -478,12 +516,36 @@ private: Tok.setAnnotationValue(ER.get()); } +public: // If NeedType is true, then TryAnnotateTypeOrScopeToken will try harder to // find a type name by attempting typo correction. bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false, bool NeedType = false); + bool TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, + bool NeedType, + CXXScopeSpec &SS, + bool IsNewScope); bool TryAnnotateCXXScopeToken(bool EnteringContext = false); +private: + enum AnnotatedNameKind { + /// Annotation has failed and emitted an error. + ANK_Error, + /// The identifier is a tentatively-declared name. + ANK_TentativeDecl, + /// The identifier is a template name. FIXME: Add an annotation for that. + ANK_TemplateName, + /// The identifier can't be resolved. + ANK_Unresolved, + /// Annotation was successful. + ANK_Success + }; + AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC = 0); + + /// Push a tok::annot_cxxscope token onto the token stream. + void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation); + /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens, /// replacing them with the non-context-sensitive keywords. This returns /// true if the token was replaced. @@ -529,12 +591,15 @@ private: class TentativeParsingAction { Parser &P; Token PrevTok; + size_t PrevTentativelyDeclaredIdentifierCount; unsigned short PrevParenCount, PrevBracketCount, PrevBraceCount; bool isActive; public: explicit TentativeParsingAction(Parser& p) : P(p) { PrevTok = P.Tok; + PrevTentativelyDeclaredIdentifierCount = + P.TentativelyDeclaredIdentifiers.size(); PrevParenCount = P.ParenCount; PrevBracketCount = P.BracketCount; PrevBraceCount = P.BraceCount; @@ -543,6 +608,8 @@ private: } void Commit() { assert(isActive && "Parsing action was finished!"); + P.TentativelyDeclaredIdentifiers.resize( + PrevTentativelyDeclaredIdentifierCount); P.PP.CommitBacktrackedTokens(); isActive = false; } @@ -550,6 +617,8 @@ private: assert(isActive && "Parsing action was finished!"); P.PP.Backtrack(); P.Tok = PrevTok; + P.TentativelyDeclaredIdentifiers.resize( + PrevTentativelyDeclaredIdentifierCount); P.ParenCount = PrevParenCount; P.BracketCount = PrevBracketCount; P.BraceCount = PrevBraceCount; @@ -608,6 +677,7 @@ private: /// \brief Consume any extra semi-colons until the end of the line. void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified); +public: //===--------------------------------------------------------------------===// // Scope manipulation @@ -619,8 +689,8 @@ private: /// the parser will exit the scope. class ParseScope { Parser *Self; - ParseScope(const ParseScope&); // do not implement - ParseScope& operator=(const ParseScope&); // do not implement + ParseScope(const ParseScope &) LLVM_DELETED_FUNCTION; + void operator=(const ParseScope &) LLVM_DELETED_FUNCTION; public: // ParseScope - Construct a new object to manage a scope in the @@ -655,12 +725,13 @@ private: /// ExitScope - Pop a scope off the scope stack. void ExitScope(); +private: /// \brief RAII object used to modify the scope flags for the current scope. class ParseScopeFlags { Scope *CurScope; unsigned OldFlags; - ParseScopeFlags(const ParseScopeFlags &); // do not implement - void operator=(const ParseScopeFlags &); // do not implement + ParseScopeFlags(const ParseScopeFlags &) LLVM_DELETED_FUNCTION; + void operator=(const ParseScopeFlags &) LLVM_DELETED_FUNCTION; public: ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags = true); @@ -682,6 +753,7 @@ private: SourceRange ParenRange); void CheckNestedObjCContexts(SourceLocation AtLoc); +public: /// SkipUntil - Read tokens until we get to the specified token, then consume /// it (unless DontConsume is true). Because we cannot guarantee that the /// token will ever occur, this skips to the next token, or to some likely @@ -713,6 +785,7 @@ private: /// point for skipping past a simple-declaration. void SkipMalformedDecl(); +private: //===--------------------------------------------------------------------===// // Lexing and parsing of C++ inline methods. @@ -775,9 +848,16 @@ private: void addDecl(Decl *D) { Decls.push_back(D); } }; - /// A list of late parsed attributes. Used by ParseGNUAttributes. - typedef llvm::SmallVector LateParsedAttrList; + // A list of late-parsed attributes. Used by ParseGNUAttributes. + class LateParsedAttrList: public llvm::SmallVector { + public: + LateParsedAttrList(bool PSoon = false) : ParseSoon(PSoon) { } + + bool parseSoon() { return ParseSoon; } + private: + bool ParseSoon; // Are we planning to parse these shortly after creation? + }; /// Contains the lexed tokens of a member function definition /// which needs to be parsed at the end of the class declaration @@ -880,9 +960,9 @@ private: /// any member function declarations or definitions that need to be /// parsed after the corresponding top-level class is complete. struct ParsingClass { - ParsingClass(Decl *TagOrTemplate, bool TopLevelClass) + ParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface) : TopLevelClass(TopLevelClass), TemplateScope(false), - TagOrTemplate(TagOrTemplate) { } + IsInterface(IsInterface), TagOrTemplate(TagOrTemplate) { } /// \brief Whether this is a "top-level" class, meaning that it is /// not nested within another class. @@ -893,6 +973,9 @@ private: /// othewise, it is a tag declaration. bool TemplateScope : 1; + /// \brief Whether this class is an __interface. + bool IsInterface : 1; + /// \brief The class or class template whose definition we are parsing. Decl *TagOrTemplate; @@ -919,9 +1002,10 @@ private: Sema::ParsingClassState State; public: - ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass) + ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass, + bool IsInterface) : P(P), Popped(false), - State(P.PushParsingClass(TagOrTemplate, TopLevelClass)) { + State(P.PushParsingClass(TagOrTemplate, TopLevelClass, IsInterface)) { } /// \brief Pop this class of the stack. @@ -1009,7 +1093,7 @@ private: void LateTemplateParser(const FunctionDecl *FD); Sema::ParsingClassState - PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass); + PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface); void DeallocateParsedClasses(ParsingClass *Class); void PopParsingClass(Sema::ParsingClassState); @@ -1145,6 +1229,7 @@ private: Decl *ParseObjCMethodDefinition(); +public: //===--------------------------------------------------------------------===// // C99 6.5: Expressions. @@ -1160,6 +1245,7 @@ private: // Expr that doesn't include commas. ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast); +private: ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); @@ -1174,6 +1260,9 @@ private: bool isAddressOfOperand = false, TypeCastState isTypeCast = NotTypeCast); + /// Returns true if the next token cannot start an expression. + bool isNotExpressionStart(); + /// Returns true if the next token would start a postfix-expression /// suffix. bool isPostfixExpressionSuffixStart() { @@ -1245,6 +1334,8 @@ private: bool *MayBePseudoDestructor = 0, bool IsTypename = false); + void CheckForLParenAfterColonColon(); + //===--------------------------------------------------------------------===// // C++0x 5.1.2: Lambda expressions @@ -1379,8 +1470,16 @@ private: //===--------------------------------------------------------------------===// // C99 6.8: Statements and Blocks. + /// A SmallVector of statements, with stack size 32 (as that is the only one + /// used.) + typedef SmallVector StmtVector; + /// A SmallVector of expressions, with stack size 12 (the maximum used.) + typedef SmallVector ExprVector; + /// A SmallVector of types. + typedef SmallVector TypeVector; + StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0) { - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc); } StmtResult ParseStatementOrDeclaration(StmtVector &Stmts, @@ -1399,6 +1498,7 @@ private: StmtResult ParseCompoundStatement(bool isStmtExpr = false); StmtResult ParseCompoundStatement(bool isStmtExpr, unsigned ScopeFlags); + void ParseCompoundStatementLeadingPragmas(); StmtResult ParseCompoundStatementBody(bool isStmtExpr = false); bool ParseParenExprOrCondition(ExprResult &ExprResult, Decl *&DeclResult, @@ -1463,8 +1563,8 @@ private: // C++ 6: Statements and Blocks StmtResult ParseCXXTryBlock(); - StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); - StmtResult ParseCXXCatchBlock(); + StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry = false); + StmtResult ParseCXXCatchBlock(bool FnCatch = false); //===--------------------------------------------------------------------===// // MS: SEH Statements and Blocks @@ -1578,6 +1678,15 @@ private: /// specifier or if we're not sure. bool isKnownToBeTypeSpecifier(const Token &Tok) const; + /// \brief Return true if we know that we are definitely looking at a + /// decl-specifier, and isn't part of an expression such as a function-style + /// cast. Return false if it's no a decl-specifier, or we're not sure. + bool isKnownToBeDeclarationSpecifier() { + if (getLangOpts().CPlusPlus) + return isCXXDeclarationSpecifier() == TPResult::True(); + return isDeclarationSpecifier(true); + } + /// isDeclarationStatement - Disambiguates between a declaration or an /// expression statement, when parsing function bodies. /// Returns true for declaration, false for expression. @@ -1707,6 +1816,11 @@ private: isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False(), bool *HasMissingTypename = 0); + /// \brief Determine whether an identifier has been tentatively declared as a + /// non-type. Such tentative declarations should not be found to name a type + /// during a tentative parse, but also should not be annotated as a non-type. + bool isTentativelyDeclared(IdentifierInfo *II); + // "Tentative parsing" functions, used for disambiguation. If a parsing error // is encountered they will return TPResult::Error(). // Returning TPResult::True()/False() indicates that the ambiguity was @@ -1724,11 +1838,14 @@ private: TPResult TryParseFunctionDeclarator(); TPResult TryParseBracketDeclarator(); +public: TypeResult ParseTypeName(SourceRange *Range = 0, Declarator::TheContext Context = Declarator::TypeNameContext, AccessSpecifier AS = AS_none, Decl **OwnedType = 0); + +private: void ParseBlockId(SourceLocation CaretLoc); // Check for the start of a C++11 attribute-specifier-seq in a context where @@ -1748,6 +1865,11 @@ private: } void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs); + // Forbid C++11 attributes that appear on certain syntactic + // locations which standard permits but we don't supported yet, + // for example, attributes appertain to decl specifiers. + void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs); + void MaybeParseGNUAttributes(Declarator &D, LateParsedAttrList *LateAttrs = 0) { if (Tok.is(tok::kw___attribute)) { @@ -1769,7 +1891,10 @@ private: void ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, - SourceLocation *EndLoc); + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax); void MaybeParseCXX0XAttributes(Declarator &D) { if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) { @@ -1799,6 +1924,7 @@ private: SourceLocation *EndLoc = 0); void ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *EndLoc = 0); + IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc); void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs, @@ -1856,7 +1982,7 @@ private: VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const { return isCXX0XVirtSpecifier(Tok); } - void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS); + void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface); bool isCXX0XFinalKeyword() const; @@ -2004,6 +2130,8 @@ private: bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, ParsedType ObjectType, UnqualifiedId &Result); + +public: bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, @@ -2011,6 +2139,7 @@ private: SourceLocation& TemplateKWLoc, UnqualifiedId &Result); +private: //===--------------------------------------------------------------------===// // C++ 14: Templates [temp] diff --git a/include/clang/Rewrite/ASTConsumers.h b/include/clang/Rewrite/ASTConsumers.h deleted file mode 100644 index c9c92e3a0188..000000000000 --- a/include/clang/Rewrite/ASTConsumers.h +++ /dev/null @@ -1,48 +0,0 @@ -//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// AST Consumers. -// -//===----------------------------------------------------------------------===// - -#ifndef REWRITE_ASTCONSUMERS_H -#define REWRITE_ASTCONSUMERS_H - -#include "clang/Basic/LLVM.h" -#include - -namespace clang { - -class ASTConsumer; -class DiagnosticsEngine; -class LangOptions; -class Preprocessor; - -// ObjC rewriter: attempts to rewrite ObjC constructs into pure C code. -// This is considered experimental, and only works with Apple's ObjC runtime. -ASTConsumer *CreateObjCRewriter(const std::string &InFile, - raw_ostream *OS, - DiagnosticsEngine &Diags, - const LangOptions &LOpts, - bool SilenceRewriteMacroWarning); -ASTConsumer *CreateModernObjCRewriter(const std::string &InFile, - raw_ostream *OS, - DiagnosticsEngine &Diags, - const LangOptions &LOpts, - bool SilenceRewriteMacroWarning); - -/// CreateHTMLPrinter - Create an AST consumer which rewrites source code to -/// HTML with syntax highlighting suitable for viewing in a web-browser. -ASTConsumer *CreateHTMLPrinter(raw_ostream *OS, Preprocessor &PP, - bool SyntaxHighlight = true, - bool HighlightMacros = true); - -} // end clang namespace - -#endif diff --git a/include/clang/Rewrite/Core/DeltaTree.h b/include/clang/Rewrite/Core/DeltaTree.h new file mode 100644 index 000000000000..a6109bf90157 --- /dev/null +++ b/include/clang/Rewrite/Core/DeltaTree.h @@ -0,0 +1,50 @@ +//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- 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 DeltaTree class. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_REWRITE_DELTATREE_H +#define CLANG_REWRITE_DELTATREE_H + +#include "llvm/Support/Compiler.h" + +namespace clang { + + /// DeltaTree - a multiway search tree (BTree) structure with some fancy + /// features. B-Trees are generally more memory and cache efficient than + /// binary trees, because they store multiple keys/values in each node. This + /// implements a key/value mapping from index to delta, and allows fast lookup + /// on index. However, an added (important) bonus is that it can also + /// efficiently tell us the full accumulated delta for a specific file offset + /// as well, without traversing the whole tree. + class DeltaTree { + void *Root; // "DeltaTreeNode *" + void operator=(const DeltaTree &) LLVM_DELETED_FUNCTION; + public: + DeltaTree(); + + // Note: Currently we only support copying when the RHS is empty. + DeltaTree(const DeltaTree &RHS); + ~DeltaTree(); + + /// getDeltaAt - Return the accumulated delta at the specified file offset. + /// This includes all insertions or delections that occurred *before* the + /// specified file index. + int getDeltaAt(unsigned FileIndex) const; + + /// AddDelta - When a change is made that shifts around the text buffer, + /// this method is used to record that info. It inserts a delta of 'Delta' + /// into the current DeltaTree at offset FileIndex. + void AddDelta(unsigned FileIndex, int Delta); + }; +} // end namespace clang + +#endif diff --git a/include/clang/Rewrite/Core/HTMLRewrite.h b/include/clang/Rewrite/Core/HTMLRewrite.h new file mode 100644 index 000000000000..88caf85e6010 --- /dev/null +++ b/include/clang/Rewrite/Core/HTMLRewrite.h @@ -0,0 +1,81 @@ +//==- HTMLRewrite.h - Translate source code into prettified HTML ---*- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a set of functions used for translating source code +// into beautified HTML. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_HTMLREWRITER_H +#define LLVM_CLANG_HTMLREWRITER_H + +#include "clang/Basic/SourceLocation.h" +#include + +namespace clang { + +class Rewriter; +class RewriteBuffer; +class Preprocessor; + +namespace html { + + /// HighlightRange - Highlight a range in the source code with the specified + /// start/end tags. B/E must be in the same file. This ensures that + /// start/end tags are placed at the start/end of each line if the range is + /// multiline. + void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, + const char *StartTag, const char *EndTag); + + /// HighlightRange - Highlight a range in the source code with the specified + /// start/end tags. The Start/end of the range must be in the same file. + /// This ensures that start/end tags are placed at the start/end of each line + /// if the range is multiline. + inline void HighlightRange(Rewriter &R, SourceRange Range, + const char *StartTag, const char *EndTag) { + HighlightRange(R, Range.getBegin(), Range.getEnd(), StartTag, EndTag); + } + + /// HighlightRange - This is the same as the above method, but takes + /// decomposed file locations. + void HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E, + const char *BufferStart, + const char *StartTag, const char *EndTag); + + /// EscapeText - HTMLize a specified file so that special characters are + /// are translated so that they are not interpreted as HTML tags. + void EscapeText(Rewriter& R, FileID FID, + bool EscapeSpaces = false, bool ReplaceTabs = false); + + /// EscapeText - HTMLized the provided string so that special characters + /// in 's' are not interpreted as HTML tags. Unlike the version of + /// EscapeText that rewrites a file, this version by default replaces tabs + /// with spaces. + std::string EscapeText(const std::string& s, + bool EscapeSpaces = false, bool ReplaceTabs = false); + + void AddLineNumbers(Rewriter& R, FileID FID); + + void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID, + const char *title = NULL); + + /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with + /// information about keywords, comments, etc. + void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP); + + /// HighlightMacros - This uses the macro table state from the end of the + /// file, to reexpand macros and insert (into the HTML) information about the + /// macro expansions. This won't be perfectly perfect, but it will be + /// reasonably close. + void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP); + +} // end html namespace +} // end clang namespace + +#endif diff --git a/include/clang/Rewrite/Core/RewriteRope.h b/include/clang/Rewrite/Core/RewriteRope.h new file mode 100644 index 000000000000..9f1bbe501318 --- /dev/null +++ b/include/clang/Rewrite/Core/RewriteRope.h @@ -0,0 +1,239 @@ +//===--- RewriteRope.h - Rope specialized for rewriter ----------*- 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 RewriteRope class, which is a powerful string class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITEROPE_H +#define LLVM_CLANG_REWRITEROPE_H + +#include "llvm/Support/Compiler.h" + +#include +#include +#include +#include + +namespace clang { + //===--------------------------------------------------------------------===// + // RopeRefCountString Class + //===--------------------------------------------------------------------===// + + /// RopeRefCountString - This struct is allocated with 'new char[]' from the + /// heap, and represents a reference counted chunk of string data. When its + /// ref count drops to zero, it is delete[]'d. This is primarily managed + /// through the RopePiece class below. + struct RopeRefCountString { + unsigned RefCount; + char Data[1]; // Variable sized. + + void addRef() { + ++RefCount; + } + + void dropRef() { + if (--RefCount == 0) + delete [] (char*)this; + } + }; + + //===--------------------------------------------------------------------===// + // RopePiece Class + //===--------------------------------------------------------------------===// + + /// RopePiece - This class represents a view into a RopeRefCountString object. + /// This allows references to string data to be efficiently chopped up and + /// moved around without having to push around the string data itself. + /// + /// For example, we could have a 1M RopePiece and want to insert something + /// into the middle of it. To do this, we split it into two RopePiece objects + /// that both refer to the same underlying RopeRefCountString (just with + /// different offsets) which is a nice constant time operation. + struct RopePiece { + RopeRefCountString *StrData; + unsigned StartOffs; + unsigned EndOffs; + + RopePiece() : StrData(0), StartOffs(0), EndOffs(0) {} + + RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End) + : StrData(Str), StartOffs(Start), EndOffs(End) { + if (StrData) + StrData->addRef(); + } + RopePiece(const RopePiece &RP) + : StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) { + if (StrData) + StrData->addRef(); + } + + ~RopePiece() { + if (StrData) + StrData->dropRef(); + } + + void operator=(const RopePiece &RHS) { + if (StrData != RHS.StrData) { + if (StrData) + StrData->dropRef(); + StrData = RHS.StrData; + if (StrData) + StrData->addRef(); + } + StartOffs = RHS.StartOffs; + EndOffs = RHS.EndOffs; + } + + const char &operator[](unsigned Offset) const { + return StrData->Data[Offset+StartOffs]; + } + char &operator[](unsigned Offset) { + return StrData->Data[Offset+StartOffs]; + } + + unsigned size() const { return EndOffs-StartOffs; } + }; + + //===--------------------------------------------------------------------===// + // RopePieceBTreeIterator Class + //===--------------------------------------------------------------------===// + + /// RopePieceBTreeIterator - This class provides read-only forward iteration + /// over bytes that are in a RopePieceBTree. This first iterates over bytes + /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf, + /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree. + class RopePieceBTreeIterator : + public std::iterator { + /// CurNode - The current B+Tree node that we are inspecting. + const void /*RopePieceBTreeLeaf*/ *CurNode; + /// CurPiece - The current RopePiece in the B+Tree node that we're + /// inspecting. + const RopePiece *CurPiece; + /// CurChar - The current byte in the RopePiece we are pointing to. + unsigned CurChar; + public: + // begin iterator. + RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N); + // end iterator + RopePieceBTreeIterator() : CurNode(0), CurPiece(0), CurChar(0) {} + + char operator*() const { + return (*CurPiece)[CurChar]; + } + + bool operator==(const RopePieceBTreeIterator &RHS) const { + return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar; + } + bool operator!=(const RopePieceBTreeIterator &RHS) const { + return !operator==(RHS); + } + + RopePieceBTreeIterator& operator++() { // Preincrement + if (CurChar+1 < CurPiece->size()) + ++CurChar; + else + MoveToNextPiece(); + return *this; + } + inline RopePieceBTreeIterator operator++(int) { // Postincrement + RopePieceBTreeIterator tmp = *this; ++*this; return tmp; + } + private: + void MoveToNextPiece(); + }; + + //===--------------------------------------------------------------------===// + // RopePieceBTree Class + //===--------------------------------------------------------------------===// + + class RopePieceBTree { + void /*RopePieceBTreeNode*/ *Root; + void operator=(const RopePieceBTree &) LLVM_DELETED_FUNCTION; + public: + RopePieceBTree(); + RopePieceBTree(const RopePieceBTree &RHS); + ~RopePieceBTree(); + + typedef RopePieceBTreeIterator iterator; + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + unsigned size() const; + unsigned empty() const { return size() == 0; } + + void clear(); + + void insert(unsigned Offset, const RopePiece &R); + + void erase(unsigned Offset, unsigned NumBytes); + }; + + //===--------------------------------------------------------------------===// + // RewriteRope Class + //===--------------------------------------------------------------------===// + +/// RewriteRope - A powerful string class. This class supports extremely +/// efficient insertions and deletions into the middle of it, even for +/// ridiculously long strings. +class RewriteRope { + RopePieceBTree Chunks; + + /// We allocate space for string data out of a buffer of size AllocChunkSize. + /// This keeps track of how much space is left. + RopeRefCountString *AllocBuffer; + unsigned AllocOffs; + enum { AllocChunkSize = 4080 }; + +public: + RewriteRope() : AllocBuffer(0), AllocOffs(AllocChunkSize) {} + RewriteRope(const RewriteRope &RHS) + : Chunks(RHS.Chunks), AllocBuffer(0), AllocOffs(AllocChunkSize) { + } + + ~RewriteRope() { + // If we had an allocation buffer, drop our reference to it. + if (AllocBuffer) + AllocBuffer->dropRef(); + } + + typedef RopePieceBTree::iterator iterator; + typedef RopePieceBTree::iterator const_iterator; + iterator begin() const { return Chunks.begin(); } + iterator end() const { return Chunks.end(); } + unsigned size() const { return Chunks.size(); } + + void clear() { + Chunks.clear(); + } + + void assign(const char *Start, const char *End) { + clear(); + if (Start != End) + Chunks.insert(0, MakeRopeString(Start, End)); + } + + void insert(unsigned Offset, const char *Start, const char *End) { + assert(Offset <= size() && "Invalid position to insert!"); + if (Start == End) return; + Chunks.insert(Offset, MakeRopeString(Start, End)); + } + + void erase(unsigned Offset, unsigned NumBytes) { + assert(Offset+NumBytes <= size() && "Invalid region to erase!"); + if (NumBytes == 0) return; + Chunks.erase(Offset, NumBytes); + } + +private: + RopePiece MakeRopeString(const char *Start, const char *End); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h new file mode 100644 index 000000000000..a33ea134a7ac --- /dev/null +++ b/include/clang/Rewrite/Core/Rewriter.h @@ -0,0 +1,295 @@ +//===--- Rewriter.h - Code rewriting interface ------------------*- 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 Rewriter class, which is used for code +// transformations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITER_H +#define LLVM_CLANG_REWRITER_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Rewrite/Core/DeltaTree.h" +#include "clang/Rewrite/Core/RewriteRope.h" +#include "llvm/ADT/StringRef.h" +#include +#include +#include + +namespace clang { + class LangOptions; + class Rewriter; + class SourceManager; + class Stmt; + +/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original +/// input with modifications get a new RewriteBuffer associated with them. The +/// RewriteBuffer captures the modified text itself as well as information used +/// to map between SourceLocation's in the original input and offsets in the +/// RewriteBuffer. For example, if text is inserted into the buffer, any +/// locations after the insertion point have to be mapped. +class RewriteBuffer { + friend class Rewriter; + /// Deltas - Keep track of all the deltas in the source code due to insertions + /// and deletions. + DeltaTree Deltas; + + /// Buffer - This is the actual buffer itself. Note that using a vector or + /// string is a horribly inefficient way to do this, we should use a rope + /// instead. + typedef RewriteRope BufferTy; + BufferTy Buffer; +public: + typedef BufferTy::const_iterator iterator; + iterator begin() const { return Buffer.begin(); } + iterator end() const { return Buffer.end(); } + unsigned size() const { return Buffer.size(); } + + raw_ostream &write(raw_ostream &) const; + + /// RemoveText - Remove the specified text. + void RemoveText(unsigned OrigOffset, unsigned Size, + bool removeLineIfEmpty = false); + + /// InsertText - Insert some text at the specified point, where the offset in + /// the buffer is specified relative to the original SourceBuffer. The + /// text is inserted after the specified location. + /// + void InsertText(unsigned OrigOffset, StringRef Str, + bool InsertAfter = true); + + + /// InsertTextBefore - Insert some text before the specified point, where the + /// offset in the buffer is specified relative to the original + /// SourceBuffer. The text is inserted before the specified location. This is + /// method is the same as InsertText with "InsertAfter == false". + void InsertTextBefore(unsigned OrigOffset, StringRef Str) { + InsertText(OrigOffset, Str, false); + } + + /// InsertTextAfter - Insert some text at the specified point, where the + /// offset in the buffer is specified relative to the original SourceBuffer. + /// The text is inserted after the specified location. + void InsertTextAfter(unsigned OrigOffset, StringRef Str) { + InsertText(OrigOffset, Str); + } + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + void ReplaceText(unsigned OrigOffset, unsigned OrigLength, + StringRef NewStr); + +private: // Methods only usable by Rewriter. + + /// Initialize - Start this rewrite buffer out with a copy of the unmodified + /// input buffer. + void Initialize(const char *BufStart, const char *BufEnd) { + Buffer.assign(BufStart, BufEnd); + } + + /// getMappedOffset - Given an offset into the original SourceBuffer that this + /// RewriteBuffer is based on, map it into the offset space of the + /// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a + /// position where text is inserted, the location returned will be after any + /// inserted text at the position. + unsigned getMappedOffset(unsigned OrigOffset, + bool AfterInserts = false) const{ + return Deltas.getDeltaAt(2*OrigOffset+AfterInserts)+OrigOffset; + } + + /// AddInsertDelta - When an insertion is made at a position, this + /// method is used to record that information. + void AddInsertDelta(unsigned OrigOffset, int Change) { + return Deltas.AddDelta(2*OrigOffset, Change); + } + + /// AddReplaceDelta - When a replacement/deletion is made at a position, this + /// method is used to record that information. + void AddReplaceDelta(unsigned OrigOffset, int Change) { + return Deltas.AddDelta(2*OrigOffset+1, Change); + } +}; + + +/// Rewriter - This is the main interface to the rewrite buffers. Its primary +/// job is to dispatch high-level requests to the low-level RewriteBuffers that +/// are involved. +class Rewriter { + SourceManager *SourceMgr; + const LangOptions *LangOpts; + std::map RewriteBuffers; +public: + struct RewriteOptions { + /// \brief Given a source range, true to include previous inserts at the + /// beginning of the range as part of the range itself (true by default). + bool IncludeInsertsAtBeginOfRange; + /// \brief Given a source range, true to include previous inserts at the + /// end of the range as part of the range itself (true by default). + bool IncludeInsertsAtEndOfRange; + /// \brief If true and removing some text leaves a blank line + /// also remove the empty line (false by default). + bool RemoveLineIfEmpty; + + RewriteOptions() + : IncludeInsertsAtBeginOfRange(true), + IncludeInsertsAtEndOfRange(true), + RemoveLineIfEmpty(false) { } + }; + + typedef std::map::iterator buffer_iterator; + + explicit Rewriter(SourceManager &SM, const LangOptions &LO) + : SourceMgr(&SM), LangOpts(&LO) {} + explicit Rewriter() : SourceMgr(0), LangOpts(0) {} + + void setSourceMgr(SourceManager &SM, const LangOptions &LO) { + SourceMgr = &SM; + LangOpts = &LO; + } + SourceManager &getSourceMgr() const { return *SourceMgr; } + const LangOptions &getLangOpts() const { return *LangOpts; } + + /// isRewritable - Return true if this location is a raw file location, which + /// is rewritable. Locations from macros, etc are not rewritable. + static bool isRewritable(SourceLocation Loc) { + return Loc.isFileID(); + } + + /// getRangeSize - Return the size in bytes of the specified range if they + /// are in the same file. If not, this returns -1. + int getRangeSize(SourceRange Range, + RewriteOptions opts = RewriteOptions()) const; + int getRangeSize(const CharSourceRange &Range, + RewriteOptions opts = RewriteOptions()) const; + + /// getRewrittenText - Return the rewritten form of the text in the specified + /// range. If the start or end of the range was unrewritable or if they are + /// in different buffers, this returns an empty string. + /// + /// Note that this method is not particularly efficient. + /// + std::string getRewrittenText(SourceRange Range) const; + + /// InsertText - Insert the specified string at the specified location in the + /// original buffer. This method returns true (and does nothing) if the input + /// location was not rewritable, false otherwise. + /// + /// \param indentNewLines if true new lines in the string are indented + /// using the indentation of the source line in position \p Loc. + bool InsertText(SourceLocation Loc, StringRef Str, + bool InsertAfter = true, bool indentNewLines = false); + + /// InsertTextAfter - Insert the specified string at the specified location in + /// the original buffer. This method returns true (and does nothing) if + /// the input location was not rewritable, false otherwise. Text is + /// inserted after any other text that has been previously inserted + /// at the some point (the default behavior for InsertText). + bool InsertTextAfter(SourceLocation Loc, StringRef Str) { + return InsertText(Loc, Str); + } + + /// \brief Insert the specified string after the token in the + /// specified location. + bool InsertTextAfterToken(SourceLocation Loc, StringRef Str); + + /// InsertText - Insert the specified string at the specified location in the + /// original buffer. This method returns true (and does nothing) if the input + /// location was not rewritable, false otherwise. Text is + /// inserted before any other text that has been previously inserted + /// at the some point. + bool InsertTextBefore(SourceLocation Loc, StringRef Str) { + return InsertText(Loc, Str, false); + } + + /// RemoveText - Remove the specified text region. + bool RemoveText(SourceLocation Start, unsigned Length, + RewriteOptions opts = RewriteOptions()); + + /// \brief Remove the specified text region. + bool RemoveText(CharSourceRange range, + RewriteOptions opts = RewriteOptions()) { + return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); + } + + /// \brief Remove the specified text region. + bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) { + return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); + } + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceLocation Start, unsigned OrigLength, + StringRef NewStr); + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceRange range, StringRef NewStr) { + return ReplaceText(range.getBegin(), getRangeSize(range), NewStr); + } + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceRange range, SourceRange replacementRange); + + /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty + /// printer to generate the replacement code. This returns true if the input + /// could not be rewritten, or false if successful. + bool ReplaceStmt(Stmt *From, Stmt *To); + + /// \brief Increase indentation for the lines between the given source range. + /// To determine what the indentation should be, 'parentIndent' is used + /// that should be at a source location with an indentation one degree + /// lower than the given range. + bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent); + bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) { + return IncreaseIndentation(CharSourceRange::getTokenRange(range), + parentIndent); + } + + /// ConvertToString converts statement 'From' to a string using the + /// pretty printer. + std::string ConvertToString(Stmt *From); + + /// getEditBuffer - This is like getRewriteBufferFor, but always returns a + /// buffer, and allows you to write on it directly. This is useful if you + /// want efficient low-level access to apis for scribbling on one specific + /// FileID's buffer. + RewriteBuffer &getEditBuffer(FileID FID); + + /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID. + /// If no modification has been made to it, return null. + const RewriteBuffer *getRewriteBufferFor(FileID FID) const { + std::map::const_iterator I = + RewriteBuffers.find(FID); + return I == RewriteBuffers.end() ? 0 : &I->second; + } + + // Iterators over rewrite buffers. + buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } + buffer_iterator buffer_end() { return RewriteBuffers.end(); } + + /// SaveFiles - Save all changed files to disk. + /// + /// Returns whether not all changes were saved successfully. + /// Outputs diagnostics via the source manager's diagnostic engine + /// in case of an error. + bool overwriteChangedFiles(); + +private: + unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Rewrite/Core/TokenRewriter.h b/include/clang/Rewrite/Core/TokenRewriter.h new file mode 100644 index 000000000000..ec0bb5ba0827 --- /dev/null +++ b/include/clang/Rewrite/Core/TokenRewriter.h @@ -0,0 +1,79 @@ +//===--- TokenRewriter.h - Token-based Rewriter -----------------*- 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 TokenRewriter class, which is used for code +// transformations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOKENREWRITER_H +#define LLVM_CLANG_TOKENREWRITER_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/OwningPtr.h" +#include +#include + +namespace clang { + class LangOptions; + class ScratchBuffer; + + class TokenRewriter { + /// TokenList - This is the list of raw tokens that make up this file. Each + /// of these tokens has a unique SourceLocation, which is a FileID. + std::list TokenList; + + /// TokenRefTy - This is the type used to refer to a token in the TokenList. + typedef std::list::iterator TokenRefTy; + + /// TokenAtLoc - This map indicates which token exists at a specific + /// SourceLocation. Since each token has a unique SourceLocation, this is a + /// one to one map. The token can return its own location directly, to map + /// backwards. + std::map TokenAtLoc; + + /// ScratchBuf - This is the buffer that we create scratch tokens from. + /// + OwningPtr ScratchBuf; + + TokenRewriter(const TokenRewriter &) LLVM_DELETED_FUNCTION; + void operator=(const TokenRewriter &) LLVM_DELETED_FUNCTION; + public: + /// TokenRewriter - This creates a TokenRewriter for the file with the + /// specified FileID. + TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO); + ~TokenRewriter(); + + typedef std::list::const_iterator token_iterator; + token_iterator token_begin() const { return TokenList.begin(); } + token_iterator token_end() const { return TokenList.end(); } + + + token_iterator AddTokenBefore(token_iterator I, const char *Val); + token_iterator AddTokenAfter(token_iterator I, const char *Val) { + assert(I != token_end() && "Cannot insert after token_end()!"); + return AddTokenBefore(++I, Val); + } + + private: + /// RemapIterator - Convert from token_iterator (a const iterator) to + /// TokenRefTy (a non-const iterator). + TokenRefTy RemapIterator(token_iterator I); + + /// AddToken - Add the specified token into the Rewriter before the other + /// position. + TokenRefTy AddToken(const Token &T, TokenRefTy Where); + }; + + + +} // end namespace clang + +#endif diff --git a/include/clang/Rewrite/DeltaTree.h b/include/clang/Rewrite/DeltaTree.h deleted file mode 100644 index f32906a323e0..000000000000 --- a/include/clang/Rewrite/DeltaTree.h +++ /dev/null @@ -1,48 +0,0 @@ -//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- 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 DeltaTree class. -// -//===----------------------------------------------------------------------===// - -#ifndef CLANG_REWRITE_DELTATREE_H -#define CLANG_REWRITE_DELTATREE_H - -namespace clang { - - /// DeltaTree - a multiway search tree (BTree) structure with some fancy - /// features. B-Trees are generally more memory and cache efficient than - /// binary trees, because they store multiple keys/values in each node. This - /// implements a key/value mapping from index to delta, and allows fast lookup - /// on index. However, an added (important) bonus is that it can also - /// efficiently tell us the full accumulated delta for a specific file offset - /// as well, without traversing the whole tree. - class DeltaTree { - void *Root; // "DeltaTreeNode *" - void operator=(const DeltaTree&); // DO NOT IMPLEMENT - public: - DeltaTree(); - - // Note: Currently we only support copying when the RHS is empty. - DeltaTree(const DeltaTree &RHS); - ~DeltaTree(); - - /// getDeltaAt - Return the accumulated delta at the specified file offset. - /// This includes all insertions or delections that occurred *before* the - /// specified file index. - int getDeltaAt(unsigned FileIndex) const; - - /// AddDelta - When a change is made that shifts around the text buffer, - /// this method is used to record that info. It inserts a delta of 'Delta' - /// into the current DeltaTree at offset FileIndex. - void AddDelta(unsigned FileIndex, int Delta); - }; -} // end namespace clang - -#endif diff --git a/include/clang/Rewrite/FixItRewriter.h b/include/clang/Rewrite/FixItRewriter.h deleted file mode 100644 index 44f0611b17e6..000000000000 --- a/include/clang/Rewrite/FixItRewriter.h +++ /dev/null @@ -1,130 +0,0 @@ -//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a diagnostic client adaptor that performs rewrites as -// suggested by code modification hints attached to diagnostics. It -// then forwards any diagnostics to the adapted diagnostic client. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H -#define LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H - -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Rewrite/Rewriter.h" -#include "clang/Edit/EditedSource.h" - -namespace clang { - -class SourceManager; -class FileEntry; - -class FixItOptions { -public: - FixItOptions() : FixWhatYouCan(false), - FixOnlyWarnings(false), Silent(false) { } - - virtual ~FixItOptions(); - - /// \brief This file is about to be rewritten. Return the name of the file - /// that is okay to write to. - /// - /// \param fd out parameter for file descriptor. After the call it may be set - /// to an open file descriptor for the returned filename, or it will be -1 - /// otherwise. - /// - virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0; - - /// \brief Whether to abort fixing a file when not all errors could be fixed. - bool FixWhatYouCan; - - /// \brief Whether to only fix warnings and not errors. - bool FixOnlyWarnings; - - /// \brief If true, only pass the diagnostic to the actual diagnostic consumer - /// if it is an error or a fixit was applied as part of the diagnostic. - /// It basically silences warnings without accompanying fixits. - bool Silent; -}; - -class FixItRewriter : public DiagnosticConsumer { - /// \brief The diagnostics machinery. - DiagnosticsEngine &Diags; - - edit::EditedSource Editor; - - /// \brief The rewriter used to perform the various code - /// modifications. - Rewriter Rewrite; - - /// \brief The diagnostic client that performs the actual formatting - /// of error messages. - DiagnosticConsumer *Client; - bool OwnsClient; - - /// \brief Turn an input path into an output path. NULL implies overwriting - /// the original. - FixItOptions *FixItOpts; - - /// \brief The number of rewriter failures. - unsigned NumFailures; - - /// \brief Whether the previous diagnostic was not passed to the consumer. - bool PrevDiagSilenced; - -public: - typedef Rewriter::buffer_iterator iterator; - - /// \brief Initialize a new fix-it rewriter. - FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr, - const LangOptions &LangOpts, FixItOptions *FixItOpts); - - /// \brief Destroy the fix-it rewriter. - ~FixItRewriter(); - - /// \brief Check whether there are modifications for a given file. - bool IsModified(FileID ID) const { - return Rewrite.getRewriteBufferFor(ID) != NULL; - } - - // Iteration over files with changes. - iterator buffer_begin() { return Rewrite.buffer_begin(); } - iterator buffer_end() { return Rewrite.buffer_end(); } - - /// \brief Write a single modified source file. - /// - /// \returns true if there was an error, false otherwise. - bool WriteFixedFile(FileID ID, raw_ostream &OS); - - /// \brief Write the modified source files. - /// - /// \returns true if there was an error, false otherwise. - bool WriteFixedFiles( - std::vector > *RewrittenFiles = 0); - - /// IncludeInDiagnosticCounts - This method (whose default implementation - /// returns true) indicates whether the diagnostics handled by this - /// DiagnosticConsumer should be included in the number of diagnostics - /// reported by DiagnosticsEngine. - virtual bool IncludeInDiagnosticCounts() const; - - /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or - /// capturing it to a log as needed. - virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info); - - /// \brief Emit a diagnostic via the adapted diagnostic client. - void Diag(SourceLocation Loc, unsigned DiagID); - - DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const; -}; - -} - -#endif // LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H diff --git a/include/clang/Rewrite/Frontend/ASTConsumers.h b/include/clang/Rewrite/Frontend/ASTConsumers.h new file mode 100644 index 000000000000..c9c92e3a0188 --- /dev/null +++ b/include/clang/Rewrite/Frontend/ASTConsumers.h @@ -0,0 +1,48 @@ +//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AST Consumers. +// +//===----------------------------------------------------------------------===// + +#ifndef REWRITE_ASTCONSUMERS_H +#define REWRITE_ASTCONSUMERS_H + +#include "clang/Basic/LLVM.h" +#include + +namespace clang { + +class ASTConsumer; +class DiagnosticsEngine; +class LangOptions; +class Preprocessor; + +// ObjC rewriter: attempts to rewrite ObjC constructs into pure C code. +// This is considered experimental, and only works with Apple's ObjC runtime. +ASTConsumer *CreateObjCRewriter(const std::string &InFile, + raw_ostream *OS, + DiagnosticsEngine &Diags, + const LangOptions &LOpts, + bool SilenceRewriteMacroWarning); +ASTConsumer *CreateModernObjCRewriter(const std::string &InFile, + raw_ostream *OS, + DiagnosticsEngine &Diags, + const LangOptions &LOpts, + bool SilenceRewriteMacroWarning); + +/// CreateHTMLPrinter - Create an AST consumer which rewrites source code to +/// HTML with syntax highlighting suitable for viewing in a web-browser. +ASTConsumer *CreateHTMLPrinter(raw_ostream *OS, Preprocessor &PP, + bool SyntaxHighlight = true, + bool HighlightMacros = true); + +} // end clang namespace + +#endif diff --git a/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h new file mode 100644 index 000000000000..f12a034bd716 --- /dev/null +++ b/include/clang/Rewrite/Frontend/FixItRewriter.h @@ -0,0 +1,130 @@ +//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a diagnostic client adaptor that performs rewrites as +// suggested by code modification hints attached to diagnostics. It +// then forwards any diagnostics to the adapted diagnostic client. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H +#define LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Edit/EditedSource.h" + +namespace clang { + +class SourceManager; +class FileEntry; + +class FixItOptions { +public: + FixItOptions() : FixWhatYouCan(false), + FixOnlyWarnings(false), Silent(false) { } + + virtual ~FixItOptions(); + + /// \brief This file is about to be rewritten. Return the name of the file + /// that is okay to write to. + /// + /// \param fd out parameter for file descriptor. After the call it may be set + /// to an open file descriptor for the returned filename, or it will be -1 + /// otherwise. + /// + virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0; + + /// \brief Whether to abort fixing a file when not all errors could be fixed. + bool FixWhatYouCan; + + /// \brief Whether to only fix warnings and not errors. + bool FixOnlyWarnings; + + /// \brief If true, only pass the diagnostic to the actual diagnostic consumer + /// if it is an error or a fixit was applied as part of the diagnostic. + /// It basically silences warnings without accompanying fixits. + bool Silent; +}; + +class FixItRewriter : public DiagnosticConsumer { + /// \brief The diagnostics machinery. + DiagnosticsEngine &Diags; + + edit::EditedSource Editor; + + /// \brief The rewriter used to perform the various code + /// modifications. + Rewriter Rewrite; + + /// \brief The diagnostic client that performs the actual formatting + /// of error messages. + DiagnosticConsumer *Client; + bool OwnsClient; + + /// \brief Turn an input path into an output path. NULL implies overwriting + /// the original. + FixItOptions *FixItOpts; + + /// \brief The number of rewriter failures. + unsigned NumFailures; + + /// \brief Whether the previous diagnostic was not passed to the consumer. + bool PrevDiagSilenced; + +public: + typedef Rewriter::buffer_iterator iterator; + + /// \brief Initialize a new fix-it rewriter. + FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr, + const LangOptions &LangOpts, FixItOptions *FixItOpts); + + /// \brief Destroy the fix-it rewriter. + ~FixItRewriter(); + + /// \brief Check whether there are modifications for a given file. + bool IsModified(FileID ID) const { + return Rewrite.getRewriteBufferFor(ID) != NULL; + } + + // Iteration over files with changes. + iterator buffer_begin() { return Rewrite.buffer_begin(); } + iterator buffer_end() { return Rewrite.buffer_end(); } + + /// \brief Write a single modified source file. + /// + /// \returns true if there was an error, false otherwise. + bool WriteFixedFile(FileID ID, raw_ostream &OS); + + /// \brief Write the modified source files. + /// + /// \returns true if there was an error, false otherwise. + bool WriteFixedFiles( + std::vector > *RewrittenFiles = 0); + + /// IncludeInDiagnosticCounts - This method (whose default implementation + /// returns true) indicates whether the diagnostics handled by this + /// DiagnosticConsumer should be included in the number of diagnostics + /// reported by DiagnosticsEngine. + virtual bool IncludeInDiagnosticCounts() const; + + /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or + /// capturing it to a log as needed. + virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info); + + /// \brief Emit a diagnostic via the adapted diagnostic client. + void Diag(SourceLocation Loc, unsigned DiagID); + + DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const; +}; + +} + +#endif // LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H diff --git a/include/clang/Rewrite/Frontend/FrontendActions.h b/include/clang/Rewrite/Frontend/FrontendActions.h new file mode 100644 index 000000000000..ea876d9980f6 --- /dev/null +++ b/include/clang/Rewrite/Frontend/FrontendActions.h @@ -0,0 +1,83 @@ +//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITE_FRONTENDACTIONS_H +#define LLVM_CLANG_REWRITE_FRONTENDACTIONS_H + +#include "clang/Frontend/FrontendAction.h" + +namespace clang { +class FixItRewriter; +class FixItOptions; + +//===----------------------------------------------------------------------===// +// AST Consumer Actions +//===----------------------------------------------------------------------===// + +class HTMLPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); +}; + +class FixItAction : public ASTFrontendAction { +protected: + OwningPtr Rewriter; + OwningPtr FixItOpts; + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); + + virtual bool BeginSourceFileAction(CompilerInstance &CI, + StringRef Filename); + + virtual void EndSourceFileAction(); + + virtual bool hasASTFileSupport() const { return false; } + +public: + FixItAction(); + ~FixItAction(); +}; + +/// \brief Emits changes to temporary files and uses them for the original +/// frontend action. +class FixItRecompile : public WrapperFrontendAction { +public: + FixItRecompile(FrontendAction *WrappedAction) + : WrapperFrontendAction(WrappedAction) {} + +protected: + virtual bool BeginInvocation(CompilerInstance &CI); +}; + +class RewriteObjCAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); +}; + +class RewriteMacrosAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class RewriteTestAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class RewriteIncludesAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Rewrite/Frontend/Rewriters.h b/include/clang/Rewrite/Frontend/Rewriters.h new file mode 100644 index 000000000000..f5ade5ad35d3 --- /dev/null +++ b/include/clang/Rewrite/Frontend/Rewriters.h @@ -0,0 +1,35 @@ +//===--- Rewriters.h - Rewriter implementations -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains miscellaneous utilities for various front-end actions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITE_REWRITERS_H +#define LLVM_CLANG_REWRITE_REWRITERS_H + +#include "clang/Basic/LLVM.h" + +namespace clang { +class Preprocessor; +class PreprocessorOutputOptions; + +/// RewriteMacrosInInput - Implement -rewrite-macros mode. +void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS); + +/// DoRewriteTest - A simple test for the TokenRewriter class. +void DoRewriteTest(Preprocessor &PP, raw_ostream *OS); + +/// RewriteIncludesInInput - Implement -frewrite-includes mode. +void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, + const PreprocessorOutputOptions &Opts); + +} // end namespace clang + +#endif diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h deleted file mode 100644 index ea876d9980f6..000000000000 --- a/include/clang/Rewrite/FrontendActions.h +++ /dev/null @@ -1,83 +0,0 @@ -//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITE_FRONTENDACTIONS_H -#define LLVM_CLANG_REWRITE_FRONTENDACTIONS_H - -#include "clang/Frontend/FrontendAction.h" - -namespace clang { -class FixItRewriter; -class FixItOptions; - -//===----------------------------------------------------------------------===// -// AST Consumer Actions -//===----------------------------------------------------------------------===// - -class HTMLPrintAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); -}; - -class FixItAction : public ASTFrontendAction { -protected: - OwningPtr Rewriter; - OwningPtr FixItOpts; - - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); - - virtual bool BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename); - - virtual void EndSourceFileAction(); - - virtual bool hasASTFileSupport() const { return false; } - -public: - FixItAction(); - ~FixItAction(); -}; - -/// \brief Emits changes to temporary files and uses them for the original -/// frontend action. -class FixItRecompile : public WrapperFrontendAction { -public: - FixItRecompile(FrontendAction *WrappedAction) - : WrapperFrontendAction(WrappedAction) {} - -protected: - virtual bool BeginInvocation(CompilerInstance &CI); -}; - -class RewriteObjCAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); -}; - -class RewriteMacrosAction : public PreprocessorFrontendAction { -protected: - void ExecuteAction(); -}; - -class RewriteTestAction : public PreprocessorFrontendAction { -protected: - void ExecuteAction(); -}; - -class RewriteIncludesAction : public PreprocessorFrontendAction { -protected: - void ExecuteAction(); -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Rewrite/HTMLRewrite.h b/include/clang/Rewrite/HTMLRewrite.h deleted file mode 100644 index 88caf85e6010..000000000000 --- a/include/clang/Rewrite/HTMLRewrite.h +++ /dev/null @@ -1,81 +0,0 @@ -//==- HTMLRewrite.h - Translate source code into prettified HTML ---*- C++ -*-// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a set of functions used for translating source code -// into beautified HTML. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_HTMLREWRITER_H -#define LLVM_CLANG_HTMLREWRITER_H - -#include "clang/Basic/SourceLocation.h" -#include - -namespace clang { - -class Rewriter; -class RewriteBuffer; -class Preprocessor; - -namespace html { - - /// HighlightRange - Highlight a range in the source code with the specified - /// start/end tags. B/E must be in the same file. This ensures that - /// start/end tags are placed at the start/end of each line if the range is - /// multiline. - void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, - const char *StartTag, const char *EndTag); - - /// HighlightRange - Highlight a range in the source code with the specified - /// start/end tags. The Start/end of the range must be in the same file. - /// This ensures that start/end tags are placed at the start/end of each line - /// if the range is multiline. - inline void HighlightRange(Rewriter &R, SourceRange Range, - const char *StartTag, const char *EndTag) { - HighlightRange(R, Range.getBegin(), Range.getEnd(), StartTag, EndTag); - } - - /// HighlightRange - This is the same as the above method, but takes - /// decomposed file locations. - void HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E, - const char *BufferStart, - const char *StartTag, const char *EndTag); - - /// EscapeText - HTMLize a specified file so that special characters are - /// are translated so that they are not interpreted as HTML tags. - void EscapeText(Rewriter& R, FileID FID, - bool EscapeSpaces = false, bool ReplaceTabs = false); - - /// EscapeText - HTMLized the provided string so that special characters - /// in 's' are not interpreted as HTML tags. Unlike the version of - /// EscapeText that rewrites a file, this version by default replaces tabs - /// with spaces. - std::string EscapeText(const std::string& s, - bool EscapeSpaces = false, bool ReplaceTabs = false); - - void AddLineNumbers(Rewriter& R, FileID FID); - - void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID, - const char *title = NULL); - - /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with - /// information about keywords, comments, etc. - void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP); - - /// HighlightMacros - This uses the macro table state from the end of the - /// file, to reexpand macros and insert (into the HTML) information about the - /// macro expansions. This won't be perfectly perfect, but it will be - /// reasonably close. - void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP); - -} // end html namespace -} // end clang namespace - -#endif diff --git a/include/clang/Rewrite/RewriteRope.h b/include/clang/Rewrite/RewriteRope.h deleted file mode 100644 index cb3f8a86f8ab..000000000000 --- a/include/clang/Rewrite/RewriteRope.h +++ /dev/null @@ -1,231 +0,0 @@ -//===--- RewriteRope.h - Rope specialized for rewriter ----------*- 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 RewriteRope class, which is a powerful string class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITEROPE_H -#define LLVM_CLANG_REWRITEROPE_H - -#include -#include -#include -#include - -namespace clang { - //===--------------------------------------------------------------------===// - // RopeRefCountString Class - //===--------------------------------------------------------------------===// - - /// RopeRefCountString - This struct is allocated with 'new char[]' from the - /// heap, and represents a reference counted chunk of string data. When its - /// ref count drops to zero, it is delete[]'d. This is primarily managed - /// through the RopePiece class below. - struct RopeRefCountString { - unsigned RefCount; - char Data[1]; // Variable sized. - - void addRef() { - if (this) ++RefCount; - } - - void dropRef() { - if (this && --RefCount == 0) - delete [] (char*)this; - } - }; - - //===--------------------------------------------------------------------===// - // RopePiece Class - //===--------------------------------------------------------------------===// - - /// RopePiece - This class represents a view into a RopeRefCountString object. - /// This allows references to string data to be efficiently chopped up and - /// moved around without having to push around the string data itself. - /// - /// For example, we could have a 1M RopePiece and want to insert something - /// into the middle of it. To do this, we split it into two RopePiece objects - /// that both refer to the same underlying RopeRefCountString (just with - /// different offsets) which is a nice constant time operation. - struct RopePiece { - RopeRefCountString *StrData; - unsigned StartOffs; - unsigned EndOffs; - - RopePiece() : StrData(0), StartOffs(0), EndOffs(0) {} - - RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End) - : StrData(Str), StartOffs(Start), EndOffs(End) { - StrData->addRef(); - } - RopePiece(const RopePiece &RP) - : StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) { - StrData->addRef(); - } - - ~RopePiece() { - StrData->dropRef(); - } - - void operator=(const RopePiece &RHS) { - if (StrData != RHS.StrData) { - StrData->dropRef(); - StrData = RHS.StrData; - StrData->addRef(); - } - StartOffs = RHS.StartOffs; - EndOffs = RHS.EndOffs; - } - - const char &operator[](unsigned Offset) const { - return StrData->Data[Offset+StartOffs]; - } - char &operator[](unsigned Offset) { - return StrData->Data[Offset+StartOffs]; - } - - unsigned size() const { return EndOffs-StartOffs; } - }; - - //===--------------------------------------------------------------------===// - // RopePieceBTreeIterator Class - //===--------------------------------------------------------------------===// - - /// RopePieceBTreeIterator - This class provides read-only forward iteration - /// over bytes that are in a RopePieceBTree. This first iterates over bytes - /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf, - /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree. - class RopePieceBTreeIterator : - public std::iterator { - /// CurNode - The current B+Tree node that we are inspecting. - const void /*RopePieceBTreeLeaf*/ *CurNode; - /// CurPiece - The current RopePiece in the B+Tree node that we're - /// inspecting. - const RopePiece *CurPiece; - /// CurChar - The current byte in the RopePiece we are pointing to. - unsigned CurChar; - public: - // begin iterator. - RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N); - // end iterator - RopePieceBTreeIterator() : CurNode(0), CurPiece(0), CurChar(0) {} - - char operator*() const { - return (*CurPiece)[CurChar]; - } - - bool operator==(const RopePieceBTreeIterator &RHS) const { - return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar; - } - bool operator!=(const RopePieceBTreeIterator &RHS) const { - return !operator==(RHS); - } - - RopePieceBTreeIterator& operator++() { // Preincrement - if (CurChar+1 < CurPiece->size()) - ++CurChar; - else - MoveToNextPiece(); - return *this; - } - inline RopePieceBTreeIterator operator++(int) { // Postincrement - RopePieceBTreeIterator tmp = *this; ++*this; return tmp; - } - private: - void MoveToNextPiece(); - }; - - //===--------------------------------------------------------------------===// - // RopePieceBTree Class - //===--------------------------------------------------------------------===// - - class RopePieceBTree { - void /*RopePieceBTreeNode*/ *Root; - void operator=(const RopePieceBTree &); // DO NOT IMPLEMENT - public: - RopePieceBTree(); - RopePieceBTree(const RopePieceBTree &RHS); - ~RopePieceBTree(); - - typedef RopePieceBTreeIterator iterator; - iterator begin() const { return iterator(Root); } - iterator end() const { return iterator(); } - unsigned size() const; - unsigned empty() const { return size() == 0; } - - void clear(); - - void insert(unsigned Offset, const RopePiece &R); - - void erase(unsigned Offset, unsigned NumBytes); - }; - - //===--------------------------------------------------------------------===// - // RewriteRope Class - //===--------------------------------------------------------------------===// - -/// RewriteRope - A powerful string class. This class supports extremely -/// efficient insertions and deletions into the middle of it, even for -/// ridiculously long strings. -class RewriteRope { - RopePieceBTree Chunks; - - /// We allocate space for string data out of a buffer of size AllocChunkSize. - /// This keeps track of how much space is left. - RopeRefCountString *AllocBuffer; - unsigned AllocOffs; - enum { AllocChunkSize = 4080 }; - -public: - RewriteRope() : AllocBuffer(0), AllocOffs(AllocChunkSize) {} - RewriteRope(const RewriteRope &RHS) - : Chunks(RHS.Chunks), AllocBuffer(0), AllocOffs(AllocChunkSize) { - } - - ~RewriteRope() { - // If we had an allocation buffer, drop our reference to it. - AllocBuffer->dropRef(); - } - - typedef RopePieceBTree::iterator iterator; - typedef RopePieceBTree::iterator const_iterator; - iterator begin() const { return Chunks.begin(); } - iterator end() const { return Chunks.end(); } - unsigned size() const { return Chunks.size(); } - - void clear() { - Chunks.clear(); - } - - void assign(const char *Start, const char *End) { - clear(); - if (Start != End) - Chunks.insert(0, MakeRopeString(Start, End)); - } - - void insert(unsigned Offset, const char *Start, const char *End) { - assert(Offset <= size() && "Invalid position to insert!"); - if (Start == End) return; - Chunks.insert(Offset, MakeRopeString(Start, End)); - } - - void erase(unsigned Offset, unsigned NumBytes) { - assert(Offset+NumBytes <= size() && "Invalid region to erase!"); - if (NumBytes == 0) return; - Chunks.erase(Offset, NumBytes); - } - -private: - RopePiece MakeRopeString(const char *Start, const char *End); -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h deleted file mode 100644 index 5ffd88b05df5..000000000000 --- a/include/clang/Rewrite/Rewriter.h +++ /dev/null @@ -1,295 +0,0 @@ -//===--- Rewriter.h - Code rewriting interface ------------------*- 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 Rewriter class, which is used for code -// transformations. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITER_H -#define LLVM_CLANG_REWRITER_H - -#include "clang/Basic/SourceLocation.h" -#include "clang/Rewrite/DeltaTree.h" -#include "clang/Rewrite/RewriteRope.h" -#include "llvm/ADT/StringRef.h" -#include -#include -#include - -namespace clang { - class LangOptions; - class Rewriter; - class SourceManager; - class Stmt; - -/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original -/// input with modifications get a new RewriteBuffer associated with them. The -/// RewriteBuffer captures the modified text itself as well as information used -/// to map between SourceLocation's in the original input and offsets in the -/// RewriteBuffer. For example, if text is inserted into the buffer, any -/// locations after the insertion point have to be mapped. -class RewriteBuffer { - friend class Rewriter; - /// Deltas - Keep track of all the deltas in the source code due to insertions - /// and deletions. - DeltaTree Deltas; - - /// Buffer - This is the actual buffer itself. Note that using a vector or - /// string is a horribly inefficient way to do this, we should use a rope - /// instead. - typedef RewriteRope BufferTy; - BufferTy Buffer; -public: - typedef BufferTy::const_iterator iterator; - iterator begin() const { return Buffer.begin(); } - iterator end() const { return Buffer.end(); } - unsigned size() const { return Buffer.size(); } - - raw_ostream &write(raw_ostream &) const; - - /// RemoveText - Remove the specified text. - void RemoveText(unsigned OrigOffset, unsigned Size, - bool removeLineIfEmpty = false); - - /// InsertText - Insert some text at the specified point, where the offset in - /// the buffer is specified relative to the original SourceBuffer. The - /// text is inserted after the specified location. - /// - void InsertText(unsigned OrigOffset, StringRef Str, - bool InsertAfter = true); - - - /// InsertTextBefore - Insert some text before the specified point, where the - /// offset in the buffer is specified relative to the original - /// SourceBuffer. The text is inserted before the specified location. This is - /// method is the same as InsertText with "InsertAfter == false". - void InsertTextBefore(unsigned OrigOffset, StringRef Str) { - InsertText(OrigOffset, Str, false); - } - - /// InsertTextAfter - Insert some text at the specified point, where the - /// offset in the buffer is specified relative to the original SourceBuffer. - /// The text is inserted after the specified location. - void InsertTextAfter(unsigned OrigOffset, StringRef Str) { - InsertText(OrigOffset, Str); - } - - /// ReplaceText - This method replaces a range of characters in the input - /// buffer with a new string. This is effectively a combined "remove/insert" - /// operation. - void ReplaceText(unsigned OrigOffset, unsigned OrigLength, - StringRef NewStr); - -private: // Methods only usable by Rewriter. - - /// Initialize - Start this rewrite buffer out with a copy of the unmodified - /// input buffer. - void Initialize(const char *BufStart, const char *BufEnd) { - Buffer.assign(BufStart, BufEnd); - } - - /// getMappedOffset - Given an offset into the original SourceBuffer that this - /// RewriteBuffer is based on, map it into the offset space of the - /// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a - /// position where text is inserted, the location returned will be after any - /// inserted text at the position. - unsigned getMappedOffset(unsigned OrigOffset, - bool AfterInserts = false) const{ - return Deltas.getDeltaAt(2*OrigOffset+AfterInserts)+OrigOffset; - } - - /// AddInsertDelta - When an insertion is made at a position, this - /// method is used to record that information. - void AddInsertDelta(unsigned OrigOffset, int Change) { - return Deltas.AddDelta(2*OrigOffset, Change); - } - - /// AddReplaceDelta - When a replacement/deletion is made at a position, this - /// method is used to record that information. - void AddReplaceDelta(unsigned OrigOffset, int Change) { - return Deltas.AddDelta(2*OrigOffset+1, Change); - } -}; - - -/// Rewriter - This is the main interface to the rewrite buffers. Its primary -/// job is to dispatch high-level requests to the low-level RewriteBuffers that -/// are involved. -class Rewriter { - SourceManager *SourceMgr; - const LangOptions *LangOpts; - std::map RewriteBuffers; -public: - struct RewriteOptions { - /// \brief Given a source range, true to include previous inserts at the - /// beginning of the range as part of the range itself (true by default). - bool IncludeInsertsAtBeginOfRange; - /// \brief Given a source range, true to include previous inserts at the - /// end of the range as part of the range itself (true by default). - bool IncludeInsertsAtEndOfRange; - /// \brief If true and removing some text leaves a blank line - /// also remove the empty line (false by default). - bool RemoveLineIfEmpty; - - RewriteOptions() - : IncludeInsertsAtBeginOfRange(true), - IncludeInsertsAtEndOfRange(true), - RemoveLineIfEmpty(false) { } - }; - - typedef std::map::iterator buffer_iterator; - - explicit Rewriter(SourceManager &SM, const LangOptions &LO) - : SourceMgr(&SM), LangOpts(&LO) {} - explicit Rewriter() : SourceMgr(0), LangOpts(0) {} - - void setSourceMgr(SourceManager &SM, const LangOptions &LO) { - SourceMgr = &SM; - LangOpts = &LO; - } - SourceManager &getSourceMgr() const { return *SourceMgr; } - const LangOptions &getLangOpts() const { return *LangOpts; } - - /// isRewritable - Return true if this location is a raw file location, which - /// is rewritable. Locations from macros, etc are not rewritable. - static bool isRewritable(SourceLocation Loc) { - return Loc.isFileID(); - } - - /// getRangeSize - Return the size in bytes of the specified range if they - /// are in the same file. If not, this returns -1. - int getRangeSize(SourceRange Range, - RewriteOptions opts = RewriteOptions()) const; - int getRangeSize(const CharSourceRange &Range, - RewriteOptions opts = RewriteOptions()) const; - - /// getRewrittenText - Return the rewritten form of the text in the specified - /// range. If the start or end of the range was unrewritable or if they are - /// in different buffers, this returns an empty string. - /// - /// Note that this method is not particularly efficient. - /// - std::string getRewrittenText(SourceRange Range) const; - - /// InsertText - Insert the specified string at the specified location in the - /// original buffer. This method returns true (and does nothing) if the input - /// location was not rewritable, false otherwise. - /// - /// \param indentNewLines if true new lines in the string are indented - /// using the indentation of the source line in position \arg Loc. - bool InsertText(SourceLocation Loc, StringRef Str, - bool InsertAfter = true, bool indentNewLines = false); - - /// InsertTextAfter - Insert the specified string at the specified location in - /// the original buffer. This method returns true (and does nothing) if - /// the input location was not rewritable, false otherwise. Text is - /// inserted after any other text that has been previously inserted - /// at the some point (the default behavior for InsertText). - bool InsertTextAfter(SourceLocation Loc, StringRef Str) { - return InsertText(Loc, Str); - } - - /// \brief Insert the specified string after the token in the - /// specified location. - bool InsertTextAfterToken(SourceLocation Loc, StringRef Str); - - /// InsertText - Insert the specified string at the specified location in the - /// original buffer. This method returns true (and does nothing) if the input - /// location was not rewritable, false otherwise. Text is - /// inserted before any other text that has been previously inserted - /// at the some point. - bool InsertTextBefore(SourceLocation Loc, StringRef Str) { - return InsertText(Loc, Str, false); - } - - /// RemoveText - Remove the specified text region. - bool RemoveText(SourceLocation Start, unsigned Length, - RewriteOptions opts = RewriteOptions()); - - /// \brief Remove the specified text region. - bool RemoveText(CharSourceRange range, - RewriteOptions opts = RewriteOptions()) { - return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); - } - - /// \brief Remove the specified text region. - bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) { - return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); - } - - /// ReplaceText - This method replaces a range of characters in the input - /// buffer with a new string. This is effectively a combined "remove/insert" - /// operation. - bool ReplaceText(SourceLocation Start, unsigned OrigLength, - StringRef NewStr); - - /// ReplaceText - This method replaces a range of characters in the input - /// buffer with a new string. This is effectively a combined "remove/insert" - /// operation. - bool ReplaceText(SourceRange range, StringRef NewStr) { - return ReplaceText(range.getBegin(), getRangeSize(range), NewStr); - } - - /// ReplaceText - This method replaces a range of characters in the input - /// buffer with a new string. This is effectively a combined "remove/insert" - /// operation. - bool ReplaceText(SourceRange range, SourceRange replacementRange); - - /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty - /// printer to generate the replacement code. This returns true if the input - /// could not be rewritten, or false if successful. - bool ReplaceStmt(Stmt *From, Stmt *To); - - /// \brief Increase indentation for the lines between the given source range. - /// To determine what the indentation should be, 'parentIndent' is used - /// that should be at a source location with an indentation one degree - /// lower than the given range. - bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent); - bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) { - return IncreaseIndentation(CharSourceRange::getTokenRange(range), - parentIndent); - } - - /// ConvertToString converts statement 'From' to a string using the - /// pretty printer. - std::string ConvertToString(Stmt *From); - - /// getEditBuffer - This is like getRewriteBufferFor, but always returns a - /// buffer, and allows you to write on it directly. This is useful if you - /// want efficient low-level access to apis for scribbling on one specific - /// FileID's buffer. - RewriteBuffer &getEditBuffer(FileID FID); - - /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID. - /// If no modification has been made to it, return null. - const RewriteBuffer *getRewriteBufferFor(FileID FID) const { - std::map::const_iterator I = - RewriteBuffers.find(FID); - return I == RewriteBuffers.end() ? 0 : &I->second; - } - - // Iterators over rewrite buffers. - buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } - buffer_iterator buffer_end() { return RewriteBuffers.end(); } - - /// SaveFiles - Save all changed files to disk. - /// - /// Returns whether not all changes were saved successfully. - /// Outputs diagnostics via the source manager's diagnostic engine - /// in case of an error. - bool overwriteChangedFiles(); - -private: - unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Rewrite/Rewriters.h b/include/clang/Rewrite/Rewriters.h deleted file mode 100644 index f5ade5ad35d3..000000000000 --- a/include/clang/Rewrite/Rewriters.h +++ /dev/null @@ -1,35 +0,0 @@ -//===--- Rewriters.h - Rewriter implementations -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header contains miscellaneous utilities for various front-end actions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITE_REWRITERS_H -#define LLVM_CLANG_REWRITE_REWRITERS_H - -#include "clang/Basic/LLVM.h" - -namespace clang { -class Preprocessor; -class PreprocessorOutputOptions; - -/// RewriteMacrosInInput - Implement -rewrite-macros mode. -void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS); - -/// DoRewriteTest - A simple test for the TokenRewriter class. -void DoRewriteTest(Preprocessor &PP, raw_ostream *OS); - -/// RewriteIncludesInInput - Implement -frewrite-includes mode. -void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, - const PreprocessorOutputOptions &Opts); - -} // end namespace clang - -#endif diff --git a/include/clang/Rewrite/TokenRewriter.h b/include/clang/Rewrite/TokenRewriter.h deleted file mode 100644 index 894db0953f7f..000000000000 --- a/include/clang/Rewrite/TokenRewriter.h +++ /dev/null @@ -1,79 +0,0 @@ -//===--- TokenRewriter.h - Token-based Rewriter -----------------*- 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 TokenRewriter class, which is used for code -// transformations. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOKENREWRITER_H -#define LLVM_CLANG_TOKENREWRITER_H - -#include "clang/Basic/SourceLocation.h" -#include "clang/Lex/Token.h" -#include "llvm/ADT/OwningPtr.h" -#include -#include - -namespace clang { - class LangOptions; - class ScratchBuffer; - - class TokenRewriter { - /// TokenList - This is the list of raw tokens that make up this file. Each - /// of these tokens has a unique SourceLocation, which is a FileID. - std::list TokenList; - - /// TokenRefTy - This is the type used to refer to a token in the TokenList. - typedef std::list::iterator TokenRefTy; - - /// TokenAtLoc - This map indicates which token exists at a specific - /// SourceLocation. Since each token has a unique SourceLocation, this is a - /// one to one map. The token can return its own location directly, to map - /// backwards. - std::map TokenAtLoc; - - /// ScratchBuf - This is the buffer that we create scratch tokens from. - /// - OwningPtr ScratchBuf; - - TokenRewriter(const TokenRewriter&); // DO NOT IMPLEMENT - void operator=(const TokenRewriter&); // DO NOT IMPLEMENT. - public: - /// TokenRewriter - This creates a TokenRewriter for the file with the - /// specified FileID. - TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO); - ~TokenRewriter(); - - typedef std::list::const_iterator token_iterator; - token_iterator token_begin() const { return TokenList.begin(); } - token_iterator token_end() const { return TokenList.end(); } - - - token_iterator AddTokenBefore(token_iterator I, const char *Val); - token_iterator AddTokenAfter(token_iterator I, const char *Val) { - assert(I != token_end() && "Cannot insert after token_end()!"); - return AddTokenBefore(++I, Val); - } - - private: - /// RemapIterator - Convert from token_iterator (a const iterator) to - /// TokenRefTy (a non-const iterator). - TokenRefTy RemapIterator(token_iterator I); - - /// AddToken - Add the specified token into the Rewriter before the other - /// position. - TokenRefTy AddToken(const Token &T, TokenRefTy Where); - }; - - - -} // end namespace clang - -#endif diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index bf358862b09e..2e8b0c03f770 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -140,10 +140,10 @@ private: return *reinterpret_cast(this + 1); } - AttributeList(const AttributeList &); // DO NOT IMPLEMENT - void operator=(const AttributeList &); // DO NOT IMPLEMENT - void operator delete(void *); // DO NOT IMPLEMENT - ~AttributeList(); // DO NOT IMPLEMENT + AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION; + void operator=(const AttributeList &) LLVM_DELETED_FUNCTION; + void operator delete(void *) LLVM_DELETED_FUNCTION; + ~AttributeList() LLVM_DELETED_FUNCTION; size_t allocated_size() const; diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index d43aaafb2924..b128bd866903 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -439,9 +439,6 @@ private: /// \brief The availability of this code-completion result. unsigned Availability : 2; - - /// \brief The kind of the parent context. - unsigned ParentKind : 14; /// \brief The name of the parent context. StringRef ParentName; @@ -450,13 +447,13 @@ private: /// entity being completed by this result. const char *BriefComment; - CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT - CodeCompletionString &operator=(const CodeCompletionString &); // DITTO + CodeCompletionString(const CodeCompletionString &) LLVM_DELETED_FUNCTION; + void operator=(const CodeCompletionString &) LLVM_DELETED_FUNCTION; CodeCompletionString(const Chunk *Chunks, unsigned NumChunks, unsigned Priority, CXAvailabilityKind Availability, const char **Annotations, unsigned NumAnnotations, - CXCursorKind ParentKind, StringRef ParentName, + StringRef ParentName, const char *BriefComment); ~CodeCompletionString() { } @@ -489,11 +486,6 @@ public: /// \brief Retrieve the annotation string specified by \c AnnotationNr. const char *getAnnotation(unsigned AnnotationNr) const; - - /// \brief Retrieve parent context's cursor kind. - CXCursorKind getParentContextKind() const { - return (CXCursorKind)ParentKind; - } /// \brief Retrieve the name of the parent context. StringRef getParentContextName() const { @@ -577,7 +569,6 @@ private: CodeCompletionTUInfo &CCTUInfo; unsigned Priority; CXAvailabilityKind Availability; - CXCursorKind ParentKind; StringRef ParentName; const char *BriefComment; @@ -591,14 +582,14 @@ public: CodeCompletionTUInfo &CCTUInfo) : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(0), Availability(CXAvailability_Available), - ParentKind(CXCursor_NotImplemented), BriefComment(NULL) { } + BriefComment(NULL) { } CodeCompletionBuilder(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, unsigned Priority, CXAvailabilityKind Availability) : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(Priority), Availability(Availability), - ParentKind(CXCursor_NotImplemented), BriefComment(NULL) { } + BriefComment(NULL) { } /// \brief Retrieve the allocator into which the code completion /// strings should be allocated. @@ -642,7 +633,6 @@ public: void addBriefComment(StringRef Comment); - CXCursorKind getParentKind() const { return ParentKind; } StringRef getParentName() const { return ParentName; } }; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 792b0c643d8d..0728e8737638 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -266,6 +266,7 @@ public: static const TST TST_enum = clang::TST_enum; static const TST TST_union = clang::TST_union; static const TST TST_struct = clang::TST_struct; + static const TST TST_interface = clang::TST_interface; static const TST TST_class = clang::TST_class; static const TST TST_typename = clang::TST_typename; static const TST TST_typeofType = clang::TST_typeofType; @@ -378,11 +379,12 @@ private: } static bool isDeclRep(TST T) { return (T == TST_enum || T == TST_struct || - T == TST_union || T == TST_class); + T == TST_interface || T == TST_union || + T == TST_class); } - DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT - void operator=(const DeclSpec&); // DO NOT IMPLEMENT + DeclSpec(const DeclSpec &) LLVM_DELETED_FUNCTION; + void operator=(const DeclSpec &) LLVM_DELETED_FUNCTION; public: DeclSpec(AttributeFactory &attrFactory) @@ -598,8 +600,7 @@ public: } bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, const LangOptions &Lang, - bool IsTypeSpec); + unsigned &DiagID, const LangOptions &Lang); bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); @@ -781,8 +782,9 @@ private: /// \brief Represents a C++ unqualified-id that has been parsed. class UnqualifiedId { private: - const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT - + UnqualifiedId(const UnqualifiedId &Other) LLVM_DELETED_FUNCTION; + const UnqualifiedId &operator=(const UnqualifiedId &) LLVM_DELETED_FUNCTION; + public: /// \brief Describes the kind of unqualified-id parsed. enum IdKind { @@ -857,17 +859,6 @@ public: UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { } - /// \brief Do not use this copy constructor. It is temporary, and only - /// exists because we are holding FieldDeclarators in a SmallVector when we - /// don't actually need them. - /// - /// FIXME: Kill this copy constructor. - UnqualifiedId(const UnqualifiedId &Other) - : Kind(IK_Identifier), Identifier(Other.Identifier), - StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) { - assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers"); - } - /// \brief Clear out this unqualified-id, setting it to default (invalid) /// state. void clear() { @@ -1110,7 +1101,7 @@ struct DeclaratorChunk { /// \brief Whether the ref-qualifier (if any) is an lvalue reference. /// Otherwise, it's an rvalue reference. unsigned RefQualifierIsLValueRef : 1; - + /// The type qualifiers: const/volatile/restrict. /// The qualifier bitmask values are the same as in QualType. unsigned TypeQuals : 3; @@ -1125,9 +1116,15 @@ struct DeclaratorChunk { /// specified. unsigned HasTrailingReturnType : 1; + /// The location of the left parenthesis in the source. + unsigned LParenLoc; + /// When isVariadic is true, the location of the ellipsis in the source. unsigned EllipsisLoc; + /// The location of the right parenthesis in the source. + unsigned RParenLoc; + /// NumArgs - This is the number of formal arguments provided for the /// declarator. unsigned NumArgs; @@ -1202,10 +1199,19 @@ struct DeclaratorChunk { bool isKNRPrototype() const { return !hasPrototype && NumArgs != 0; } - + + SourceLocation getLParenLoc() const { + return SourceLocation::getFromRawEncoding(LParenLoc); + } + SourceLocation getEllipsisLoc() const { return SourceLocation::getFromRawEncoding(EllipsisLoc); } + + SourceLocation getRParenLoc() const { + return SourceLocation::getFromRawEncoding(RParenLoc); + } + SourceLocation getExceptionSpecLoc() const { return SourceLocation::getFromRawEncoding(ExceptionSpecLoc); } @@ -1358,11 +1364,13 @@ struct DeclaratorChunk { /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. - static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, + static DeclaratorChunk getFunction(bool hasProto, bool isAmbiguous, - SourceLocation EllipsisLoc, + SourceLocation LParenLoc, ParamInfo *ArgInfo, unsigned NumArgs, - unsigned TypeQuals, + SourceLocation EllipsisLoc, + SourceLocation RParenLoc, + unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, SourceLocation ConstQualifierLoc, diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h index c241266c9b8d..a20480c7e44b 100644 --- a/include/clang/Sema/DelayedDiagnostic.h +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -124,6 +124,7 @@ public: static DelayedDiagnostic makeDeprecation(SourceLocation Loc, const NamedDecl *D, const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, StringRef Msg); static DelayedDiagnostic makeAccess(SourceLocation Loc, @@ -193,12 +194,17 @@ public: return DeprecationData.UnknownObjCClass; } + const ObjCPropertyDecl *getObjCProperty() const { + return DeprecationData.ObjCProperty; + } + private: union { /// Deprecation. struct { const NamedDecl *Decl; const ObjCInterfaceDecl *UnknownObjCClass; + const ObjCPropertyDecl *ObjCProperty; const char *Message; size_t MessageLen; } DeprecationData; @@ -220,9 +226,8 @@ class DelayedDiagnosticPool { const DelayedDiagnosticPool *Parent; llvm::SmallVector Diagnostics; - // Do not implement. - DelayedDiagnosticPool(const DelayedDiagnosticPool &other); - DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &other); + DelayedDiagnosticPool(const DelayedDiagnosticPool &) LLVM_DELETED_FUNCTION; + void operator=(const DelayedDiagnosticPool &) LLVM_DELETED_FUNCTION; public: DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {} ~DelayedDiagnosticPool() { diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 785bf6acd12c..7a598498ff31 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -175,7 +175,6 @@ public: static bool classof(const ExternalASTSource *Source) { return Source->SemaSource; } - static bool classof(const ExternalSemaSource *) { return true; } }; } // end namespace clang diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 77659be1470f..0b0af0cff6ef 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -901,9 +901,9 @@ public: /// \brief Add a constructor-initialization step. /// - /// \arg FromInitList The constructor call is syntactically an initializer + /// \param FromInitList The constructor call is syntactically an initializer /// list. - /// \arg AsInitList The constructor is called as an init list constructor. + /// \param AsInitList The constructor is called as an init list constructor. void AddConstructorInitializationStep(CXXConstructorDecl *Constructor, AccessSpecifier Access, QualType T, diff --git a/include/clang/Sema/LocInfoType.h b/include/clang/Sema/LocInfoType.h index 93cb8cbda45f..63dfa72b8f74 100644 --- a/include/clang/Sema/LocInfoType.h +++ b/include/clang/Sema/LocInfoType.h @@ -55,7 +55,6 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == (TypeClass)LocInfo; } - static bool classof(const LocInfoType *) { return true; } }; } // end namespace clang diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h new file mode 100644 index 000000000000..1513aebb3e1e --- /dev/null +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -0,0 +1,367 @@ +//===--- MultiplexExternalSemaSource.h - External Sema Interface-*- 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 ExternalSemaSource interface, dispatching to all clients +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H +#define LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H + +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Weak.h" + +#include "llvm/ADT/SmallVector.h" + +#include + +namespace clang { + + class CXXConstructorDecl; + class CXXRecordDecl; + class DeclaratorDecl; + struct ExternalVTableUse; + class LookupResult; + class NamespaceDecl; + class Scope; + class Sema; + class TypedefNameDecl; + class ValueDecl; + class VarDecl; + + +/// \brief An abstract interface that should be implemented by +/// external AST sources that also provide information for semantic +/// analysis. +class MultiplexExternalSemaSource : public ExternalSemaSource { + +private: + llvm::SmallVector Sources; // doesn't own them. + +public: + + ///\brief Constructs a new multiplexing external sema source and appends the + /// given element to it. + /// + ///\param[in] s1 - A non-null (old) ExternalSemaSource. + ///\param[in] s2 - A non-null (new) ExternalSemaSource. + /// + MultiplexExternalSemaSource(ExternalSemaSource& s1, ExternalSemaSource& s2); + + ~MultiplexExternalSemaSource(); + + ///\brief Appends new source to the source list. + /// + ///\param[in] source - An ExternalSemaSource. + /// + void addSource(ExternalSemaSource &source); + + //===--------------------------------------------------------------------===// + // ExternalASTSource. + //===--------------------------------------------------------------------===// + + /// \brief Resolve a declaration ID into a declaration, potentially + /// building a new declaration. + /// + /// This method only needs to be implemented if the AST source ever + /// passes back decl sets as VisibleDeclaration objects. + /// + /// The default implementation of this method is a no-op. + virtual Decl *GetExternalDecl(uint32_t ID); + + /// \brief Resolve a selector ID into a selector. + /// + /// This operation only needs to be implemented if the AST source + /// returns non-zero for GetNumKnownSelectors(). + /// + /// The default implementation of this method is a no-op. + virtual Selector GetExternalSelector(uint32_t ID); + + /// \brief Returns the number of selectors known to the external AST + /// source. + /// + /// The default implementation of this method is a no-op. + virtual uint32_t GetNumExternalSelectors(); + + /// \brief Resolve the offset of a statement in the decl stream into + /// a statement. + /// + /// This operation is meant to be used via a LazyOffsetPtr. It only + /// needs to be implemented if the AST source uses methods like + /// FunctionDecl::setLazyBody when building decls. + /// + /// The default implementation of this method is a no-op. + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); + + /// \brief Resolve the offset of a set of C++ base specifiers in the decl + /// stream into an array of specifiers. + /// + /// The default implementation of this method is a no-op. + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + + /// \brief Finds all declarations with the given name in the + /// given context. + /// + /// Generally the final step of this method is either to call + /// SetExternalVisibleDeclsForName or to recursively call lookup on + /// the DeclContext after calling SetExternalVisibleDecls. + /// + /// The default implementation of this method is a no-op. + virtual DeclContextLookupResult + FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); + + /// \brief Ensures that the table of all visible declarations inside this + /// context is up to date. + /// + /// The default implementation of this functino is a no-op. + virtual void completeVisibleDeclsMap(const DeclContext *DC); + + /// \brief Finds all declarations lexically contained within the given + /// DeclContext, after applying an optional filter predicate. + /// + /// \param isKindWeWant a predicate function that returns true if the passed + /// declaration kind is one we are looking for. If NULL, all declarations + /// are returned. + /// + /// \return an indication of whether the load succeeded or failed. + /// + /// The default implementation of this method is a no-op. + virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + SmallVectorImpl &Result); + + /// \brief Finds all declarations lexically contained within the given + /// DeclContext. + /// + /// \return true if an error occurred + ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, + SmallVectorImpl &Result) { + return FindExternalLexicalDecls(DC, 0, Result); + } + + template + ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC, + SmallVectorImpl &Result) { + return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); + } + + /// \brief Get the decls that are contained in a file in the Offset/Length + /// range. \p Length can be 0 to indicate a point at \p Offset instead of + /// a range. + virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, + SmallVectorImpl &Decls); + + /// \brief Gives the external AST source an opportunity to complete + /// an incomplete type. + virtual void CompleteType(TagDecl *Tag); + + /// \brief Gives the external AST source an opportunity to complete an + /// incomplete Objective-C class. + /// + /// This routine will only be invoked if the "externally completed" bit is + /// set on the ObjCInterfaceDecl via the function + /// \c ObjCInterfaceDecl::setExternallyCompleted(). + virtual void CompleteType(ObjCInterfaceDecl *Class); + + /// \brief Loads comment ranges. + virtual void ReadComments(); + + /// \brief Notify ExternalASTSource that we started deserialization of + /// a decl or type so until FinishedDeserializing is called there may be + /// decls that are initializing. Must be paired with FinishedDeserializing. + /// + /// The default implementation of this method is a no-op. + virtual void StartedDeserializing(); + + /// \brief Notify ExternalASTSource that we finished the deserialization of + /// a decl or type. Must be paired with StartedDeserializing. + /// + /// The default implementation of this method is a no-op. + virtual void FinishedDeserializing(); + + /// \brief Function that will be invoked when we begin parsing a new + /// translation unit involving this external AST source. + /// + /// The default implementation of this method is a no-op. + virtual void StartTranslationUnit(ASTConsumer *Consumer); + + /// \brief Print any statistics that have been gathered regarding + /// the external AST source. + /// + /// The default implementation of this method is a no-op. + virtual void PrintStats(); + + + /// \brief Perform layout on the given record. + /// + /// This routine allows the external AST source to provide an specific + /// layout for a record, overriding the layout that would normally be + /// constructed. It is intended for clients who receive specific layout + /// details rather than source code (such as LLDB). The client is expected + /// to fill in the field offsets, base offsets, virtual base offsets, and + /// complete object size. + /// + /// \param Record The record whose layout is being requested. + /// + /// \param Size The final size of the record, in bits. + /// + /// \param Alignment The final alignment of the record, in bits. + /// + /// \param FieldOffsets The offset of each of the fields within the record, + /// expressed in bits. All of the fields must be provided with offsets. + /// + /// \param BaseOffsets The offset of each of the direct, non-virtual base + /// classes. If any bases are not given offsets, the bases will be laid + /// out according to the ABI. + /// + /// \param VirtualBaseOffsets The offset of each of the virtual base classes + /// (either direct or not). If any bases are not given offsets, the bases will + /// be laid out according to the ABI. + /// + /// \returns true if the record layout was provided, false otherwise. + virtual bool + layoutRecordType(const RecordDecl *Record, + uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets); + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + + //===--------------------------------------------------------------------===// + // ExternalSemaSource. + //===--------------------------------------------------------------------===// + + /// \brief Initialize the semantic source with the Sema instance + /// being used to perform semantic analysis on the abstract syntax + /// tree. + virtual void InitializeSema(Sema &S); + + /// \brief Inform the semantic consumer that Sema is no longer available. + virtual void ForgetSema(); + + /// \brief Load the contents of the global method pool for a given + /// selector. + virtual void ReadMethodPool(Selector Sel); + + /// \brief Load the set of namespaces that are known to the external source, + /// which will be used during typo correction. + virtual void ReadKnownNamespaces(SmallVectorImpl &Namespaces); + + /// \brief Do last resort, unqualified lookup on a LookupResult that + /// Sema cannot find. + /// + /// \param R a LookupResult that is being recovered. + /// + /// \param S the Scope of the identifier occurrence. + /// + /// \return true to tell Sema to recover using the LookupResult. + virtual bool LookupUnqualified(LookupResult &R, Scope *S); + + /// \brief Read the set of tentative definitions known to the external Sema + /// source. + /// + /// The external source should append its own tentative definitions to the + /// given vector of tentative definitions. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + virtual void ReadTentativeDefinitions(SmallVectorImpl &Defs); + + /// \brief Read the set of unused file-scope declarations known to the + /// external Sema source. + /// + /// The external source should append its own unused, filed-scope to the + /// given vector of declarations. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + virtual void ReadUnusedFileScopedDecls( + SmallVectorImpl &Decls); + + /// \brief Read the set of delegating constructors known to the + /// external Sema source. + /// + /// The external source should append its own delegating constructors to the + /// given vector of declarations. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + virtual void ReadDelegatingConstructors( + SmallVectorImpl &Decls); + + /// \brief Read the set of ext_vector type declarations known to the + /// external Sema source. + /// + /// The external source should append its own ext_vector type declarations to + /// the given vector of declarations. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + virtual void ReadExtVectorDecls(SmallVectorImpl &Decls); + + /// \brief Read the set of dynamic classes known to the external Sema source. + /// + /// The external source should append its own dynamic classes to + /// the given vector of declarations. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + virtual void ReadDynamicClasses(SmallVectorImpl &Decls); + + /// \brief Read the set of locally-scoped external declarations known to the + /// external Sema source. + /// + /// The external source should append its own locally-scoped external + /// declarations to the given vector of declarations. Note that this routine + /// may be invoked multiple times; the external source should take care not + /// to introduce the same declarations repeatedly. + virtual void ReadLocallyScopedExternalDecls(SmallVectorImpl&Decls); + + /// \brief Read the set of referenced selectors known to the + /// external Sema source. + /// + /// The external source should append its own referenced selectors to the + /// given vector of selectors. Note that this routine + /// may be invoked multiple times; the external source should take care not + /// to introduce the same selectors repeatedly. + virtual void ReadReferencedSelectors(SmallVectorImpl > &Sels); + + /// \brief Read the set of weak, undeclared identifiers known to the + /// external Sema source. + /// + /// The external source should append its own weak, undeclared identifiers to + /// the given vector. Note that this routine may be invoked multiple times; + /// the external source should take care not to introduce the same identifiers + /// repeatedly. + virtual void ReadWeakUndeclaredIdentifiers( + SmallVectorImpl > &WI); + + /// \brief Read the set of used vtables known to the external Sema source. + /// + /// The external source should append its own used vtables to the given + /// vector. Note that this routine may be invoked multiple times; the external + /// source should take care not to introduce the same vtables repeatedly. + virtual void ReadUsedVTables(SmallVectorImpl &VTables); + + /// \brief Read the set of pending instantiations known to the external + /// Sema source. + /// + /// The external source should append its own pending instantiations to the + /// given vector. Note that this routine may be invoked multiple times; the + /// external source should take care not to introduce the same instantiations + /// repeatedly. + virtual void ReadPendingInstantiations( + SmallVectorImpl >& Pending); + + // isa/cast/dyn_cast support + static bool classof(const MultiplexExternalSemaSource*) { return true; } + //static bool classof(const ExternalSemaSource*) { return true; } +}; + +} // end namespace clang + +#endif // LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index d2fc285c9e29..65ed781f743c 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -748,12 +748,14 @@ namespace clang { unsigned NumInlineSequences; char InlineSpace[16 * sizeof(ImplicitConversionSequence)]; - OverloadCandidateSet(const OverloadCandidateSet &); - OverloadCandidateSet &operator=(const OverloadCandidateSet &); - + OverloadCandidateSet(const OverloadCandidateSet &) LLVM_DELETED_FUNCTION; + void operator=(const OverloadCandidateSet &) LLVM_DELETED_FUNCTION; + + void destroyCandidates(); + public: OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){} - ~OverloadCandidateSet() { clear(); } + ~OverloadCandidateSet() { destroyCandidates(); } SourceLocation getLocation() const { return Loc; } @@ -808,7 +810,7 @@ namespace clang { void NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, llvm::ArrayRef Args, - const char *Opc = 0, + StringRef Opc = "", SourceLocation Loc = SourceLocation()); }; diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h index fb9e368dde9f..e59fb3f46ba3 100644 --- a/include/clang/Sema/Ownership.h +++ b/include/clang/Sema/Ownership.h @@ -15,7 +15,7 @@ #define LLVM_CLANG_SEMA_OWNERSHIP_H #include "clang/Basic/LLVM.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" //===----------------------------------------------------------------------===// @@ -30,8 +30,8 @@ namespace clang { class DeclGroupRef; class Expr; class NestedNameSpecifier; + class ParsedTemplateArgument; class QualType; - class Sema; class Stmt; class TemplateName; class TemplateParameterList; @@ -112,96 +112,6 @@ namespace llvm { struct isPodLike > { static const bool value = true; }; } - - -// -------------------------- About Move Emulation -------------------------- // -// The smart pointer classes in this file attempt to emulate move semantics -// as they appear in C++0x with rvalue references. Since C++03 doesn't have -// rvalue references, some tricks are needed to get similar results. -// Move semantics in C++0x have the following properties: -// 1) "Moving" means transferring the value of an object to another object, -// similar to copying, but without caring what happens to the old object. -// In particular, this means that the new object can steal the old object's -// resources instead of creating a copy. -// 2) Since moving can modify the source object, it must either be explicitly -// requested by the user, or the modifications must be unnoticeable. -// 3) As such, C++0x moving is only allowed in three contexts: -// * By explicitly using std::move() to request it. -// * From a temporary object, since that object cannot be accessed -// afterwards anyway, thus making the state unobservable. -// * On function return, since the object is not observable afterwards. -// -// To sum up: moving from a named object should only be possible with an -// explicit std::move(), or on function return. Moving from a temporary should -// be implicitly done. Moving from a const object is forbidden. -// -// The emulation is not perfect, and has the following shortcomings: -// * move() is not in namespace std. -// * move() is required on function return. -// * There are difficulties with implicit conversions. -// * Microsoft's compiler must be given the /Za switch to successfully compile. -// -// -------------------------- Implementation -------------------------------- // -// The move emulation relies on the peculiar reference binding semantics of -// C++03: as a rule, a non-const reference may not bind to a temporary object, -// except for the implicit object parameter in a member function call, which -// can refer to a temporary even when not being const. -// The moveable object has five important functions to facilitate moving: -// * A private, unimplemented constructor taking a non-const reference to its -// own class. This constructor serves a two-fold purpose. -// - It prevents the creation of a copy constructor that takes a const -// reference. Temporaries would be able to bind to the argument of such a -// constructor, and that would be bad. -// - Named objects will bind to the non-const reference, but since it's -// private, this will fail to compile. This prevents implicit moving from -// named objects. -// There's also a copy assignment operator for the same purpose. -// * An implicit, non-const conversion operator to a special mover type. This -// type represents the rvalue reference of C++0x. Being a non-const member, -// its implicit this parameter can bind to temporaries. -// * A constructor that takes an object of this mover type. This constructor -// performs the actual move operation. There is an equivalent assignment -// operator. -// There is also a free move() function that takes a non-const reference to -// an object and returns a temporary. Internally, this function uses explicit -// constructor calls to move the value from the referenced object to the return -// value. -// -// There are now three possible scenarios of use. -// * Copying from a const object. Constructor overload resolution will find the -// non-const copy constructor, and the move constructor. The first is not -// viable because the const object cannot be bound to the non-const reference. -// The second fails because the conversion to the mover object is non-const. -// Moving from a const object fails as intended. -// * Copying from a named object. Constructor overload resolution will select -// the non-const copy constructor, but fail as intended, because this -// constructor is private. -// * Copying from a temporary. Constructor overload resolution cannot select -// the non-const copy constructor, because the temporary cannot be bound to -// the non-const reference. It thus selects the move constructor. The -// temporary can be bound to the implicit this parameter of the conversion -// operator, because of the special binding rule. Construction succeeds. -// Note that the Microsoft compiler, as an extension, allows binding -// temporaries against non-const references. The compiler thus selects the -// non-const copy constructor and fails, because the constructor is private. -// Passing /Za (disable extensions) disables this behaviour. -// The free move() function is used to move from a named object. -// -// Note that when passing an object of a different type (the classes below -// have OwningResult and OwningPtr, which should be mixable), you get a problem. -// Argument passing and function return use copy initialization rules. The -// effect of this is that, when the source object is not already of the target -// type, the compiler will first seek a way to convert the source object to the -// target type, and only then attempt to copy the resulting object. This means -// that when passing an OwningResult where an OwningPtr is expected, the -// compiler will first seek a conversion from OwningResult to OwningPtr, then -// copy the OwningPtr. The resulting conversion sequence is: -// OwningResult object -> ResultMover -> OwningResult argument to -// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr -// This conversion sequence is too complex to be allowed. Thus the special -// move_* functions, which help the compiler out with some explicit -// conversions. - namespace clang { // Basic class DiagnosticBuilder; @@ -239,6 +149,7 @@ namespace clang { bool isUsable() const { return !Invalid && Val; } PtrTy get() const { return Val; } + // FIXME: Replace with get. PtrTy release() const { return Val; } PtrTy take() const { return Val; } template T *takeAs() { return static_cast(get()); } @@ -282,6 +193,7 @@ namespace clang { void *VP = reinterpret_cast(PtrWithInvalid & ~0x01); return PtrTraits::getFromVoidPointer(VP); } + // FIXME: Replace with get. PtrTy take() const { return get(); } PtrTy release() const { return get(); } template T *takeAs() { return static_cast(get()); } @@ -300,119 +212,11 @@ namespace clang { } }; - /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns - /// the individual pointers, not the array holding them. - template class ASTMultiPtr; - - template - class ASTMultiPtr { - PtrTy *Nodes; - unsigned Count; - - public: - // Normal copying implicitly defined - ASTMultiPtr() : Nodes(0), Count(0) {} - explicit ASTMultiPtr(Sema &) : Nodes(0), Count(0) {} - ASTMultiPtr(Sema &, PtrTy *nodes, unsigned count) - : Nodes(nodes), Count(count) {} - // Fake mover in Parse/AstGuard.h needs this: - ASTMultiPtr(PtrTy *nodes, unsigned count) : Nodes(nodes), Count(count) {} - - /// Access to the raw pointers. - PtrTy *get() const { return Nodes; } - - /// Access to the count. - unsigned size() const { return Count; } - - PtrTy *release() { - return Nodes; - } - }; - - class ParsedTemplateArgument; - - class ASTTemplateArgsPtr { - ParsedTemplateArgument *Args; - mutable unsigned Count; - - public: - ASTTemplateArgsPtr(Sema &actions, ParsedTemplateArgument *args, - unsigned count) : - Args(args), Count(count) { } - - // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. - ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : - Args(Other.Args), Count(Other.Count) { - } - - // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. - ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) { - Args = Other.Args; - Count = Other.Count; - return *this; - } - - ParsedTemplateArgument *getArgs() const { return Args; } - unsigned size() const { return Count; } - - void reset(ParsedTemplateArgument *args, unsigned count) { - Args = args; - Count = count; - } - - const ParsedTemplateArgument &operator[](unsigned Arg) const; - - ParsedTemplateArgument *release() const { - return Args; - } - }; - - /// \brief A small vector that owns a set of AST nodes. - template - class ASTOwningVector : public SmallVector { - ASTOwningVector(ASTOwningVector &); // do not implement - ASTOwningVector &operator=(ASTOwningVector &); // do not implement - - public: - explicit ASTOwningVector(Sema &Actions) - { } - - PtrTy *take() { - return &this->front(); - } - - template T **takeAs() { return reinterpret_cast(take()); } - }; - /// An opaque type for threading parsed type information through the /// parser. typedef OpaquePtr ParsedType; typedef UnionOpaquePtr UnionParsedType; - /// A SmallVector of statements, with stack size 32 (as that is the only one - /// used.) - typedef ASTOwningVector StmtVector; - /// A SmallVector of expressions, with stack size 12 (the maximum used.) - typedef ASTOwningVector ExprVector; - /// A SmallVector of types. - typedef ASTOwningVector TypeVector; - - template inline - ASTMultiPtr move_arg(ASTOwningVector &vec) { - return ASTMultiPtr(vec.take(), vec.size()); - } - - // These versions are hopefully no-ops. - template - inline ActionResult move(ActionResult &ptr) { - return ptr; - } - - template inline - ASTMultiPtr& move(ASTMultiPtr &ptr) { - return ptr; - } - // We can re-use the low bit of expression, statement, base, and // member-initializer pointers for the "invalid" flag of // ActionResult. @@ -438,13 +242,11 @@ namespace clang { typedef ActionResult DeclResult; typedef OpaquePtr ParsedTemplateTy; - inline Expr *move(Expr *E) { return E; } - inline Stmt *move(Stmt *S) { return S; } - - typedef ASTMultiPtr MultiExprArg; - typedef ASTMultiPtr MultiStmtArg; - typedef ASTMultiPtr MultiTypeArg; - typedef ASTMultiPtr MultiTemplateParamsArg; + typedef llvm::MutableArrayRef MultiExprArg; + typedef llvm::MutableArrayRef MultiStmtArg; + typedef llvm::MutableArrayRef ASTTemplateArgsPtr; + typedef llvm::MutableArrayRef MultiTypeArg; + typedef llvm::MutableArrayRef MultiTemplateParamsArg; inline ExprResult ExprError() { return ExprResult(true); } inline StmtResult StmtError() { return StmtResult(true); } diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h index 69080ad9b1d7..94db454a8543 100644 --- a/include/clang/Sema/ParsedTemplate.h +++ b/include/clang/Sema/ParsedTemplate.h @@ -209,11 +209,6 @@ namespace clang { /// Retrieves the range of the given template parameter lists. SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params, unsigned NumParams); - - inline const ParsedTemplateArgument & - ASTTemplateArgsPtr::operator[](unsigned Arg) const { - return Args[Arg]; - } } #endif diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index b78556e65a6c..fa508cfc22d9 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -82,7 +82,13 @@ public: SwitchScope = 0x800, /// TryScope - This is the scope of a C++ try statement. - TryScope = 0x1000 + TryScope = 0x1000, + + /// FnTryScope - This is the scope of a function-level C++ try scope. + FnTryScope = 0x3000, + + /// FnCatchScope - This is the scope of a function-level C++ catch scope. + FnCatchScope = 0x4000 }; private: /// The parent scope for this scope. This is null for the translation-unit diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index b4752f5dbb12..feda9c96b857 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file defines FunctionScopeInfo and BlockScopeInfo. +// This file defines FunctionScopeInfo and its subclasses, which contain +// information about a single function, block, lambda, or method body. // //===----------------------------------------------------------------------===// @@ -21,14 +22,20 @@ namespace clang { +class Decl; class BlockDecl; class CXXMethodDecl; +class ObjCPropertyDecl; class IdentifierInfo; class LabelDecl; class ReturnStmt; class Scope; class SwitchStmt; class VarDecl; +class DeclRefExpr; +class ObjCIvarRefExpr; +class ObjCPropertyRefExpr; +class ObjCMessageExpr; namespace sema { @@ -84,13 +91,10 @@ public: /// \brief Whether this function contains any indirect gotos. bool HasIndirectGoto; - /// A flag that is set when parsing a -dealloc method and no [super dealloc] - /// call was found yet. - bool ObjCShouldCallSuperDealloc; - - /// A flag that is set when parsing a -finalize method and no [super finalize] - /// call was found yet. - bool ObjCShouldCallSuperFinalize; + /// A flag that is set when parsing a method that must call super's + /// implementation, such as \c -dealloc, \c -finalize, or any method marked + /// with \c __attribute__((objc_requires_super)). + bool ObjCShouldCallSuper; /// \brief Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; @@ -113,6 +117,164 @@ public: /// prior to being emitted. SmallVector PossiblyUnreachableDiags; +public: + /// Represents a simple identification of a weak object. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + /// + /// This is used to determine if two weak accesses refer to the same object. + /// Here are some examples of how various accesses are "profiled": + /// + /// Access Expression | "Base" Decl | "Property" Decl + /// :---------------: | :-----------------: | :------------------------------: + /// self.property | self (VarDecl) | property (ObjCPropertyDecl) + /// self.implicitProp | self (VarDecl) | -implicitProp (ObjCMethodDecl) + /// self->ivar.prop | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl) + /// cxxObj.obj.prop | obj (FieldDecl) | prop (ObjCPropertyDecl) + /// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl) + /// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl) + /// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl) + /// weakVar | 0 (known) | weakVar (VarDecl) + /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl) + /// + /// Objects are identified with only two Decls to make it reasonably fast to + /// compare them. + class WeakObjectProfileTy { + /// The base object decl, as described in the class documentation. + /// + /// The extra flag is "true" if the Base and Property are enough to uniquely + /// identify the object in memory. + /// + /// \sa isExactProfile() + typedef llvm::PointerIntPair BaseInfoTy; + BaseInfoTy Base; + + /// The "property" decl, as described in the class documentation. + /// + /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the + /// case of "implicit" properties (regular methods accessed via dot syntax). + const NamedDecl *Property; + + /// Used to find the proper base profile for a given base expression. + static BaseInfoTy getBaseInfo(const Expr *BaseE); + + // For use in DenseMap. + friend class DenseMapInfo; + inline WeakObjectProfileTy(); + static inline WeakObjectProfileTy getSentinel(); + + public: + WeakObjectProfileTy(const ObjCPropertyRefExpr *RE); + WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property); + WeakObjectProfileTy(const DeclRefExpr *RE); + WeakObjectProfileTy(const ObjCIvarRefExpr *RE); + + const NamedDecl *getBase() const { return Base.getPointer(); } + const NamedDecl *getProperty() const { return Property; } + + /// Returns true if the object base specifies a known object in memory, + /// rather than, say, an instance variable or property of another object. + /// + /// Note that this ignores the effects of aliasing; that is, \c foo.bar is + /// considered an exact profile if \c foo is a local variable, even if + /// another variable \c foo2 refers to the same object as \c foo. + /// + /// For increased precision, accesses with base variables that are + /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to + /// be exact, though this is not true for arbitrary variables + /// (foo.prop1.prop2). + bool isExactProfile() const { + return Base.getInt(); + } + + bool operator==(const WeakObjectProfileTy &Other) const { + return Base == Other.Base && Property == Other.Property; + } + + // For use in DenseMap. + // We can't specialize the usual llvm::DenseMapInfo at the end of the file + // because by that point the DenseMap in FunctionScopeInfo has already been + // instantiated. + class DenseMapInfo { + public: + static inline WeakObjectProfileTy getEmptyKey() { + return WeakObjectProfileTy(); + } + static inline WeakObjectProfileTy getTombstoneKey() { + return WeakObjectProfileTy::getSentinel(); + } + + static unsigned getHashValue(const WeakObjectProfileTy &Val) { + typedef std::pair Pair; + return llvm::DenseMapInfo::getHashValue(Pair(Val.Base, + Val.Property)); + } + + static bool isEqual(const WeakObjectProfileTy &LHS, + const WeakObjectProfileTy &RHS) { + return LHS == RHS; + } + }; + }; + + /// Represents a single use of a weak object. + /// + /// Stores both the expression and whether the access is potentially unsafe + /// (i.e. it could potentially be warned about). + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + class WeakUseTy { + llvm::PointerIntPair Rep; + public: + WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {} + + const Expr *getUseExpr() const { return Rep.getPointer(); } + bool isUnsafe() const { return Rep.getInt(); } + void markSafe() { Rep.setInt(false); } + + bool operator==(const WeakUseTy &Other) const { + return Rep == Other.Rep; + } + }; + + /// Used to collect uses of a particular weak object in a function body. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + typedef SmallVector WeakUseVector; + + /// Used to collect all uses of weak objects in a function body. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + typedef llvm::SmallDenseMap + WeakObjectUseMap; + +private: + /// Used to collect all uses of weak objects in this function body. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + WeakObjectUseMap WeakObjectUses; + +public: + /// Record that a weak object was accessed. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + template + inline void recordUseOfWeak(const ExprT *E, bool IsRead = true); + + void recordUseOfWeak(const ObjCMessageExpr *Msg, + const ObjCPropertyDecl *Prop); + + /// Record that a given expression is a "safe" access of a weak object (e.g. + /// assigning it to a strong variable.) + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + void markSafeWeakUse(const Expr *E); + + const WeakObjectUseMap &getWeakObjectUses() const { + return WeakObjectUses; + } + void setHasBranchIntoScope() { HasBranchIntoScope = true; } @@ -135,8 +297,7 @@ public: HasBranchProtectedScope(false), HasBranchIntoScope(false), HasIndirectGoto(false), - ObjCShouldCallSuperDealloc(false), - ObjCShouldCallSuperFinalize(false), + ObjCShouldCallSuper(false), ErrorTrap(Diag) { } virtual ~FunctionScopeInfo(); @@ -144,8 +305,6 @@ public: /// \brief Clear out the information in this function scope, making it /// suitable for reuse. void Clear(); - - static bool classof(const FunctionScopeInfo *FSI) { return true; } }; class CapturingScopeInfo : public FunctionScopeInfo { @@ -262,11 +421,7 @@ public: } void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, - Expr *Cpy) { - Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, - Cpy)); - CXXThisCaptureIndex = Captures.size(); - } + Expr *Cpy); /// \brief Determine whether the C++ 'this' is captured. bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } @@ -299,7 +454,6 @@ public: static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; } - static bool classof(const CapturingScopeInfo *BSI) { return true; } }; /// \brief Retains information about a block that is currently being parsed. @@ -327,7 +481,6 @@ public: static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Block; } - static bool classof(const BlockScopeInfo *BSI) { return true; } }; class LambdaScopeInfo : public CapturingScopeInfo { @@ -379,15 +532,42 @@ public: void finishedExplicitCaptures() { NumExplicitCaptures = Captures.size(); } - - static bool classof(const FunctionScopeInfo *FSI) { + + static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Lambda; } - static bool classof(const LambdaScopeInfo *BSI) { return true; } - }; + +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() + : Base(0, false), Property(0) {} + +FunctionScopeInfo::WeakObjectProfileTy +FunctionScopeInfo::WeakObjectProfileTy::getSentinel() { + FunctionScopeInfo::WeakObjectProfileTy Result; + Result.Base.setInt(true); + return Result; +} + +template +void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { + assert(E); + WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; + Uses.push_back(WeakUseTy(E, IsRead)); } + +inline void +CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc, + QualType CaptureType, Expr *Cpy) { + Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, + Cpy)); + CXXThisCaptureIndex = Captures.size(); + + if (LambdaScopeInfo *LSI = dyn_cast(this)) + LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size()); } +} // end namespace sema +} // end namespace clang + #endif diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index acc88c0578ed..9b572d8b4d70 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -187,9 +187,16 @@ typedef std::pair, /// Sema - This implements semantic analysis and AST building for C. class Sema { - Sema(const Sema&); // DO NOT IMPLEMENT - void operator=(const Sema&); // DO NOT IMPLEMENT + Sema(const Sema &) LLVM_DELETED_FUNCTION; + void operator=(const Sema &) LLVM_DELETED_FUNCTION; mutable const TargetAttributesSema* TheTargetAttributesSema; + + ///\brief Source of additional semantic information. + ExternalSemaSource *ExternalSource; + + ///\brief Whether Sema has generated a multiplexer and has to delete it. + bool isMultiplexExternalSource; + public: typedef OpaquePtr DeclGroupPtrTy; typedef OpaquePtr TemplateTy; @@ -208,9 +215,6 @@ public: /// \brief Flag indicating whether or not to collect detailed statistics. bool CollectStats; - /// \brief Source of additional semantic information. - ExternalSemaSource *ExternalSource; - /// \brief Code-completion consumer. CodeCompleteConsumer *CodeCompleter; @@ -234,6 +238,12 @@ public: /// VisContext - Manages the stack for \#pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" + /// \brief Flag indicating if Sema is building a recovery call expression. + /// + /// This flag is used to avoid building recovery call expressions + /// if Sema is already doing so, which would cause infinite recursions. + bool IsBuildingRecoveryCallExpr; + /// ExprNeedsCleanups - True if the current evaluation context /// requires cleanups to be run at its conclusion. bool ExprNeedsCleanups; @@ -456,6 +466,26 @@ public: } }; + /// \brief RAII object to handle the state changes required to synthesize + /// a function body. + class SynthesizedFunctionScope { + Sema &S; + Sema::ContextRAII SavedContext; + + public: + SynthesizedFunctionScope(Sema &S, DeclContext *DC) + : S(S), SavedContext(S, DC) + { + S.PushFunctionScope(); + S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + } + + ~SynthesizedFunctionScope() { + S.PopExpressionEvaluationContext(); + S.PopFunctionScopeInfo(); + } + }; + /// WeakUndeclaredIdentifiers - Identifiers contained in /// \#pragma weak before declared. rare. may alias another /// identifier, declared or undeclared @@ -729,6 +759,20 @@ public: /// should not be used elsewhere. void EmitCurrentDiagnostic(unsigned DiagID); + /// Records and restores the FP_CONTRACT state on entry/exit of compound + /// statements. + class FPContractStateRAII { + public: + FPContractStateRAII(Sema& S) + : S(S), OldFPContractState(S.FPFeatures.fp_contract) {} + ~FPContractStateRAII() { + S.FPFeatures.fp_contract = OldFPContractState; + } + private: + Sema& S; + bool OldFPContractState : 1; + }; + public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind = TU_Complete, @@ -750,6 +794,14 @@ public: ASTContext &getASTContext() const { return Context; } ASTConsumer &getASTConsumer() const { return Consumer; } ASTMutationListener *getASTMutationListener() const; + ExternalSemaSource* getExternalSource() const { return ExternalSource; } + + ///\brief Registers an external source. If an external source already exists, + /// creates a multiplex external source and appends to it. + /// + ///\param[in] E - A non-null external sema source. + /// + void addExternalSource(ExternalSemaSource *E); void PrintStats() const; @@ -1203,7 +1255,7 @@ public: assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate); return Kind == NC_TypeTemplate? TNK_Type_template : TNK_Function_template; } -}; + }; /// \brief Perform name lookup on the given name, classifying it based on /// the results of name lookup and the following token. @@ -1223,11 +1275,19 @@ public: /// /// \param NextToken The token following the identifier. Used to help /// disambiguate the name. + /// + /// \param IsAddressOfOperand True if this name is the operand of a unary + /// address of ('&') expression, assuming it is classified as an + /// expression. + /// + /// \param CCC The correction callback, if typo correction is desired. NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc, - const Token &NextToken); + const Token &NextToken, + bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC = 0); Decl *ActOnDeclarator(Scope *S, Declarator &D); @@ -1265,6 +1325,7 @@ public: MultiTemplateParamsArg TemplateParamLists, bool &AddToScope); bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); + void checkVoidParamDecl(ParmVarDecl *Param); bool CheckConstexprFunctionDecl(const FunctionDecl *FD); bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body); @@ -1293,7 +1354,6 @@ public: bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, SourceLocation EqualLoc); - void CheckSelfReference(Decl *OrigDecl, Expr *E); void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit, bool TypeMayContainAuto); void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); @@ -1642,7 +1702,7 @@ public: /// \brief Checks availability of the function depending on the current /// function context.Inside an unavailable function,unavailability is ignored. /// - /// \returns true if \arg FD is unavailable and current context is inside + /// \returns true if \p FD is unavailable and current context is inside /// an available function, false otherwise. bool isFunctionConsideredUnavailable(FunctionDecl *FD); @@ -1866,8 +1926,7 @@ public: llvm::ArrayRef Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, - bool PartialOverloading = false, - bool StdNamespaceIsAssociated = false); + bool PartialOverloading = false); // Emit as a 'note' the specific overload candidate void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType()); @@ -1916,6 +1975,30 @@ public: OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); + // An enum used to represent the different possible results of building a + // range-based for loop. + enum ForRangeStatus { + FRS_Success, + FRS_NoViableFunction, + FRS_DiagnosticIssued + }; + + // An enum to represent whether something is dealing with a call to begin() + // or a call to end() in a range-based for loop. + enum BeginEndFunction { + BEF_begin, + BEF_end + }; + + ForRangeStatus BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc, + SourceLocation RangeLoc, + VarDecl *Decl, + BeginEndFunction BEF, + const DeclarationNameInfo &NameInfo, + LookupResult &MemberLookup, + OverloadCandidateSet *CandidateSet, + Expr *Range, ExprResult *CallExpr); + ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, @@ -1924,6 +2007,12 @@ public: Expr *ExecConfig, bool AllowTypoCorrection=true); + bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + OverloadCandidateSet *CandidateSet, + ExprResult *Result); + ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, const UnresolvedSetImpl &Fns, @@ -2130,8 +2219,7 @@ public: void ArgumentDependentLookup(DeclarationName Name, bool Operator, SourceLocation Loc, llvm::ArrayRef Args, - ADLResult &Functions, - bool StdNamespaceIsAssociated = false); + ADLResult &Functions); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, @@ -2148,7 +2236,8 @@ public: bool EnteringContext = false, const ObjCObjectPointerType *OPT = 0); - void FindAssociatedClassesAndNamespaces(llvm::ArrayRef Args, + void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, + llvm::ArrayRef Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses); @@ -2249,13 +2338,7 @@ public: void CollectImmediateProperties(ObjCContainerDecl *CDecl, llvm::DenseMap& PropMap, llvm::DenseMap& SuperPropMap); - - - /// LookupPropertyDecl - Looks up a property in the current class and all - /// its protocols. - ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl, - IdentifierInfo *II); - + /// Called by ActOnProperty to handle \@property declarations in /// class extensions. Decl *HandlePropertyInClassExtension(Scope *S, @@ -2399,7 +2482,7 @@ public: FullExprArg(const FullExprArg& Other) : E(Other.E) {} ExprResult release() { - return move(E); + return E; } Expr *get() const { return E; } @@ -2502,15 +2585,28 @@ public: SourceLocation RParenLoc); StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body); + enum BuildForRangeKind { + /// Initial building of a for-range statement. + BFRK_Build, + /// Instantiation or recovery rebuild of a for-range statement. Don't + /// attempt any typo-correction. + BFRK_Rebuild, + /// Determining whether a for-range statement could be built. Avoid any + /// unnecessary or irreversible actions. + BFRK_Check + }; + StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + BuildForRangeKind Kind); StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *BeginEndDecl, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + BuildForRangeKind Kind); StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body); StmtResult ActOnGotoStmt(SourceLocation GotoLoc, @@ -2528,21 +2624,19 @@ public: StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp); - StmtResult ActOnAsmStmt(SourceLocation AsmLoc, - bool IsSimple, bool IsVolatile, - unsigned NumOutputs, unsigned NumInputs, - IdentifierInfo **Names, - MultiExprArg Constraints, - MultiExprArg Exprs, - Expr *AsmString, - MultiExprArg Clobbers, - SourceLocation RParenLoc, - bool MSAsm = false); + StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg Constraints, MultiExprArg Exprs, + Expr *AsmString, MultiExprArg Clobbers, + SourceLocation RParenLoc); - StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, - SourceLocation LBraceLoc, - ArrayRef AsmToks, - SourceLocation EndLoc); + NamedDecl *LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, + unsigned &Size); + bool LookupInlineAsmField(StringRef Base, StringRef Member, + unsigned &Offset, SourceLocation AsmLoc); + StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, + ArrayRef AsmToks, SourceLocation EndLoc); VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, SourceLocation StartLoc, @@ -2639,7 +2733,8 @@ public: void EmitDeprecationWarning(NamedDecl *D, StringRef Message, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass=0); + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty); void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); @@ -2663,7 +2758,10 @@ public: void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = 0, bool IsDecltype = false); - + enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; + void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, + ReuseLambdaContextDecl_t, + bool IsDecltype = false); void PopExpressionEvaluationContext(); void DiscardCleanupsInEvaluationContext(); @@ -2815,7 +2913,8 @@ public: bool HasTrailingLParen); ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo); + const DeclarationNameInfo &NameInfo, + bool IsAddressOfOperand); ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, @@ -3279,18 +3378,11 @@ public: // Pointer to allow copying Sema *Self; // We order exception specifications thus: - // noexcept is the most restrictive, but is only used in C++0x. + // noexcept is the most restrictive, but is only used in C++11. // throw() comes next. // Then a throw(collected exceptions) - // Finally no specification. + // Finally no specification, which is expressed as noexcept(false). // throw(...) is used instead if any called function uses it. - // - // If this exception specification cannot be known yet (for instance, - // because this is the exception specification for a defaulted default - // constructor and we haven't finished parsing the deferred parts of the - // class yet), the C++0x standard does not specify how to behave. We - // record this as an 'unknown' exception specification, which overrules - // any other specification (even 'none', to keep this rule simple). ExceptionSpecificationType ComputedEST; llvm::SmallPtrSet ExceptionsSeen; SmallVector Exceptions; @@ -3330,8 +3422,17 @@ public: /// computed exception specification. void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const { EPI.ExceptionSpecType = getExceptionSpecType(); - EPI.NumExceptions = size(); - EPI.Exceptions = data(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = size(); + EPI.Exceptions = data(); + } else if (EPI.ExceptionSpecType == EST_None) { + /// C++11 [except.spec]p14: + /// The exception-specification is noexcept(false) if the set of + /// potential exceptions of the special member function contains "any" + EPI.ExceptionSpecType = EST_ComputedNoexcept; + EPI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), + tok::kw_false).take(); + } } FunctionProtoType::ExtProtoInfo getEPI() const { FunctionProtoType::ExtProtoInfo EPI; @@ -3515,7 +3616,7 @@ public: bool CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, - ASTOwningVector &ConvertedArgs, + SmallVectorImpl &ConvertedArgs, bool AllowExplicit = false); ParsedType getDestructorName(SourceLocation TildeLoc, @@ -3661,7 +3762,7 @@ public: SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, Expr *Initializer); - ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, + ExprResult BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, @@ -3991,7 +4092,8 @@ public: /// \brief Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, - bool KnownDependent = false); + TypeSourceInfo *Info, + bool KnownDependent); /// \brief Start the definition of a lambda expression. CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, @@ -4300,7 +4402,7 @@ public: SourceLocation RParenLoc, bool Failed); - FriendDecl *CheckFriendTypeDecl(SourceLocation Loc, + FriendDecl *CheckFriendTypeDecl(SourceLocation LocStart, SourceLocation FriendLoc, TypeSourceInfo *TSInfo); Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, @@ -4622,8 +4724,6 @@ public: /// \brief Parsed an elaborated-type-specifier that refers to a template-id, /// such as \c class T::template apply. - /// - /// \param TUK TypeResult ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, SourceLocation TagLoc, @@ -4799,7 +4899,8 @@ public: TemplateArgument &Converted, CheckTemplateArgumentKind CTAK = CTAK_Specified); bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, - const TemplateArgumentLoc &Arg); + const TemplateArgumentLoc &Arg, + unsigned ArgumentPackIndex); ExprResult BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, @@ -5246,6 +5347,8 @@ public: enum TemplateDeductionResult { /// \brief Template argument deduction was successful. TDK_Success = 0, + /// \brief The declaration was invalid; do nothing. + TDK_Invalid, /// \brief Template argument deduction exceeded the maximum template /// instantiation depth (which has already been diagnosed). TDK_InstantiationDepth, @@ -5681,10 +5784,10 @@ public: bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, SourceRange InstantiationRange); - InstantiatingTemplate(const InstantiatingTemplate&); // not implemented + InstantiatingTemplate(const InstantiatingTemplate&) LLVM_DELETED_FUNCTION; InstantiatingTemplate& - operator=(const InstantiatingTemplate&); // not implemented + operator=(const InstantiatingTemplate&) LLVM_DELETED_FUNCTION; }; void PrintInstantiationStack(); @@ -6016,7 +6119,7 @@ public: /// Ensure attributes are consistent with type. /// \param [in, out] Attributes The attributes to check; they will - /// be modified to be consistent with \arg PropertyTy. + /// be modified to be consistent with \p PropertyTy. void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc, unsigned &Attributes, @@ -6252,8 +6355,7 @@ public: /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align. void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, - SourceLocation PragmaLoc, - SourceLocation KindLoc); + SourceLocation PragmaLoc); enum PragmaPackKind { PPK_Default, // #pragma pack([n]) @@ -6748,6 +6850,7 @@ public: /// might create an obvious retain cycle. void checkRetainCycles(ObjCMessageExpr *msg); void checkRetainCycles(Expr *receiver, Expr *argument); + void checkRetainCycles(VarDecl *Var, Expr *Init); /// checkUnsafeAssigns - Check whether +1 expr is being assigned /// to weak/__unsafe_unretained type. @@ -6763,6 +6866,7 @@ public: /// \return true iff there were any incompatible types. bool CheckMessageArgumentTypes(QualType ReceiverType, Expr **Args, unsigned NumArgs, Selector Sel, + ArrayRef SelectorLocs, ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage, SourceLocation lbrac, SourceLocation rbrac, @@ -7210,6 +7314,14 @@ public: } AvailabilityResult getCurContextAvailability() const; + + const DeclContext *getCurObjCLexicalContext() const { + const DeclContext *DC = getCurLexicalContext(); + // A category implicitly has the attribute of the interface. + if (const ObjCCategoryDecl *CatD = dyn_cast(DC)) + DC = CatD->getClassInterface(); + return DC; + } }; /// \brief RAII object that enters a new expression evaluation context. @@ -7225,6 +7337,15 @@ public: Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, IsDecltype); } + EnterExpressionEvaluationContext(Sema &Actions, + Sema::ExpressionEvaluationContext NewContext, + Sema::ReuseLambdaContextDecl_t, + bool IsDecltype = false) + : Actions(Actions) { + Actions.PushExpressionEvaluationContext(NewContext, + Sema::ReuseLambdaContextDecl, + IsDecltype); + } ~EnterExpressionEvaluationContext() { Actions.PopExpressionEvaluationContext(); diff --git a/include/clang/Sema/SemaConsumer.h b/include/clang/Sema/SemaConsumer.h index 139cce8d7365..676646afbd59 100644 --- a/include/clang/Sema/SemaConsumer.h +++ b/include/clang/Sema/SemaConsumer.h @@ -42,7 +42,6 @@ namespace clang { static bool classof(const ASTConsumer *Consumer) { return Consumer->SemaConsumer; } - static bool classof(const SemaConsumer *) { return true; } }; } diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index 273374dfd8b0..bbccd259678a 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -239,8 +239,9 @@ namespace clang { unsigned NumArgsInPartiallySubstitutedPack; // This class is non-copyable - LocalInstantiationScope(const LocalInstantiationScope &); - LocalInstantiationScope &operator=(const LocalInstantiationScope &); + LocalInstantiationScope( + const LocalInstantiationScope &) LLVM_DELETED_FUNCTION; + void operator=(const LocalInstantiationScope &) LLVM_DELETED_FUNCTION; public: LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index 4c2d876d1f87..251a65990b3b 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -19,7 +19,6 @@ namespace clang { -class ASTContext; class TemplateArgumentList; namespace sema { @@ -28,9 +27,6 @@ namespace sema { /// deduction, whose success or failure was described by a /// TemplateDeductionResult value. class TemplateDeductionInfo { - /// \brief The context in which the template arguments are stored. - ASTContext &Context; - /// \brief The deduced template argument list. /// TemplateArgumentList *Deduced; @@ -46,17 +42,12 @@ class TemplateDeductionInfo { /// SFINAE while performing template argument deduction. SmallVector SuppressedDiagnostics; - // do not implement these - TemplateDeductionInfo(const TemplateDeductionInfo&); - TemplateDeductionInfo &operator=(const TemplateDeductionInfo&); + TemplateDeductionInfo(const TemplateDeductionInfo &) LLVM_DELETED_FUNCTION; + void operator=(const TemplateDeductionInfo &) LLVM_DELETED_FUNCTION; public: - TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc) - : Context(Context), Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false) { } - - ~TemplateDeductionInfo() { - // FIXME: if (Deduced) Deduced->Destroy(Context); - } + TemplateDeductionInfo(SourceLocation Loc) + : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false) { } /// \brief Returns the location at which template argument is /// occurring. @@ -83,7 +74,6 @@ public: /// \brief Provide a new template argument list that contains the /// results of template argument deduction. void reset(TemplateArgumentList *NewDeduced) { - // FIXME: if (Deduced) Deduced->Destroy(Context); Deduced = NewDeduced; } diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h index a8f6e1178b72..2b4a9e62167b 100644 --- a/include/clang/Sema/TypoCorrection.h +++ b/include/clang/Sema/TypoCorrection.h @@ -170,6 +170,17 @@ public: return CorrectionDecls.size() > 1; } + void setCorrectionRange(CXXScopeSpec* SS, + const DeclarationNameInfo &TypoName) { + CorrectionRange.setBegin(CorrectionNameSpec && SS ? SS->getBeginLoc() + : TypoName.getLoc()); + CorrectionRange.setEnd(TypoName.getLoc()); + } + + SourceRange getCorrectionRange() const { + return CorrectionRange; + } + typedef llvm::SmallVector::iterator decl_iterator; decl_iterator begin() { return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin(); @@ -193,6 +204,7 @@ private: unsigned CharDistance; unsigned QualifierDistance; unsigned CallbackDistance; + SourceRange CorrectionRange; }; /// @brief Base class for callback objects used by Sema::CorrectTypo to check diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index dbe6e5a31440..8c58fb281662 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -126,7 +126,13 @@ namespace clang { /// \brief The number of predefined identifier IDs. const unsigned int NUM_PREDEF_IDENT_IDS = 1; + + /// \brief An ID number that refers to a macro in an AST file. + typedef uint32_t MacroID; + /// \brief The number of predefined macro IDs. + const unsigned int NUM_PREDEF_MACRO_IDS = 1; + /// \brief An ID number that refers to an ObjC selector in an AST file. typedef uint32_t SelectorID; @@ -210,7 +216,71 @@ namespace clang { SUBMODULE_BLOCK_ID, /// \brief The block containing comments. - COMMENTS_BLOCK_ID + COMMENTS_BLOCK_ID, + + /// \brief The control block, which contains all of the + /// information that needs to be validated prior to committing + /// to loading the AST file. + CONTROL_BLOCK_ID, + + /// \brief The block of input files, which were used as inputs + /// to create this AST file. + /// + /// This block is part of the control block. + INPUT_FILES_BLOCK_ID + }; + + /// \brief Record types that occur within the control block. + enum ControlRecordTypes { + /// \brief AST file metadata, including the AST file version number + /// and information about the compiler used to build this AST file. + METADATA = 1, + + /// \brief Record code for the list of other AST files imported by + /// this AST file. + IMPORTS = 2, + + /// \brief Record code for the language options table. + /// + /// The record with this code contains the contents of the + /// LangOptions structure. We serialize the entire contents of + /// the structure, and let the reader decide which options are + /// actually important to check. + LANGUAGE_OPTIONS = 3, + + /// \brief Record code for the target options table. + TARGET_OPTIONS = 4, + + /// \brief Record code for the original file that was used to + /// generate the AST file, including both its file ID and its + /// name. + ORIGINAL_FILE = 5, + + /// \brief The directory that the PCH was originally created in. + ORIGINAL_PCH_DIR = 6, + + /// \brief Offsets into the input-files block where input files + /// reside. + INPUT_FILE_OFFSETS = 7, + + /// \brief Record code for the diagnostic options table. + DIAGNOSTIC_OPTIONS = 8, + + /// \brief Record code for the filesystem options table. + FILE_SYSTEM_OPTIONS = 9, + + /// \brief Record code for the headers search options table. + HEADER_SEARCH_OPTIONS = 10, + + /// \brief Record code for the preprocessor options table. + PREPROCESSOR_OPTIONS = 11 + }; + + /// \brief Record types that occur within the input-files block + /// inside the control block. + enum InputFileRecordTypes { + /// \brief An input file. + INPUT_FILE = 1 }; /// \brief Record types that occur within the AST block itself. @@ -241,25 +311,13 @@ namespace clang { /// reserved for the translation unit declaration. DECL_OFFSET = 2, - /// \brief Record code for the language options table. - /// - /// The record with this code contains the contents of the - /// LangOptions structure. We serialize the entire contents of - /// the structure, and let the reader decide which options are - /// actually important to check. - LANGUAGE_OPTIONS = 3, - - /// \brief AST file metadata, including the AST file version number - /// and the target triple used to build the AST file. - METADATA = 4, - /// \brief Record code for the table of offsets of each /// identifier ID. /// /// The offset table contains offsets into the blob stored in /// the IDENTIFIER_TABLE record. Each offset points to the /// NULL-terminated string that corresponds to that identifier. - IDENTIFIER_OFFSET = 5, + IDENTIFIER_OFFSET = 3, /// \brief Record code for the identifier table. /// @@ -273,7 +331,7 @@ namespace clang { /// between offsets (for unresolved identifier IDs) and /// IdentifierInfo pointers (for already-resolved identifier /// IDs). - IDENTIFIER_TABLE = 6, + IDENTIFIER_TABLE = 4, /// \brief Record code for the array of external definitions. /// @@ -283,7 +341,7 @@ namespace clang { /// reported to the AST consumer after the AST file has been /// read, since their presence can affect the semantics of the /// program (e.g., for code generation). - EXTERNAL_DEFINITIONS = 7, + EXTERNAL_DEFINITIONS = 5, /// \brief Record code for the set of non-builtin, special /// types. @@ -292,33 +350,33 @@ namespace clang { /// that are constructed during semantic analysis (e.g., /// __builtin_va_list). The SPECIAL_TYPE_* constants provide /// offsets into this record. - SPECIAL_TYPES = 8, + SPECIAL_TYPES = 6, /// \brief Record code for the extra statistics we gather while /// generating an AST file. - STATISTICS = 9, + STATISTICS = 7, /// \brief Record code for the array of tentative definitions. - TENTATIVE_DEFINITIONS = 10, + TENTATIVE_DEFINITIONS = 8, /// \brief Record code for the array of locally-scoped external /// declarations. - LOCALLY_SCOPED_EXTERNAL_DECLS = 11, + LOCALLY_SCOPED_EXTERNAL_DECLS = 9, /// \brief Record code for the table of offsets into the /// Objective-C method pool. - SELECTOR_OFFSETS = 12, + SELECTOR_OFFSETS = 10, /// \brief Record code for the Objective-C method pool, - METHOD_POOL = 13, + METHOD_POOL = 11, /// \brief The value of the next __COUNTER__ to dispense. /// [PP_COUNTER_VALUE, Val] - PP_COUNTER_VALUE = 14, + PP_COUNTER_VALUE = 12, /// \brief Record code for the table of offsets into the block /// of source-location information. - SOURCE_LOCATION_OFFSETS = 15, + SOURCE_LOCATION_OFFSETS = 13, /// \brief Record code for the set of source location entries /// that need to be preloaded by the AST reader. @@ -326,153 +384,138 @@ namespace clang { /// This set contains the source location entry for the /// predefines buffer and for any file entries that need to be /// preloaded. - SOURCE_LOCATION_PRELOADS = 16, - - /// \brief Record code for the stat() cache. - STAT_CACHE = 17, + SOURCE_LOCATION_PRELOADS = 14, /// \brief Record code for the set of ext_vector type names. - EXT_VECTOR_DECLS = 18, - - /// \brief Record code for the original file that was used to - /// generate the AST file. - ORIGINAL_FILE_NAME = 19, - - /// \brief Record code for the file ID of the original file used to - /// generate the AST file. - ORIGINAL_FILE_ID = 20, - - /// \brief Record code for the version control branch and revision - /// information of the compiler used to build this AST file. - VERSION_CONTROL_BRANCH_REVISION = 21, + EXT_VECTOR_DECLS = 16, /// \brief Record code for the array of unused file scoped decls. - UNUSED_FILESCOPED_DECLS = 22, + UNUSED_FILESCOPED_DECLS = 17, /// \brief Record code for the table of offsets to entries in the /// preprocessing record. - PPD_ENTITIES_OFFSETS = 23, + PPD_ENTITIES_OFFSETS = 18, /// \brief Record code for the array of VTable uses. - VTABLE_USES = 24, + VTABLE_USES = 19, /// \brief Record code for the array of dynamic classes. - DYNAMIC_CLASSES = 25, - - /// \brief Record code for the list of other AST files imported by - /// this AST file. - IMPORTS = 26, + DYNAMIC_CLASSES = 20, /// \brief Record code for referenced selector pool. - REFERENCED_SELECTOR_POOL = 27, + REFERENCED_SELECTOR_POOL = 21, /// \brief Record code for an update to the TU's lexically contained /// declarations. - TU_UPDATE_LEXICAL = 28, + TU_UPDATE_LEXICAL = 22, /// \brief Record code for the array describing the locations (in the /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by /// the first known ID. - LOCAL_REDECLARATIONS_MAP = 29, + LOCAL_REDECLARATIONS_MAP = 23, /// \brief Record code for declarations that Sema keeps references of. - SEMA_DECL_REFS = 30, + SEMA_DECL_REFS = 24, /// \brief Record code for weak undeclared identifiers. - WEAK_UNDECLARED_IDENTIFIERS = 31, + WEAK_UNDECLARED_IDENTIFIERS = 25, /// \brief Record code for pending implicit instantiations. - PENDING_IMPLICIT_INSTANTIATIONS = 32, + PENDING_IMPLICIT_INSTANTIATIONS = 26, /// \brief Record code for a decl replacement block. /// /// If a declaration is modified after having been deserialized, and then /// written to a dependent AST file, its ID and offset must be added to /// the replacement block. - DECL_REPLACEMENTS = 33, + DECL_REPLACEMENTS = 27, /// \brief Record code for an update to a decl context's lookup table. /// /// In practice, this should only be used for the TU and namespaces. - UPDATE_VISIBLE = 34, + UPDATE_VISIBLE = 28, /// \brief Record for offsets of DECL_UPDATES records for declarations /// that were modified after being deserialized and need updates. - DECL_UPDATE_OFFSETS = 35, + DECL_UPDATE_OFFSETS = 29, /// \brief Record of updates for a declaration that was modified after /// being deserialized. - DECL_UPDATES = 36, + DECL_UPDATES = 30, /// \brief Record code for the table of offsets to CXXBaseSpecifier /// sets. - CXX_BASE_SPECIFIER_OFFSETS = 37, + CXX_BASE_SPECIFIER_OFFSETS = 31, /// \brief Record code for \#pragma diagnostic mappings. - DIAG_PRAGMA_MAPPINGS = 38, + DIAG_PRAGMA_MAPPINGS = 32, /// \brief Record code for special CUDA declarations. - CUDA_SPECIAL_DECL_REFS = 39, + CUDA_SPECIAL_DECL_REFS = 33, /// \brief Record code for header search information. - HEADER_SEARCH_TABLE = 40, - - /// \brief The directory that the PCH was originally created in. - ORIGINAL_PCH_DIR = 41, + HEADER_SEARCH_TABLE = 34, /// \brief Record code for floating point \#pragma options. - FP_PRAGMA_OPTIONS = 42, + FP_PRAGMA_OPTIONS = 35, /// \brief Record code for enabled OpenCL extensions. - OPENCL_EXTENSIONS = 43, + OPENCL_EXTENSIONS = 36, /// \brief The list of delegating constructor declarations. - DELEGATING_CTORS = 44, + DELEGATING_CTORS = 37, - /// \brief Record code for the table of offsets into the block - /// of file source-location information. - FILE_SOURCE_LOCATION_OFFSETS = 45, - /// \brief Record code for the set of known namespaces, which are used /// for typo correction. - KNOWN_NAMESPACES = 46, + KNOWN_NAMESPACES = 38, /// \brief Record code for the remapping information used to relate /// loaded modules to the various offsets and IDs(e.g., source location /// offests, declaration and type IDs) that are used in that module to /// refer to other modules. - MODULE_OFFSET_MAP = 47, + MODULE_OFFSET_MAP = 39, /// \brief Record code for the source manager line table information, /// which stores information about \#line directives. - SOURCE_MANAGER_LINE_TABLE = 48, + SOURCE_MANAGER_LINE_TABLE = 40, /// \brief Record code for map of Objective-C class definition IDs to the /// ObjC categories in a module that are attached to that class. - OBJC_CATEGORIES_MAP = 49, + OBJC_CATEGORIES_MAP = 41, /// \brief Record code for a file sorted array of DeclIDs in a module. - FILE_SORTED_DECLS = 50, + FILE_SORTED_DECLS = 42, /// \brief Record code for an array of all of the (sub)modules that were /// imported by the AST file. - IMPORTED_MODULES = 51, + IMPORTED_MODULES = 43, /// \brief Record code for the set of merged declarations in an AST file. - MERGED_DECLARATIONS = 52, + MERGED_DECLARATIONS = 44, /// \brief Record code for the array of redeclaration chains. /// /// This array can only be interpreted properly using the local /// redeclarations map. - LOCAL_REDECLARATIONS = 53, + LOCAL_REDECLARATIONS = 45, /// \brief Record code for the array of Objective-C categories (including /// extensions). /// /// This array can only be interpreted properly using the Objective-C /// categories map. - OBJC_CATEGORIES = 54 + OBJC_CATEGORIES = 46, + + /// \brief Record code for the table of offsets of each macro ID. + /// + /// The offset table contains offsets into the blob stored in + /// the preprocessor block. Each offset points to the corresponding + /// macro definition. + MACRO_OFFSET = 47, + + /// \brief Record of updates for a macro that was modified after + /// being deserialized. + MACRO_UPDATES = 48 }; /// \brief Record types used within a source manager block. @@ -537,16 +580,21 @@ namespace clang { SUBMODULE_UMBRELLA_HEADER = 2, /// \brief Specifies a header that falls into this (sub)module. SUBMODULE_HEADER = 3, + /// \brief Specifies a top-level header that falls into this (sub)module. + SUBMODULE_TOPHEADER = 4, /// \brief Specifies an umbrella directory. - SUBMODULE_UMBRELLA_DIR = 4, + SUBMODULE_UMBRELLA_DIR = 5, /// \brief Specifies the submodules that are imported by this /// submodule. - SUBMODULE_IMPORTS = 5, + SUBMODULE_IMPORTS = 6, /// \brief Specifies the submodules that are re-exported from this /// submodule. - SUBMODULE_EXPORTS = 6, + SUBMODULE_EXPORTS = 7, /// \brief Specifies a required feature. - SUBMODULE_REQUIRES = 7 + SUBMODULE_REQUIRES = 8, + /// \brief Specifies a header that has been explicitly excluded + /// from this submodule. + SUBMODULE_EXCLUDED_HEADER = 9 }; /// \brief Record types used within a comments block. @@ -642,7 +690,9 @@ namespace clang { /// \brief The pseudo-object placeholder type. PREDEF_TYPE_PSEUDO_OBJECT = 35, /// \brief The __va_list_tag placeholder type. - PREDEF_TYPE_VA_LIST_TAG = 36 + PREDEF_TYPE_VA_LIST_TAG = 36, + /// \brief The placeholder type for builtin functions. + PREDEF_TYPE_BUILTIN_FN = 37 }; /// \brief The number of predefined type IDs that are reserved for @@ -943,6 +993,9 @@ namespace clang { /// \brief A NonTypeTemplateParmDecl record that stores an expanded /// non-type template parameter pack. DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK, + /// \brief A TemplateTemplateParmDecl record that stores an expanded + /// template template parameter pack. + DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK, /// \brief A ClassScopeFunctionSpecializationDecl record a class scope /// function specialization. (Microsoft extension). DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION, @@ -999,8 +1052,10 @@ namespace clang { STMT_RETURN, /// \brief A DeclStmt record. STMT_DECL, - /// \brief An AsmStmt record. - STMT_ASM, + /// \brief A GCC-style AsmStmt record. + STMT_GCCASM, + /// \brief A MS-style AsmStmt record. + STMT_MSASM, /// \brief A PredefinedExpr record. EXPR_PREDEFINED, /// \brief A DeclRefExpr record. @@ -1186,6 +1241,7 @@ namespace clang { EXPR_SIZEOF_PACK, // SizeOfPackExpr EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr + EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr // CUDA diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h index ab0d313a5c84..0218129fb625 100644 --- a/include/clang/Serialization/ASTDeserializationListener.h +++ b/include/clang/Serialization/ASTDeserializationListener.h @@ -23,6 +23,7 @@ class Decl; class ASTReader; class QualType; class MacroDefinition; +class MacroInfo; class Module; class ASTDeserializationListener { @@ -37,6 +38,8 @@ public: /// \brief An identifier was deserialized from the AST file. virtual void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) { } + /// \brief A macro was read from the AST file. + virtual void MacroRead(serialization::MacroID ID, MacroInfo *MI) { } /// \brief A type was deserialized from the AST file. The ID here has the /// qualifier bits already removed, and T is guaranteed to be locally /// unqualified. @@ -48,9 +51,6 @@ public: /// \brief A macro definition was read from the AST file. virtual void MacroDefinitionRead(serialization::PreprocessedEntityID, MacroDefinition *MD) { } - /// \brief A macro definition that had previously been deserialized - /// (and removed via IdentifierRead) has now been made visible. - virtual void MacroVisible(IdentifierInfo *II) { } /// \brief A module definition was read from the AST file. virtual void ModuleRead(serialization::SubmoduleID ID, Module *Mod) { } }; diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index f0b727531a57..e23ea5cca7e5 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -24,6 +24,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/PPMutationListener.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" @@ -33,6 +34,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" @@ -61,6 +63,7 @@ class ASTUnit; // FIXME: Layering violation and egregious hack. class Attr; class Decl; class DeclContext; +class DiagnosticOptions; class NestedNameSpecifier; class CXXBaseSpecifier; class CXXConstructorDecl; @@ -70,6 +73,7 @@ class MacroDefinition; class NamedDecl; class OpaqueValueExpr; class Preprocessor; +class PreprocessorOptions; class Sema; class SwitchCase; class ASTDeserializationListener; @@ -80,15 +84,7 @@ class ASTStmtReader; class TypeLocReader; struct HeaderFileInfo; class VersionTuple; - -struct PCHPredefinesBlock { - /// \brief The file ID for this predefines buffer in a PCH file. - FileID BufferID; - - /// \brief This predefines buffer in a PCH file. - StringRef Data; -}; -typedef SmallVector PCHPredefinesBlocks; +class TargetOptions; /// \brief Abstract interface for callback invocations by the ASTReader. /// @@ -103,32 +99,58 @@ public: /// \brief Receives the language options. /// /// \returns true to indicate the options are invalid or false otherwise. - virtual bool ReadLanguageOptions(const LangOptions &LangOpts) { + virtual bool ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain) { return false; } - /// \brief Receives the target triple. + /// \brief Receives the target options. /// - /// \returns true to indicate the target triple is invalid or false otherwise. - virtual bool ReadTargetTriple(StringRef Triple) { + /// \returns true to indicate the target options are invalid, or false + /// otherwise. + virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain) { return false; } - /// \brief Receives the contents of the predefines buffer. + /// \brief Receives the diagnostic options. /// - /// \param Buffers Information about the predefines buffers. + /// \returns true to indicate the diagnostic options are invalid, or false + /// otherwise. + virtual bool ReadDiagnosticOptions(const DiagnosticOptions &DiagOpts, + bool Complain) { + return false; + } + + /// \brief Receives the file system options. /// - /// \param OriginalFileName The original file name for the AST file, which - /// will appear as an entry in the predefines buffer. + /// \returns true to indicate the file system options are invalid, or false + /// otherwise. + virtual bool ReadFileSystemOptions(const FileSystemOptions &FSOpts, + bool Complain) { + return false; + } + + /// \brief Receives the header search options. + /// + /// \returns true to indicate the header search options are invalid, or false + /// otherwise. + virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + bool Complain) { + return false; + } + + /// \brief Receives the preprocessor options. /// - /// \param SuggestedPredefines If necessary, additional definitions are added - /// here. + /// \param SuggestedPredefines Can be filled in with the set of predefines + /// that are suggested by the preprocessor options. Typically only used when + /// loading a precompiled header. /// - /// \returns true to indicate the predefines are invalid or false otherwise. - virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - StringRef OriginalFileName, - std::string &SuggestedPredefines, - FileManager &FileMgr) { + /// \returns true to indicate the preprocessor options are invalid, or false + /// otherwise. + virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, + bool Complain, + std::string &SuggestedPredefines) { return false; } @@ -136,7 +158,8 @@ public: virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {} /// \brief Receives __COUNTER__ value. - virtual void ReadCounter(unsigned Value) {} + virtual void ReadCounter(const serialization::ModuleFile &M, + unsigned Value) {} }; /// \brief ASTReaderListener implementation to validate the information of @@ -151,14 +174,15 @@ public: PCHValidator(Preprocessor &PP, ASTReader &Reader) : PP(PP), Reader(Reader), NumHeaderInfos(0) {} - virtual bool ReadLanguageOptions(const LangOptions &LangOpts); - virtual bool ReadTargetTriple(StringRef Triple); - virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - StringRef OriginalFileName, - std::string &SuggestedPredefines, - FileManager &FileMgr); + virtual bool ReadLanguageOptions(const LangOptions &LangOpts, + bool Complain); + virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, + bool Complain); + virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, + bool Complain, + std::string &SuggestedPredefines); virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID); - virtual void ReadCounter(unsigned Value); + virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value); private: void Error(const char *Msg); @@ -201,7 +225,26 @@ class ASTReader public: typedef SmallVector RecordData; - enum ASTReadResult { Success, Failure, IgnorePCH }; + /// \brief The result of reading the control block of an AST file, which + /// can fail for various reasons. + enum ASTReadResult { + /// \brief The control block was read successfully. Aside from failures, + /// the AST file is safe to read into the current context. + Success, + /// \brief The AST file itself appears corrupted. + Failure, + /// \brief The AST file is out-of-date relative to its input files, + /// and needs to be regenerated. + OutOfDate, + /// \brief The AST file was written by a different version of Clang. + VersionMismatch, + /// \brief The AST file was writtten with a different language/target + /// configuration. + ConfigurationMismatch, + /// \brief The AST file has errors. + HadErrors + }; + /// \brief Types of AST files. friend class PCHValidator; friend class ASTDeclReader; @@ -341,7 +384,15 @@ private: /// \brief The set of C++ or Objective-C classes that have forward /// declarations that have not yet been linked to their definitions. llvm::SmallPtrSet PendingDefinitions; - + + typedef llvm::MapVector, + llvm::SmallVector, 4> > + PendingBodiesMap; + + /// \brief Functions or methods that have bodies that will be attached. + PendingBodiesMap PendingBodies; + /// \brief Read the records that describe the contents of declcontexts. bool ReadDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, @@ -359,11 +410,36 @@ private: typedef ContinuousRangeMap GlobalIdentifierMapType; - /// \brief Mapping from global identifer IDs to the module in which the + /// \brief Mapping from global identifier IDs to the module in which the /// identifier resides along with the offset that should be added to the /// global identifier ID to produce a local ID. GlobalIdentifierMapType GlobalIdentifierMap; + /// \brief A vector containing macros that have already been + /// loaded. + /// + /// If the pointer at index I is non-NULL, then it refers to the + /// MacroInfo for the identifier with ID=I+1 that has already + /// been loaded. + std::vector MacrosLoaded; + + typedef ContinuousRangeMap + GlobalMacroMapType; + + /// \brief Mapping from global macro IDs to the module in which the + /// macro resides along with the offset that should be added to the + /// global macro ID to produce a local ID. + GlobalMacroMapType GlobalMacroMap; + + typedef llvm::DenseMap, 1> > + MacroUpdatesMap; + + /// \brief Mapping from (global) macro IDs to the set of updates to be + /// performed to the corresponding macro. + MacroUpdatesMap MacroUpdates; + /// \brief A vector containing submodules that have already been loaded. /// /// This vector is indexed by the Submodule ID (-1). NULL submodule entries @@ -378,8 +454,55 @@ private: /// global submodule ID to produce a local ID. GlobalSubmoduleMapType GlobalSubmoduleMap; + /// \brief An entity that has been hidden. + class HiddenName { + public: + enum NameKind { + Declaration, + MacroVisibility, + MacroUndef + } Kind; + + private: + unsigned Loc; + + union { + Decl *D; + MacroInfo *MI; + }; + + IdentifierInfo *Id; + + public: + HiddenName(Decl *D) : Kind(Declaration), Loc(), D(D), Id() { } + + HiddenName(IdentifierInfo *II, MacroInfo *MI) + : Kind(MacroVisibility), Loc(), MI(MI), Id(II) { } + + HiddenName(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc) + : Kind(MacroUndef), Loc(Loc.getRawEncoding()), MI(MI), Id(II) { } + + NameKind getKind() const { return Kind; } + + Decl *getDecl() const { + assert(getKind() == Declaration && "Hidden name is not a declaration"); + return D; + } + + std::pair getMacro() const { + assert((getKind() == MacroUndef || getKind() == MacroVisibility) + && "Hidden name is not a macro!"); + return std::make_pair(Id, MI); + } + + SourceLocation getMacroUndefLoc() const { + assert(getKind() == MacroUndef && "Hidden name is not an undef!"); + return SourceLocation::getFromRawEncoding(Loc); + } +}; + /// \brief A set of hidden declarations. - typedef llvm::SmallVector, 2> + typedef llvm::SmallVector HiddenNames; typedef llvm::DenseMap HiddenNamesMapType; @@ -431,10 +554,13 @@ private: /// global method pool for this selector. llvm::DenseMap SelectorGeneration; - /// \brief Mapping from identifiers that represent macros whose definitions - /// have not yet been deserialized to the global offset where the macro - /// record resides. - llvm::DenseMap UnreadMacroRecordOffsets; + typedef llvm::MapVector > + PendingMacroIDsMap; + + /// \brief Mapping from identifiers that have a macro history to the global + /// IDs have not yet been deserialized to the global IDs of those macros. + PendingMacroIDsMap PendingMacroIDs; typedef ContinuousRangeMap GlobalPreprocessedEntityMapType; @@ -553,28 +679,9 @@ private: SmallVector ImportedModules; //@} - /// \brief The original file name that was used to build the primary AST file, - /// which may have been modified for relocatable-pch support. - std::string OriginalFileName; - - /// \brief The actual original file name that was used to build the primary - /// AST file. - std::string ActualOriginalFileName; - - /// \brief The file ID for the original file that was used to build the - /// primary AST file. - FileID OriginalFileID; - - /// \brief The directory that the PCH was originally created in. Used to - /// allow resolving headers even after headers+PCH was moved to a new path. - std::string OriginalDir; - /// \brief The directory that the PCH we are reading is stored in. std::string CurrentDir; - /// \brief Whether this precompiled header is a relocatable PCH file. - bool RelocatablePCH; - /// \brief The system include root to be used when loading the /// precompiled header. std::string isysroot; @@ -583,9 +690,6 @@ private: /// headers when they are loaded. bool DisableValidation; - /// \brief Whether to disable the use of stat caches in AST files. - bool DisableStatCache; - /// \brief Whether to accept an AST file with compiler errors. bool AllowASTWithCompilerErrors; @@ -602,10 +706,6 @@ private: SwitchCaseMapTy *CurrSwitchCaseStmts; - /// \brief The number of stat() calls that hit/missed the stat - /// cache. - unsigned NumStatHits, NumStatMisses; - /// \brief The number of source location entries de-serialized from /// the PCH file. unsigned NumSLocEntriesRead; @@ -687,7 +787,7 @@ private: /// Objective-C protocols. std::deque InterestingDecls; - /// \brief The set of redeclarable declaraations that have been deserialized + /// \brief The set of redeclarable declarations that have been deserialized /// since the last time the declaration chains were linked. llvm::SmallPtrSet RedeclsDeserialized; @@ -758,8 +858,8 @@ private: ASTReader &Reader; enum ReadingKind PrevKind; - ReadingKindTracker(const ReadingKindTracker&); // do not implement - ReadingKindTracker &operator=(const ReadingKindTracker&);// do not implement + ReadingKindTracker(const ReadingKindTracker &) LLVM_DELETED_FUNCTION; + void operator=(const ReadingKindTracker &) LLVM_DELETED_FUNCTION; public: ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader) @@ -770,10 +870,6 @@ private: ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; } }; - /// \brief All predefines buffers in the chain, to be treated as if - /// concatenated. - PCHPredefinesBlocks PCHPredefinesBuffers; - /// \brief Suggested contents of the predefines buffer, after this /// PCH file has been processed. /// @@ -787,24 +883,45 @@ private: /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); + typedef llvm::PointerIntPair InputFile; + + /// \brief Retrieve the file entry and 'overridden' bit for an input + /// file in the given module file. + InputFile getInputFile(ModuleFile &F, unsigned ID, bool Complain = true); + /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take /// into account all the necessary relocations. const FileEntry *getFileEntry(StringRef filename); - void MaybeAddSystemRootToFilename(std::string &Filename); + void MaybeAddSystemRootToFilename(ModuleFile &M, std::string &Filename); ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type, - ModuleFile *ImportedBy); - ASTReadResult ReadASTBlock(ModuleFile &F); - bool CheckPredefinesBuffers(); + ModuleFile *ImportedBy, + llvm::SmallVectorImpl &Loaded, + unsigned ClientLoadCapabilities); + ASTReadResult ReadControlBlock(ModuleFile &F, + llvm::SmallVectorImpl &Loaded, + unsigned ClientLoadCapabilities); + bool ReadASTBlock(ModuleFile &F); bool ParseLineTable(ModuleFile &F, SmallVectorImpl &Record); - ASTReadResult ReadSourceManagerBlock(ModuleFile &F); - ASTReadResult ReadSLocEntryRecord(int ID); + bool ReadSourceManagerBlock(ModuleFile &F); llvm::BitstreamCursor &SLocCursorForID(int ID); SourceLocation getImportLocation(ModuleFile *F); - ASTReadResult ReadSubmoduleBlock(ModuleFile &F); - bool ParseLanguageOptions(const RecordData &Record); - + bool ReadSubmoduleBlock(ModuleFile &F); + static bool ParseLanguageOptions(const RecordData &Record, bool Complain, + ASTReaderListener &Listener); + static bool ParseTargetOptions(const RecordData &Record, bool Complain, + ASTReaderListener &Listener); + static bool ParseDiagnosticOptions(const RecordData &Record, bool Complain, + ASTReaderListener &Listener); + static bool ParseFileSystemOptions(const RecordData &Record, bool Complain, + ASTReaderListener &Listener); + static bool ParseHeaderSearchOptions(const RecordData &Record, bool Complain, + ASTReaderListener &Listener); + static bool ParsePreprocessorOptions(const RecordData &Record, bool Complain, + ASTReaderListener &Listener, + std::string &SuggestedPredefines); + struct RecordLocation { RecordLocation(ModuleFile *M, uint64_t O) : F(M), Offset(O) {} @@ -836,18 +953,82 @@ private: /// \brief Find the next module that contains entities and return the ID /// of the first entry. - /// \arg SLocMapI points at a chunk of a module that contains no + /// + /// \param SLocMapI points at a chunk of a module that contains no /// preprocessed entities or the entities it contains are not the /// ones we are looking for. serialization::PreprocessedEntityID findNextPreprocessedEntity( GlobalSLocOffsetMapType::const_iterator SLocMapI) const; - /// \brief Returns (ModuleFile, Local index) pair for \arg GlobalIndex of a + /// \brief Returns (ModuleFile, Local index) pair for \p GlobalIndex of a /// preprocessed entity. std::pair getModulePreprocessedEntity(unsigned GlobalIndex); + /// \brief Returns (begin, end) pair for the preprocessed entities of a + /// particular module. + std::pair + getModulePreprocessedEntities(ModuleFile &Mod) const; + + class ModuleDeclIterator { + ASTReader *Reader; + ModuleFile *Mod; + const serialization::LocalDeclID *Pos; + + public: + typedef const Decl *value_type; + typedef value_type& reference; + typedef value_type* pointer; + + ModuleDeclIterator() : Reader(0), Mod(0), Pos(0) { } + + ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod, + const serialization::LocalDeclID *Pos) + : Reader(Reader), Mod(Mod), Pos(Pos) { } + + value_type operator*() const { + return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, *Pos)); + } + + ModuleDeclIterator &operator++() { + ++Pos; + return *this; + } + + ModuleDeclIterator operator++(int) { + ModuleDeclIterator Prev(*this); + ++Pos; + return Prev; + } + + ModuleDeclIterator &operator--() { + --Pos; + return *this; + } + + ModuleDeclIterator operator--(int) { + ModuleDeclIterator Prev(*this); + --Pos; + return Prev; + } + + friend bool operator==(const ModuleDeclIterator &LHS, + const ModuleDeclIterator &RHS) { + assert(LHS.Reader == RHS.Reader && LHS.Mod == RHS.Mod); + return LHS.Pos == RHS.Pos; + } + + friend bool operator!=(const ModuleDeclIterator &LHS, + const ModuleDeclIterator &RHS) { + assert(LHS.Reader == RHS.Reader && LHS.Mod == RHS.Mod); + return LHS.Pos != RHS.Pos; + } + }; + + std::pair + getModuleFileLevelDecls(ModuleFile &Mod); + void PassInterestingDeclsToConsumer(); void PassInterestingDeclToConsumer(Decl *D); @@ -861,8 +1042,8 @@ private: void Error(unsigned DiagID, StringRef Arg1 = StringRef(), StringRef Arg2 = StringRef()); - ASTReader(const ASTReader&); // do not implement - ASTReader &operator=(const ASTReader &); // do not implement + ASTReader(const ASTReader &) LLVM_DELETED_FUNCTION; + void operator=(const ASTReader &) LLVM_DELETED_FUNCTION; public: /// \brief Load the AST file and validate its contents against the given /// Preprocessor. @@ -881,29 +1062,49 @@ public: /// of its regular consistency checking, allowing the use of precompiled /// headers that cannot be determined to be compatible. /// - /// \param DisableStatCache If true, the AST reader will ignore the - /// stat cache in the AST files. This performance pessimization can - /// help when an AST file is being used in cases where the - /// underlying files in the file system may have changed, but - /// parsing should still continue. - /// /// \param AllowASTWithCompilerErrors If true, the AST reader will accept an /// AST file the was created out of an AST with compiler errors, /// otherwise it will reject it. ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", - bool DisableValidation = false, bool DisableStatCache = false, + bool DisableValidation = false, bool AllowASTWithCompilerErrors = false); ~ASTReader(); SourceManager &getSourceManager() const { return SourceMgr; } - /// \brief Load the AST file designated by the given file name. - ASTReadResult ReadAST(const std::string &FileName, ModuleKind Type); + /// \brief Flags that indicate what kind of AST loading failures the client + /// of the AST reader can directly handle. + /// + /// When a client states that it can handle a particular kind of failure, + /// the AST reader will not emit errors when producing that kind of failure. + enum LoadFailureCapabilities { + /// \brief The client can't handle any AST loading failures. + ARR_None = 0, + /// \brief The client can handle an AST file that cannot load because it + /// is out-of-date relative to its input files. + ARR_OutOfDate = 0x1, + /// \brief The client can handle an AST file that cannot load because it + /// was built with a different version of Clang. + ARR_VersionMismatch = 0x2, + /// \brief The client can handle an AST file that cannot load because it's + /// compiled configuration doesn't match that of the context it was + /// loaded into. + ARR_ConfigurationMismatch = 0x4 + }; - /// \brief Checks that no file that is stored in PCH is out-of-sync with - /// the actual file in the file system. - ASTReadResult validateFileEntries(ModuleFile &M); + /// \brief Load the AST file designated by the given file name. + /// + /// \param FileName The name of the AST file to load. + /// + /// \param Type The kind of AST being loaded, e.g., PCH, module, main file, + /// or preamble. + /// + /// \param ClientLoadCapabilities The set of client load-failure + /// capabilities, represented as a bitset of the enumerators of + /// LoadFailureCapabilities. + ASTReadResult ReadAST(const std::string &FileName, ModuleKind Type, + unsigned ClientLoadCapabilities); /// \brief Make the entities in the given module and any of its (non-explicit) /// submodules visible to name lookup. @@ -947,8 +1148,11 @@ public: /// \brief Retrieve the preprocessor. Preprocessor &getPreprocessor() const { return PP; } - /// \brief Retrieve the name of the original source file name - const std::string &getOriginalSourceFile() { return OriginalFileName; } + /// \brief Retrieve the name of the original source file name for the primary + /// module file. + StringRef getOriginalSourceFile() { + return ModuleMgr.getPrimaryModule().OriginalSourceFileName; + } /// \brief Retrieve the name of the original source file name directly from /// the AST file, without actually loading the AST file. @@ -956,6 +1160,21 @@ public: FileManager &FileMgr, DiagnosticsEngine &Diags); + /// \brief Read the control block for the named AST file. + /// + /// \returns true if an error occurred, false otherwise. + static bool readASTFileControlBlock(StringRef Filename, + FileManager &FileMgr, + ASTReaderListener &Listener); + + /// \brief Determine whether the given AST file is acceptable to load into a + /// translation unit with the given language and target options. + static bool isAcceptableASTFile(StringRef Filename, + FileManager &FileMgr, + const LangOptions &LangOpts, + const TargetOptions &TargetOpts, + const PreprocessorOptions &PPOpts); + /// \brief Returns the suggested contents of the predefines buffer, /// which contains a (typically-empty) subset of the predefines /// build prior to including the precompiled header. @@ -968,12 +1187,12 @@ public: virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index); /// \brief Returns a pair of [Begin, End) indices of preallocated - /// preprocessed entities that \arg Range encompasses. + /// preprocessed entities that \p Range encompasses. virtual std::pair findPreprocessedEntitiesInRange(SourceRange Range); /// \brief Optionally returns true or false if the preallocated preprocessed - /// entity with index \arg Index came from file \arg FID. + /// entity with index \p Index came from file \p FID. virtual llvm::Optional isPreprocessedEntityInFileID(unsigned Index, FileID FID); @@ -992,6 +1211,11 @@ public: return static_cast(IdentifiersLoaded.size()); } + /// \brief Returns the number of macros found in the chain. + unsigned getTotalNumMacros() const { + return static_cast(MacrosLoaded.size()); + } + /// \brief Returns the number of types found in the chain. unsigned getTotalNumTypes() const { return static_cast(TypesLoaded.size()); @@ -1065,17 +1289,17 @@ public: /// \brief Map from a local declaration ID within a given module to a /// global declaration ID. - serialization::DeclID getGlobalDeclID(ModuleFile &F, unsigned LocalID) const; + serialization::DeclID getGlobalDeclID(ModuleFile &F, + serialization::LocalDeclID LocalID) const; - /// \brief Returns true if global DeclID \arg ID originated from module - /// \arg M. + /// \brief Returns true if global DeclID \p ID originated from module \p M. bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const; /// \brief Retrieve the module file that owns the given declaration, or NULL /// if the declaration is not from a module file. ModuleFile *getOwningModuleFile(Decl *D); - /// \brief Returns the source location for the decl \arg ID. + /// \brief Returns the source location for the decl \p ID. SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID); /// \brief Resolve a declaration ID into a declaration, potentially @@ -1172,7 +1396,7 @@ public: SmallVectorImpl &Decls); /// \brief Get the decls that are contained in a file in the Offset/Length - /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of + /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, SmallVectorImpl &Decls); @@ -1285,6 +1509,9 @@ public: } virtual IdentifierInfo *GetIdentifier(serialization::IdentifierID ID) { + // Note that we are loading an identifier. + Deserializing AnIdentifier(this); + return DecodeIdentifierInfo(ID); } @@ -1293,6 +1520,13 @@ public: serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M, unsigned LocalID); + /// \brief Retrieve the macro with the given ID. + MacroInfo *getMacro(serialization::MacroID ID, MacroInfo *Hint = 0); + + /// \brief Retrieve the global macro ID corresponding to the given local + /// ID within the given module file. + serialization::MacroID getGlobalMacroID(ModuleFile &M, unsigned LocalID); + /// \brief Read the source location entry with index ID. virtual bool ReadSLocEntry(int ID); @@ -1404,10 +1638,10 @@ public: llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx); // \brief Read a string - std::string ReadString(const RecordData &Record, unsigned &Idx); + static std::string ReadString(const RecordData &Record, unsigned &Idx); /// \brief Read a version tuple. - VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); + static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record, unsigned &Idx); @@ -1436,43 +1670,29 @@ public: Expr *ReadSubExpr(); /// \brief Reads the macro record located at the given offset. - void ReadMacroRecord(ModuleFile &F, uint64_t Offset); + void ReadMacroRecord(ModuleFile &F, uint64_t Offset, MacroInfo *Hint = 0); /// \brief Determine the global preprocessed entity ID that corresponds to /// the given local ID within the given module. serialization::PreprocessedEntityID getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const; - /// \brief Note that the identifier is a macro whose record will be loaded - /// from the given AST file at the given (file-local) offset. + /// \brief Note that the identifier has a macro history. /// /// \param II The name of the macro. /// - /// \param F The module file from which the macro definition was deserialized. - /// - /// \param Offset The offset into the module file at which the macro - /// definition is located. - /// - /// \param Visible Whether the macro should be made visible. - void setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F, - uint64_t Offset, bool Visible); + /// \param IDs The global macro IDs that are associated with this identifier. + void setIdentifierIsMacro(IdentifierInfo *II, + ArrayRef IDs); /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros(); - /// \brief Read the macro definition for this identifier. - virtual void LoadMacroDefinition(IdentifierInfo *II); - /// \brief Update an out-of-date identifier. virtual void updateOutOfDateIdentifier(IdentifierInfo &II); /// \brief Note that this identifier is up-to-date. void markIdentifierUpToDate(IdentifierInfo *II); - - /// \brief Read the macro definition corresponding to this iterator - /// into the unread macro record offsets table. - void LoadMacroDefinition( - llvm::DenseMap::iterator Pos); /// \brief Load all external visible decls in the given DeclContext. void completeVisibleDeclsMap(const DeclContext *DC); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index d038d58aed8b..ac81e2164c57 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/Lex/PPMutationListener.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" #include "clang/Sema/SemaConsumer.h" @@ -25,6 +26,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/Bitcode/BitstreamWriter.h" #include @@ -43,14 +45,15 @@ class ASTContext; class NestedNameSpecifier; class CXXBaseSpecifier; class CXXCtorInitializer; +class FileEntry; class FPOptions; class HeaderSearch; class IdentifierResolver; class MacroDefinition; -class MemorizeStatCalls; class OpaqueValueExpr; class OpenCLOptions; class ASTReader; +class MacroInfo; class Module; class PreprocessedEntity; class PreprocessingRecord; @@ -70,6 +73,7 @@ namespace SrcMgr { class SLocEntry; } /// data structures. This bitstream can be de-serialized via an /// instance of the ASTReader class. class ASTWriter : public ASTDeserializationListener, + public PPMutationListener, public ASTMutationListener { public: typedef SmallVector RecordData; @@ -117,6 +121,10 @@ private: /// \brief Indicates that the AST contained compiler errors. bool ASTHasCompilerErrors; + /// \brief Mapping from input file entries to the index into the + /// offset table where information about that input file is stored. + llvm::DenseMap InputFileIDs; + /// \brief Stores a declaration or a type to be written to the AST file. class DeclOrType { public: @@ -171,8 +179,7 @@ private: /// indicates the index that this particular vector has in the global one. unsigned FirstDeclIndex; }; - typedef llvm::DenseMap FileDeclIDsTy; + typedef llvm::DenseMap FileDeclIDsTy; /// \brief Map from file SLocEntries to info about the file-level declarations /// that it contains. @@ -215,6 +222,15 @@ private: /// IdentifierInfo. llvm::DenseMap IdentifierIDs; + /// \brief The first ID number we can use for our own macros. + serialization::MacroID FirstMacroID; + + /// \brief The identifier ID that will be assigned to the next new identifier. + serialization::MacroID NextMacroID; + + /// \brief Map that provides the ID numbers of each macro. + llvm::DenseMap MacroIDs; + /// @name FlushStmt Caches /// @{ @@ -250,16 +266,10 @@ private: /// table, indexed by the Selector ID (-1). std::vector SelectorOffsets; - /// \brief Offsets of each of the macro identifiers into the - /// bitstream. - /// - /// For each identifier that is associated with a macro, this map - /// provides the offset into the bitstream where that macro is - /// defined. - llvm::DenseMap MacroOffsets; + typedef llvm::MapVector MacroUpdatesMap; - /// \brief The set of identifiers that had macro definitions at some point. - std::vector DeserializedMacroNames; + /// \brief Updates to macro definitions that were loaded from an AST file. + MacroUpdatesMap MacroUpdates; /// \brief Mapping from macro definitions (as they occur in the preprocessing /// record) to the macro IDs. @@ -403,10 +413,9 @@ private: llvm::DenseSet &ParentStmts); void WriteBlockInfoBlock(); - void WriteMetadata(ASTContext &Context, StringRef isysroot, - const std::string &OutputFile); - void WriteLanguageOptions(const LangOptions &LangOpts); - void WriteStatCache(MemorizeStatCalls &StatCalls); + void WriteControlBlock(Preprocessor &PP, ASTContext &Context, + StringRef isysroot, const std::string &OutputFile); + void WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP, StringRef isysroot); @@ -428,6 +437,7 @@ private: void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); void WriteAttributes(ArrayRef Attrs, RecordDataImpl &Record); + void WriteMacroUpdates(); void ResolveDeclUpdatesBlocks(); void WriteDeclUpdatesBlocks(); void WriteDeclReplacementsBlock(); @@ -455,7 +465,7 @@ private: void WriteDeclsBlockAbbrevs(); void WriteDecl(ASTContext &Context, Decl *D); - void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, + void WriteASTCore(Sema &SemaRef, StringRef isysroot, const std::string &OutputFile, Module *WritingModule); @@ -470,15 +480,12 @@ public: /// \param SemaRef a reference to the semantic analysis object that processed /// the AST to be written into the precompiled header. /// - /// \param StatCalls the object that cached all of the stat() calls made while - /// searching for source files and headers. - /// /// \param WritingModule The module that we are writing. If null, we are /// writing a precompiled header. /// /// \param isysroot if non-empty, write a relocatable file whose headers /// are relative to the given system root. - void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, + void WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors = false); @@ -501,6 +508,9 @@ public: /// \brief Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record); + /// \brief Emit a reference to a macro. + void addMacroRef(MacroInfo *MI, RecordDataImpl &Record); + /// \brief Emit a Selector (which is a smart pointer reference). void AddSelectorRef(Selector, RecordDataImpl &Record); @@ -518,15 +528,8 @@ public: /// \brief Get the unique number used to refer to the given identifier. serialization::IdentID getIdentifierRef(const IdentifierInfo *II); - /// \brief Retrieve the offset of the macro definition for the given - /// identifier. - /// - /// The identifier must refer to a macro. - uint64_t getMacroOffset(const IdentifierInfo *II) { - assert(MacroOffsets.find(II) != MacroOffsets.end() && - "Identifier does not name a macro"); - return MacroOffsets[II]; - } + /// \brief Get the unique number used to refer to the given macro. + serialization::MacroID getMacroRef(MacroInfo *MI); /// \brief Emit a reference to a type. void AddTypeRef(QualType T, RecordDataImpl &Record); @@ -689,13 +692,16 @@ public: // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader); void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II); + void MacroRead(serialization::MacroID ID, MacroInfo *MI); void TypeRead(serialization::TypeIdx Idx, QualType T); void SelectorRead(serialization::SelectorID ID, Selector Sel); void MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinition *MD); - void MacroVisible(IdentifierInfo *II); void ModuleRead(serialization::SubmoduleID ID, Module *Mod); - + + // PPMutationListener implementation. + virtual void UndefinedMacro(MacroInfo *MI); + // ASTMutationListener implementation. virtual void CompletedTagDefinition(const TagDecl *D); virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D); @@ -722,7 +728,6 @@ class PCHGenerator : public SemaConsumer { std::string isysroot; raw_ostream *Out; Sema *SemaPtr; - MemorizeStatCalls *StatCalls; // owned by the FileManager llvm::SmallVector Buffer; llvm::BitstreamWriter Stream; ASTWriter Writer; @@ -738,6 +743,7 @@ public: ~PCHGenerator(); virtual void InitializeSema(Sema &S) { SemaPtr = &S; } virtual void HandleTranslationUnit(ASTContext &Ctx); + virtual PPMutationListener *GetPPMutationListener(); virtual ASTMutationListener *GetASTMutationListener(); virtual ASTDeserializationListener *GetASTDeserializationListener(); }; diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h index f368a80a97d8..d89cd02903d6 100644 --- a/include/clang/Serialization/ContinuousRangeMap.h +++ b/include/clang/Serialization/ContinuousRangeMap.h @@ -108,8 +108,8 @@ public: class Builder { ContinuousRangeMap &Self; - Builder(const Builder&); // DO NOT IMPLEMENT - Builder &operator=(const Builder&); // DO NOT IMPLEMENT + Builder(const Builder&) LLVM_DELETED_FUNCTION; + Builder &operator=(const Builder&) LLVM_DELETED_FUNCTION; public: explicit Builder(ContinuousRangeMap &Self) : Self(Self) { } diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 786ecd33c1d3..39fa3d90ced4 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -25,6 +25,7 @@ namespace clang { +class FileEntry; class DeclContext; class Module; template class OnDiskChainedHashTable; @@ -74,6 +75,29 @@ public: /// \brief The file name of the module file. std::string FileName; + /// \brief The original source file name that was used to build the + /// primary AST file, which may have been modified for + /// relocatable-pch support. + std::string OriginalSourceFileName; + + /// \brief The actual original source file name that was used to + /// build this AST file. + std::string ActualOriginalSourceFileName; + + /// \brief The file ID for the original source file that was used to + /// build this AST file. + FileID OriginalSourceFileID; + + /// \brief The directory that the PCH was originally created in. Used to + /// allow resolving headers even after headers+PCH was moved to a new path. + std::string OriginalDir; + + /// \brief Whether this precompiled header is a relocatable PCH file. + bool RelocatablePCH; + + /// \brief The file entry for the module file. + const FileEntry *File; + /// \brief Whether this module has been directly imported by the /// user. bool DirectlyImported; @@ -98,11 +122,24 @@ public: llvm::BitstreamCursor Stream; /// \brief The source location where this module was first imported. + /// FIXME: This is not properly initialized yet. SourceLocation ImportLoc; /// \brief The first source location in this module. SourceLocation FirstLoc; + // === Input Files === + /// \brief The cursor to the start of the input-files block. + llvm::BitstreamCursor InputFilesCursor; + + /// \brief Offsets for all of the input file entries in the AST file. + const uint32_t *InputFileOffsets; + + /// \brief The input files that have been loaded from this AST file, along + /// with a bool indicating whether this was an overridden buffer. + std::vector > + InputFilesLoaded; + // === Source Locations === /// \brief Cursor used to read source location entries. @@ -124,13 +161,6 @@ public: /// \brief SLocEntries that we're going to preload. SmallVector PreloadSLocEntries; - /// \brief The number of source location file entries in this AST file. - unsigned LocalNumSLocFileEntries; - - /// \brief Offsets for all of the source location file entries in the - /// AST file. - const uint32_t *SLocFileOffsets; - /// \brief Remapping table for source locations in this module. ContinuousRangeMap SLocRemap; @@ -168,6 +198,22 @@ public: /// all of the macro definitions. llvm::BitstreamCursor MacroCursor; + /// \brief The number of macros in this AST file. + unsigned LocalNumMacros; + + /// \brief Offsets of macros in the preprocessor block. + /// + /// This array is indexed by the macro ID (-1), and provides + /// the offset into the preprocessor block where macro definitions are + /// stored. + const uint32_t *MacroOffsets; + + /// \brief Base macro ID for macros local to this module. + serialization::MacroID BaseMacroID; + + /// \brief Remapping table for macro IDs in this module. + ContinuousRangeMap MacroRemap; + /// \brief The offset of the start of the set of defined macros. uint64_t MacroStartOffset; @@ -294,6 +340,7 @@ public: /// \brief Array of file-level DeclIDs sorted by file. const serialization::DeclID *FileSortedDecls; + unsigned NumFileSortedDecls; /// \brief Array of redeclaration chain location information within this /// module file, sorted by the first declaration ID. @@ -338,11 +385,6 @@ public: /// \brief Diagnostic IDs and their mappings that the user changed. SmallVector PragmaDiagMappings; - /// \brief The AST stat cache installed for this file, if any. - /// - /// The dynamic type of this stat cache is always ASTStatCache - void *StatCache; - /// \brief List of modules which depend on this module llvm::SetVector ImportedBy; diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index 6ff0640b64d1..6dcaa210d2d8 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -34,7 +34,7 @@ class ModuleManager { /// \brief FileManager that handles translating between filenames and /// FileEntry *. - FileManager FileMgr; + FileManager &FileMgr; /// \brief A lookup of in-memory (virtual file) buffers llvm::DenseMap InMemoryBuffers; @@ -45,7 +45,7 @@ public: typedef SmallVector::reverse_iterator ModuleReverseIterator; typedef std::pair ModuleOffset; - ModuleManager(const FileSystemOptions &FSO); + explicit ModuleManager(FileManager &FileMgr); ~ModuleManager(); /// \brief Forward iterator to traverse all loaded modules. This is reverse @@ -105,7 +105,10 @@ public: std::pair addModule(StringRef FileName, ModuleKind Type, ModuleFile *ImportedBy, unsigned Generation, std::string &ErrorStr); - + + /// \brief Remove the given set of modules. + void removeModules(ModuleIterator first, ModuleIterator last); + /// \brief Add an in-memory buffer the list of known buffers void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer); diff --git a/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h b/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h deleted file mode 100644 index f9cce9ca9c62..000000000000 --- a/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h +++ /dev/null @@ -1,35 +0,0 @@ -//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This defines NullDerefChecker and UndefDerefChecker, two builtin checks -// in ExprEngine that check for null and undefined pointers at loads -// and stores. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_DEREFCHECKER -#define LLVM_CLANG_GR_DEREFCHECKER - -#include - -namespace clang { - -namespace ento { - -class ExprEngine; -class ExplodedNode; - -std::pair -GetImplicitNullDereferences(ExprEngine &Eng); - -} // end GR namespace - -} // end clang namespace - -#endif diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def new file mode 100644 index 000000000000..01a6ffd7142c --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/Analyses.def @@ -0,0 +1,67 @@ +//===-- Analyses.def - Metadata about Static Analyses -----------*- 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 set of static analyses used by AnalysisConsumer. +// +//===----------------------------------------------------------------------===// + +#ifndef ANALYSIS_STORE +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) +#endif + +ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager) + +#ifndef ANALYSIS_CONSTRAINTS +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) +#endif + +ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager) + +#ifndef ANALYSIS_DIAGNOSTICS +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) +#endif + +ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer, false) +ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer, true) +ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer, true) +ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true) +ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true) + +#ifndef ANALYSIS_PURGE +#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraints before every statement") +ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block") +ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints") + +#ifndef ANALYSIS_IPA +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_IPA(None, "none", "Perform only intra-procedural analysis") +ANALYSIS_IPA(BasicInlining, "basic-inlining", "Inline C functions and blocks when their definitions are available") +ANALYSIS_IPA(Inlining, "inlining", "Inline callees when their definitions are available") +ANALYSIS_IPA(DynamicDispatch, "dynamic", "Experimental: Enable inlining of dynamically dispatched methods") +ANALYSIS_IPA(DynamicDispatchBifurcate, "dynamic-bifurcate", "Experimental: Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailable") + +#ifndef ANALYSIS_INLINING_MODE +#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions in the order defined in the TU") +ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined, use call graph to order") + +#undef ANALYSIS_STORE +#undef ANALYSIS_CONSTRAINTS +#undef ANALYSIS_DIAGNOSTICS +#undef ANALYSIS_PURGE +#undef ANALYSIS_INLINING_MODE +#undef ANALYSIS_IPA + diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h new file mode 100644 index 000000000000..fa0754acb150 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -0,0 +1,308 @@ +//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines various options for the static analyzer that are set +// by the frontend and are consulted throughout the analyzer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYZEROPTIONS_H +#define LLVM_CLANG_ANALYZEROPTIONS_H + +#include +#include +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringMap.h" + +namespace clang { +class ASTConsumer; +class DiagnosticsEngine; +class Preprocessor; +class LangOptions; + +/// Analysis - Set of available source code analyses. +enum Analyses { +#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME, +#include "clang/StaticAnalyzer/Core/Analyses.def" +NumAnalyses +}; + +/// AnalysisStores - Set of available analysis store models. +enum AnalysisStores { +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, +#include "clang/StaticAnalyzer/Core/Analyses.def" +NumStores +}; + +/// AnalysisConstraints - Set of available constraint models. +enum AnalysisConstraints { +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, +#include "clang/StaticAnalyzer/Core/Analyses.def" +NumConstraints +}; + +/// AnalysisDiagClients - Set of available diagnostic clients for rendering +/// analysis results. +enum AnalysisDiagClients { +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME, +#include "clang/StaticAnalyzer/Core/Analyses.def" +NUM_ANALYSIS_DIAG_CLIENTS +}; + +/// AnalysisPurgeModes - Set of available strategies for dead symbol removal. +enum AnalysisPurgeMode { +#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME, +#include "clang/StaticAnalyzer/Core/Analyses.def" +NumPurgeModes +}; + +/// AnalysisIPAMode - Set of inter-procedural modes. +enum AnalysisIPAMode { +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) NAME, +#include "clang/StaticAnalyzer/Core/Analyses.def" +NumIPAModes +}; + +/// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. +enum AnalysisInliningMode { +#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, +#include "clang/StaticAnalyzer/Core/Analyses.def" +NumInliningModes +}; + +/// \brief Describes the different kinds of C++ member functions which can be +/// considered for inlining by the analyzer. +/// +/// These options are cumulative; enabling one kind of member function will +/// enable all kinds with lower enum values. +enum CXXInlineableMemberKind { + // Uninitialized = 0, + + /// A dummy mode in which no C++ inlining is enabled. + CIMK_None = 1, + + /// Refers to regular member function and operator calls. + CIMK_MemberFunctions, + + /// Refers to constructors (implicit or explicit). + /// + /// Note that a constructor will not be inlined if the corresponding + /// destructor is non-trivial. + CIMK_Constructors, + + /// Refers to destructors (implicit or explicit). + CIMK_Destructors +}; + + +class AnalyzerOptions : public llvm::RefCountedBase { +public: + typedef llvm::StringMap ConfigTable; + + /// \brief Pair of checker name and enable/disable. + std::vector > CheckersControlList; + + /// \brief A key-value table of use-specified configuration values. + ConfigTable Config; + AnalysisStores AnalysisStoreOpt; + AnalysisConstraints AnalysisConstraintsOpt; + AnalysisDiagClients AnalysisDiagOpt; + AnalysisPurgeMode AnalysisPurgeOpt; + + // \brief The interprocedural analysis mode. + AnalysisIPAMode IPAMode; + + std::string AnalyzeSpecificFunction; + + /// \brief The maximum number of exploded nodes the analyzer will generate. + unsigned MaxNodes; + + /// \brief The maximum number of times the analyzer visits a block. + unsigned maxBlockVisitOnPath; + + + unsigned ShowCheckerHelp : 1; + unsigned AnalyzeAll : 1; + unsigned AnalyzerDisplayProgress : 1; + unsigned AnalyzeNestedBlocks : 1; + + /// \brief The flag regulates if we should eagerly assume evaluations of + /// conditionals, thus, bifurcating the path. + /// + /// This flag indicates how the engine should handle expressions such as: 'x = + /// (y != 0)'. When this flag is true then the subexpression 'y != 0' will be + /// eagerly assumed to be true or false, thus evaluating it to the integers 0 + /// or 1 respectively. The upside is that this can increase analysis + /// precision until we have a better way to lazily evaluate such logic. The + /// downside is that it eagerly bifurcates paths. + unsigned eagerlyAssumeBinOpBifurcation : 1; + + unsigned TrimGraph : 1; + unsigned visualizeExplodedGraphWithGraphViz : 1; + unsigned visualizeExplodedGraphWithUbiGraph : 1; + unsigned UnoptimizedCFG : 1; + unsigned PrintStats : 1; + + /// \brief Do not re-analyze paths leading to exhausted nodes with a different + /// strategy. We get better code coverage when retry is enabled. + unsigned NoRetryExhausted : 1; + + /// \brief The inlining stack depth limit. + unsigned InlineMaxStackDepth; + + /// \brief The mode of function selection used during inlining. + unsigned InlineMaxFunctionSize; + + /// \brief The mode of function selection used during inlining. + AnalysisInliningMode InliningMode; + +private: + /// Controls which C++ member functions will be considered for inlining. + CXXInlineableMemberKind CXXMemberInliningMode; + + /// \sa includeTemporaryDtorsInCFG + llvm::Optional IncludeTemporaryDtorsInCFG; + + /// \sa mayInlineCXXStandardLibrary + llvm::Optional InlineCXXStandardLibrary; + + /// \sa mayInlineTemplateFunctions + llvm::Optional InlineTemplateFunctions; + + /// \sa mayInlineObjCMethod + llvm::Optional ObjCInliningMode; + + // Cache of the "ipa-always-inline-size" setting. + // \sa getAlwaysInlineSize + llvm::Optional AlwaysInlineSize; + + /// \sa shouldPruneNullReturnPaths + llvm::Optional PruneNullReturnPaths; + + /// \sa shouldAvoidSuppressingNullArgumentPaths + llvm::Optional AvoidSuppressingNullArgumentPaths; + + /// \sa getGraphTrimInterval + llvm::Optional GraphTrimInterval; + + /// Interprets an option's string value as a boolean. + /// + /// Accepts the strings "true" and "false". + /// If an option value is not provided, returns the given \p DefaultVal. + bool getBooleanOption(StringRef Name, bool DefaultVal); + + /// Variant that accepts a Optional value to cache the result. + bool getBooleanOption(llvm::Optional &V, StringRef Name, + bool DefaultVal); + + /// Interprets an option's string value as an integer value. + int getOptionAsInteger(llvm::StringRef Name, int DefaultVal); + +public: + /// Returns the option controlling which C++ member functions will be + /// considered for inlining. + /// + /// This is controlled by the 'c++-inlining' config option. + /// + /// \sa CXXMemberInliningMode + bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K); + + /// Returns true if ObjectiveC inlining is enabled, false otherwise. + bool mayInlineObjCMethod(); + + /// Returns whether or not the destructors for C++ temporary objects should + /// be included in the CFG. + /// + /// This is controlled by the 'cfg-temporary-dtors' config option, which + /// accepts the values "true" and "false". + bool includeTemporaryDtorsInCFG(); + + /// Returns whether or not C++ standard library functions may be considered + /// for inlining. + /// + /// This is controlled by the 'c++-stdlib-inlining' config option, which + /// accepts the values "true" and "false". + bool mayInlineCXXStandardLibrary(); + + /// Returns whether or not templated functions may be considered for inlining. + /// + /// This is controlled by the 'c++-template-inlining' config option, which + /// accepts the values "true" and "false". + bool mayInlineTemplateFunctions(); + + /// Returns whether or not paths that go through null returns should be + /// suppressed. + /// + /// This is a heuristic for avoiding bug reports with paths that go through + /// inlined functions that are more defensive than their callers. + /// + /// This is controlled by the 'suppress-null-return-paths' config option, + /// which accepts the values "true" and "false". + bool shouldPruneNullReturnPaths(); + + /// Returns whether a bug report should \em not be suppressed if its path + /// includes a call with a null argument, even if that call has a null return. + /// + /// This option has no effect when #shouldPruneNullReturnPaths() is false. + /// + /// This is a counter-heuristic to avoid false negatives. + /// + /// This is controlled by the 'avoid-suppressing-null-argument-paths' config + /// option, which accepts the values "true" and "false". + bool shouldAvoidSuppressingNullArgumentPaths(); + + // Returns the size of the functions (in basic blocks), which should be + // considered to be small enough to always inline. + // + // This is controlled by "ipa-always-inline-size" analyzer-config option. + unsigned getAlwaysInlineSize(); + + /// Returns true if the analyzer engine should synthesize fake bodies + /// for well-known functions. + bool shouldSynthesizeBodies(); + + /// Returns how often nodes in the ExplodedGraph should be recycled to save + /// memory. + /// + /// This is controlled by the 'graph-trim-interval' config option. To disable + /// node reclamation, set the option to "0". + unsigned getGraphTrimInterval(); + +public: + AnalyzerOptions() : CXXMemberInliningMode() { + AnalysisStoreOpt = RegionStoreModel; + AnalysisConstraintsOpt = RangeConstraintsModel; + AnalysisDiagOpt = PD_HTML; + AnalysisPurgeOpt = PurgeStmt; + IPAMode = DynamicDispatchBifurcate; + ShowCheckerHelp = 0; + AnalyzeAll = 0; + AnalyzerDisplayProgress = 0; + AnalyzeNestedBlocks = 0; + eagerlyAssumeBinOpBifurcation = 0; + TrimGraph = 0; + visualizeExplodedGraphWithGraphViz = 0; + visualizeExplodedGraphWithUbiGraph = 0; + UnoptimizedCFG = 0; + PrintStats = 0; + NoRetryExhausted = 0; + // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). + InlineMaxStackDepth = 5; + InlineMaxFunctionSize = 200; + InliningMode = NoRedundancy; + } +}; + +typedef llvm::IntrusiveRefCntPtr AnalyzerOptionsRef; + +} + +#endif diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 48393a379b39..b5a88ba9f6c6 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -24,6 +24,7 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/ImmutableSet.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallSet.h" namespace clang { @@ -95,6 +96,10 @@ protected: /// for multiple PathDiagnosticConsumers. llvm::SmallVector interestingRegions; + /// A set of location contexts that correspoind to call sites which should be + /// considered "interesting". + llvm::SmallSet InterestingLocationContexts; + /// A set of custom visitors which generate "event" diagnostics at /// interesting points in the path. VisitorList Callbacks; @@ -111,6 +116,19 @@ protected: /// when reporting an issue. bool DoNotPrunePath; + /// Used to track unique reasons why a bug report might be invalid. + /// + /// \sa markInvalid + /// \sa removeInvalidation + typedef std::pair InvalidationRecord; + + /// If non-empty, this bug report is likely a false positive and should not be + /// shown to the user. + /// + /// \sa markInvalid + /// \sa removeInvalidation + llvm::SmallSet Invalidations; + private: // Used internally by BugReporter. Symbols &getInterestingSymbols(); @@ -147,7 +165,8 @@ public: PathDiagnosticLocation LocationToUnique) : BT(bt), DeclWithIssue(0), Description(desc), UniqueingLocation(LocationToUnique), - ErrorNode(errornode), ConfigurationChangeToken(0) {} + ErrorNode(errornode), ConfigurationChangeToken(0), + DoNotPrunePath(false) {} virtual ~BugReport(); @@ -158,8 +177,10 @@ public: const StringRef getDescription() const { return Description; } - const StringRef getShortDescription() const { - return ShortDescription.empty() ? Description : ShortDescription; + const StringRef getShortDescription(bool UseFallback = true) const { + if (ShortDescription.empty() && UseFallback) + return Description; + return ShortDescription; } /// Indicates whether or not any path pruning should take place @@ -172,14 +193,44 @@ public: void markInteresting(SymbolRef sym); void markInteresting(const MemRegion *R); void markInteresting(SVal V); + void markInteresting(const LocationContext *LC); bool isInteresting(SymbolRef sym); bool isInteresting(const MemRegion *R); bool isInteresting(SVal V); + bool isInteresting(const LocationContext *LC); unsigned getConfigurationChangeToken() const { return ConfigurationChangeToken; } + + /// Returns whether or not this report should be considered valid. + /// + /// Invalid reports are those that have been classified as likely false + /// positives after the fact. + bool isValid() const { + return Invalidations.empty(); + } + + /// Marks the current report as invalid, meaning that it is probably a false + /// positive and should not be reported to the user. + /// + /// The \p Tag and \p Data arguments are intended to be opaque identifiers for + /// this particular invalidation, where \p Tag represents the visitor + /// responsible for invalidation, and \p Data represents the reason this + /// visitor decided to invalidate the bug report. + /// + /// \sa removeInvalidation + void markInvalid(const void *Tag, const void *Data) { + Invalidations.insert(std::make_pair(Tag, Data)); + } + + /// Reverses the effects of a previous invalidation. + /// + /// \sa markInvalid + void removeInvalidation(const void *Tag, const void *Data) { + Invalidations.erase(std::make_pair(Tag, Data)); + } /// Return the canonical declaration, be it a method or class, where /// this issue semantically occurred. @@ -342,6 +393,11 @@ private: /// A vector of BugReports for tracking the allocated pointers and cleanup. std::vector EQClassesVector; + /// A map from PathDiagnosticPiece to the LocationContext of the inlined + /// function call it represents. + llvm::DenseMap LocationContextMap; + protected: BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), D(d) {} @@ -378,9 +434,14 @@ public: SourceManager& getSourceManager() { return D.getSourceManager(); } - virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic, + virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, PathDiagnosticConsumer &PC, - ArrayRef &bugReports) {} + ArrayRef &bugReports) { + return true; + } + + bool RemoveUneededCalls(PathPieces &pieces, BugReport *R, + PathDiagnosticCallPiece *CallWithLoc = 0); void Register(BugType *BT); @@ -389,7 +450,7 @@ public: /// The reports are usually generated by the checkers. Further, they are /// folded based on the profile value, which is done to coalesce similar /// reports. - void EmitReport(BugReport *R); + void emitReport(BugReport *R); void EmitBasicReport(const Decl *DeclWithIssue, StringRef BugName, StringRef BugCategory, @@ -409,8 +470,10 @@ public: EmitBasicReport(DeclWithIssue, BugName, Category, BugStr, Loc, &R, 1); } - static bool classof(const BugReporter* R) { return true; } - + void addCallPieceLocationContextPair(const PathDiagnosticCallPiece *C, + const LocationContext *LC) { + LocationContextMap[C] = LC; + } private: llvm::StringMap StrBugTypes; @@ -440,7 +503,15 @@ public: /// engine. ProgramStateManager &getStateManager(); - virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic, + /// Generates a path corresponding to one of the given bug reports. + /// + /// Which report is used for path generation is not specified. The + /// bug reporter will try to pick the shortest path, but this is not + /// guaranteed. + /// + /// \return True if the report was valid and a path was generated, + /// false if the reports should be considered invalid. + virtual bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, ArrayRef &bugReports); diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index f53c15f117c9..78e35ca82b89 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -100,7 +100,6 @@ class FindLastStoreBRVisitor const MemRegion *R; SVal V; bool satisfied; - const ExplodedNode *StoreSite; public: /// \brief Convenience method to create a visitor given only the MemRegion. @@ -114,7 +113,7 @@ public: static void registerStatementVarDecls(BugReport &BR, const Stmt *S); FindLastStoreBRVisitor(SVal v, const MemRegion *r) - : R(r), V(v), satisfied(false), StoreSite(0) { + : R(r), V(v), satisfied(false) { assert (!V.isUnknown() && "Cannot track unknown value."); // TODO: Does it make sense to allow undef values here? @@ -142,6 +141,10 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const; + /// Return the tag associated with this visitor. This tag will be used + /// to make all PathDiagnosticPieces created by this visitor. + static const char *getTag(); + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, @@ -171,6 +174,9 @@ public: ID.AddPointer(&x); } + /// Return the tag associated with this visitor. This tag will be used + /// to make all PathDiagnosticPieces created by this visitor. + static const char *getTag(); virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *Prev, @@ -223,15 +229,57 @@ public: const ExplodedNode *N, llvm::Optional &prunable); }; - + +/// \brief When a region containing undefined value or '0' value is passed +/// as an argument in a call, marks the call as interesting. +/// +/// As a result, BugReporter will not prune the path through the function even +/// if the region's contents are not modified/accessed by the call. +class UndefOrNullArgVisitor + : public BugReporterVisitorImpl { + + /// The interesting memory region this visitor is tracking. + const MemRegion *R; + +public: + UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {} + + virtual void Profile(llvm::FoldingSetNodeID &ID) const { + static int Tag = 0; + ID.AddPointer(&Tag); + ID.AddPointer(R); + } + + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR); +}; + namespace bugreporter { -void addTrackNullOrUndefValueVisitor(const ExplodedNode *N, const Stmt *S, - BugReport *R); +/// Attempts to add visitors to trace a null or undefined value back to its +/// point of origin, whether it is a symbol constrained to null or an explicit +/// assignment. +/// +/// \param N A node "downstream" from the evaluation of the statement. +/// \param S The statement whose value is null or undefined. +/// \param R The bug report to which visitors should be attached. +/// \param IsArg Whether the statement is an argument to an inlined function. +/// If this is the case, \p N \em must be the CallEnter node for +/// the function. +/// +/// \return Whether or not the function was able to add visitors for this +/// statement. Note that returning \c true does not actually imply +/// that any visitors were added. +bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, + bool IsArg = false); const Stmt *GetDerefExpr(const ExplodedNode *N); const Stmt *GetDenomExpr(const ExplodedNode *N); const Stmt *GetRetValExpr(const ExplodedNode *N); +bool isDeclRefExprToReference(const Expr *E); + } // end namespace clang } // end namespace ento diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 973cfb109c05..6dc26e670344 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -52,7 +52,31 @@ class PathDiagnostic; class PathDiagnosticConsumer { public: - typedef std::vector > FilesMade; + class PDFileEntry : public llvm::FoldingSetNode { + public: + PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {} + + typedef std::vector > ConsumerFiles; + + /// \brief A vector of pairs. + ConsumerFiles files; + + /// \brief A precomputed hash tag used for uniquing PDFileEntry objects. + const llvm::FoldingSetNodeID NodeID; + + /// \brief Used for profiling in the FoldingSet. + void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; } + }; + + struct FilesMade : public llvm::FoldingSet { + llvm::BumpPtrAllocator Alloc; + + void addDiagnostic(const PathDiagnostic &PD, + StringRef ConsumerName, + StringRef fileName); + + PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD); + }; private: virtual void anchor(); @@ -73,7 +97,6 @@ public: virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } virtual bool supportsAllBlockEdges() const { return false; } - virtual bool useVerboseDescription() const { return true; } /// Return true if the PathDiagnosticConsumer supports individual /// PathDiagnostics that span multiple files. @@ -114,8 +137,6 @@ private: Kind kind) : K(kind), S(0), D(0), SM(&sm), Loc(genLocation(L)), Range(genRange()) { - assert(Loc.isValid()); - assert(Range.isValid()); } FullSourceLoc @@ -134,12 +155,14 @@ public: PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac) - : K(StmtK), S(s), D(0), SM(&sm), + : K(s->getLocStart().isValid() ? StmtK : SingleLocK), + S(K == StmtK ? s : 0), + D(0), SM(&sm), Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) { - assert(S); - assert(Loc.isValid()); - assert(Range.isValid()); + assert(K == SingleLocK || S); + assert(K == SingleLocK || Loc.isValid()); + assert(K == SingleLocK || Range.isValid()); } /// Create a location corresponding to the given declaration. @@ -297,12 +320,18 @@ private: const std::string str; const Kind kind; const DisplayHint Hint; + + /// A constant string that can be used to tag the PathDiagnosticPiece, + /// typically with the identification of the creator. The actual pointer + /// value is meant to be an identifier; the string itself is useful for + /// debugging. + StringRef Tag; + std::vector ranges; - // Do not implement: - PathDiagnosticPiece(); - PathDiagnosticPiece(const PathDiagnosticPiece &P); - PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P); + PathDiagnosticPiece() LLVM_DELETED_FUNCTION; + PathDiagnosticPiece(const PathDiagnosticPiece &P) LLVM_DELETED_FUNCTION; + void operator=(const PathDiagnosticPiece &P) LLVM_DELETED_FUNCTION; protected: PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below); @@ -312,8 +341,18 @@ protected: public: virtual ~PathDiagnosticPiece(); - const std::string& getString() const { return str; } + llvm::StringRef getString() const { return str; } + /// Tag this PathDiagnosticPiece with the given C-string. + void setTag(const char *tag) { Tag = tag; } + + /// Return the opaque tag (if any) on the PathDiagnosticPiece. + const void *getTag() const { return Tag.data(); } + + /// Return the string representation of the tag. This is useful + /// for debugging. + StringRef getTagStr() const { return Tag; } + /// getDisplayHint - Return a hint indicating where the diagnostic should /// be displayed by the PathDiagnosticConsumer. DisplayHint getDisplayHint() const { return Hint; } @@ -338,10 +377,6 @@ public: /// Return the SourceRanges associated with this PathDiagnosticPiece. ArrayRef getRanges() const { return ranges; } - static inline bool classof(const PathDiagnosticPiece *P) { - return true; - } - virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; @@ -377,6 +412,10 @@ public: virtual void flattenLocations() { Pos.flatten(); } virtual void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const PathDiagnosticPiece *P) { + return P->getKind() == Event || P->getKind() == Macro; + } }; /// \brief Interface for classes constructing Stack hints. @@ -410,10 +449,6 @@ public: /// 'getMessageForX()' methods to construct a specific message. virtual std::string getMessage(const ExplodedNode *N); - /// Prints the ordinal form of the given integer, - /// only valid for ValNo : ValNo > 0. - void printOrdinal(unsigned ValNo, llvm::raw_svector_ostream &Out); - /// Produces the message of the following form: /// 'Msg via Nth parameter' virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex); @@ -629,14 +664,22 @@ public: class PathDiagnostic : public llvm::FoldingSetNode { const Decl *DeclWithIssue; std::string BugType; - std::string Desc; + std::string VerboseDesc; + std::string ShortDesc; std::string Category; std::deque OtherDesc; + PathDiagnosticLocation Loc; PathPieces pathImpl; llvm::SmallVector pathStack; PathDiagnostic(); // Do not implement. public: + PathDiagnostic(const Decl *DeclWithIssue, StringRef bugtype, + StringRef verboseDesc, StringRef shortDesc, + StringRef category); + + ~PathDiagnostic(); + const PathPieces &path; /// Return the path currently used by builders for constructing the @@ -659,16 +702,24 @@ public: void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); } bool isWithinCall() const { return !pathStack.empty(); } - - // PathDiagnostic(); - PathDiagnostic(const Decl *DeclWithIssue, - StringRef bugtype, - StringRef desc, - StringRef category); - ~PathDiagnostic(); + void setEndOfPath(PathDiagnosticPiece *EndPiece) { + assert(!Loc.isValid() && "End location already set!"); + Loc = EndPiece->getLocation(); + assert(Loc.isValid() && "Invalid location for end-of-path piece"); + getActivePath().push_back(EndPiece); + } - StringRef getDescription() const { return Desc; } + void resetPath() { + pathStack.clear(); + pathImpl.clear(); + Loc = PathDiagnosticLocation(); + } + + StringRef getVerboseDescription() const { return VerboseDesc; } + StringRef getShortDescription() const { + return ShortDesc.empty() ? VerboseDesc : ShortDesc; + } StringRef getBugType() const { return BugType; } StringRef getCategory() const { return Category; } @@ -682,15 +733,27 @@ public: meta_iterator meta_end() const { return OtherDesc.end(); } void addMeta(StringRef s) { OtherDesc.push_back(s); } - PathDiagnosticLocation getLocation() const; + PathDiagnosticLocation getLocation() const { + assert(Loc.isValid() && "No end-of-path location set yet!"); + return Loc; + } void flattenLocations() { + Loc.flatten(); for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); I != E; ++I) (*I)->flattenLocations(); } - + + /// Profiles the diagnostic, independent of the path it references. + /// + /// This can be used to merge diagnostics that refer to the same issue + /// along different paths. void Profile(llvm::FoldingSetNodeID &ID) const; - + + /// Profiles the diagnostic, including its path. + /// + /// Two diagnostics with the same issue along different paths will generate + /// different profiles. void FullProfile(llvm::FoldingSetNodeID &ID) const; }; diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 3214d96c5398..9eb1248f6a71 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -366,23 +366,6 @@ public: } }; -class InlineCall { - template - static bool _inlineCall(void *checker, const CallExpr *CE, - ExprEngine &Eng, - ExplodedNode *Pred, - ExplodedNodeSet &Dst) { - return ((const CHECKER *)checker)->inlineCall(CE, Eng, Pred, Dst); - } - -public: - template - static void _register(CHECKER *checker, CheckerManager &mgr) { - mgr._registerForInlineCall( - CheckerManager::InlineCallFunc(checker, _inlineCall)); - } -}; - } // end eval namespace class CheckerBase : public ProgramPointTag { diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index e11b6d518a4e..7ae8e53784bf 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -258,7 +258,7 @@ public: const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, - ProgramPoint::Kind PointKind); + const ProgramPoint &PP); /// \brief Run checkers for end of analysis. void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, @@ -267,6 +267,7 @@ public: /// \brief Run checkers for end of path. void runCheckersForEndPath(NodeBuilderContext &BC, ExplodedNodeSet &Dst, + ExplodedNode *Pred, ExprEngine &Eng); /// \brief Run checkers for branch condition. @@ -407,11 +408,6 @@ public: typedef CheckerFn EvalCallFunc; - typedef CheckerFn - InlineCallFunc; - typedef CheckerFn CheckEndOfTranslationUnit; @@ -449,8 +445,6 @@ public: void _registerForEvalCall(EvalCallFunc checkfn); - void _registerForInlineCall(InlineCallFunc checkfn); - void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); //===----------------------------------------------------------------------===// @@ -576,8 +570,6 @@ private: std::vector EvalCallCheckers; - std::vector InlineCallCheckers; - std::vector EndOfTranslationUnitCheckers; struct EventInfo { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index e1ff17b361aa..27f3677bba22 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -66,6 +66,10 @@ public: return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned); } + llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY { + return (llvm::APSInt(BitWidth, IsUnsigned) = RawValue); + } + /// Used to classify whether a value is representable using this type. /// /// \see testInRange diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 876196ba4f7f..9038ae5276a7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -16,7 +16,7 @@ #define LLVM_CLANG_GR_ANALYSISMANAGER_H #include "clang/Analysis/AnalysisContext.h" -#include "clang/Frontend/AnalyzerOptions.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" @@ -41,64 +41,16 @@ class AnalysisManager : public BugReporterData { CheckerManager *CheckerMgr; - /// \brief The maximum number of exploded nodes the analyzer will generate. - unsigned MaxNodes; - - /// \brief The maximum number of times the analyzer visits a block. - unsigned MaxVisit; - - bool VisualizeEGDot; - bool VisualizeEGUbi; - AnalysisPurgeMode PurgeDead; - - /// \brief The flag regulates if we should eagerly assume evaluations of - /// conditionals, thus, bifurcating the path. - /// - /// EagerlyAssume - A flag indicating how the engine should handle - /// expressions such as: 'x = (y != 0)'. When this flag is true then - /// the subexpression 'y != 0' will be eagerly assumed to be true or false, - /// thus evaluating it to the integers 0 or 1 respectively. The upside - /// is that this can increase analysis precision until we have a better way - /// to lazily evaluate such logic. The downside is that it eagerly - /// bifurcates paths. - bool EagerlyAssume; - bool TrimGraph; - bool EagerlyTrimEGraph; - -public: - // \brief inter-procedural analysis mode. - AnalysisIPAMode IPAMode; - - // Settings for inlining tuning. - /// \brief The inlining stack depth limit. - unsigned InlineMaxStackDepth; - /// \brief The max number of basic blocks in a function being inlined. - unsigned InlineMaxFunctionSize; - /// \brief The mode of function selection used during inlining. - AnalysisInliningMode InliningMode; - - /// \brief Do not re-analyze paths leading to exhausted nodes with a different - /// strategy. We get better code coverage when retry is enabled. - bool NoRetryExhausted; - public: + AnalyzerOptions &options; + AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags, const LangOptions &lang, const PathDiagnosticConsumers &Consumers, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, - unsigned maxnodes, unsigned maxvisit, - bool vizdot, bool vizubi, AnalysisPurgeMode purge, - bool eager, bool trim, - bool useUnoptimizedCFG, - bool addImplicitDtors, - bool eagerlyTrimEGraph, - AnalysisIPAMode ipa, - unsigned inlineMaxStack, - unsigned inlineMaxFunctionSize, - AnalysisInliningMode inliningMode, - bool NoRetry); + AnalyzerOptions &Options); ~AnalysisManager(); @@ -142,27 +94,14 @@ public: void FlushDiagnostics(); - unsigned getMaxNodes() const { return MaxNodes; } - - unsigned getMaxVisit() const { return MaxVisit; } - - bool shouldVisualizeGraphviz() const { return VisualizeEGDot; } - - bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; } - bool shouldVisualize() const { - return VisualizeEGDot || VisualizeEGUbi; + return options.visualizeExplodedGraphWithGraphViz || + options.visualizeExplodedGraphWithUbiGraph; } - bool shouldEagerlyTrimExplodedGraph() const { return EagerlyTrimEGraph; } - - bool shouldTrimGraph() const { return TrimGraph; } - - AnalysisPurgeMode getPurgeMode() const { return PurgeDead; } - - bool shouldEagerlyAssume() const { return EagerlyAssume; } - - bool shouldInlineCall() const { return (IPAMode != None); } + bool shouldInlineCall() const { + return options.IPAMode != None; + } CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); @@ -180,7 +119,6 @@ public: AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) { return AnaCtxMgr.getContext(D); } - }; } // enAnaCtxMgrspace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index b4a9de76f4d1..fb393548b1af 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -73,6 +73,10 @@ class BasicValueFactory { llvm::FoldingSet CompoundValDataSet; llvm::FoldingSet LazyCompoundValDataSet; + // This is private because external clients should use the factory + // method that takes a QualType. + const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); + public: BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc) : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0), @@ -84,7 +88,6 @@ public: const llvm::APSInt& getValue(const llvm::APSInt& X); const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned); - const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); const llvm::APSInt& getValue(uint64_t X, QualType T); /// Returns the type of the APSInt used to store values of the given QualType. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index f6c5830c2955..a6a91e2b66df 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -20,6 +20,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/PointerIntPair.h" @@ -68,15 +69,22 @@ public: } }; +/// \class RuntimeDefinition /// \brief Defines the runtime definition of the called function. +/// +/// Encapsulates the information we have about which Decl will be used +/// when the call is executed on the given path. When dealing with dynamic +/// dispatch, the information is based on DynamicTypeInfo and might not be +/// precise. class RuntimeDefinition { - /// The Declaration of the function which will be called at runtime. - /// 0 if not available. + /// The Declaration of the function which could be called at runtime. + /// NULL if not available. const Decl *D; /// The region representing an object (ObjC/C++) on which the method is /// called. With dynamic dispatch, the method definition depends on the - /// runtime type of this object. 0 when there is no dynamic dispatch. + /// runtime type of this object. NULL when the DynamicTypeInfo is + /// precise. const MemRegion *R; public: @@ -84,8 +92,15 @@ public: RuntimeDefinition(const Decl *InD): D(InD), R(0) {} RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {} const Decl *getDecl() { return D; } - const MemRegion *getDispatchRegion() { return R; } + + /// \brief Check if the definition we have is precise. + /// If not, it is possible that the call dispatches to another definition at + /// execution time. bool mayHaveOtherDefinitions() { return R != 0; } + + /// When other definitions are possible, returns the region whose runtime type + /// determines the method definition. + const MemRegion *getDispatchRegion() { return R; } }; /// \brief Represents an abstract call to a function or method along a @@ -106,8 +121,7 @@ private: const LocationContext *LCtx; llvm::PointerUnion Origin; - // DO NOT IMPLEMENT - CallEvent &operator=(const CallEvent &); + void operator=(const CallEvent &) LLVM_DELETED_FUNCTION; protected: // This is user data for subclasses. @@ -139,16 +153,6 @@ protected: : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin), Data(Original.Data), Location(Original.Location), RefCount(0) {} - - ProgramStateRef getState() const { - return State; - } - - const LocationContext *getLocationContext() const { - return LCtx; - } - - /// Copies this CallEvent, with vtable intact, into a new block of memory. virtual void cloneTo(void *Dest) const = 0; @@ -164,8 +168,6 @@ protected: /// result of this call. virtual void getExtraInvalidatedRegions(RegionList &Regions) const {} - virtual QualType getDeclaredResultType() const = 0; - public: virtual ~CallEvent() {} @@ -178,6 +180,16 @@ public: return Origin.dyn_cast(); } + /// \brief The state in which the call is being evaluated. + ProgramStateRef getState() const { + return State; + } + + /// \brief The context in which the call is being evaluated. + const LocationContext *getLocationContext() const { + return LCtx; + } + /// \brief Returns the definition of the function or method that will be /// called. virtual RuntimeDefinition getRuntimeDefinition() const = 0; @@ -237,6 +249,12 @@ public: /// \brief Returns the result type, adjusted for references. QualType getResultType() const; + /// \brief Returns the return value of the call. + /// + /// This should only be called if the CallEvent was created using a state in + /// which the return value has already been bound to the origin expression. + SVal getReturnValue() const; + /// \brief Returns true if any of the arguments appear to represent callbacks. bool hasNonZeroCallbackArg() const; @@ -249,6 +267,38 @@ public: return hasNonZeroCallbackArg(); } + /// \brief Returns true if the callee is an externally-visible function in the + /// top-level namespace, such as \c malloc. + /// + /// You can use this call to determine that a particular function really is + /// a library function and not, say, a C++ member function with the same name. + /// + /// If a name is provided, the function must additionally match the given + /// name. + /// + /// Note that this deliberately excludes C++ library functions in the \c std + /// namespace, but will include C library functions accessed through the + /// \c std namespace. This also does not check if the function is declared + /// as 'extern "C"', or if it uses C++ name mangling. + // FIXME: Add a helper for checking namespaces. + // FIXME: Move this down to AnyFunctionCall once checkers have more + // precise callbacks. + bool isGlobalCFunction(StringRef SpecificName = StringRef()) const; + + /// \brief Returns the name of the callee, if its name is a simple identifier. + /// + /// Note that this will fail for Objective-C methods, blocks, and C++ + /// overloaded operators. The former is named by a Selector rather than a + /// simple identifier, and the latter two do not have names. + // FIXME: Move this down to AnyFunctionCall once checkers have more + // precise callbacks. + const IdentifierInfo *getCalleeIdentifier() const { + const NamedDecl *ND = dyn_cast_or_null(getDecl()); + if (!ND) + return 0; + return ND->getIdentifier(); + } + /// \brief Returns an appropriate ProgramPoint for this call. ProgramPoint getProgramPoint(bool IsPreVisit = false, const ProgramPointTag *Tag = 0) const; @@ -277,12 +327,12 @@ public: return cloneWithState(NewState); } - /// \brief Returns true if this is a statement that can be considered for - /// inlining. - /// - /// FIXME: This should go away once CallEvents are cheap and easy to - /// construct from ExplodedNodes. - static bool mayBeInlined(const Stmt *S); + /// \brief Returns true if this is a statement is a function or method call + /// of some kind. + static bool isCallStmt(const Stmt *S); + + /// \brief Returns the result type of a function, method declaration. + static QualType getDeclaredResultType(const Decl *D); // Iterator access to formal parameters and their types. private: @@ -329,8 +379,6 @@ public: // For debugging purposes only void dump(raw_ostream &Out) const; LLVM_ATTRIBUTE_USED void dump() const; - - static bool classof(const CallEvent *) { return true; } }; @@ -346,8 +394,6 @@ protected: : CallEvent(D, St, LCtx) {} AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {} - virtual QualType getDeclaredResultType() const; - public: // This function is overridden by subclasses, but they must return // a FunctionDecl. @@ -357,9 +403,16 @@ public: virtual RuntimeDefinition getRuntimeDefinition() const { const FunctionDecl *FD = getDecl(); - // Note that hasBody() will fill FD with the definition FunctionDecl. - if (FD && FD->hasBody(FD)) - return RuntimeDefinition(FD); + // Note that the AnalysisDeclContext will have the FunctionDecl with + // the definition (if one exists). + if (FD) { + AnalysisDeclContext *AD = + getLocationContext()->getAnalysisDeclContext()-> + getManager()->getContext(FD); + if (AD->getBody()) + return RuntimeDefinition(AD->getDecl()); + } + return RuntimeDefinition(); } @@ -442,8 +495,6 @@ protected: virtual void getExtraInvalidatedRegions(RegionList &Regions) const; - virtual QualType getDeclaredResultType() const; - public: /// \brief Returns the region associated with this instance of the block. /// @@ -499,13 +550,7 @@ public: virtual const Expr *getCXXThisExpr() const { return 0; } /// \brief Returns the value of the implicit 'this' object. - virtual SVal getCXXThisVal() const { - const Expr *Base = getCXXThisExpr(); - // FIXME: This doesn't handle an overloaded ->* operator. - if (!Base) - return UnknownVal(); - return getSVal(Base); - } + virtual SVal getCXXThisVal() const; virtual const FunctionDecl *getDecl() const; @@ -550,6 +595,8 @@ public: } virtual const Expr *getCXXThisExpr() const; + + virtual RuntimeDefinition getRuntimeDefinition() const; virtual Kind getKind() const { return CE_CXXMember; } @@ -605,6 +652,8 @@ class CXXDestructorCall : public CXXInstanceCall { friend class CallEventManager; protected: + typedef llvm::PointerIntPair DtorDataTy; + /// Creates an implicit destructor. /// /// \param DD The destructor that will be called. @@ -613,10 +662,10 @@ protected: /// \param St The path-sensitive state at this point in the program. /// \param LCtx The location context at this point in the program. CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, - const MemRegion *Target, ProgramStateRef St, - const LocationContext *LCtx) + const MemRegion *Target, bool IsBaseDestructor, + ProgramStateRef St, const LocationContext *LCtx) : CXXInstanceCall(DD, St, LCtx) { - Data = Target; + Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue(); Location = Trigger->getLocEnd(); } @@ -627,9 +676,16 @@ public: virtual SourceRange getSourceRange() const { return Location; } virtual unsigned getNumArgs() const { return 0; } + virtual RuntimeDefinition getRuntimeDefinition() const; + /// \brief Returns the value of the implicit 'this' object. virtual SVal getCXXThisVal() const; + /// Returns true if this is a call to a base class destructor. + bool isBaseDestructor() const { + return DtorDataTy::getFromOpaqueValue(Data).getInt(); + } + virtual Kind getKind() const { return CE_CXXDestructor; } static bool classof(const CallEvent *CA) { @@ -651,10 +707,10 @@ protected: /// a new symbolic region will be used. /// \param St The path-sensitive state at this point in the program. /// \param LCtx The location context at this point in the program. - CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *target, + CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target, ProgramStateRef St, const LocationContext *LCtx) : AnyFunctionCall(CE, St, LCtx) { - Data = target; + Data = Target; } CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){} @@ -761,8 +817,6 @@ protected: virtual void getExtraInvalidatedRegions(RegionList &Regions) const; - virtual QualType getDeclaredResultType() const; - /// Check if the selector may have multiple definitions (may have overrides). virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, Selector Sel) const; @@ -796,6 +850,9 @@ public: /// \brief Returns the value of the receiver at the time of this call. SVal getReceiverSVal() const; + /// \brief Return the value of 'self' if available. + SVal getSelfSVal() const; + /// \brief Get the interface for the receiver. /// /// This works whether this is an instance message or a class message. @@ -804,6 +861,9 @@ public: return getOriginExpr()->getReceiverInterface(); } + /// \brief Checks if the receiver refers to 'self' or 'super'. + bool isReceiverSelfOrSuper() const; + /// Returns how the message was written in the source (property access, /// subscript, or explicit message send). ObjCMessageKind getMessageKind() const; @@ -879,6 +939,13 @@ class CallEventManager { return new (allocate()) T(A1, A2, A3, St, LCtx); } + template + T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St, + const LocationContext *LCtx) { + return new (allocate()) T(A1, A2, A3, A4, St, LCtx); + } + public: CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {} @@ -905,9 +972,9 @@ public: CallEventRef getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, - const MemRegion *Target, ProgramStateRef State, - const LocationContext *LCtx) { - return create(DD, Trigger, Target, State, LCtx); + const MemRegion *Target, bool IsBase, + ProgramStateRef State, const LocationContext *LCtx) { + return create(DD, Trigger, Target, IsBase, State, LCtx); } CallEventRef diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 8c8e82ce20dd..4558cd9c9480 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -16,10 +16,57 @@ #define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" namespace clang { namespace ento { + /// Declares an immutable map of type \p NameTy, suitable for placement into + /// the ProgramState. This is implementing using llvm::ImmutableMap. + /// + /// \code + /// State = State->set(K, V); + /// const Value *V = State->get(K); // Returns NULL if not in the map. + /// State = State->remove(K); + /// NameTy Map = State->get(); + /// \endcode + /// + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \ + REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \ + CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)) + + /// Declares an immutable set of type \p NameTy, suitable for placement into + /// the ProgramState. This is implementing using llvm::ImmutableSet. + /// + /// \code + /// State = State->add(E); + /// State = State->remove(E); + /// bool Present = State->contains(E); + /// NameTy Set = State->get(); + /// \endcode + /// + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \ + REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet) + + /// Declares an immutable list of type \p NameTy, suitable for placement into + /// the ProgramState. This is implementing using llvm::ImmutableList. + /// + /// \code + /// State = State->add(E); // Adds to the /end/ of the list. + /// bool Present = State->contains(E); + /// NameTy List = State->get(); + /// \endcode + /// + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \ + REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList) + + class CheckerContext { ExprEngine &Eng; /// The current exploded(symbolic execution) graph node. @@ -64,6 +111,10 @@ public: return Eng.getStoreManager(); } + const AnalyzerOptions::ConfigTable &getConfig() const { + return Eng.getAnalysisManager().options.Config; + } + /// \brief Returns the previous node in the exploded graph, which includes /// the state of the program before the checker ran. Note, checkers should /// not retain the node in their state since the nodes might get invalidated. @@ -76,8 +127,8 @@ public: /// \brief Returns the number of times the current block has been visited /// along the analyzed path. - unsigned getCurrentBlockCount() const { - return NB.getContext().getCurrentBlockCount(); + unsigned blockCount() const { + return NB.getContext().blockCount(); } ASTContext &getASTContext() { @@ -96,6 +147,9 @@ public: return Pred->getStackFrame(); } + /// Return true if the current LocationContext has no caller context. + bool inTopFrame() const { return getLocationContext()->inTopFrame(); } + BugReporter &getBugReporter() { return Eng.getBugReporter(); } @@ -144,20 +198,15 @@ public: /// \brief Generates a new transition in the program state graph /// (ExplodedGraph). Uses the default CheckerContext predecessor node. /// - /// @param State The state of the generated node. + /// @param State The state of the generated node. If not specified, the state + /// will not be changed, but the new node will have the checker's tag. /// @param Tag The tag is used to uniquely identify the creation site. If no /// tag is specified, a default tag, unique to the given checker, /// will be used. Tags are used to prevent states generated at /// different sites from caching out. - ExplodedNode *addTransition(ProgramStateRef State, + ExplodedNode *addTransition(ProgramStateRef State = 0, const ProgramPointTag *Tag = 0) { - return addTransitionImpl(State, false, 0, Tag); - } - - /// \brief Generates a default transition (containing checker tag but no - /// checker state changes). - ExplodedNode *addTransition() { - return addTransition(getState()); + return addTransitionImpl(State ? State : getState(), false, 0, Tag); } /// \brief Generates a new transition with the given predecessor. @@ -167,25 +216,24 @@ public: /// @param Pred The transition will be generated from the specified Pred node /// to the newly generated node. /// @param Tag The tag to uniquely identify the creation site. - /// @param IsSink Mark the new node as sink, which will stop exploration of - /// the given path. ExplodedNode *addTransition(ProgramStateRef State, - ExplodedNode *Pred, - const ProgramPointTag *Tag = 0, - bool IsSink = false) { - return addTransitionImpl(State, IsSink, Pred, Tag); + ExplodedNode *Pred, + const ProgramPointTag *Tag = 0) { + return addTransitionImpl(State, false, Pred, Tag); } - /// \brief Generate a sink node. Generating sink stops exploration of the + /// \brief Generate a sink node. Generating a sink stops exploration of the /// given path. - ExplodedNode *generateSink(ProgramStateRef state = 0) { - return addTransitionImpl(state ? state : getState(), true); + ExplodedNode *generateSink(ProgramStateRef State = 0, + ExplodedNode *Pred = 0, + const ProgramPointTag *Tag = 0) { + return addTransitionImpl(State ? State : getState(), true, Pred, Tag); } /// \brief Emit the diagnostics report. - void EmitReport(BugReport *R) { + void emitReport(BugReport *R) { Changed = true; - Eng.getBugReporter().EmitReport(R); + Eng.getBugReporter().emitReport(R); } /// \brief Get the declaration of the called function (path-sensitive). @@ -194,17 +242,33 @@ public: /// \brief Get the name of the called function (path-sensitive). StringRef getCalleeName(const FunctionDecl *FunDecl) const; + /// \brief Get the identifier of the called function (path-sensitive). + const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const { + const FunctionDecl *FunDecl = getCalleeDecl(CE); + if (FunDecl) + return FunDecl->getIdentifier(); + else + return 0; + } + /// \brief Get the name of the called function (path-sensitive). StringRef getCalleeName(const CallExpr *CE) const { const FunctionDecl *FunDecl = getCalleeDecl(CE); return getCalleeName(FunDecl); } - /// Given a function declaration and a name checks if this is a C lib - /// function with the given name. - bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name); - static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name, - ASTContext &Context); + /// \brief Returns true if the callee is an externally-visible function in the + /// top-level namespace, such as \c malloc. + /// + /// If a name is provided, the function must additionally match the given + /// name. + /// + /// Note that this deliberately excludes C++ library functions in the \c std + /// namespace, but will include C library functions accessed through the + /// \c std namespace. This also does not check if the function is declared + /// as 'extern "C"', or if it uses C++ name mangling. + static bool isCLibraryFunction(const FunctionDecl *FD, + StringRef Name = StringRef()); /// \brief Depending on wither the location corresponds to a macro, return /// either the macro name or the token spelling. @@ -226,9 +290,15 @@ private: return Pred; Changed = true; - ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location, - State, - P ? P : Pred, MarkAsSink); + const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); + if (!P) + P = Pred; + + ExplodedNode *node; + if (MarkAsSink) + node = NB.generateSink(LocalLoc, State, P); + else + node = NB.generateNode(LocalLoc, State, P); return node; } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 631858dd7c5b..4a78849024ae 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -16,6 +16,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/Support/SaveAndRestore.h" namespace llvm { class APSInt; @@ -26,29 +27,83 @@ namespace ento { class SubEngine; +class ConditionTruthVal { + llvm::Optional Val; +public: + /// Construct a ConditionTruthVal indicating the constraint is constrained + /// to either true or false, depending on the boolean value provided. + ConditionTruthVal(bool constraint) : Val(constraint) {} + + /// Construct a ConstraintVal indicating the constraint is underconstrained. + ConditionTruthVal() {} + + /// Return true if the constraint is perfectly constrained to 'true'. + bool isConstrainedTrue() const { + return Val.hasValue() && Val.getValue(); + } + + /// Return true if the constraint is perfectly constrained to 'false'. + bool isConstrainedFalse() const { + return Val.hasValue() && !Val.getValue(); + } + + /// Return true if the constrained is perfectly constrained. + bool isConstrained() const { + return Val.hasValue(); + } + + /// Return true if the constrained is underconstrained and we do not know + /// if the constraint is true of value. + bool isUnderconstrained() const { + return !Val.hasValue(); + } +}; + class ConstraintManager { public: + ConstraintManager() : NotifyAssumeClients(true) {} + virtual ~ConstraintManager(); virtual ProgramStateRef assume(ProgramStateRef state, - DefinedSVal Cond, - bool Assumption) = 0; - - std::pair - assumeDual(ProgramStateRef state, DefinedSVal Cond) - { - std::pair res = - std::make_pair(assume(state, Cond, true), assume(state, Cond, false)); - - assert(!(!res.first && !res.second) && "System is over constrained."); - return res; + DefinedSVal Cond, + bool Assumption) = 0; + + typedef std::pair ProgramStatePair; + + /// Returns a pair of states (StTrue, StFalse) where the given condition is + /// assumed to be true or false, respectively. + ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond) { + ProgramStateRef StTrue = assume(State, Cond, true); + + // If StTrue is infeasible, asserting the falseness of Cond is unnecessary + // because the existing constraints already establish this. + if (!StTrue) { + // FIXME: This is fairly expensive and should be disabled even in + // Release+Asserts builds. + assert(assume(State, Cond, false) && "System is over constrained."); + return ProgramStatePair((ProgramStateRef)NULL, State); + } + + ProgramStateRef StFalse = assume(State, Cond, false); + if (!StFalse) { + // We are careful to return the original state, /not/ StTrue, + // because we want to avoid having callers generate a new node + // in the ExplodedGraph. + return ProgramStatePair(State, (ProgramStateRef)NULL); + } + + return ProgramStatePair(StTrue, StFalse); } + /// \brief If a symbol is perfectly constrained to a constant, attempt + /// to return the concrete value. + /// + /// Note that a ConstraintManager is not obligated to return a concretized + /// value for a symbol, even if it is perfectly constrained. virtual const llvm::APSInt* getSymVal(ProgramStateRef state, - SymbolRef sym) const = 0; - - virtual bool isEqual(ProgramStateRef state, - SymbolRef sym, - const llvm::APSInt& V) const = 0; + SymbolRef sym) const { + return 0; + } virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper& SymReaper) = 0; @@ -59,20 +114,38 @@ public: const char *sep) = 0; virtual void EndPath(ProgramStateRef state) {} + + /// Convenience method to query the state to see if a symbol is null or + /// not null, or if neither assumption can be made. + ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) { + llvm::SaveAndRestore DisableNotify(NotifyAssumeClients, false); + + return checkNull(State, Sym); + } protected: + /// A flag to indicate that clients should be notified of assumptions. + /// By default this is the case, but sometimes this needs to be restricted + /// to avoid infinite recursions within the ConstraintManager. + /// + /// Note that this flag allows the ConstraintManager to be re-entrant, + /// but not thread-safe. + bool NotifyAssumeClients; + /// canReasonAbout - Not all ConstraintManagers can accurately reason about /// all SVal values. This method returns true if the ConstraintManager can /// reasonably handle a given SVal value. This is typically queried by /// ExprEngine to determine if the value should be replaced with a /// conjured symbolic value in order to recover some precision. virtual bool canReasonAbout(SVal X) const = 0; + + /// Returns whether or not a symbol is known to be null ("true"), known to be + /// non-null ("false"), or may be either ("underconstrained"). + virtual ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym); }; -ConstraintManager* CreateBasicConstraintManager(ProgramStateManager& statemgr, - SubEngine &subengine); ConstraintManager* CreateRangeConstraintManager(ProgramStateManager& statemgr, - SubEngine &subengine); + SubEngine *subengine); } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index e75cdd87596b..b6686409e5aa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -80,10 +80,6 @@ private: /// usually because it could not reason about something. BlocksAborted blocksAborted; - /// The functions which have been analyzed through inlining. This is owned by - /// AnalysisConsumer. It can be null. - SetOfConstDecls *AnalyzedCallees; - /// The information about functions shared by the whole translation unit. /// (This data is owned by AnalysisConsumer.) FunctionSummariesTy *FunctionSummaries; @@ -101,19 +97,18 @@ private: ExplodedNode *Pred); private: - CoreEngine(const CoreEngine&); // Do not implement. - CoreEngine& operator=(const CoreEngine&); + CoreEngine(const CoreEngine &) LLVM_DELETED_FUNCTION; + void operator=(const CoreEngine &) LLVM_DELETED_FUNCTION; ExplodedNode *generateCallExitBeginNode(ExplodedNode *N); public: /// Construct a CoreEngine object to analyze the provided CFG. - CoreEngine(SubEngine& subengine, SetOfConstDecls *VisitedCallees, + CoreEngine(SubEngine& subengine, FunctionSummariesTy *FS) : SubEng(subengine), G(new ExplodedGraph()), WList(WorkList::makeDFS()), BCounterFactory(G->getAllocator()), - AnalyzedCallees(VisitedCallees), FunctionSummaries(FS){} /// getGraph - Returns the exploded graph. @@ -185,20 +180,18 @@ public: struct NodeBuilderContext { const CoreEngine &Eng; const CFGBlock *Block; - ExplodedNode *Pred; + const LocationContext *LC; NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N) - : Eng(E), Block(B), Pred(N) { assert(B); assert(!N->isSink()); } - - ExplodedNode *getPred() const { return Pred; } + : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); } /// \brief Return the CFGBlock associated with this builder. const CFGBlock *getBlock() const { return Block; } /// \brief Returns the number of times the current basic block has been /// visited on the exploded graph path. - unsigned getCurrentBlockCount() const { + unsigned blockCount() const { return Eng.WList->getBlockCounter().getNumVisited( - Pred->getLocationContext()->getCurrentStackFrame(), + LC->getCurrentStackFrame(), Block->getBlockID()); } }; @@ -265,14 +258,21 @@ public: virtual ~NodeBuilder() {} /// \brief Generates a node in the ExplodedGraph. + ExplodedNode *generateNode(const ProgramPoint &PP, + ProgramStateRef State, + ExplodedNode *Pred) { + return generateNodeImpl(PP, State, Pred, false); + } + + /// \brief Generates a sink in the ExplodedGraph. /// /// When a node is marked as sink, the exploration from the node is stopped - - /// the node becomes the last node on the path. - ExplodedNode *generateNode(const ProgramPoint &PP, + /// the node becomes the last node on the path and certain kinds of bugs are + /// suppressed. + ExplodedNode *generateSink(const ProgramPoint &PP, ProgramStateRef State, - ExplodedNode *Pred, - bool MarkAsSink = false) { - return generateNodeImpl(PP, State, Pred, MarkAsSink); + ExplodedNode *Pred) { + return generateNodeImpl(PP, State, Pred, true); } const ExplodedNodeSet &getResults() { @@ -317,13 +317,18 @@ public: NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx, ProgramPoint &L) : NodeBuilder(Pred, DstSet, Ctx), Location(L) {} + ExplodedNode *generateNode(ProgramStateRef State, ExplodedNode *Pred, - const ProgramPointTag *Tag = 0, - bool MarkAsSink = false) { - ProgramPoint LocalLoc = (Tag ? Location.withTag(Tag): Location); + const ProgramPointTag *Tag = 0) { + const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); + return NodeBuilder::generateNode(LocalLoc, State, Pred); + } - ExplodedNode *N = generateNodeImpl(LocalLoc, State, Pred, MarkAsSink); + ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred, + const ProgramPointTag *Tag = 0) { + const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); + ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred); if (N && N->isSink()) sinksGenerated.push_back(N); return N; @@ -336,7 +341,7 @@ public: /// \class StmtNodeBuilder /// \brief This builder class is useful for generating nodes that resulted from -/// visiting a statement. The main difference from it's parent NodeBuilder is +/// visiting a statement. The main difference from its parent NodeBuilder is /// that it creates a statement specific ProgramPoint. class StmtNodeBuilder: public NodeBuilder { NodeBuilder *EnclosingBldr; @@ -363,22 +368,27 @@ public: virtual ~StmtNodeBuilder(); + using NodeBuilder::generateNode; + using NodeBuilder::generateSink; + ExplodedNode *generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, - bool MarkAsSink = false, const ProgramPointTag *tag = 0, ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, Pred->getLocationContext(), tag); - return generateNodeImpl(L, St, Pred, MarkAsSink); + return NodeBuilder::generateNode(L, St, Pred); } - ExplodedNode *generateNode(const ProgramPoint &PP, + ExplodedNode *generateSink(const Stmt *S, ExplodedNode *Pred, - ProgramStateRef State, - bool MarkAsSink = false) { - return generateNodeImpl(PP, State, Pred, MarkAsSink); + ProgramStateRef St, + const ProgramPointTag *tag = 0, + ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ + const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, + Pred->getLocationContext(), tag); + return NodeBuilder::generateSink(L, St, Pred); } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h new file mode 100644 index 000000000000..5ac97dbc3145 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h @@ -0,0 +1,52 @@ +//== DynamicTypeInfo.h - Runtime type information ----------------*- C++ -*--=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SA_CORE_DYNAMICTYPEINFO_H +#define LLVM_CLANG_SA_CORE_DYNAMICTYPEINFO_H + +#include "clang/AST/Type.h" + +namespace clang { +namespace ento { + +/// \brief Stores the currently inferred strictest bound on the runtime type +/// of a region in a given state along the analysis path. +class DynamicTypeInfo { +private: + QualType T; + bool CanBeASubClass; + +public: + + DynamicTypeInfo() : T(QualType()) {} + DynamicTypeInfo(QualType WithType, bool CanBeSub = true) + : T(WithType), CanBeASubClass(CanBeSub) {} + + /// \brief Return false if no dynamic type info is available. + bool isValid() const { return !T.isNull(); } + + /// \brief Returns the currently inferred upper bound on the runtime type. + QualType getType() const { return T; } + + /// \brief Returns false if the type information is precise (the type T is + /// the only type in the lattice), true otherwise. + bool canBeASubClass() const { return CanBeASubClass; } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.Add(T); + ID.AddInteger((unsigned)CanBeASubClass); + } + bool operator==(const DynamicTypeInfo &X) const { + return T == X.T && CanBeASubClass == X.CanBeASubClass; + } +}; + +} // end ento +} // end clang + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index b80213e249a2..eb9bd85fe64d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -33,10 +33,11 @@ class SValBuilder; /// other things. class EnvironmentEntry : public std::pair { + friend class EnvironmentManager; + EnvironmentEntry makeLocation() const; + public: - EnvironmentEntry(const Stmt *s, const LocationContext *L) - : std::pair(s, L ? L->getCurrentStackFrame():0) {} + EnvironmentEntry(const Stmt *s, const LocationContext *L); const Stmt *getStmt() const { return first; } const LocationContext *getLocationContext() const { return second; } @@ -76,9 +77,7 @@ public: /// Fetches the current binding of the expression in the /// Environment. - SVal getSVal(const EnvironmentEntry &E, - SValBuilder &svalBuilder, - bool useOnlyDirectBindings = false) const; + SVal getSVal(const EnvironmentEntry &E, SValBuilder &svalBuilder) const; /// Profile - Profile the contents of an Environment object for use /// in a FoldingSet. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index 1052d9491a96..b112e66d30d3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -60,45 +60,50 @@ class ExplodedNode : public llvm::FoldingSetNode { friend class SwitchNodeBuilder; friend class EndOfFunctionNodeBuilder; + /// Efficiently stores a list of ExplodedNodes, or an optional flag. + /// + /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing + /// for the case when there is only one node in the group. This is a fairly + /// common case in an ExplodedGraph, where most nodes have only one + /// predecessor and many have only one successor. It can also be used to + /// store a flag rather than a node list, which ExplodedNode uses to mark + /// whether a node is a sink. If the flag is set, the group is implicitly + /// empty and no nodes may be added. class NodeGroup { - enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 }; + // Conceptually a discriminated union. If the low bit is set, the node is + // a sink. If the low bit is not set, the pointer refers to the storage + // for the nodes in the group. + // This is not a PointerIntPair in order to keep the storage type opaque. uintptr_t P; - - unsigned getKind() const { - return P & 0x1; - } - - void *getPtr() const { - assert (!getFlag()); - return reinterpret_cast(P & ~Mask); - } - - ExplodedNode *getNode() const { - return reinterpret_cast(getPtr()); - } public: - NodeGroup() : P(0) {} + NodeGroup(bool Flag = false) : P(Flag) { + assert(getFlag() == Flag); + } - ExplodedNode **begin() const; + ExplodedNode * const *begin() const; - ExplodedNode **end() const; + ExplodedNode * const *end() const; unsigned size() const; - bool empty() const { return (P & ~Mask) == 0; } + bool empty() const { return P == 0 || getFlag() != 0; } + /// Adds a node to the list. + /// + /// The group must not have been created with its flag set. void addNode(ExplodedNode *N, ExplodedGraph &G); + /// Replaces the single node in this group with a new node. + /// + /// Note that this should only be used when you know the group was not + /// created with its flag set, and that the group is empty or contains + /// only a single node. void replaceNode(ExplodedNode *node); - void setFlag() { - assert(P == 0); - P = AuxFlag; - } - + /// Returns whether this group was created with its flag set. bool getFlag() const { - return P & AuxFlag ? true : false; + return (P & 1); } }; @@ -119,9 +124,8 @@ public: explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state, bool IsSink) - : Location(loc), State(state) { - if (IsSink) - Succs.setFlag(); + : Location(loc), State(state), Succs(IsSink) { + assert(isSink() == IsSink); } ~ExplodedNode() {} @@ -190,9 +194,9 @@ public: } // Iterators over successor and predecessor vertices. - typedef ExplodedNode** succ_iterator; + typedef ExplodedNode* const * succ_iterator; typedef const ExplodedNode* const * const_succ_iterator; - typedef ExplodedNode** pred_iterator; + typedef ExplodedNode* const * pred_iterator; typedef const ExplodedNode* const * const_pred_iterator; pred_iterator pred_begin() { return Preds.begin(); } @@ -278,11 +282,13 @@ protected: /// A list of nodes that can be reused. NodeVector FreeNodes; - /// A flag that indicates whether nodes should be recycled. - bool reclaimNodes; + /// Determines how often nodes are reclaimed. + /// + /// If this is 0, nodes will never be reclaimed. + unsigned ReclaimNodeInterval; /// Counter to determine when to reclaim nodes. - unsigned reclaimCounter; + unsigned ReclaimCounter; public: @@ -370,7 +376,9 @@ public: /// Enable tracking of recently allocated nodes for potential reclamation /// when calling reclaimRecentlyAllocatedNodes(). - void enableNodeReclamation() { reclaimNodes = true; } + void enableNodeReclamation(unsigned Interval) { + ReclaimCounter = ReclaimNodeInterval = Interval; + } /// Reclaim "uninteresting" nodes created since the last time this method /// was called. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 4addb9d4ec49..78b254222e9e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_GR_EXPRENGINE #define LLVM_CLANG_GR_EXPRENGINE +#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" @@ -70,17 +71,14 @@ class ExprEngine : public SubEngine { /// variables and symbols (as determined by a liveness analysis). ProgramStateRef CleanedState; - /// currentStmt - The current block-level statement. - const Stmt *currentStmt; - unsigned int currentStmtIdx; - const NodeBuilderContext *currentBuilderContext; - - /// Obj-C Class Identifiers. - IdentifierInfo* NSExceptionII; - - /// Obj-C Selectors. - Selector* NSExceptionInstanceRaiseSelectors; - Selector RaiseSel; + /// currStmt - The current block-level statement. + const Stmt *currStmt; + unsigned int currStmtIdx; + const NodeBuilderContext *currBldrCtx; + + /// Helper object to determine if an Objective-C message expression + /// implicitly never returns. + ObjCNoReturn ObjCNoRet; /// Whether or not GC is enabled in this analysis. bool ObjCGCEnabled; @@ -90,9 +88,13 @@ class ExprEngine : public SubEngine { /// destructor is called before the rest of the ExprEngine is destroyed. GRBugReporter BR; + /// The functions which have been analyzed through inlining. This is owned by + /// AnalysisConsumer. It can be null. + SetOfConstDecls *VisitedCallees; + public: ExprEngine(AnalysisManager &mgr, bool gcEnabled, - SetOfConstDecls *VisitedCallees, + SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS); ~ExprEngine(); @@ -126,8 +128,8 @@ public: BugReporter& getBugReporter() { return BR; } const NodeBuilderContext &getBuilderContext() { - assert(currentBuilderContext); - return *currentBuilderContext; + assert(currBldrCtx); + return *currBldrCtx; } bool isObjCGCEnabled() { return ObjCGCEnabled; } @@ -165,8 +167,12 @@ public: /// are usually reported here). /// \param K - In some cases it is possible to use PreStmt kind. (Do /// not use it unless you know what you are doing.) + /// If the ReferenceStmt is NULL, everything is this and parent contexts is + /// considered live. + /// If the stack frame context is NULL, everything on stack is considered + /// dead. void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, - const Stmt *ReferenceStmt, const LocationContext *LC, + const Stmt *ReferenceStmt, const StackFrameContext *LC, const Stmt *DiagnosticStmt, ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind); @@ -192,7 +198,8 @@ public: /// Called by CoreEngine when processing the entrance of a CFGBlock. virtual void processCFGBlockEntrance(const BlockEdge &L, - NodeBuilderWithSinks &nodeBuilder); + NodeBuilderWithSinks &nodeBuilder, + ExplodedNode *Pred); /// ProcessBranch - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. @@ -213,7 +220,13 @@ public: /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. - void processEndOfFunction(NodeBuilderContext& BC); + void processEndOfFunction(NodeBuilderContext& BC, + ExplodedNode *Pred); + + /// Remove dead bindings/symbols before exiting a function. + void removeDeadOnEndOfFunction(NodeBuilderContext& BC, + ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// Generate the entry node of the callee. void processCallEnter(CallEnter CE, ExplodedNode *Pred); @@ -258,9 +271,6 @@ public: BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); } - const BasicValueFactory& getBasicVals() const { - return StateMgr.getBasicVals(); - } // FIXME: Remove when we migrate over to just using ValueManager. SymbolManager& getSymbolManager() { return SymMgr; } @@ -283,13 +293,14 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst); - /// VisitAsmStmt - Transfer function logic for inline asm. - void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst); + /// VisitGCCAsmStmt - Transfer function logic for inline asm. + void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// VisitMSAsmStmt - Transfer function logic for MS inline asm. void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst); - + /// VisitBlockExpr - Transfer function logic for BlockExprs. void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -380,8 +391,8 @@ public: void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXDestructor(QualType ObjectType, - const MemRegion *Dest, const Stmt *S, + void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, + const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst); void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, @@ -395,14 +406,14 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst); - /// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic + /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) /// with those assumptions. - void evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex); std::pair - getEagerlyAssumeTags(); + geteagerlyAssumeBinOpBifurcationTags(); SVal evalMinus(SVal X) { return X.isValid() ? svalBuilder.evalMinus(cast(X)) : X; @@ -433,7 +444,8 @@ protected: /// evalBind - Handle the semantics of binding a value to a specific location. /// This method is used by evalStore, VisitDeclStmt, and others. void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, - SVal location, SVal Val, bool atDeclInit = false); + SVal location, SVal Val, bool atDeclInit = false, + const ProgramPoint *PP = 0); public: // FIXME: 'tag' should be removed, and a LocationContext should be used @@ -490,6 +502,10 @@ private: ProgramStateRef St, SVal location, const ProgramPointTag *tag, bool isLoad); + /// Count the stack depth and determine if the call is recursive. + void examineStackFrames(const Decl *D, const LocationContext *LCtx, + bool &IsRecursive, unsigned &StackDepth); + bool shouldInlineDecl(const Decl *D, ExplodedNode *Pred); bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State); @@ -510,6 +526,8 @@ private: /// Traits for storing the call processing policy inside GDM. /// The GDM stores the corresponding CallExpr pointer. +// FIXME: This does not use the nice trait macros because it must be accessible +// from multiple translation units. struct ReplayWithoutInlining{}; template <> struct ProgramStateTrait : diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 8044ed839a75..34fbc3ca9e83 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -99,11 +99,11 @@ public: // Untyped regions. SymbolicRegionKind, AllocaRegionKind, - BlockDataRegionKind, // Typed regions. BEG_TYPED_REGIONS, FunctionTextRegionKind = BEG_TYPED_REGIONS, BlockTextRegionKind, + BlockDataRegionKind, BEG_TYPED_VALUE_REGIONS, CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS, CXXThisRegionKind, @@ -140,6 +140,9 @@ public: const MemRegion *getBaseRegion() const; + /// Check if the region is a subregion of the given region. + virtual bool isSubRegionOf(const MemRegion *R) const; + const MemRegion *StripCasts(bool StripBaseCasts = true) const; bool hasGlobalsOrParametersStorage() const; @@ -171,8 +174,6 @@ public: template const RegionTy* getAs() const; virtual bool isBoundable() const { return false; } - - static bool classof(const MemRegion*) { return true; } }; /// MemSpaceRegion - A memory region that represents a "memory space"; @@ -416,7 +417,7 @@ public: MemRegionManager* getMemRegionManager() const; - bool isSubRegionOf(const MemRegion* R) const; + virtual bool isSubRegionOf(const MemRegion* R) const; static bool classof(const MemRegion* R) { return R->getKind() > END_MEMSPACES; @@ -530,16 +531,28 @@ public: /// FunctionTextRegion - A region that represents code texts of function. class FunctionTextRegion : public CodeTextRegion { - const FunctionDecl *FD; + const NamedDecl *FD; public: - FunctionTextRegion(const FunctionDecl *fd, const MemRegion* sreg) - : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {} + FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg) + : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) { + assert(isa(fd) || isa(fd)); + } QualType getLocationType() const { - return getContext().getPointerType(FD->getType()); + const ASTContext &Ctx = getContext(); + if (const FunctionDecl *D = dyn_cast(FD)) { + return Ctx.getPointerType(D->getType()); + } + + assert(isa(FD)); + assert(false && "Getting the type of ObjCMethod is not supported yet"); + + // TODO: We might want to return a different type here (ex: id (*ty)(...)) + // depending on how it is used. + return QualType(); } - - const FunctionDecl *getDecl() const { + + const NamedDecl *getDecl() const { return FD; } @@ -547,7 +560,7 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD, + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, const MemRegion*); static bool classof(const MemRegion* R) { @@ -603,7 +616,7 @@ public: /// which correspond to "code+data". The distinction is important, because /// like a closure a block captures the values of externally referenced /// variables. -class BlockDataRegion : public SubRegion { +class BlockDataRegion : public TypedRegion { friend class MemRegionManager; const BlockTextRegion *BC; const LocationContext *LC; // Can be null */ @@ -612,13 +625,15 @@ class BlockDataRegion : public SubRegion { BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, const MemRegion *sreg) - : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), + : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0), OriginalVars(0) {} public: const BlockTextRegion *getCodeRegion() const { return BC; } const BlockDecl *getDecl() const { return BC->getDecl(); } + + QualType getLocationType() const { return BC->getLocationType(); } class referenced_vars_iterator { const MemRegion * const *R; @@ -1212,7 +1227,7 @@ public: return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion); } - const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); + const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, AnalysisDeclContext *AC); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index b0c51dd5b928..86c94deab5e8 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines SymbolRef, ExprBindKey, and ProgramState*. +// This file defines the state of the program along the analysisa path. // //===----------------------------------------------------------------------===// @@ -16,6 +16,7 @@ #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" @@ -39,7 +40,7 @@ class CallEvent; class CallEventManager; typedef ConstraintManager* (*ConstraintManagerCreator)(ProgramStateManager&, - SubEngine&); + SubEngine*); typedef StoreManager* (*StoreManagerCreator)(ProgramStateManager&); //===----------------------------------------------------------------------===// @@ -56,32 +57,6 @@ template struct ProgramStateTrait { } }; -/// \class Stores the dynamic type information. -/// Information about type of an object at runtime. This is used by dynamic -/// dispatch implementation. -class DynamicTypeInfo { - QualType T; - bool CanBeASubClass; - -public: - DynamicTypeInfo() : T(QualType()) {} - DynamicTypeInfo(QualType WithType, bool CanBeSub = true) - : T(WithType), CanBeASubClass(CanBeSub) {} - - bool isValid() const { return !T.isNull(); } - - QualType getType() const { return T; } - bool canBeASubClass() const { return CanBeASubClass; } - - void Profile(llvm::FoldingSetNodeID &ID) const { - T.Profile(ID); - ID.AddInteger((unsigned)CanBeASubClass); - } - bool operator==(const DynamicTypeInfo &X) const { - return T == X.T && CanBeASubClass == X.CanBeASubClass; - } -}; - /// \class ProgramState /// ProgramState - This class encapsulates: /// @@ -100,7 +75,7 @@ public: typedef llvm::ImmutableMap GenericDataMap; private: - void operator=(const ProgramState& R) const; // Do not implement. + void operator=(const ProgramState& R) LLVM_DELETED_FUNCTION; friend class ProgramStateManager; friend class ExplodedGraph; @@ -130,7 +105,12 @@ public: ~ProgramState(); /// Return the ProgramStateManager associated with this state. - ProgramStateManager &getStateManager() const { return *stateMgr; } + ProgramStateManager &getStateManager() const { + return *stateMgr; + } + + /// Return the ConstraintManager. + ConstraintManager &getConstraintManager() const; /// getEnvironment - Return the environment associated with this state. /// The environment is the mapping from expressions to values. @@ -210,11 +190,13 @@ public: // Binding and retrieving values to/from the environment and symbolic store. //==---------------------------------------------------------------------==// - /// BindCompoundLiteral - Return the state that has the bindings currently - /// in this state plus the bindings for the CompoundLiteral. + /// \brief Create a new state with the specified CompoundLiteral binding. + /// \param CL the compound literal expression (the binding key) + /// \param LC the LocationContext of the binding + /// \param V the value to bind. ProgramStateRef bindCompoundLiteral(const CompoundLiteralExpr *CL, - const LocationContext *LC, - SVal V) const; + const LocationContext *LC, + SVal V) const; /// Create a new state by binding the value 'V' to the statement 'S' in the /// state's environment. @@ -226,18 +208,16 @@ public: ProgramStateRef bindExprAndLocation(const Stmt *S, const LocationContext *LCtx, SVal location, SVal V) const; - - ProgramStateRef bindDecl(const VarRegion *VR, SVal V) const; - ProgramStateRef bindDeclWithNoInit(const VarRegion *VR) const; - - ProgramStateRef bindLoc(Loc location, SVal V) const; + ProgramStateRef bindLoc(Loc location, + SVal V, + bool notifyChanges = true) const; ProgramStateRef bindLoc(SVal location, SVal V) const; ProgramStateRef bindDefault(SVal loc, SVal V) const; - ProgramStateRef unbindLoc(Loc LV) const; + ProgramStateRef killBinding(Loc LV) const; /// invalidateRegions - Returns the state with bindings for the given regions /// cleared from the store. The regions are provided as a continuous array @@ -271,11 +251,8 @@ public: /// Get the lvalue for an array index. SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const; - const llvm::APSInt *getSymVal(SymbolRef sym) const; - /// Returns the SVal bound to the statement 'S' in the state's environment. - SVal getSVal(const Stmt *S, const LocationContext *LCtx, - bool useOnlyDirectBindings = false) const; + SVal getSVal(const Stmt *S, const LocationContext *LCtx) const; SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const; @@ -469,7 +446,7 @@ public: StoreManagerCreator CreateStoreManager, ConstraintManagerCreator CreateConstraintManager, llvm::BumpPtrAllocator& alloc, - SubEngine &subeng); + SubEngine *subeng); ~ProgramStateManager(); @@ -481,9 +458,6 @@ public: BasicValueFactory &getBasicVals() { return svalBuilder->getBasicValueFactory(); } - const BasicValueFactory& getBasicVals() const { - return svalBuilder->getBasicValueFactory(); - } SValBuilder &getSValBuilder() { return *svalBuilder; @@ -515,10 +489,6 @@ public: const StackFrameContext *LCtx, SymbolReaper& SymReaper); - /// Marshal a new state for the callee in another translation unit. - /// 'state' is owned by the caller's engine. - ProgramStateRef MarshalState(ProgramStateRef state, const StackFrameContext *L); - public: SVal ArrayToPointer(Loc Array) { @@ -617,10 +587,6 @@ public: return ProgramStateTrait::MakeContext(p); } - const llvm::APSInt* getSymVal(ProgramStateRef St, SymbolRef sym) { - return ConstraintMgr->getSymVal(St, sym); - } - void EndPath(ProgramStateRef St) { ConstraintMgr->EndPath(St); } @@ -631,6 +597,10 @@ public: // Out-of-line method definitions for ProgramState. //===----------------------------------------------------------------------===// +inline ConstraintManager &ProgramState::getConstraintManager() const { + return stateMgr->getConstraintManager(); +} + inline const VarRegion* ProgramState::getRegion(const VarDecl *D, const LocationContext *LC) const { @@ -695,15 +665,10 @@ inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) c return UnknownVal(); } -inline const llvm::APSInt *ProgramState::getSymVal(SymbolRef sym) const { - return getStateManager().getSymVal(this, sym); -} - -inline SVal ProgramState::getSVal(const Stmt *Ex, const LocationContext *LCtx, - bool useOnlyDirectBindings) const{ +inline SVal ProgramState::getSVal(const Stmt *Ex, + const LocationContext *LCtx) const{ return Env.getSVal(EnvironmentEntry(Ex, LCtx), - *getStateManager().svalBuilder, - useOnlyDirectBindings); + *getStateManager().svalBuilder); } inline SVal @@ -821,7 +786,7 @@ public: bool scan(const SymExpr *sym); }; -} // end GR namespace +} // end ento namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index 1c7bedb82f24..ea2a8525ba47 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -31,6 +31,26 @@ namespace clang { namespace ento { template struct ProgramStatePartialTrait; + /// Declares a program state trait for type \p Type called \p Name, and + /// introduce a typedef named \c NameTy. + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ + namespace { \ + class Name {}; \ + typedef Type Name ## Ty; \ + } \ + namespace clang { \ + namespace ento { \ + template <> \ + struct ProgramStateTrait \ + : public ProgramStatePartialTrait { \ + static void *GDMIndex() { static int Index; return &Index; } \ + }; \ + } \ + } + + // Partial-specialization for ImmutableMap. template @@ -71,6 +91,15 @@ namespace ento { } }; + /// Helper for registering a map trait. + /// + /// If the map type were written directly in the invocation of + /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments + /// would be treated as a macro argument separator, which is wrong. + /// This allows the user to specify a map type in a way that the preprocessor + /// can deal with. + #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap + // Partial-specialization for ImmutableSet. @@ -113,6 +142,7 @@ namespace ento { } }; + // Partial-specialization for ImmutableList. template @@ -150,6 +180,7 @@ namespace ento { delete (typename data_type::Factory*) Ctx; } }; + // Partial specialization for bool. template <> struct ProgramStatePartialTrait { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 83c3a5634586..5d72e73a3d94 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -72,7 +72,7 @@ public: virtual ~SValBuilder() {} bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) { - return haveSameType(Sym1->getType(Context), Sym2->getType(Context)); + return haveSameType(Sym1->getType(), Sym2->getType()); } bool haveSameType(QualType Ty1, QualType Ty2) { @@ -142,19 +142,19 @@ public: // Forwarding methods to SymbolManager. - const SymbolConjured* getConjuredSymbol(const Stmt *stmt, - const LocationContext *LCtx, - QualType type, - unsigned visitCount, - const void *symbolTag = 0) { - return SymMgr.getConjuredSymbol(stmt, LCtx, type, visitCount, symbolTag); + const SymbolConjured* conjureSymbol(const Stmt *stmt, + const LocationContext *LCtx, + QualType type, + unsigned visitCount, + const void *symbolTag = 0) { + return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag); } - const SymbolConjured* getConjuredSymbol(const Expr *expr, - const LocationContext *LCtx, - unsigned visitCount, - const void *symbolTag = 0) { - return SymMgr.getConjuredSymbol(expr, LCtx, visitCount, symbolTag); + const SymbolConjured* conjureSymbol(const Expr *expr, + const LocationContext *LCtx, + unsigned visitCount, + const void *symbolTag = 0) { + return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag); } /// Construct an SVal representing '0' for the specified type. @@ -169,20 +169,20 @@ public: /// The advantage of symbols derived/built from other symbols is that we /// preserve the relation between related(or even equivalent) expressions, so /// conjured symbols should be used sparingly. - DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, - const Expr *expr, - const LocationContext *LCtx, - unsigned count); - DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, - const Expr *expr, - const LocationContext *LCtx, - QualType type, - unsigned count); + DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, + const Expr *expr, + const LocationContext *LCtx, + unsigned count); + DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, + const Expr *expr, + const LocationContext *LCtx, + QualType type, + unsigned count); - DefinedOrUnknownSVal getConjuredSymbolVal(const Stmt *stmt, - const LocationContext *LCtx, - QualType type, - unsigned visitCount); + DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt, + const LocationContext *LCtx, + QualType type, + unsigned visitCount); /// \brief Conjure a symbol representing heap allocated memory region. /// /// Note, the expression should represent a location. @@ -227,7 +227,7 @@ public: BasicVals.getValue(integer->getValue(), integer->getType()->isUnsignedIntegerOrEnumerationType())); } - + nonloc::ConcreteInt makeBoolVal(const ObjCBoolLiteralExpr *boolean) { return makeTruthVal(boolean->getValue(), boolean->getType()); } @@ -262,11 +262,6 @@ public: BasicVals.getIntWithPtrWidth(integer, isUnsigned)); } - NonLoc makeIntVal(uint64_t integer, unsigned bitWidth, bool isUnsigned) { - return nonloc::ConcreteInt( - BasicVals.getValue(integer, bitWidth, isUnsigned)); - } - NonLoc makeLocAsInteger(Loc loc, unsigned bits) { return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits)); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index e0b5f64b900b..c2134cf04826 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -154,9 +154,6 @@ public: SymExpr::symbol_iterator symbol_end() const { return SymExpr::symbol_end(); } - - // Implement isa support. - static inline bool classof(const SVal*) { return true; } }; @@ -257,7 +254,7 @@ public: namespace nonloc { -enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind, +enum Kind { ConcreteIntKind, SymbolValKind, LocAsIntegerKind, CompoundValKind, LazyCompoundValKind }; /// \brief Represents symbolic expression. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 138a590b1b24..979546b6ed47 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -25,6 +25,7 @@ namespace clang { class Stmt; class Expr; class ObjCIvarDecl; +class CXXBasePath; class StackFrameContext; namespace ento { @@ -67,15 +68,26 @@ public: virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0; virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V); - virtual StoreRef Remove(Store St, Loc L) = 0; - /// BindCompoundLiteral - Return the store that has the bindings currently - /// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region - /// for the compound literal and 'BegInit' and 'EndInit' represent an - /// array of initializer values. - virtual StoreRef BindCompoundLiteral(Store store, - const CompoundLiteralExpr *cl, - const LocationContext *LC, SVal v) = 0; + /// \brief Create a new store with the specified binding removed. + /// \param ST the original store, that is the basis for the new store. + /// \param L the location whose binding should be removed. + virtual StoreRef killBinding(Store ST, Loc L) = 0; + + /// \brief Create a new store that binds a value to a compound literal. + /// + /// \param ST The original store whose bindings are the basis for the new + /// store. + /// + /// \param CL The compound literal to bind (the binding key). + /// + /// \param LC The LocationContext for the binding. + /// + /// \param V The value to bind to the compound literal. + virtual StoreRef bindCompoundLiteral(Store ST, + const CompoundLiteralExpr *CL, + const LocationContext *LC, + SVal V) = 0; /// getInitialStore - Returns the initial "empty" store representing the /// value bindings upon entry to an analyzed function. @@ -114,11 +126,15 @@ public: /// conversions between arrays and pointers. virtual SVal ArrayToPointer(Loc Array) = 0; - /// Evaluates DerivedToBase casts. - SVal evalDerivedToBase(SVal derived, const CastExpr *Cast); + /// Evaluates a chain of derived-to-base casts through the path specified in + /// \p Cast. + SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast); + + /// Evaluates a chain of derived-to-base casts through the specified path. + SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath); /// Evaluates a derived-to-base cast through a single level of derivation. - virtual SVal evalDerivedToBase(SVal derived, QualType derivedPtrType) = 0; + SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType); /// \brief Evaluates C++ dynamic_cast cast. /// The callback may result in the following 3 scenarios: @@ -128,8 +144,7 @@ public: /// enough info to determine if the cast will succeed at run time). /// The function returns an SVal representing the derived class; it's /// valid only if Failed flag is set to false. - virtual SVal evalDynamicCast(SVal base, QualType derivedPtrType, - bool &Failed) = 0; + SVal evalDynamicCast(SVal Base, QualType DerivedPtrType, bool &Failed); const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T); @@ -141,10 +156,6 @@ public: virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, SymbolReaper& SymReaper) = 0; - virtual StoreRef BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0; - - virtual StoreRef BindDeclWithNoInit(Store store, const VarRegion *VR) = 0; - virtual bool includedInBindings(Store store, const MemRegion *region) const = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 68b81f19a4fd..1e710778d9be 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -60,7 +60,8 @@ public: /// SubEngine is expected to populate dstNodes with new nodes representing /// updated analysis state, or generate no nodes at all if it doesn't. virtual void processCFGBlockEntrance(const BlockEdge &L, - NodeBuilderWithSinks &nodeBuilder) = 0; + NodeBuilderWithSinks &nodeBuilder, + ExplodedNode *Pred) = 0; /// Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. @@ -81,7 +82,8 @@ public: /// Called by CoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. - virtual void processEndOfFunction(NodeBuilderContext& BC) = 0; + virtual void processEndOfFunction(NodeBuilderContext& BC, + ExplodedNode *Pred) = 0; // Generate the entry node of the callee. virtual void processCallEnter(CallEnter CE, ExplodedNode *Pred) = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 5d27f8654eb0..873f773b459d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -65,12 +65,9 @@ public: virtual void dumpToStream(raw_ostream &os) const {} - virtual QualType getType(ASTContext&) const = 0; + virtual QualType getType() const = 0; virtual void Profile(llvm::FoldingSetNodeID& profile) = 0; - // Implement isa support. - static inline bool classof(const SymExpr*) { return true; } - /// \brief Iterator over symbols that the current symbol depends on. /// /// For SymbolData, it's the symbol itself; for expressions, it's the @@ -144,7 +141,7 @@ public: virtual void dumpToStream(raw_ostream &os) const; - QualType getType(ASTContext&) const; + QualType getType() const; // Implement isa support. static inline bool classof(const SymExpr *SE) { @@ -173,7 +170,7 @@ public: unsigned getCount() const { return Count; } const void *getTag() const { return SymbolTag; } - QualType getType(ASTContext&) const; + QualType getType() const; virtual void dumpToStream(raw_ostream &os) const; @@ -211,7 +208,7 @@ public: SymbolRef getParentSymbol() const { return parentSymbol; } const TypedValueRegion *getRegion() const { return R; } - QualType getType(ASTContext&) const; + QualType getType() const; virtual void dumpToStream(raw_ostream &os) const; @@ -244,7 +241,7 @@ public: const SubRegion *getRegion() const { return R; } - QualType getType(ASTContext&) const; + QualType getType() const; virtual void dumpToStream(raw_ostream &os) const; @@ -283,7 +280,7 @@ public: unsigned getCount() const { return Count; } const void *getTag() const { return Tag; } - QualType getType(ASTContext&) const; + QualType getType() const; virtual void dumpToStream(raw_ostream &os) const; @@ -320,7 +317,7 @@ public: SymbolCast(const SymExpr *In, QualType From, QualType To) : SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { } - QualType getType(ASTContext &C) const { return ToTy; } + QualType getType() const { return ToTy; } const SymExpr *getOperand() const { return Operand; } @@ -358,7 +355,7 @@ public: // FIXME: We probably need to make this out-of-line to avoid redundant // generation of virtual functions. - QualType getType(ASTContext &C) const { return T; } + QualType getType() const { return T; } BinaryOperator::Opcode getOpcode() const { return Op; } @@ -399,7 +396,7 @@ public: const SymExpr *rhs, QualType t) : SymExpr(IntSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} - QualType getType(ASTContext &C) const { return T; } + QualType getType() const { return T; } BinaryOperator::Opcode getOpcode() const { return Op; } @@ -446,7 +443,7 @@ public: // FIXME: We probably need to make this out-of-line to avoid redundant // generation of virtual functions. - QualType getType(ASTContext &C) const { return T; } + QualType getType() const { return T; } virtual void dumpToStream(raw_ostream &os) const; @@ -495,18 +492,17 @@ public: /// \brief Make a unique symbol for MemRegion R according to its kind. const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R); - const SymbolConjured* getConjuredSymbol(const Stmt *E, - const LocationContext *LCtx, - QualType T, - unsigned VisitCount, - const void *SymbolTag = 0); + const SymbolConjured* conjureSymbol(const Stmt *E, + const LocationContext *LCtx, + QualType T, + unsigned VisitCount, + const void *SymbolTag = 0); - const SymbolConjured* getConjuredSymbol(const Expr *E, - const LocationContext *LCtx, - unsigned VisitCount, - const void *SymbolTag = 0) { - return getConjuredSymbol(E, LCtx, E->getType(), - VisitCount, SymbolTag); + const SymbolConjured* conjureSymbol(const Expr *E, + const LocationContext *LCtx, + unsigned VisitCount, + const void *SymbolTag = 0) { + return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag); } const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol, @@ -541,7 +537,7 @@ public: const SymExpr *rhs, QualType t); QualType getType(const SymExpr *SE) const { - return SE->getType(Ctx); + return SE->getType(); } /// \brief Add artificial symbol dependency. @@ -584,9 +580,11 @@ public: /// /// If the statement is NULL, everything is this and parent contexts is /// considered live. - SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr, + /// If the stack frame context is NULL, everything on stack is considered + /// dead. + SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr, StoreManager &storeMgr) - : LCtx(ctx->getCurrentStackFrame()), Loc(s), SymMgr(symmgr), + : LCtx(Ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {} ~SymbolReaper() {} diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h index 53205d3b720c..c274cea8413e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h @@ -22,6 +22,8 @@ namespace ento { /// The GDM component containing the tainted root symbols. We lazily infer the /// taint of the dependent symbols. Currently, this is a map from a symbol to /// tag kind. TODO: Should support multiple tag kinds. +// FIXME: This does not use the nice trait macros because it must be accessible +// from multiple translation units. struct TaintMap {}; typedef llvm::ImmutableMap TaintMapImpl; template<> struct ProgramStateTrait diff --git a/include/clang/Tooling/CommandLineClangTool.h b/include/clang/Tooling/CommandLineClangTool.h deleted file mode 100644 index c29c30236416..000000000000 --- a/include/clang/Tooling/CommandLineClangTool.h +++ /dev/null @@ -1,80 +0,0 @@ -//===- CommandLineClangTool.h - command-line clang tools driver -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the CommandLineClangTool class used to run clang -// tools as separate command-line applications with a consistent common -// interface for handling compilation database and input files. -// -// It provides a common subset of command-line options, common algorithm -// for locating a compilation database and source files, and help messages -// for the basic command-line interface. -// -// It creates a CompilationDatabase, initializes a ClangTool and runs a -// user-specified FrontendAction over all TUs in which the given files are -// compiled. -// -// This class uses the Clang Tooling infrastructure, see -// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html -// for details on setting it up with LLVM source tree. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H -#define LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H - -#include "llvm/Support/CommandLine.h" -#include "clang/Tooling/CompilationDatabase.h" - -namespace clang { - -namespace tooling { - -class CompilationDatabase; -class FrontendActionFactory; - -/// \brief A common driver for command-line Clang tools. -/// -/// Parses a common subset of command-line arguments, locates and loads a -/// compilation commands database, runs a tool with user-specified action. It -/// also contains a help message for the common command-line options. -/// An example of usage: -/// @code -/// int main(int argc, const char **argv) { -/// CommandLineClangTool Tool; -/// cl::extrahelp MoreHelp("\nMore help text..."); -/// Tool.initialize(argc, argv); -/// return Tool.run(newFrontendActionFactory()); -/// } -/// @endcode -/// -class CommandLineClangTool { -public: - /// Sets up command-line options and help messages. - /// Add your own help messages after constructing this tool. - CommandLineClangTool(); - - /// Parses command-line, initializes a compilation database. - /// This method exits program in case of error. - void initialize(int argc, const char **argv); - - /// Runs a clang tool with an action created by \c ActionFactory. - int run(FrontendActionFactory *ActionFactory); - -private: - llvm::OwningPtr Compilations; - llvm::cl::opt BuildPath; - llvm::cl::list SourcePaths; - llvm::cl::extrahelp MoreHelp; -}; - -} // namespace tooling - -} // namespace clang - -#endif // LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h new file mode 100644 index 000000000000..a1bad1269d80 --- /dev/null +++ b/include/clang/Tooling/CommonOptionsParser.h @@ -0,0 +1,89 @@ +//===- CommonOptionsParser.h - common options for clang tools -*- C++ -*-=====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CommonOptionsParser class used to parse common +// command-line options for clang tools, so that they can be run as separate +// command-line applications with a consistent common interface for handling +// compilation database and input files. +// +// It provides a common subset of command-line options, common algorithm +// for locating a compilation database and source files, and help messages +// for the basic command-line interface. +// +// It creates a CompilationDatabase and reads common command-line options. +// +// This class uses the Clang Tooling infrastructure, see +// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +// for details on setting it up with LLVM source tree. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H +#define LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H + +#include "clang/Tooling/CompilationDatabase.h" + +namespace clang { +namespace tooling { +/// \brief A parser for options common to all command-line Clang tools. +/// +/// Parses a common subset of command-line arguments, locates and loads a +/// compilation commands database and runs a tool with user-specified action. It +/// also contains a help message for the common command-line options. +/// +/// An example of usage: +/// \code +/// #include "clang/Frontend/FrontendActions.h" +/// #include "clang/Tooling/CommonOptionsParser.h" +/// #include "llvm/Support/CommandLine.h" +/// +/// using namespace clang::tooling; +/// using namespace llvm; +/// +/// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); +/// static cl::extrahelp MoreHelp("\nMore help text..."); +/// static cl:opt YourOwnOption(...); +/// ... +/// +/// int main(int argc, const char **argv) { +/// CommonOptionsParser OptionsParser(argc, argv); +/// ClangTool Tool(OptionsParser.GetCompilations(), +/// OptionsParser.GetSourcePathListi()); +/// return Tool.run(newFrontendActionFactory()); +/// } +/// \endcode +class CommonOptionsParser { +public: + /// \brief Parses command-line, initializes a compilation database. + /// This constructor can change argc and argv contents, e.g. consume + /// command-line options used for creating FixedCompilationDatabase. + /// This constructor exits program in case of error. + CommonOptionsParser(int &argc, const char **argv); + + /// Returns a reference to the loaded compilations database. + CompilationDatabase &GetCompilations() { + return *Compilations; + } + + /// Returns a list of source file paths to process. + std::vector GetSourcePathList() { + return SourcePathList; + } + + static const char *const HelpMessage; + +private: + llvm::OwningPtr Compilations; + std::vector SourcePathList; +}; + +} // namespace tooling +} // namespace clang + +#endif // LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h index f78ffaed284c..a40bffec78ba 100644 --- a/include/clang/Tooling/CompilationDatabase.h +++ b/include/clang/Tooling/CompilationDatabase.h @@ -31,12 +31,9 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/YAMLParser.h" + #include #include @@ -111,6 +108,27 @@ public: virtual std::vector getAllFiles() const = 0; }; +/// \brief Interface for compilation database plugins. +/// +/// A compilation database plugin allows the user to register custom compilation +/// databases that are picked up as compilation database if the corresponding +/// library is linked in. To register a plugin, declare a static variable like: +/// +/// \code +/// static CompilationDatabasePluginRegistry::Add +/// X("my-compilation-database", "Reads my own compilation database"); +/// \endcode +class CompilationDatabasePlugin { +public: + virtual ~CompilationDatabasePlugin(); + + /// \brief Loads a compilation database from a build directory. + /// + /// \see CompilationDatabase::loadFromDirectory(). + virtual CompilationDatabase *loadFromDirectory(StringRef Directory, + std::string &ErrorMessage) = 0; +}; + /// \brief A compilation database that returns a single compile command line. /// /// Useful when we want a tool to behave more like a compiler invocation. @@ -169,75 +187,6 @@ private: std::vector CompileCommands; }; -/// \brief A JSON based compilation database. -/// -/// JSON compilation database files must contain a list of JSON objects which -/// provide the command lines in the attributes 'directory', 'command' and -/// 'file': -/// [ -/// { "directory": "", -/// "command": "", -/// "file": "" -/// }, -/// ... -/// ] -/// Each object entry defines one compile action. The specified file is -/// considered to be the main source file for the translation unit. -/// -/// JSON compilation databases can for example be generated in CMake projects -/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS. -class JSONCompilationDatabase : public CompilationDatabase { -public: - /// \brief Loads a JSON compilation database from the specified file. - /// - /// Returns NULL and sets ErrorMessage if the database could not be - /// loaded from the given file. - static JSONCompilationDatabase *loadFromFile(StringRef FilePath, - std::string &ErrorMessage); - - /// \brief Loads a JSON compilation database from a data buffer. - /// - /// Returns NULL and sets ErrorMessage if the database could not be loaded. - static JSONCompilationDatabase *loadFromBuffer(StringRef DatabaseString, - std::string &ErrorMessage); - - /// \brief Returns all compile comamnds in which the specified file was - /// compiled. - /// - /// FIXME: Currently FilePath must be an absolute path inside the - /// source directory which does not have symlinks resolved. - virtual std::vector getCompileCommands( - StringRef FilePath) const; - - /// \brief Returns the list of all files available in the compilation database. - /// - /// These are the 'file' entries of the JSON objects. - virtual std::vector getAllFiles() const; - -private: - /// \brief Constructs a JSON compilation database on a memory buffer. - JSONCompilationDatabase(llvm::MemoryBuffer *Database) - : Database(Database), YAMLStream(Database->getBuffer(), SM) {} - - /// \brief Parses the database file and creates the index. - /// - /// Returns whether parsing succeeded. Sets ErrorMessage if parsing - /// failed. - bool parse(std::string &ErrorMessage); - - // Tuple (directory, commandline) where 'commandline' pointing to the - // corresponding nodes in the YAML stream. - typedef std::pair CompileCommandRef; - - // Maps file paths to the compile command lines for that file. - llvm::StringMap< std::vector > IndexByFile; - - llvm::OwningPtr Database; - llvm::SourceMgr SM; - llvm::yaml::Stream YAMLStream; -}; - } // end namespace tooling } // end namespace clang diff --git a/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/include/clang/Tooling/CompilationDatabasePluginRegistry.h new file mode 100644 index 000000000000..84fcd24b4a12 --- /dev/null +++ b/include/clang/Tooling/CompilationDatabasePluginRegistry.h @@ -0,0 +1,27 @@ +//===--- CompilationDatabasePluginRegistry.h - ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_COMPILATION_DATABASE_PLUGIN_REGISTRY_H +#define LLVM_CLANG_TOOLING_COMPILATION_DATABASE_PLUGIN_REGISTRY_H + +#include "clang/Tooling/CompilationDatabase.h" +#include "llvm/Support/Registry.h" + +namespace clang { +namespace tooling { + +class CompilationDatabasePlugin; + +typedef llvm::Registry + CompilationDatabasePluginRegistry; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_PLUGIN_REGISTRY_H diff --git a/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h new file mode 100644 index 000000000000..ff988bebf2ca --- /dev/null +++ b/include/clang/Tooling/FileMatchTrie.h @@ -0,0 +1,90 @@ +//===--- FileMatchTrie.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 implements a match trie to find the matching file in a compilation +// database based on a given path in the presence of symlinks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H +#define LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" + +#include +#include + +namespace clang { +namespace tooling { + +struct PathComparator { + virtual ~PathComparator() {} + virtual bool equivalent(StringRef FileA, StringRef FileB) const = 0; +}; +class FileMatchTrieNode; + +/// \brief A trie to efficiently match against the entries of the compilation +/// database in order of matching suffix length. +/// +/// When a clang tool is supposed to operate on a specific file, we have to +/// find the corresponding file in the compilation database. Although entries +/// in the compilation database are keyed by filename, a simple string match +/// is insufficient because of symlinks. Commonly, a project hierarchy looks +/// like this: +/// //src//.cc (used as input for the tool) +/// //build///.cc (stored in DB) +/// +/// Furthermore, there might be symlinks inside the source folder or inside the +/// database, so that the same source file is translated with different build +/// options. +/// +/// For a given input file, the \c FileMatchTrie finds its entries in order +/// of matching suffix length. For each suffix length, there might be one or +/// more entries in the database. For each of those entries, it calls +/// \c llvm::sys::fs::equivalent() (injected as \c PathComparator). There might +/// be zero or more entries with the same matching suffix length that are +/// equivalent to the input file. Three cases are distinguished: +/// 0 equivalent files: Continue with the next suffix length. +/// 1 equivalent file: Best match found, return it. +/// >1 equivalent files: Match is ambiguous, return error. +class FileMatchTrie { +public: + FileMatchTrie(); + + /// \brief Construct a new \c FileMatchTrie with the given \c PathComparator. + /// + /// The \c FileMatchTrie takes ownership of 'Comparator'. Used for testing. + FileMatchTrie(PathComparator* Comparator); + + ~FileMatchTrie(); + + /// \brief Insert a new absolute path. Relative paths are ignored. + void insert(StringRef NewPath); + + /// \brief Finds the corresponding file in this trie. + /// + /// Returns file name stored in this trie that is equivalent to 'FileName' + /// according to 'Comparator', if it can be uniquely identified. If there + /// are no matches an empty \c StringRef is returned. If there are ambigious + /// matches, an empty \c StringRef is returned and a corresponding message + /// written to 'Error'. + StringRef findEquivalent(StringRef FileName, + llvm::raw_ostream &Error) const; +private: + FileMatchTrieNode *Root; + OwningPtr Comparator; +}; + + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H diff --git a/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h new file mode 100644 index 000000000000..d62ab5c5036e --- /dev/null +++ b/include/clang/Tooling/JSONCompilationDatabase.h @@ -0,0 +1,107 @@ +//===--- JSONCompilationDatabase.h - ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The JSONCompilationDatabase finds compilation databases supplied as a file +// 'compile_commands.json'. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_JSON_COMPILATION_DATABASE_H +#define LLVM_CLANG_TOOLING_JSON_COMPILATION_DATABASE_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/CompilationDatabase.h" +#include "clang/Tooling/FileMatchTrie.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLParser.h" +#include +#include + +namespace clang { +namespace tooling { + +/// \brief A JSON based compilation database. +/// +/// JSON compilation database files must contain a list of JSON objects which +/// provide the command lines in the attributes 'directory', 'command' and +/// 'file': +/// [ +/// { "directory": "", +/// "command": "", +/// "file": "" +/// }, +/// ... +/// ] +/// Each object entry defines one compile action. The specified file is +/// considered to be the main source file for the translation unit. +/// +/// JSON compilation databases can for example be generated in CMake projects +/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS. +class JSONCompilationDatabase : public CompilationDatabase { +public: + /// \brief Loads a JSON compilation database from the specified file. + /// + /// Returns NULL and sets ErrorMessage if the database could not be + /// loaded from the given file. + static JSONCompilationDatabase *loadFromFile(StringRef FilePath, + std::string &ErrorMessage); + + /// \brief Loads a JSON compilation database from a data buffer. + /// + /// Returns NULL and sets ErrorMessage if the database could not be loaded. + static JSONCompilationDatabase *loadFromBuffer(StringRef DatabaseString, + std::string &ErrorMessage); + + /// \brief Returns all compile comamnds in which the specified file was + /// compiled. + /// + /// FIXME: Currently FilePath must be an absolute path inside the + /// source directory which does not have symlinks resolved. + virtual std::vector getCompileCommands( + StringRef FilePath) const; + + /// \brief Returns the list of all files available in the compilation database. + /// + /// These are the 'file' entries of the JSON objects. + virtual std::vector getAllFiles() const; + +private: + /// \brief Constructs a JSON compilation database on a memory buffer. + JSONCompilationDatabase(llvm::MemoryBuffer *Database) + : Database(Database), YAMLStream(Database->getBuffer(), SM) {} + + /// \brief Parses the database file and creates the index. + /// + /// Returns whether parsing succeeded. Sets ErrorMessage if parsing + /// failed. + bool parse(std::string &ErrorMessage); + + // Tuple (directory, commandline) where 'commandline' pointing to the + // corresponding nodes in the YAML stream. + typedef std::pair CompileCommandRef; + + // Maps file paths to the compile command lines for that file. + llvm::StringMap< std::vector > IndexByFile; + + FileMatchTrie MatchTrie; + + llvm::OwningPtr Database; + llvm::SourceMgr SM; + llvm::yaml::Stream YAMLStream; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_JSON_COMPILATION_DATABASE_H diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h index 0e42a0ec64fc..aaffc1a29e06 100644 --- a/include/clang/Tooling/Refactoring.h +++ b/include/clang/Tooling/Refactoring.h @@ -74,6 +74,7 @@ public: StringRef getFilePath() const { return FilePath; } unsigned getOffset() const { return Offset; } unsigned getLength() const { return Length; } + StringRef getReplacementText() const { return ReplacementText; } /// @} /// \brief Applies the replacement on the Rewriter. diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index e06705f0279b..a03bcb1bbb84 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -74,6 +74,14 @@ public: template FrontendActionFactory *newFrontendActionFactory(); +/// \brief Called at the end of each source file when used with +/// \c newFrontendActionFactory. +class EndOfSourceFileCallback { +public: + virtual ~EndOfSourceFileCallback() {} + virtual void run() = 0; +}; + /// \brief Returns a new FrontendActionFactory for any type that provides an /// implementation of newASTConsumer(). /// @@ -87,7 +95,7 @@ FrontendActionFactory *newFrontendActionFactory(); /// newFrontendActionFactory(&Factory); template inline FrontendActionFactory *newFrontendActionFactory( - FactoryT *ConsumerFactory); + FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback = NULL); /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. /// @@ -99,6 +107,19 @@ inline FrontendActionFactory *newFrontendActionFactory( bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, const Twine &FileName = "input.cc"); +/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and +/// with additional other flags. +/// +/// \param ToolAction The action to run over the code. +/// \param Code C++ code. +/// \param Args Additional flags to pass on. +/// \param FileName The file name which 'Code' will be mapped as. +/// +/// \return - True if 'ToolAction' was successfully executed. +bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code, + const std::vector &Args, + const Twine &FileName = "input.cc"); + /// \brief Utility to run a FrontendAction in a single clang invocation. class ToolInvocation { public: @@ -204,34 +225,45 @@ FrontendActionFactory *newFrontendActionFactory() { template inline FrontendActionFactory *newFrontendActionFactory( - FactoryT *ConsumerFactory) { + FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback) { class FrontendActionFactoryAdapter : public FrontendActionFactory { public: - explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory) - : ConsumerFactory(ConsumerFactory) {} + explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory, + EndOfSourceFileCallback *EndCallback) + : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {} virtual clang::FrontendAction *create() { - return new ConsumerFactoryAdaptor(ConsumerFactory); + return new ConsumerFactoryAdaptor(ConsumerFactory, EndCallback); } private: class ConsumerFactoryAdaptor : public clang::ASTFrontendAction { public: - ConsumerFactoryAdaptor(FactoryT *ConsumerFactory) - : ConsumerFactory(ConsumerFactory) {} + ConsumerFactoryAdaptor(FactoryT *ConsumerFactory, + EndOfSourceFileCallback *EndCallback) + : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {} clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &, llvm::StringRef) { return ConsumerFactory->newASTConsumer(); } + protected: + virtual void EndSourceFileAction() { + if (EndCallback != NULL) + EndCallback->run(); + clang::ASTFrontendAction::EndSourceFileAction(); + } + private: FactoryT *ConsumerFactory; + EndOfSourceFileCallback *EndCallback; }; FactoryT *ConsumerFactory; + EndOfSourceFileCallback *EndCallback; }; - return new FrontendActionFactoryAdapter(ConsumerFactory); + return new FrontendActionFactoryAdapter(ConsumerFactory, EndCallback); } /// \brief Returns the absolute path of \c File, by prepending it with -- cgit v1.2.3

; -def _no_pedantic : Flag<"--no-pedantic">, Alias; -def _no_standard_includes : Flag<"--no-standard-includes">, Alias; -def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias; -def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>; -def _no_warnings : Flag<"--no-warnings">, Alias; -def _optimize_EQ : Joined<"--optimize=">, Alias; -def _optimize : Flag<"--optimize">, Alias; -def _output_class_directory_EQ : Joined<"--output-class-directory=">, Alias; -def _output_class_directory : Separate<"--output-class-directory">, Alias; -def _output_EQ : Joined<"--output=">, Alias; -def _output : Separate<"--output">, Alias; -def _param : Separate<"--param">; -def _param_EQ : Joined<"--param=">, Alias<_param>; -def _pass_exit_codes : Flag<"--pass-exit-codes">, Alias; -def _pedantic_errors : Flag<"--pedantic-errors">, Alias; -def _pedantic : Flag<"--pedantic">, Alias; -def _pipe : Flag<"--pipe">, Alias; -def _prefix_EQ : Joined<"--prefix=">, Alias; -def _prefix : Separate<"--prefix">, Alias; -def _preprocess : Flag<"--preprocess">, Alias; -def _print_diagnostic_categories : Flag<"--print-diagnostic-categories">; -def _print_file_name_EQ : Joined<"--print-file-name=">, Alias; -def _print_file_name : Separate<"--print-file-name">, Alias; -def _print_libgcc_file_name : Flag<"--print-libgcc-file-name">, Alias; -def _print_missing_file_dependencies : Flag<"--print-missing-file-dependencies">, Alias; -def _print_multi_directory : Flag<"--print-multi-directory">, Alias; -def _print_multi_lib : Flag<"--print-multi-lib">, Alias; -def _print_multi_os_directory : Flag<"--print-multi-os-directory">, Alias; -def _print_prog_name_EQ : Joined<"--print-prog-name=">, Alias; -def _print_prog_name : Separate<"--print-prog-name">, Alias; -def _print_search_dirs : Flag<"--print-search-dirs">, Alias; -def _profile_blocks : Flag<"--profile-blocks">, Alias; -def _profile : Flag<"--profile">, Alias