aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2011-02-20 13:06:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2011-02-20 13:06:31 +0000
commitbca07a4524feb4edec581062d631a13116320a24 (patch)
treea9243275843fbeaa590afc07ee888e006b8d54ea /include/clang
parent998bc5802ecdd65ce3b270f6c69a8ae8557f0a10 (diff)
downloadsrc-bca07a4524feb4edec581062d631a13116320a24.tar.gz
src-bca07a4524feb4edec581062d631a13116320a24.zip
Vendor import of clang trunk r126079:vendor/clang/clang-r126079
Notes
Notes: svn path=/vendor/clang/dist/; revision=218887 svn path=/vendor/clang/clang-r126079/; revision=218888; tag=vendor/clang/clang-r126079
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/ASTConsumer.h8
-rw-r--r--include/clang/AST/ASTContext.h545
-rw-r--r--include/clang/AST/ASTDiagnostic.h2
-rw-r--r--include/clang/AST/ASTImporter.h55
-rw-r--r--include/clang/AST/ASTMutationListener.h48
-rw-r--r--include/clang/AST/Attr.h31
-rw-r--r--include/clang/AST/CXXInheritance.h7
-rw-r--r--include/clang/AST/CanonicalType.h20
-rw-r--r--include/clang/AST/CharUnits.h50
-rw-r--r--include/clang/AST/Decl.h581
-rw-r--r--include/clang/AST/DeclBase.h75
-rw-r--r--include/clang/AST/DeclCXX.h563
-rw-r--r--include/clang/AST/DeclFriend.h29
-rw-r--r--include/clang/AST/DeclGroup.h2
-rw-r--r--include/clang/AST/DeclObjC.h119
-rw-r--r--include/clang/AST/DeclTemplate.h402
-rw-r--r--include/clang/AST/DeclarationName.h10
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h82
-rw-r--r--include/clang/AST/Expr.h1158
-rw-r--r--include/clang/AST/ExprCXX.h1061
-rw-r--r--include/clang/AST/ExprObjC.h386
-rw-r--r--include/clang/AST/ExternalASTSource.h48
-rw-r--r--include/clang/AST/FullExpr.h88
-rw-r--r--include/clang/AST/Mangle.h150
-rw-r--r--include/clang/AST/NestedNameSpecifier.h23
-rw-r--r--include/clang/AST/OperationKinds.h201
-rw-r--r--include/clang/AST/ParentMap.h10
-rw-r--r--include/clang/AST/PrettyPrinter.h4
-rw-r--r--include/clang/AST/RecordLayout.h169
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h325
-rw-r--r--include/clang/AST/Redeclarable.h20
-rw-r--r--include/clang/AST/Stmt.h371
-rw-r--r--include/clang/AST/StmtCXX.h12
-rw-r--r--include/clang/AST/StmtIterator.h96
-rw-r--r--include/clang/AST/StmtObjC.h39
-rw-r--r--include/clang/AST/TemplateBase.h283
-rw-r--r--include/clang/AST/TemplateName.h146
-rw-r--r--include/clang/AST/Type.h1915
-rw-r--r--include/clang/AST/TypeLoc.h347
-rw-r--r--include/clang/AST/TypeLocBuilder.h155
-rw-r--r--include/clang/AST/TypeNodes.def5
-rw-r--r--include/clang/AST/TypeVisitor.h9
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h13
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h3
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValuesV2.h40
-rw-r--r--include/clang/Analysis/AnalysisContext.h37
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h2
-rw-r--r--include/clang/Analysis/CFG.h409
-rw-r--r--include/clang/Analysis/DomainSpecific/CocoaConventions.h (renamed from include/clang/Checker/DomainSpecific/CocoaConventions.h)9
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h18
-rw-r--r--include/clang/Analysis/ProgramPoint.h48
-rw-r--r--include/clang/Analysis/Support/BumpVector.h29
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h4
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtVisitor.h5
-rw-r--r--include/clang/Analysis/Visitors/CFGStmtVisitor.h4
-rw-r--r--include/clang/Basic/ABI.h126
-rw-r--r--include/clang/Basic/Attr.td241
-rw-r--r--include/clang/Basic/AttrKinds.h1
-rw-r--r--include/clang/Basic/Builtins.def291
-rw-r--r--include/clang/Basic/Builtins.h23
-rw-r--r--include/clang/Basic/BuiltinsPPC.def22
-rw-r--r--include/clang/Basic/BuiltinsX86.def15
-rw-r--r--include/clang/Basic/DeclNodes.td4
-rw-r--r--include/clang/Basic/Diagnostic.h440
-rw-r--r--include/clang/Basic/Diagnostic.td2
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td29
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td14
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td30
-rw-r--r--include/clang/Basic/DiagnosticGroups.td48
-rw-r--r--include/clang/Basic/DiagnosticIDs.h212
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td14
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td87
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td720
-rw-r--r--include/clang/Basic/FileManager.h190
-rw-r--r--include/clang/Basic/FileSystemOptions.h31
-rw-r--r--include/clang/Basic/FileSystemStatCache.h101
-rw-r--r--include/clang/Basic/IdentifierTable.h93
-rw-r--r--include/clang/Basic/LangOptions.h90
-rw-r--r--include/clang/Basic/OnDiskHashTable.h70
-rw-r--r--include/clang/Basic/OpenCLExtensions.def28
-rw-r--r--include/clang/Basic/PartialDiagnostic.h55
-rw-r--r--include/clang/Basic/SourceLocation.h45
-rw-r--r--include/clang/Basic/SourceManager.h36
-rw-r--r--include/clang/Basic/Specifiers.h17
-rw-r--r--include/clang/Basic/StmtNodes.td24
-rw-r--r--include/clang/Basic/TargetInfo.h35
-rw-r--r--include/clang/Basic/TokenKinds.def40
-rw-r--r--include/clang/Basic/TokenKinds.h6
-rw-r--r--include/clang/Basic/TypeTraits.h6
-rw-r--r--include/clang/Basic/Version.h2
-rw-r--r--include/clang/Basic/Visibility.h48
-rw-r--r--include/clang/Basic/arm_neon.td386
-rw-r--r--include/clang/CMakeLists.txt1
-rw-r--r--include/clang/Checker/AnalysisConsumer.h35
-rw-r--r--include/clang/Checker/Checkers/LocalCheckers.h61
-rw-r--r--include/clang/Checker/ManagerRegistry.h53
-rw-r--r--include/clang/Checker/PathSensitive/GRAuditor.h35
-rw-r--r--include/clang/Checker/PathSensitive/GRSimpleAPICheck.h31
-rw-r--r--include/clang/Checker/PathSensitive/GRSubEngine.h107
-rw-r--r--include/clang/Checker/PathSensitive/GRTransferFuncs.h87
-rw-r--r--include/clang/Checker/PathSensitive/GRWorkList.h79
-rw-r--r--include/clang/Checker/PathSensitive/SValuator.h70
-rw-r--r--include/clang/CodeGen/CodeGenAction.h26
-rw-r--r--include/clang/Config/config.h.cmake17
-rw-r--r--include/clang/Driver/ArgList.h2
-rw-r--r--include/clang/Driver/CC1AsOptions.td4
-rw-r--r--include/clang/Driver/CC1Options.td133
-rw-r--r--include/clang/Driver/Driver.h22
-rw-r--r--include/clang/Driver/DriverDiagnostic.h2
-rw-r--r--include/clang/Driver/HostInfo.h2
-rw-r--r--include/clang/Driver/OptTable.h4
-rw-r--r--include/clang/Driver/Options.td76
-rw-r--r--include/clang/Driver/ToolChain.h39
-rw-r--r--include/clang/Driver/Types.def1
-rw-r--r--include/clang/Frontend/ASTConsumers.h10
-rw-r--r--include/clang/Frontend/ASTUnit.h151
-rw-r--r--include/clang/Frontend/Analyses.def40
-rw-r--r--include/clang/Frontend/AnalyzerOptions.h15
-rw-r--r--include/clang/Frontend/CodeGenOptions.h32
-rw-r--r--include/clang/Frontend/CommandLineSourceLoc.h8
-rw-r--r--include/clang/Frontend/CompilerInstance.h102
-rw-r--r--include/clang/Frontend/CompilerInvocation.h35
-rw-r--r--include/clang/Frontend/DeclXML.def5
-rw-r--r--include/clang/Frontend/DependencyOutputOptions.h10
-rw-r--r--include/clang/Frontend/DiagnosticOptions.h4
-rw-r--r--include/clang/Frontend/FrontendAction.h7
-rw-r--r--include/clang/Frontend/FrontendActions.h13
-rw-r--r--include/clang/Frontend/FrontendDiagnostic.h2
-rw-r--r--include/clang/Frontend/FrontendOptions.h16
-rw-r--r--include/clang/Frontend/HeaderSearchOptions.h3
-rw-r--r--include/clang/Frontend/LangStandards.def5
-rw-r--r--include/clang/Frontend/MultiplexConsumer.h54
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h17
-rw-r--r--include/clang/Frontend/PreprocessorOutputOptions.h2
-rw-r--r--include/clang/Frontend/StmtXML.def7
-rw-r--r--include/clang/Frontend/TypeXML.def10
-rw-r--r--include/clang/Frontend/Utils.h12
-rw-r--r--include/clang/Frontend/VerifyDiagnosticsClient.h4
-rw-r--r--include/clang/Lex/CMakeLists.txt6
-rw-r--r--include/clang/Lex/ExternalPreprocessorSource.h3
-rw-r--r--include/clang/Lex/HeaderMap.h2
-rw-r--r--include/clang/Lex/HeaderSearch.h61
-rw-r--r--include/clang/Lex/LexDiagnostic.h2
-rw-r--r--include/clang/Lex/Lexer.h53
-rw-r--r--include/clang/Lex/LiteralSupport.h31
-rw-r--r--include/clang/Lex/MacroInfo.h13
-rw-r--r--include/clang/Lex/Makefile13
-rw-r--r--include/clang/Lex/PPCallbacks.h139
-rw-r--r--include/clang/Lex/PTHManager.h6
-rw-r--r--include/clang/Lex/Pragma.h31
-rw-r--r--include/clang/Lex/PreprocessingRecord.h93
-rw-r--r--include/clang/Lex/Preprocessor.h106
-rw-r--r--include/clang/Lex/PreprocessorLexer.h12
-rw-r--r--include/clang/Lex/Token.h42
-rw-r--r--include/clang/Makefile2
-rw-r--r--include/clang/Parse/ParseDiagnostic.h2
-rw-r--r--include/clang/Parse/Parser.h358
-rw-r--r--include/clang/Rewrite/ASTConsumers.h2
-rw-r--r--include/clang/Rewrite/FixItRewriter.h2
-rw-r--r--include/clang/Sema/AttributeList.h108
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h282
-rw-r--r--include/clang/Sema/DeclSpec.h328
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h41
-rw-r--r--include/clang/Sema/ExternalSemaSource.h8
-rw-r--r--include/clang/Sema/Initialization.h55
-rw-r--r--include/clang/Sema/Lookup.h20
-rw-r--r--include/clang/Sema/Overload.h48
-rw-r--r--include/clang/Sema/Ownership.h9
-rw-r--r--include/clang/Sema/ParsedTemplate.h30
-rw-r--r--include/clang/Sema/Scope.h23
-rw-r--r--include/clang/Sema/ScopeInfo.h38
-rw-r--r--include/clang/Sema/Sema.h1325
-rw-r--r--include/clang/Sema/SemaDiagnostic.h2
-rw-r--r--include/clang/Sema/Template.h211
-rw-r--r--include/clang/Sema/TemplateDeduction.h25
-rw-r--r--include/clang/Serialization/ASTBitCodes.h135
-rw-r--r--include/clang/Serialization/ASTDeserializationListener.h21
-rw-r--r--include/clang/Serialization/ASTReader.h484
-rw-r--r--include/clang/Serialization/ASTSerializationListener.h44
-rw-r--r--include/clang/Serialization/ASTWriter.h230
-rw-r--r--include/clang/StaticAnalyzer/Checkers/CheckerBase.td38
-rw-r--r--include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h (renamed from include/clang/Checker/Checkers/DereferenceChecker.h)14
-rw-r--r--include/clang/StaticAnalyzer/Checkers/LocalCheckers.h51
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h (renamed from include/clang/Checker/BugReporter/BugReporter.h)99
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h (renamed from include/clang/Checker/BugReporter/BugType.h)8
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (renamed from include/clang/Checker/BugReporter/PathDiagnostic.h)6
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h109
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerProvider.h54
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerV2.h93
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h (renamed from include/clang/Checker/PathDiagnosticClients.h)20
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h (renamed from include/clang/Checker/PathSensitive/AnalysisManager.h)64
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h (renamed from include/clang/Checker/PathSensitive/BasicValueFactory.h)32
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h (renamed from include/clang/Checker/PathSensitive/GRBlockCounter.h)24
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h (renamed from include/clang/Checker/PathSensitive/Checker.h)166
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h (renamed from include/clang/Checker/PathSensitive/CheckerHelpers.h)13
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def (renamed from include/clang/Checker/PathSensitive/CheckerVisitor.def)23
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h (renamed from include/clang/Checker/PathSensitive/CheckerVisitor.h)38
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h (renamed from include/clang/Checker/PathSensitive/ConstraintManager.h)28
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h (renamed from include/clang/Checker/PathSensitive/GRCoreEngine.h)295
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h (renamed from include/clang/Checker/PathSensitive/Environment.h)40
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h (renamed from include/clang/Checker/PathSensitive/ExplodedGraph.h)77
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (renamed from include/clang/Checker/PathSensitive/GRExprEngine.h)310
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h (renamed from include/clang/Checker/PathSensitive/GRExprEngineBuilders.h)40
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h (renamed from include/clang/Checker/PathSensitive/GRState.h)267
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h (renamed from include/clang/Checker/PathSensitive/GRStateTrait.h)31
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h (renamed from include/clang/Checker/PathSensitive/MemRegion.h)119
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h210
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h (renamed from include/clang/Checker/PathSensitive/ValueManager.h)124
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h (renamed from include/clang/Checker/PathSensitive/SVals.h)119
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (renamed from include/clang/Checker/PathSensitive/Store.h)166
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h116
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h (renamed from include/clang/Checker/PathSensitive/SummaryManager.h)8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h (renamed from include/clang/Checker/PathSensitive/SymbolManager.h)18
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h93
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h101
-rw-r--r--include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h26
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h (renamed from include/clang/Checker/FrontendActions.h)10
218 files changed, 15902 insertions, 6941 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 84833c099f97..08ee4ef40de0 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -19,6 +19,7 @@ namespace clang {
class CXXRecordDecl;
class DeclGroupRef;
class HandleTagDeclDefinition;
+ class ASTMutationListener;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
@@ -86,10 +87,13 @@ public:
/// it was actually used.
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
+ /// \brief If the consumer is interested in entities getting modified after
+ /// their initial creation, it should return a pointer to
+ /// a GetASTMutationListener here.
+ virtual ASTMutationListener *GetASTMutationListener() { return 0; }
+
/// \brief If the consumer is interested in entities being deserialized from
/// AST files, it should return a pointer to a ASTDeserializationListener here
- ///
- /// The return type is void* because ASTDS lives in Frontend.
virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
/// PrintStats - If desired, print any statistics.
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index ae4ee946fe27..0e887133d01e 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -45,6 +45,7 @@ namespace clang {
class Diagnostic;
class Expr;
class ExternalASTSource;
+ class ASTMutationListener;
class IdentifierTable;
class SelectorTable;
class SourceManager;
@@ -56,6 +57,7 @@ namespace clang {
class CXXRecordDecl;
class Decl;
class FieldDecl;
+ class MangleContext;
class ObjCIvarDecl;
class ObjCIvarRefExpr;
class ObjCPropertyDecl;
@@ -78,49 +80,61 @@ namespace clang {
class ASTContext {
ASTContext &this_() { return *this; }
- std::vector<Type*> Types;
- llvm::FoldingSet<ExtQuals> ExtQualNodes;
- llvm::FoldingSet<ComplexType> ComplexTypes;
- llvm::FoldingSet<PointerType> PointerTypes;
- llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
- llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
- llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
- llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
- llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
- llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
- std::vector<VariableArrayType*> VariableArrayTypes;
- llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
- llvm::FoldingSet<DependentSizedExtVectorType> DependentSizedExtVectorTypes;
- llvm::FoldingSet<VectorType> VectorTypes;
- llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
- llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
- llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
- llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
- llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
- llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;
- llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
+ mutable std::vector<Type*> Types;
+ mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
+ mutable llvm::FoldingSet<ComplexType> ComplexTypes;
+ mutable llvm::FoldingSet<PointerType> PointerTypes;
+ mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
+ mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
+ mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
+ mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
+ mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
+ mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
+ mutable std::vector<VariableArrayType*> VariableArrayTypes;
+ mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
+ mutable llvm::FoldingSet<DependentSizedExtVectorType>
+ DependentSizedExtVectorTypes;
+ mutable llvm::FoldingSet<VectorType> VectorTypes;
+ mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
+ mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
+ mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
+ mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
+ mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
+ mutable llvm::FoldingSet<SubstTemplateTypeParmType>
+ SubstTemplateTypeParmTypes;
+ mutable llvm::FoldingSet<SubstTemplateTypeParmPackType>
+ SubstTemplateTypeParmPackTypes;
+ mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
TemplateSpecializationTypes;
- llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
- llvm::FoldingSet<DependentNameType> DependentNameTypes;
- llvm::ContextualFoldingSet<DependentTemplateSpecializationType, ASTContext&>
+ mutable llvm::FoldingSet<ParenType> ParenTypes;
+ mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
+ mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
+ mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
+ ASTContext&>
DependentTemplateSpecializationTypes;
- llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
- llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
-
- llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
- llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
-
+ llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
+ mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
+ mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ llvm::FoldingSet<AttributedType> AttributedTypes;
+
+ mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
+ mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
+ mutable llvm::FoldingSet<SubstTemplateTemplateParmPackStorage>
+ SubstTemplateTemplateParmPacks;
+
/// \brief The set of nested name specifiers.
///
/// This set is managed by the NestedNameSpecifier class.
- llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
- NestedNameSpecifier *GlobalNestedNameSpecifier;
+ mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
+ mutable NestedNameSpecifier *GlobalNestedNameSpecifier;
friend class NestedNameSpecifier;
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
/// This is lazily created. This is intentionally not serialized.
- llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
- llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts;
+ mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>
+ ASTRecordLayouts;
+ mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*>
+ ObjCLayouts;
/// KeyFunctions - A cache mapping from CXXRecordDecls to key functions.
llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions;
@@ -128,6 +142,9 @@ class ASTContext {
/// \brief Mapping from ObjCContainers to their ObjCImplementations.
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
+ /// \brief Mapping from __block VarDecls to their copy initialization expr.
+ llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
+
/// \brief Representation of a "canonical" template template parameter that
/// is used in canonical template names.
class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
@@ -144,10 +161,11 @@ class ASTContext {
static void Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *Parm);
};
- llvm::FoldingSet<CanonicalTemplateTemplateParm> CanonTemplateTemplateParms;
+ mutable llvm::FoldingSet<CanonicalTemplateTemplateParm>
+ CanonTemplateTemplateParms;
- TemplateTemplateParmDecl *getCanonicalTemplateTemplateParmDecl(
- TemplateTemplateParmDecl *TTP);
+ TemplateTemplateParmDecl *
+ getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
/// \brief Whether __[u]int128_t identifier is installed.
bool IsInt128Installed;
@@ -171,11 +189,11 @@ class ASTContext {
QualType ObjCClassTypedefType;
QualType ObjCConstantStringType;
- RecordDecl *CFConstantStringTypeDecl;
+ mutable RecordDecl *CFConstantStringTypeDecl;
- RecordDecl *NSConstantStringTypeDecl;
+ mutable RecordDecl *NSConstantStringTypeDecl;
- RecordDecl *ObjCFastEnumerationStateTypeDecl;
+ mutable RecordDecl *ObjCFastEnumerationStateTypeDecl;
/// \brief The type for the C FILE type.
TypeDecl *FILEDecl;
@@ -187,10 +205,13 @@ class ASTContext {
TypeDecl *sigjmp_bufDecl;
/// \brief Type for the Block descriptor for Blocks CodeGen.
- RecordDecl *BlockDescriptorType;
+ mutable RecordDecl *BlockDescriptorType;
/// \brief Type for the Block descriptor for Blocks CodeGen.
- RecordDecl *BlockDescriptorExtendedType;
+ mutable RecordDecl *BlockDescriptorExtendedType;
+
+ /// \brief Declaration for the CUDA cudaConfigureCall function.
+ FunctionDecl *cudaConfigureCallDecl;
TypeSourceInfo NullTypeSourceInfo;
@@ -279,7 +300,7 @@ class ASTContext {
///
/// AST objects are never destructed; rather, all memory associated with the
/// AST objects will be released when the ASTContext itself is destroyed.
- llvm::BumpPtrAllocator BumpAlloc;
+ mutable llvm::BumpPtrAllocator BumpAlloc;
/// \brief Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator;
@@ -287,14 +308,17 @@ class ASTContext {
/// \brief The current C++ ABI.
llvm::OwningPtr<CXXABI> ABI;
CXXABI *createCXXABI(const TargetInfo &T);
-
+
+ friend class ASTDeclReader;
+
public:
const TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
- DeclarationNameTable DeclarationNames;
+ mutable DeclarationNameTable DeclarationNames;
llvm::OwningPtr<ExternalASTSource> ExternalSource;
+ ASTMutationListener *Listener;
clang::PrintingPolicy PrintingPolicy;
// Typedefs which may be provided defining the structure of Objective-C
@@ -305,10 +329,10 @@ public:
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
- void *Allocate(unsigned Size, unsigned Align = 8) {
+ void *Allocate(unsigned Size, unsigned Align = 8) const {
return BumpAlloc.Allocate(Size, Align);
}
- void Deallocate(void *Ptr) { }
+ void Deallocate(void *Ptr) const { }
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator;
@@ -316,6 +340,8 @@ public:
const LangOptions& getLangOptions() const { return LangOpts; }
+ Diagnostic &getDiagnostics() const;
+
FullSourceLoc getFullLoc(SourceLocation Loc) const {
return FullSourceLoc(Loc,SourceMgr);
}
@@ -388,7 +414,6 @@ public:
CanQualType VoidPtrTy, NullPtrTy;
CanQualType OverloadTy;
CanQualType DependentTy;
- CanQualType UndeducedAutoTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
@@ -409,6 +434,19 @@ public:
/// with this AST context, if any.
ExternalASTSource *getExternalSource() const { return ExternalSource.get(); }
+ /// \brief Attach an AST mutation listener to the AST context.
+ ///
+ /// The AST mutation listener provides the ability to track modifications to
+ /// the abstract syntax tree entities committed after they were initially
+ /// created.
+ void setASTMutationListener(ASTMutationListener *Listener) {
+ this->Listener = Listener;
+ }
+
+ /// \brief Retrieve a pointer to the AST mutation listener associated
+ /// with this AST context, if any.
+ ASTMutationListener *getASTMutationListener() const { return Listener; }
+
void PrintStats() const;
const std::vector<Type*>& getTypes() const { return Types; }
@@ -418,9 +456,9 @@ public:
private:
/// getExtQualType - Return a type with extended qualifiers.
- QualType getExtQualType(const Type *Base, Qualifiers Quals);
+ QualType getExtQualType(const Type *Base, Qualifiers Quals) const;
- QualType getTypeDeclTypeSlow(const TypeDecl *Decl);
+ QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const;
public:
/// getAddSpaceQualType - Return the uniqued reference to the type for an
@@ -428,24 +466,26 @@ public:
/// 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);
+ 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.
- QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr);
+ 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'.
- QualType getRestrictType(QualType T) {
+ 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'.
- QualType getVolatileType(QualType T);
+ 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
@@ -453,44 +493,33 @@ public:
///
/// It can be reasonably expected that this will always be
/// equivalent to calling T.withConst().
- QualType getConstType(QualType T) { return T.withConst(); }
-
- /// getNoReturnType - Add or remove the noreturn attribute to the given type
- /// which must be a FunctionType or a pointer to an allowable type or a
- /// BlockPointer.
- QualType getNoReturnType(QualType T, bool AddNoReturn = true);
-
- /// getCallConvType - Adds the specified calling convention attribute to
- /// the given type, which must be a FunctionType or a pointer to an
- /// allowable type.
- QualType getCallConvType(QualType T, CallingConv CallConv);
+ QualType getConstType(QualType T) const { return T.withConst(); }
- /// getRegParmType - Sets the specified regparm attribute to
- /// the given type, which must be a FunctionType or a pointer to an
- /// allowable type.
- QualType getRegParmType(QualType T, unsigned RegParm);
+ /// adjustFunctionType - 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
/// number with the specified element type.
- QualType getComplexType(QualType T);
- CanQualType getComplexType(CanQualType T) {
+ 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
/// the specified type.
- QualType getPointerType(QualType T);
- CanQualType getPointerType(CanQualType T) {
+ QualType getPointerType(QualType T) const;
+ CanQualType getPointerType(CanQualType T) const {
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
}
/// getBlockPointerType - Return the uniqued reference to the type for a block
/// of the specified type.
- QualType getBlockPointerType(QualType T);
+ QualType getBlockPointerType(QualType T) const;
/// This gets the struct used to keep track of the descriptor for pointer to
/// blocks.
- QualType getBlockDescriptorType();
+ QualType getBlockDescriptorType() const;
// Set the type for a Block descriptor type.
void setBlockDescriptorType(QualType T);
@@ -503,48 +532,56 @@ public:
/// This gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
- QualType getBlockDescriptorExtendedType();
+ QualType getBlockDescriptorExtendedType() const;
// Set the type for a Block descriptor extended type.
void setBlockDescriptorExtendedType(QualType T);
/// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been
/// built.
- QualType getRawBlockdescriptorExtendedType() {
+ QualType getRawBlockdescriptorExtendedType() const {
if (BlockDescriptorExtendedType)
return getTagDeclType(BlockDescriptorExtendedType);
return QualType();
}
+ void setcudaConfigureCallDecl(FunctionDecl *FD) {
+ cudaConfigureCallDecl = FD;
+ }
+ FunctionDecl *getcudaConfigureCallDecl() {
+ return cudaConfigureCallDecl;
+ }
+
/// This gets the struct used to keep track of pointer to blocks, complete
/// with captured variables.
QualType getBlockParmType(bool BlockHasCopyDispose,
- llvm::SmallVectorImpl<const Expr *> &Layout);
+ llvm::SmallVectorImpl<const Expr *> &Layout) const;
/// This builds the struct used for __block variables.
- QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty);
+ QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const;
/// Returns true iff we need copy/dispose helpers for the given type.
- bool BlockRequiresCopying(QualType Ty);
+ bool BlockRequiresCopying(QualType Ty) const;
/// getLValueReferenceType - Return the uniqued reference to the type for an
/// lvalue reference to the specified type.
- QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true);
+ QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true)
+ const;
/// getRValueReferenceType - Return the uniqued reference to the type for an
/// rvalue reference to the specified type.
- QualType getRValueReferenceType(QualType T);
+ 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.
- QualType getMemberPointerType(QualType T, const Type *Cls);
+ 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.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals,
- SourceRange Brackets);
+ unsigned IndexTypeQuals,
+ SourceRange Brackets) const;
/// getDependentSizedArrayType - Returns a non-unique reference to
/// the type for a dependently-sized array of the specified element
@@ -552,30 +589,34 @@ public:
/// comparable, at some point.
QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals,
- SourceRange Brackets);
+ unsigned IndexTypeQuals,
+ SourceRange Brackets) const;
/// getIncompleteArrayType - Returns a unique reference to the type for a
/// incomplete array of the specified element type.
QualType getIncompleteArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals);
+ unsigned IndexTypeQuals) const;
/// getConstantArrayType - 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 EltTypeQuals);
+ unsigned IndexTypeQuals) const;
+
+ /// getVariableArrayDecayedType - 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.
QualType getVectorType(QualType VectorType, unsigned NumElts,
- VectorType::AltiVecSpecific AltiVecSpec);
+ 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.
- QualType getExtVectorType(QualType VectorType, unsigned NumElts);
+ 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
@@ -583,30 +624,27 @@ public:
/// comparable, at some point.
QualType getDependentSizedExtVectorType(QualType VectorType,
Expr *SizeExpr,
- SourceLocation AttrLoc);
+ SourceLocation AttrLoc) const;
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType getFunctionNoProtoType(QualType ResultTy,
- const FunctionType::ExtInfo &Info);
+ const FunctionType::ExtInfo &Info) const;
- QualType getFunctionNoProtoType(QualType ResultTy) {
+ QualType getFunctionNoProtoType(QualType ResultTy) const {
return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo());
}
- /// getFunctionType - Return a normal function type with a typed argument
- /// list. isVariadic indicates whether the argument list includes '...'.
- QualType getFunctionType(QualType ResultTy, const QualType *ArgArray,
- unsigned NumArgs, bool isVariadic,
- unsigned TypeQuals, bool hasExceptionSpec,
- bool hasAnyExceptionSpec,
- unsigned NumExs, const QualType *ExArray,
- const FunctionType::ExtInfo &Info);
+ /// getFunctionType - 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.
QualType getTypeDeclType(const TypeDecl *Decl,
- const TypeDecl *PrevDecl = 0) {
+ const TypeDecl *PrevDecl = 0) const {
assert(Decl && "Passed null for Decl param");
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
@@ -621,77 +659,93 @@ public:
/// getTypedefType - Return the unique reference to the type for the
/// specified typename decl.
- QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType());
+ QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType())
+ const;
+
+ QualType getRecordType(const RecordDecl *Decl) const;
- QualType getRecordType(const RecordDecl *Decl);
+ QualType getEnumType(const EnumDecl *Decl) const;
- QualType getEnumType(const EnumDecl *Decl);
+ QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
- QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST);
+ QualType getAttributedType(AttributedType::Kind attrKind,
+ QualType modifiedType,
+ QualType equivalentType);
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
- QualType Replacement);
+ QualType Replacement) const;
+ QualType getSubstTemplateTypeParmPackType(
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack);
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
bool ParameterPack,
- IdentifierInfo *Name = 0);
+ IdentifierInfo *Name = 0) const;
QualType getTemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
QualType getCanonicalTemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
- unsigned NumArgs);
+ unsigned NumArgs) const;
QualType getTemplateSpecializationType(TemplateName T,
const TemplateArgumentListInfo &Args,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
TypeSourceInfo *
getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
const TemplateArgumentListInfo &Args,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
+
+ QualType getParenType(QualType NamedType) const;
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
- QualType NamedType);
+ QualType NamedType) const;
QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
- QualType Canon = QualType());
+ QualType Canon = QualType()) const;
QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
- const TemplateArgumentListInfo &Args);
+ const TemplateArgumentListInfo &Args) const;
QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
unsigned NumArgs,
- const TemplateArgument *Args);
+ const TemplateArgument *Args) const;
+
+ QualType getPackExpansionType(QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions);
- QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl);
+ QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const;
QualType getObjCObjectType(QualType Base,
ObjCProtocolDecl * const *Protocols,
- unsigned NumProtocols);
+ unsigned NumProtocols) const;
/// getObjCObjectPointerType - Return a ObjCObjectPointerType type
/// for the given ObjCObjectType.
- QualType getObjCObjectPointerType(QualType OIT);
+ QualType getObjCObjectPointerType(QualType OIT) const;
/// getTypeOfType - GCC extension.
- QualType getTypeOfExprType(Expr *e);
- QualType getTypeOfType(QualType t);
+ QualType getTypeOfExprType(Expr *e) const;
+ QualType getTypeOfType(QualType t) const;
/// getDecltypeType - C++0x decltype.
- QualType getDecltypeType(Expr *e);
+ QualType getDecltypeType(Expr *e) const;
+
+ /// getAutoType - C++0x deduced auto type.
+ QualType getAutoType(QualType DeducedType) const;
/// getTagDeclType - Return the unique reference to the type for the
/// specified TagDecl (struct/union/class/enum) decl.
- QualType getTagDeclType(const TagDecl *Decl);
+ QualType getTagDeclType(const TagDecl *Decl) const;
/// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
/// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
@@ -716,14 +770,14 @@ public:
// getCFConstantStringType - Return the C structure type used to represent
// constant CFStrings.
- QualType getCFConstantStringType();
+ QualType getCFConstantStringType() const;
// getNSConstantStringType - Return the C structure type used to represent
// constant NSStrings.
- QualType getNSConstantStringType();
+ QualType getNSConstantStringType() const;
/// Get the structure type used to representation NSStrings, or NULL
/// if it hasn't yet been built.
- QualType getRawNSConstantStringType() {
+ QualType getRawNSConstantStringType() const {
if (NSConstantStringTypeDecl)
return getTagDeclType(NSConstantStringTypeDecl);
return QualType();
@@ -733,7 +787,7 @@ public:
/// Get the structure type used to representation CFStrings, or NULL
/// if it hasn't yet been built.
- QualType getRawCFConstantStringType() {
+ QualType getRawCFConstantStringType() const {
if (CFConstantStringTypeDecl)
return getTagDeclType(CFConstantStringTypeDecl);
return QualType();
@@ -747,11 +801,11 @@ public:
}
//// This gets the struct used to keep track of fast enumerations.
- QualType getObjCFastEnumerationStateType();
+ QualType getObjCFastEnumerationStateType() const;
/// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet
/// been built.
- QualType getRawObjCFastEnumerationStateType() {
+ QualType getRawObjCFastEnumerationStateType() const {
if (ObjCFastEnumerationStateTypeDecl)
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
return QualType();
@@ -763,7 +817,7 @@ public:
void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; }
/// \brief Retrieve the C FILE type.
- QualType getFILEType() {
+ QualType getFILEType() const {
if (FILEDecl)
return getTypeDeclType(FILEDecl);
return QualType();
@@ -775,7 +829,7 @@ public:
}
/// \brief Retrieve the C jmp_buf type.
- QualType getjmp_bufType() {
+ QualType getjmp_bufType() const {
if (jmp_bufDecl)
return getTypeDeclType(jmp_bufDecl);
return QualType();
@@ -787,17 +841,22 @@ public:
}
/// \brief Retrieve the C sigjmp_buf type.
- QualType getsigjmp_bufType() {
+ QualType getsigjmp_bufType() const {
if (sigjmp_bufDecl)
return getTypeDeclType(sigjmp_bufDecl);
return QualType();
}
+ /// \brief The result type of logical operations, '<', '>', '!=', etc.
+ QualType getLogicalOperationType() const {
+ return getLangOptions().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,
- const FieldDecl *Field=0);
+ const FieldDecl *Field=0) const;
void getLegacyIntegralTypeEncoding(QualType &t) const;
@@ -805,13 +864,18 @@ public:
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.
+ void getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S);
+
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
- void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S);
+ void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S)
+ const;
- /// getObjCEncodingForBlockDecl - Return the encoded type for this block
+ /// getObjCEncodingForBlock - Return the encoded type for this block
/// declaration.
- void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S);
+ std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const;
/// getObjCEncodingForPropertyDecl - Return the encoded type for
/// this method declaration. If non-NULL, Container must be either
@@ -819,14 +883,14 @@ public:
/// only be NULL when getting encodings for protocol properties.
void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
const Decl *Container,
- std::string &S);
+ std::string &S) const;
bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
- ObjCProtocolDecl *rProto);
+ ObjCProtocolDecl *rProto) const;
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose in characters.
- CharUnits getObjCEncodingTypeSize(QualType t);
+ CharUnits getObjCEncodingTypeSize(QualType t) const;
/// \brief Whether __[u]int128_t identifier is installed.
bool isInt128Installed() const { return IsInt128Installed; }
@@ -854,12 +918,12 @@ public:
/// getCVRQualifiedType - Returns a type with additional const,
/// volatile, or restrict qualifiers.
- QualType getCVRQualifiedType(QualType T, unsigned CVR) {
+ QualType getCVRQualifiedType(QualType T, unsigned CVR) const {
return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
}
/// getQualifiedType - Returns a type with additional qualifiers.
- QualType getQualifiedType(QualType T, Qualifiers Qs) {
+ QualType getQualifiedType(QualType T, Qualifiers Qs) const {
if (!Qs.hasNonFastQualifiers())
return T.withFastQualifiers(Qs.getFastQualifiers());
QualifierCollector Qc(Qs);
@@ -868,35 +932,41 @@ public:
}
/// getQualifiedType - Returns a type with additional qualifiers.
- QualType getQualifiedType(const Type *T, Qualifiers Qs) {
+ QualType getQualifiedType(const Type *T, Qualifiers Qs) const {
if (!Qs.hasNonFastQualifiers())
return QualType(T, Qs.getFastQualifiers());
return getExtQualType(T, Qs);
}
DeclarationNameInfo getNameForTemplate(TemplateName Name,
- SourceLocation NameLoc);
+ SourceLocation NameLoc) const;
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
- UnresolvedSetIterator End);
+ UnresolvedSetIterator End) const;
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
- TemplateDecl *Template);
+ TemplateDecl *Template) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
- const IdentifierInfo *Name);
+ const IdentifierInfo *Name) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
- OverloadedOperatorKind Operator);
-
+ OverloadedOperatorKind Operator) const;
+ TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
+ const TemplateArgument &ArgPack) const;
+
enum GetBuiltinTypeError {
GE_None, //< No error
GE_Missing_stdio, //< Missing a type from <stdio.h>
GE_Missing_setjmp //< Missing a type from <setjmp.h>
};
- /// GetBuiltinType - Return the type for the specified builtin.
- QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error);
+ /// GetBuiltinType - Return the type for the specified builtin. If
+ /// 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,
+ unsigned *IntegerConstantArgs = 0) const;
private:
CanQualType getFromTargetType(unsigned Type) const;
@@ -909,11 +979,12 @@ public:
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
/// garbage collection attribute.
///
- Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
+ Qualifiers::GC getObjCGCAttrKind(QualType Ty) const;
- /// areCompatibleVectorTypes - Return true if the given vector types either
- /// are of the same unqualified type or if one is GCC and other - equivalent
- /// AltiVec vector type.
+ /// 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.
bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
/// isObjCNSObjectType - Return true if this is an NSObject object with
@@ -930,76 +1001,83 @@ public:
/// getTypeInfo - Get the size and alignment of the specified complete type in
/// bits.
- std::pair<uint64_t, unsigned> getTypeInfo(const Type *T);
- std::pair<uint64_t, unsigned> getTypeInfo(QualType T) {
+ std::pair<uint64_t, unsigned> getTypeInfo(const Type *T) const;
+ std::pair<uint64_t, unsigned> 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.
- uint64_t getTypeSize(QualType T) {
+ uint64_t getTypeSize(QualType T) const {
return getTypeInfo(T).first;
}
- uint64_t getTypeSize(const Type *T) {
+ uint64_t getTypeSize(const Type *T) const {
return getTypeInfo(T).first;
}
/// getCharWidth - Return the size of the character type, in bits
- uint64_t getCharWidth() {
+ uint64_t getCharWidth() const {
return getTypeSize(CharTy);
}
+ /// toCharUnitsFromBits - 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.
+ int64_t toBits(CharUnits CharSize) const;
+
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
- CharUnits getTypeSizeInChars(QualType T);
- CharUnits getTypeSizeInChars(const Type *T);
+ 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.
- unsigned getTypeAlign(QualType T) {
+ unsigned getTypeAlign(QualType T) const {
return getTypeInfo(T).second;
}
- unsigned getTypeAlign(const Type *T) {
+ unsigned getTypeAlign(const Type *T) const {
return getTypeInfo(T).second;
}
/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
/// characters. This method does not work on incomplete types.
- CharUnits getTypeAlignInChars(QualType T);
- CharUnits getTypeAlignInChars(const Type *T);
+ CharUnits getTypeAlignInChars(QualType T) const;
+ CharUnits getTypeAlignInChars(const Type *T) const;
- std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T);
- std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T);
+ std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
+ std::pair<CharUnits, CharUnits> 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.
- unsigned getPreferredTypeAlign(const Type *T);
+ 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
/// (for alignof), else they're treated like pointers (for CodeGen).
- CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false);
+ 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
/// position information.
- const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D);
+ const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
/// getASTObjCInterfaceLayout - Get or compute information about the
/// layout of the specified Objective-C interface.
- const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D);
+ const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D)
+ const;
- void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS);
+ void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS) 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.
const ASTRecordLayout &
- getASTObjCImplementationLayout(const ObjCImplementationDecl *D);
+ 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
@@ -1009,13 +1087,18 @@ public:
/// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
+ bool isNearlyEmpty(const CXXRecordDecl *RD) const;
+
+ MangleContext *createMangleContext();
+
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars)
+ const;
void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const;
- unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);
+ unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const;
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
@@ -1029,8 +1112,11 @@ public:
/// 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 Type *getCanonicalType(const Type *T) {
+ CanQualType getCanonicalType(QualType T) const {
+ return CanQualType::CreateUnsafe(T.getCanonicalType());
+ }
+
+ const Type *getCanonicalType(const Type *T) const {
return T->getCanonicalTypeInternal().getTypePtr();
}
@@ -1038,7 +1124,7 @@ public:
/// 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);
+ CanQualType getCanonicalParamType(QualType T) const;
/// \brief Determine whether the given types are equivalent.
bool hasSameType(QualType T1, QualType T2) {
@@ -1062,13 +1148,8 @@ public:
/// \brief Determine whether the given types are equivalent after
/// cvr-qualifiers have been removed.
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
- CanQualType CT1 = getCanonicalType(T1);
- CanQualType CT2 = getCanonicalType(T2);
-
- Qualifiers Quals;
- QualType UnqualT1 = getUnqualifiedArrayType(CT1, Quals);
- QualType UnqualT2 = getUnqualifiedArrayType(CT2, Quals);
- return UnqualT1 == UnqualT2;
+ return getCanonicalType(T1).getTypePtr() ==
+ getCanonicalType(T2).getTypePtr();
}
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
@@ -1097,11 +1178,15 @@ public:
/// by declarations in the type system and the canonical type for
/// the template type parameter 'T' is template-param-0-0.
NestedNameSpecifier *
- getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS);
+ getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
+
+ /// \brief Retrieves the default calling convention to use for
+ /// C++ instance methods.
+ CallingConv getDefaultMethodCallConv();
/// \brief Retrieves the canonical representation of the given
/// calling convention.
- CallingConv getCanonicalCallConv(CallingConv CC) {
+ CallingConv getCanonicalCallConv(CallingConv CC) const {
if (CC == CC_C)
return CC_Default;
return CC;
@@ -1131,7 +1216,7 @@ public:
/// template name uses the shortest form of the dependent
/// nested-name-specifier, which itself contains all canonical
/// types, values, and templates.
- TemplateName getCanonicalTemplateName(TemplateName Name);
+ TemplateName getCanonicalTemplateName(TemplateName Name) const;
/// \brief Determine whether the given template names refer to the same
/// template.
@@ -1142,33 +1227,35 @@ public:
/// The canonical template argument is the simplest template argument
/// (which may be a type, value, expression, or declaration) that
/// expresses the value of the argument.
- TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg);
+ TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
+ const;
/// Type Query functions. If the type is an instance of the specified class,
/// return the Type pointer for the underlying maximally pretty type. This
/// is a member of ASTContext because this may need to do some amount of
/// canonicalization, e.g. to move type qualifiers into the element type.
- const ArrayType *getAsArrayType(QualType T);
- const ConstantArrayType *getAsConstantArrayType(QualType T) {
+ const ArrayType *getAsArrayType(QualType T) const;
+ const ConstantArrayType *getAsConstantArrayType(QualType T) const {
return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T));
}
- const VariableArrayType *getAsVariableArrayType(QualType T) {
+ const VariableArrayType *getAsVariableArrayType(QualType T) const {
return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T));
}
- const IncompleteArrayType *getAsIncompleteArrayType(QualType T) {
+ const IncompleteArrayType *getAsIncompleteArrayType(QualType T) const {
return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T));
}
- const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T) {
+ const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T)
+ const {
return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T));
}
/// getBaseElementType - Returns the innermost element type of an array type.
/// For example, will return "int" for int[m][n]
- QualType getBaseElementType(const ArrayType *VAT);
+ QualType getBaseElementType(const ArrayType *VAT) const;
/// getBaseElementType - Returns the innermost element type of a type
/// (which needn't actually be an array type).
- QualType getBaseElementType(QualType QT);
+ QualType getBaseElementType(QualType QT) const;
/// getConstantArrayElementCount - Returns number of constant array elements.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
@@ -1179,30 +1266,30 @@ public:
/// 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);
+ 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.
- QualType getPromotedIntegerType(QualType PromotableType);
+ QualType getPromotedIntegerType(QualType PromotableType) const;
/// \brief Whether this is a promotable bitfield reference according
/// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
///
/// \returns the type this bit-field will promote to, or NULL if no
/// promotion occurs.
- QualType isPromotableBitField(Expr *E);
+ 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.
- int getIntegerTypeOrder(QualType LHS, QualType RHS);
+ 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.
- int getFloatingTypeOrder(QualType LHS, QualType RHS);
+ int getFloatingTypeOrder(QualType LHS, QualType RHS) const;
/// getFloatingTypeOfSizeWithinDomain - Returns a real floating
/// point or a complex type (based on typeDomain/typeSize).
@@ -1213,7 +1300,7 @@ public:
private:
// Helper for integer ordering
- unsigned getIntegerRank(Type* T);
+ unsigned getIntegerRank(const Type *T) const;
public:
@@ -1260,14 +1347,15 @@ public:
bool Unqualified = false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false);
+ QualType mergeFunctionArgumentTypes(QualType, QualType,
+ bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeTransparentUnionType(QualType, QualType,
+ bool OfBlockPointer=false,
+ bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType);
- /// UsualArithmeticConversionsType - handles the various conversions
- /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
- /// and returns the result type of that conversion.
- QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
-
void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0;
}
@@ -1278,7 +1366,7 @@ public:
// The width of an integer, as defined in C99 6.2.6.2. This is the number
// of bits in an integer type excluding any padding bits.
- unsigned getIntWidth(QualType T);
+ unsigned getIntWidth(QualType T) const;
// 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
@@ -1303,7 +1391,7 @@ public:
/// MakeIntValue - Make an APSInt of the appropriate width and
/// signedness for the given \arg Value and integer \arg Type.
- llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) {
+ llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType());
Res = Value;
return Res;
@@ -1314,12 +1402,23 @@ public:
/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
+ /// \brief returns true if there is at lease one @implementation in TU.
+ bool AnyObjCImplementation() {
+ return !ObjCImpls.empty();
+ }
+
/// \brief Set the implementation of ObjCInterfaceDecl.
void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
ObjCImplementationDecl *ImplD);
/// \brief Set the implementation of ObjCCategoryDecl.
void setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCCategoryImplDecl *ImplD);
+
+ /// \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 Allocate an uninitialized TypeSourceInfo.
///
@@ -1332,13 +1431,14 @@ public:
///
/// \param Size the size of the type info to create, or 0 if the size
/// should be calculated based on the type.
- TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0);
+ TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0) const;
/// \brief Allocate a TypeSourceInfo where all locations have been
/// initialized to a given location, which defaults to the empty
/// location.
TypeSourceInfo *
- getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation());
+ getTrivialTypeSourceInfo(QualType T,
+ SourceLocation Loc = SourceLocation()) const;
TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; }
@@ -1407,10 +1507,11 @@ private:
bool ExpandStructures,
const FieldDecl *Field,
bool OutermostType = false,
- bool EncodingProperty = false);
+ bool EncodingProperty = false) const;
- const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
- const ObjCImplementationDecl *Impl);
+ const ASTRecordLayout &
+ getObjCLayout(const ObjCInterfaceDecl *D,
+ const ObjCImplementationDecl *Impl) const;
private:
/// \brief A set of deallocations that should be performed when the
@@ -1423,8 +1524,8 @@ private:
llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM;
/// \brief A counter used to uniquely identify "blocks".
- unsigned int UniqueBlockByRefTypeID;
- unsigned int UniqueBlockParmTypeID;
+ mutable unsigned int UniqueBlockByRefTypeID;
+ mutable unsigned int UniqueBlockParmTypeID;
friend class DeclContext;
friend class DeclarationNameTable;
@@ -1469,7 +1570,7 @@ static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
/// @param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
/// @return The allocated memory. Could be NULL.
-inline void *operator new(size_t Bytes, clang::ASTContext &C,
+inline void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment) throw () {
return C.Allocate(Bytes, Alignment);
}
@@ -1479,7 +1580,7 @@ inline void *operator new(size_t Bytes, clang::ASTContext &C,
/// invoking it directly; see the new operator for more details. This operator
/// is called implicitly by the compiler if a placement new expression using
/// the ASTContext throws in the object constructor.
-inline void operator delete(void *Ptr, clang::ASTContext &C, size_t)
+inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t)
throw () {
C.Deallocate(Ptr);
}
@@ -1503,7 +1604,7 @@ inline void operator delete(void *Ptr, clang::ASTContext &C, size_t)
/// @param Alignment The alignment of the allocated memory (if the underlying
/// allocator supports it).
/// @return The allocated memory. Could be NULL.
-inline void *operator new[](size_t Bytes, clang::ASTContext& C,
+inline void *operator new[](size_t Bytes, const clang::ASTContext& C,
size_t Alignment = 8) throw () {
return C.Allocate(Bytes, Alignment);
}
@@ -1514,7 +1615,7 @@ inline void *operator new[](size_t Bytes, clang::ASTContext& C,
/// invoking it directly; see the new[] operator for more details. This operator
/// is called implicitly by the compiler if a placement new[] expression using
/// the ASTContext throws in the object constructor.
-inline void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
+inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t)
throw () {
C.Deallocate(Ptr);
}
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 7cbf3a511705..1ab53b3e9148 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
#undef DIAG
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 9380058118c5..b659ce74bb7c 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -45,13 +45,13 @@ namespace clang {
/// \brief The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
-
- /// \brief The diagnostics object that we should use to emit diagnostics.
- Diagnostic &Diags;
+
+ /// \brief Whether to perform a minimal import.
+ bool Minimal;
/// \brief Mapping from the already-imported types in the "from" context
/// to the corresponding types in the "to" context.
- llvm::DenseMap<Type *, Type *> ImportedTypes;
+ llvm::DenseMap<const Type *, const Type *> ImportedTypes;
/// \brief Mapping from the already-imported declarations in the "from"
/// context to the corresponding declarations in the "to" context.
@@ -63,7 +63,7 @@ namespace clang {
/// \brief Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
- llvm::DenseMap<unsigned, FileID> ImportedFileIDs;
+ llvm::DenseMap<FileID, FileID> ImportedFileIDs;
/// \brief Imported, anonymous tag declarations that are missing their
/// corresponding typedefs.
@@ -74,12 +74,29 @@ namespace clang {
NonEquivalentDeclSet NonEquivalentDecls;
public:
- ASTImporter(Diagnostic &Diags,
- ASTContext &ToContext, FileManager &ToFileManager,
- ASTContext &FromContext, FileManager &FromFileManager);
+ /// \brief Create a new AST importer.
+ ///
+ /// \param ToContext The context we'll be importing into.
+ ///
+ /// \param ToFileManager The file manager we'll be importing into.
+ ///
+ /// \param FromContext The context we'll be importing from.
+ ///
+ /// \param FromFileManager The file manager we'll be importing into.
+ ///
+ /// \param MinimalImport If true, the importer will attempt to import
+ /// as little as it can, e.g., by importing declarations as forward
+ /// declarations that can be completed at a later point.
+ ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ bool MinimalImport);
virtual ~ASTImporter();
+ /// \brief Whether the importer will perform a minimal import, creating
+ /// to-be-completed forward declarations when possible.
+ bool isMinimalImport() const { return Minimal; }
+
/// \brief Import the given type from the "from" context into the "to"
/// context.
///
@@ -129,6 +146,10 @@ namespace clang {
/// context, or NULL if an error occurred.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
+ /// \brief Import the goven template name from the "from" context into the
+ /// "to" context.
+ TemplateName Import(TemplateName From);
+
/// \brief Import the given source location from the "from" context into
/// the "to" context.
///
@@ -154,7 +175,7 @@ namespace clang {
/// into the "to" context.
///
/// \returns the equivalent identifier in the "to" context.
- IdentifierInfo *Import(IdentifierInfo *FromId);
+ IdentifierInfo *Import(const IdentifierInfo *FromId);
/// \brief Import the given Objective-C selector from the "from"
/// context into the "to" context.
@@ -169,6 +190,12 @@ namespace clang {
/// context.
FileID Import(FileID);
+ /// \brief Import the definition of the given declaration, including all of
+ /// the declarations it contains.
+ ///
+ /// This routine is intended to be used
+ void ImportDefinition(Decl *From);
+
/// \brief Cope with a name conflict when importing a declaration into the
/// given context.
///
@@ -212,9 +239,6 @@ namespace clang {
/// \brief Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
-
- /// \brief Retrieve the diagnostic formatter.
- Diagnostic &getDiags() const { return Diags; }
/// \brief Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
@@ -228,12 +252,13 @@ namespace clang {
/// \brief Note that we have imported the "from" declaration by mapping it
/// to the (potentially-newly-created) "to" declaration.
///
- /// \returns \p To
- Decl *Imported(Decl *From, Decl *To);
+ /// Subclasses can override this function to observe all of the \c From ->
+ /// \c To declaration mappings as they are imported.
+ virtual Decl *Imported(Decl *From, Decl *To);
/// \brief Determine whether the given types are structurally
/// equivalent.
- bool IsStructurallyEquivalent(QualType From, QualType To);
+ bool IsStructurallyEquivalent(QualType From, QualType To);
};
}
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
new file mode 100644
index 000000000000..01e618024913
--- /dev/null
+++ b/include/clang/AST/ASTMutationListener.h
@@ -0,0 +1,48 @@
+//===--- ASTMutationListener.h - AST 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 ASTMutationListener interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
+#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
+
+namespace clang {
+ class Decl;
+ class DeclContext;
+ class TagDecl;
+ class CXXRecordDecl;
+ class ClassTemplateDecl;
+ class ClassTemplateSpecializationDecl;
+
+/// \brief An abstract interface that should be implemented by listeners
+/// that want to be notified when an AST entity gets modified after its
+/// initial creation.
+class ASTMutationListener {
+public:
+ virtual ~ASTMutationListener();
+
+ /// \brief A new TagDecl definition was completed.
+ virtual void CompletedTagDefinition(const TagDecl *D) { }
+
+ /// \brief A new declaration with name has been added to a DeclContext.
+ virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {}
+
+ /// \brief An implicit member was added after the definition was completed.
+ virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {}
+
+ /// \brief A template specialization (or partial one) was added to the
+ /// template declaration.
+ virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D) {}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 62ca49fbf3b1..67968fde2d6b 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -36,19 +36,19 @@ namespace clang {
}
// Defined in ASTContext.h
-void *operator new(size_t Bytes, clang::ASTContext &C,
+void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment = 16) throw ();
// FIXME: Being forced to not have a default argument here due to redeclaration
// rules on default arguments sucks
-void *operator new[](size_t Bytes, clang::ASTContext &C,
+void *operator new[](size_t Bytes, const clang::ASTContext &C,
size_t Alignment) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
-void operator delete(void *Ptr, clang::ASTContext &C, size_t)
+void operator delete(void *Ptr, const clang::ASTContext &C, size_t)
throw ();
-void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
+void operator delete[](void *Ptr, const clang::ASTContext &C, size_t)
throw ();
namespace clang {
@@ -58,9 +58,10 @@ class Attr {
private:
SourceLocation Loc;
unsigned AttrKind : 16;
- bool Inherited : 1;
protected:
+ bool Inherited : 1;
+
virtual ~Attr();
void* operator new(size_t bytes) throw() {
@@ -88,10 +89,6 @@ protected:
public:
- /// \brief Whether this attribute should be merged to new
- /// declarations.
- virtual bool isMerged() const { return true; }
-
attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
}
@@ -100,7 +97,6 @@ public:
void setLocation(SourceLocation L) { Loc = L; }
bool isInherited() const { return Inherited; }
- void setInherited(bool I) { Inherited = I; }
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@@ -109,6 +105,21 @@ public:
static bool classof(const Attr *) { return true; }
};
+class InheritableAttr : public Attr {
+protected:
+ InheritableAttr(attr::Kind AK, SourceLocation L)
+ : Attr(AK, L) {}
+
+public:
+ void setInherited(bool I) { Inherited = I; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() <= attr::LAST_INHERITABLE;
+ }
+ static bool classof(const InheritableAttr *) { return true; }
+};
+
#include "clang/AST/Attrs.inc"
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 5a84e404a1b6..2d30cb3b8b62 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -20,6 +20,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include <list>
#include <map>
@@ -359,7 +360,11 @@ public:
/// subobjects of that type.
class CXXFinalOverriderMap
: public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { };
-
+
+/// \brief A set of all the primary bases for a class.
+class CXXIndirectPrimaryBaseSet
+ : public llvm::SmallSet<const CXXRecordDecl*, 32> { };
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index dad4dfc926e1..4d7fcfd1d121 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -66,7 +66,16 @@ public:
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type.
- T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
+ ///
+ /// The underlying pointer must not be NULL.
+ const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
+
+ /// \brief Retrieve the underlying type pointer, which refers to a
+ /// canonical type, or NULL.
+ ///
+ const T *getTypePtrOrNull() const {
+ return cast_or_null<T>(Stored.getTypePtrOrNull());
+ }
/// \brief Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
@@ -78,6 +87,8 @@ public:
return Stored.isNull();
}
+ SplitQualType split() const { return Stored.split(); }
+
/// \brief Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
@@ -216,7 +227,7 @@ protected:
public:
/// \brief Retrieve the pointer to the underlying Type
- T* getTypePtr() const { return Stored.getTypePtr(); }
+ const T *getTypePtr() const { return Stored.getTypePtr(); }
/// \brief Implicit conversion to the underlying pointer.
///
@@ -225,7 +236,7 @@ public:
/// @code
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
/// @endcode
- operator const T*() const { return this->Stored.getTypePtr(); }
+ operator const T*() const { return this->Stored.getTypePtrOrNull(); }
/// \brief Try to convert the given canonical type to a specific structural
/// type.
@@ -336,7 +347,7 @@ namespace llvm {
/// to return smart pointer (proxies?).
template<typename T>
struct simplify_type<const ::clang::CanQual<T> > {
- typedef T* SimpleType;
+ typedef const T *SimpleType;
static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
return Val.getTypePtr();
}
@@ -630,7 +641,6 @@ struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace)
};
template<>
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 0bb4b769d0f3..cf909e88220f 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -14,7 +14,9 @@
#ifndef LLVM_CLANG_AST_CHARUNITS_H
#define LLVM_CLANG_AST_CHARUNITS_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
namespace clang {
@@ -131,12 +133,24 @@ namespace clang {
CharUnits operator- (const CharUnits &Other) const {
return CharUnits(Quantity - Other.Quantity);
}
+ CharUnits operator- () const {
+ return CharUnits(-Quantity);
+ }
+
// Conversions.
/// getQuantity - Get the raw integer representation of this quantity.
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.
+ CharUnits RoundUpToAlignment(const CharUnits &Align) {
+ return CharUnits(llvm::RoundUpToAlignment(Quantity,
+ Align.Quantity));
+ }
+
}; // class CharUnit
} // namespace clang
@@ -146,4 +160,38 @@ inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
return CU * Scale;
}
+namespace llvm {
+
+template<> struct DenseMapInfo<clang::CharUnits> {
+ static clang::CharUnits getEmptyKey() {
+ clang::CharUnits::QuantityType Quantity =
+ DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
+
+ return clang::CharUnits::fromQuantity(Quantity);
+ }
+
+ static clang::CharUnits getTombstoneKey() {
+ clang::CharUnits::QuantityType Quantity =
+ DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
+
+ return clang::CharUnits::fromQuantity(Quantity);
+ }
+
+ static unsigned getHashValue(const clang::CharUnits &CU) {
+ clang::CharUnits::QuantityType Quantity = CU.getQuantity();
+ return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
+ }
+
+ static bool isEqual(const clang::CharUnits &LHS,
+ const clang::CharUnits &RHS) {
+ return LHS == RHS;
+ }
+};
+
+template <> struct isPodLike<clang::CharUnits> {
+ static const bool value = true;
+};
+
+} // end namespace llvm
+
#endif // LLVM_CLANG_AST_CHARUNITS_H
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 674925532210..ee515da0835c 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -36,6 +36,7 @@ class FunctionTemplateSpecializationInfo;
class DependentFunctionTemplateSpecializationInfo;
class TypeLoc;
class UnresolvedSetImpl;
+class LabelStmt;
/// \brief A container of type source information.
///
@@ -196,9 +197,86 @@ public:
/// determine whether it's an instance member of its class.
bool isCXXInstanceMember() const;
+ class LinkageInfo {
+ Linkage linkage_;
+ Visibility visibility_;
+ bool explicit_;
+
+ public:
+ LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
+ explicit_(false) {}
+ LinkageInfo(Linkage L, Visibility V, bool E)
+ : linkage_(L), visibility_(V), explicit_(E) {}
+
+ static LinkageInfo external() {
+ return LinkageInfo();
+ }
+ static LinkageInfo internal() {
+ return LinkageInfo(InternalLinkage, DefaultVisibility, false);
+ }
+ static LinkageInfo uniqueExternal() {
+ return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false);
+ }
+ static LinkageInfo none() {
+ return LinkageInfo(NoLinkage, DefaultVisibility, false);
+ }
+
+ Linkage linkage() const { return linkage_; }
+ Visibility visibility() const { return visibility_; }
+ bool visibilityExplicit() const { return explicit_; }
+
+ void setLinkage(Linkage L) { linkage_ = L; }
+ void setVisibility(Visibility V) { visibility_ = V; }
+ void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
+ void setVisibility(LinkageInfo Other) {
+ setVisibility(Other.visibility(), Other.visibilityExplicit());
+ }
+
+ void mergeLinkage(Linkage L) {
+ setLinkage(minLinkage(linkage(), L));
+ }
+ void mergeLinkage(LinkageInfo Other) {
+ setLinkage(minLinkage(linkage(), Other.linkage()));
+ }
+
+ void mergeVisibility(Visibility V) {
+ setVisibility(minVisibility(visibility(), V));
+ }
+ void mergeVisibility(Visibility V, bool E) {
+ setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E);
+ }
+ void mergeVisibility(LinkageInfo Other) {
+ mergeVisibility(Other.visibility(), Other.visibilityExplicit());
+ }
+
+ void merge(LinkageInfo Other) {
+ mergeLinkage(Other);
+ mergeVisibility(Other);
+ }
+ void merge(std::pair<Linkage,Visibility> LV) {
+ mergeLinkage(LV.first);
+ mergeVisibility(LV.second);
+ }
+
+ friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) {
+ L.merge(R);
+ return L;
+ }
+ };
+
/// \brief Determine what kind of linkage this entity has.
Linkage getLinkage() const;
+ /// \brief Determines the visibility of this entity.
+ Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); }
+
+ /// \brief Determines the linkage and visibility of this entity.
+ LinkageInfo getLinkageAndVisibility() const;
+
+ /// \brief Clear the linkage cache in response to a change
+ /// to the declaration.
+ void ClearLinkageCache();
+
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
/// the underlying named decl.
NamedDecl *getUnderlyingDecl();
@@ -217,6 +295,29 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
return OS;
}
+/// LabelDecl - Represents the declaration of a label. Labels also have a
+/// corresponding LabelStmt, which indicates the position that the label was
+/// defined at. For normal labels, the location of the decl is the same as the
+/// location of the statement. For GNU local labels (__label__), the decl
+/// location is where the __label__ is.
+class LabelDecl : public NamedDecl {
+ LabelStmt *TheStmt;
+ LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S)
+ : NamedDecl(Label, DC, L, II), TheStmt(S) {}
+
+public:
+ static LabelDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *II);
+
+ LabelStmt *getStmt() const { return TheStmt; }
+ void setStmt(LabelStmt *T) { TheStmt = T; }
+
+ // 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; }
+};
+
/// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext {
bool IsInline : 1;
@@ -232,7 +333,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// NextNamespace points to the next extended declaration.
// OrigNamespace points to the original namespace declaration.
// OrigNamespace of the first namespace decl points to its anonymous namespace
- NamespaceDecl *NextNamespace;
+ LazyDeclPtr NextNamespace;
/// \brief A pointer to either the original namespace definition for
/// this namespace (if the boolean value is false) or the anonymous
@@ -250,7 +351,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
- IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { }
+ IsInline(false), NextNamespace(), OrigOrAnonNamespace(0, true) { }
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
@@ -281,8 +382,10 @@ public:
/// \brief Return the next extended namespace declaration or null if there
/// is none.
- NamespaceDecl *getNextNamespace() { return NextNamespace; }
- const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
+ NamespaceDecl *getNextNamespace();
+ const NamespaceDecl *getNextNamespace() const {
+ return const_cast<NamespaceDecl *>(this)->getNextNamespace();
+ }
/// \brief Set the next extended namespace declaration.
void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; }
@@ -331,9 +434,9 @@ public:
SourceLocation getLBracLoc() const { return LBracLoc; }
SourceLocation getRBracLoc() const { return RBracLoc; }
- void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; }
- void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
-
+ void setLBracLoc(SourceLocation L) { LBracLoc = L; }
+ void setRBracLoc(SourceLocation R) { RBracLoc = R; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NamespaceDecl *D) { return true; }
@@ -471,6 +574,9 @@ public:
static bool classofKind(Kind K) {
return K >= firstDeclarator && K <= lastDeclarator;
}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// \brief Structure used to store a statement, the constant value to
@@ -545,15 +651,21 @@ private:
/// \brief Whether this local variable could be allocated in the return
/// slot of its function, enabling the named return value optimization (NRVO).
bool NRVOVariable : 1;
+
+ /// \brief Whether this variable has a deduced C++0x auto type for which we're
+ /// currently parsing the initializer.
+ bool ParsingAutoInit : 1;
friend class StmtIteratorBase;
+ friend class ASTDeclReader;
+
protected:
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
- ExceptionVar(false), NRVOVariable(false) {
+ ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) {
SClass = SC;
SClassAsWritten = SCAsWritten;
}
@@ -582,10 +694,7 @@ public:
StorageClass getStorageClassAsWritten() const {
return (StorageClass) SClassAsWritten;
}
- void setStorageClass(StorageClass SC) {
- assert(isLegalForVariable(SC));
- SClass = SC;
- }
+ void setStorageClass(StorageClass SC);
void setStorageClassAsWritten(StorageClass SC) {
assert(isLegalForVariable(SC));
SClassAsWritten = SC;
@@ -630,13 +739,13 @@ public:
/// external, C linkage.
bool isExternC() const;
- /// isBlockVarDecl - Returns true for local variable declarations. Note that
- /// this includes static variables inside of functions. It also includes
- /// variables inside blocks.
+ /// isLocalVarDecl - Returns true for local variable declarations
+ /// other than parameters. Note that this includes static variables
+ /// inside of functions. It also includes variables inside blocks.
///
/// void foo() { int x; static int y; extern int z; }
///
- bool isBlockVarDecl() const {
+ bool isLocalVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
@@ -644,8 +753,8 @@ public:
return false;
}
- /// isFunctionOrMethodVarDecl - Similar to isBlockVarDecl, but excludes
- /// variables declared in blocks.
+ /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
+ /// excludes variables declared in blocks.
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
@@ -683,6 +792,10 @@ public:
/// definition.
DefinitionKind isThisDeclarationADefinition() const;
+ /// \brief Check whether this variable is defined in this
+ /// translation unit.
+ DefinitionKind hasDefinition() const;
+
/// \brief Get the tentative definition that acts as the real definition in
/// a TU. Returns null if there is a proper definition available.
VarDecl *getActingDefinition();
@@ -733,7 +846,7 @@ public:
const Expr *getAnyInitializer(const VarDecl *&D) const;
bool hasInit() const {
- return !Init.isNull();
+ return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>());
}
const Expr *getInit() const {
if (Init.isNull())
@@ -776,6 +889,18 @@ public:
void setInit(Expr *I);
+ /// \brief Check whether we are in the process of parsing an initializer
+ /// needed to deduce the type of this variable.
+ bool isParsingAutoInit() const {
+ return ParsingAutoInit;
+ }
+
+ /// \brief Note whether we are currently parsing an initializer needed to
+ /// deduce the type of this variable.
+ void setParsingAutoInit(bool P) {
+ ParsingAutoInit = P;
+ }
+
EvaluatedStmt *EnsureEvaluatedStmt() const {
EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
if (!Eval) {
@@ -928,7 +1053,9 @@ class ImplicitParamDecl : public VarDecl {
protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType Tw)
- : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {}
+ : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {
+ setImplicit();
+ }
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -1046,6 +1173,10 @@ public:
return getType();
}
+ /// \brief Determine whether this parameter is actually a function
+ /// parameter pack.
+ bool isParameterPack() const;
+
/// setOwningFunction - Sets the function declaration that owns this
/// ParmVarDecl. Since ParmVarDecls are often created before the
/// FunctionDecls that own them, this routine is required to update
@@ -1096,13 +1227,13 @@ private:
unsigned SClass : 2;
unsigned SClassAsWritten : 2;
bool IsInline : 1;
+ bool IsInlineSpecified : 1;
bool IsVirtualAsWritten : 1;
bool IsPure : 1;
bool HasInheritedPrototype : 1;
bool HasWrittenPrototype : 1;
bool IsDeleted : 1;
bool IsTrivial : 1; // sunk from CXXMethodDecl
- bool IsCopyAssignment : 1; // sunk from CXXMethodDecl
bool HasImplicitReturnZero : 1;
/// \brief End part of this FunctionDecl's source range.
@@ -1136,19 +1267,54 @@ private:
/// declaration name embedded in the DeclaratorDecl base class.
DeclarationNameLoc DNLoc;
+ /// \brief Specify that this function declaration is actually a function
+ /// template specialization.
+ ///
+ /// \param C the ASTContext.
+ ///
+ /// \param Template the function template that this function template
+ /// specialization specializes.
+ ///
+ /// \param TemplateArgs the template arguments that produced this
+ /// function template specialization from the template.
+ ///
+ /// \param InsertPos If non-NULL, the position in the function template
+ /// specialization set where the function template specialization data will
+ /// be inserted.
+ ///
+ /// \param TSK the kind of template specialization this is.
+ ///
+ /// \param TemplateArgsAsWritten location info of template arguments.
+ ///
+ /// \param PointOfInstantiation point at which the function template
+ /// specialization was first instantiated.
+ void setFunctionTemplateSpecialization(ASTContext &C,
+ FunctionTemplateDecl *Template,
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation PointOfInstantiation);
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member function FD.
+ void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD,
+ TemplateSpecializationKind TSK);
+
+ void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams);
+
protected:
FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
- StorageClass S, StorageClass SCAsWritten, bool isInline)
+ StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified)
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo),
DeclContext(DK),
ParamInfo(0), Body(),
- SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline),
+ SClass(S), SClassAsWritten(SCAsWritten),
+ IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
- IsCopyAssignment(false),
- HasImplicitReturnZero(false),
- EndRangeLoc(NameInfo.getEndLoc()),
+ HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()),
TemplateOrSpecialization(),
DNLoc(NameInfo.getInfo()) {}
@@ -1169,11 +1335,11 @@ public:
TypeSourceInfo *TInfo,
StorageClass S = SC_None,
StorageClass SCAsWritten = SC_None,
- bool isInline = false,
+ bool isInlineSpecified = false,
bool hasWrittenPrototype = true) {
DeclarationNameInfo NameInfo(N, L);
return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten,
- isInline, hasWrittenPrototype);
+ isInlineSpecified, hasWrittenPrototype);
}
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1181,7 +1347,7 @@ public:
QualType T, TypeSourceInfo *TInfo,
StorageClass S = SC_None,
StorageClass SCAsWritten = SC_None,
- bool isInline = false,
+ bool isInlineSpecified = false,
bool hasWrittenPrototype = true);
DeclarationNameInfo getNameInfo() const {
@@ -1246,7 +1412,7 @@ public:
/// Whether this virtual function is pure, i.e. makes the containing class
/// abstract.
bool isPure() const { return IsPure; }
- void setPure(bool P = true) { IsPure = P; }
+ void setPure(bool P = true);
/// Whether this function is "trivial" in some specialized C++ senses.
/// Can only be true for default constructors, copy constructors,
@@ -1255,9 +1421,6 @@ public:
bool isTrivial() const { return IsTrivial; }
void setTrivial(bool IT) { IsTrivial = IT; }
- bool isCopyAssignment() const { return IsCopyAssignment; }
- void setCopyAssignment(bool CA) { IsCopyAssignment = CA; }
-
/// Whether falling off this function implicitly returns null/zero.
/// If a more specific implicit return value is required, front-ends
/// should synthesize the appropriate return statements.
@@ -1273,7 +1436,6 @@ public:
}
bool hasWrittenPrototype() const { return HasWrittenPrototype; }
- void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; }
/// \brief Whether this function inherited its prototype from a
/// previous declaration.
@@ -1343,7 +1505,9 @@ public:
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
- void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
+ void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
+ setParams(getASTContext(), NewParamInfo, NumParams);
+ }
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
@@ -1361,31 +1525,32 @@ public:
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
- void setStorageClass(StorageClass SC) {
- assert(isLegalForFunction(SC));
- SClass = SC;
- }
+ void setStorageClass(StorageClass SC);
StorageClass getStorageClassAsWritten() const {
return StorageClass(SClassAsWritten);
}
- void setStorageClassAsWritten(StorageClass SC) {
- assert(isLegalForFunction(SC));
- SClassAsWritten = SC;
- }
/// \brief Determine whether the "inline" keyword was specified for this
/// function.
- bool isInlineSpecified() const { return IsInline; }
+ bool isInlineSpecified() const { return IsInlineSpecified; }
/// Set whether the "inline" keyword was specified for this function.
- void setInlineSpecified(bool I) { IsInline = I; }
+ void setInlineSpecified(bool I) {
+ IsInlineSpecified = I;
+ IsInline = I;
+ }
+
+ /// Flag that this function is implicitly inline.
+ void setImplicitlyInline() {
+ IsInline = true;
+ }
/// \brief Determine whether this function should be inlined, because it is
/// either marked "inline" or is a member function of a C++ class that
/// was defined in the class body.
bool isInlined() const;
-
+
bool isInlineDefinitionExternallyVisible() const;
/// isOverloadedOperator - Whether this function declaration
@@ -1432,7 +1597,9 @@ public:
/// \brief Specify that this record is an instantiation of the
/// member function FD.
void setInstantiationOfMemberFunction(FunctionDecl *FD,
- TemplateSpecializationKind TSK);
+ TemplateSpecializationKind TSK) {
+ setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
+ }
/// \brief Retrieves the function template that is described by this
/// function declaration.
@@ -1526,43 +1693,11 @@ public:
void *InsertPos,
TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
const TemplateArgumentListInfo *TemplateArgsAsWritten = 0,
- SourceLocation PointOfInstantiation = SourceLocation());
-
- /// \brief Specify that this function declaration is actually a function
- /// template specialization.
- ///
- /// \param Template the function template that this function template
- /// specialization specializes.
- ///
- /// \param NumTemplateArgs number of template arguments that produced this
- /// function template specialization from the template.
- ///
- /// \param TemplateArgs array of template arguments that produced this
- /// function template specialization from the template.
- ///
- /// \param TSK the kind of template specialization this is.
- ///
- /// \param NumTemplateArgsAsWritten number of template arguments that produced
- /// this function template specialization from the template.
- ///
- /// \param TemplateArgsAsWritten array of location info for the template
- /// arguments.
- ///
- /// \param LAngleLoc location of left angle token.
- ///
- /// \param RAngleLoc location of right angle token.
- ///
- /// \param PointOfInstantiation point at which the function template
- /// specialization was first instantiated.
- void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
- unsigned NumTemplateArgs,
- const TemplateArgument *TemplateArgs,
- TemplateSpecializationKind TSK,
- unsigned NumTemplateArgsAsWritten,
- TemplateArgumentLoc *TemplateArgsAsWritten,
- SourceLocation LAngleLoc,
- SourceLocation RAngleLoc,
- SourceLocation PointOfInstantiation);
+ SourceLocation PointOfInstantiation = SourceLocation()) {
+ setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs,
+ InsertPos, TSK, TemplateArgsAsWritten,
+ PointOfInstantiation);
+ }
/// \brief Specifies that this function declaration is actually a
/// dependent function template specialization.
@@ -1620,19 +1755,26 @@ public:
class FieldDecl : public DeclaratorDecl {
// FIXME: This can be packed into the bitfields in Decl.
bool Mutable : 1;
+ mutable unsigned CachedFieldIndex : 31;
+
Expr *BitWidth;
protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
Expr *BW, bool Mutable)
- : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Mutable(Mutable), BitWidth(BW) {
+ : DeclaratorDecl(DK, DC, L, Id, T, TInfo),
+ Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) {
}
public:
- static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T,
+ static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable);
+ /// getFieldIndex - Returns the index of this field within its record,
+ /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
+ unsigned getFieldIndex() const;
+
/// isMutable - Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }
@@ -1707,6 +1849,45 @@ public:
friend class StmtIteratorBase;
};
+/// IndirectFieldDecl - An instance of this class is created to represent a
+/// field injected from an anonymous union/struct into the parent scope.
+/// IndirectFieldDecl are always implicit.
+class IndirectFieldDecl : public ValueDecl {
+ NamedDecl **Chaining;
+ unsigned ChainingSize;
+
+ IndirectFieldDecl(DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T,
+ NamedDecl **CH, unsigned CHS)
+ : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
+
+public:
+ static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, NamedDecl **CH, unsigned CHS);
+
+ typedef NamedDecl * const *chain_iterator;
+ chain_iterator chain_begin() const { return Chaining; }
+ chain_iterator chain_end() const { return Chaining+ChainingSize; }
+
+ unsigned getChainingSize() const { return ChainingSize; }
+
+ FieldDecl *getAnonField() const {
+ assert(ChainingSize >= 2);
+ return cast<FieldDecl>(Chaining[ChainingSize - 1]);
+ }
+
+ VarDecl *getVarDecl() const {
+ assert(ChainingSize >= 2);
+ return dyn_cast<VarDecl>(*chain_begin());
+ }
+
+ // 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;
+};
/// TypeDecl - Represents a declaration of a type.
///
@@ -1715,7 +1896,7 @@ class TypeDecl : public NamedDecl {
/// this TypeDecl. It is a cache maintained by
/// ASTContext::getTypedefType, ASTContext::getTagDeclType, and
/// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl.
- mutable Type *TypeForDecl;
+ mutable const Type *TypeForDecl;
friend class ASTContext;
friend class DeclContext;
friend class TagDecl;
@@ -1729,8 +1910,8 @@ protected:
public:
// Low-level accessor
- Type *getTypeForDecl() const { return TypeForDecl; }
- void setTypeForDecl(Type *TD) { TypeForDecl = TD; }
+ const Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(const Type *TD) { TypeForDecl = TD; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -1820,6 +2001,19 @@ protected:
unsigned NumPositiveBits : 8;
unsigned NumNegativeBits : 8;
+ /// IsScoped - True if this tag declaration is a scoped enumeration. Only
+ /// possible in C++0x mode.
+ bool IsScoped : 1;
+ /// IsScopedUsingClassTag - If this tag declaration is a scoped enum,
+ /// then this is true if the scoped enum was declared using the class
+ /// tag, false if it was declared with the struct tag. No meaning is
+ /// associated if this tag declaration is not a scoped enum.
+ bool IsScopedUsingClassTag : 1;
+
+ /// IsFixed - True if this is an enumeration with fixed underlying type. Only
+ /// possible in C++0x mode.
+ bool IsFixed : 1;
+
private:
SourceLocation TagKeywordLoc;
SourceLocation RBraceLoc;
@@ -1859,6 +2053,11 @@ protected:
typedef Redeclarable<TagDecl> redeclarable_base;
virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+ /// @brief Completes the definition of this tag declaration.
+ ///
+ /// This is a helper function for derived classes.
+ void completeDefinition();
+
public:
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
@@ -1923,9 +2122,6 @@ public:
/// where it is in the process of being defined.
void startDefinition();
- /// @brief Completes the definition of this tag declaration.
- void completeDefinition();
-
/// getDefinition - Returns the TagDecl that actually defines this
/// struct/union/class/enum. When determining whether or not a
/// struct/union/class/enum is completely defined, one should use this method
@@ -2001,7 +2197,19 @@ class EnumDecl : public TagDecl {
/// IntegerType - This represent the integer type that the enum corresponds
/// to for code generation purposes. Note that the enumerator constants may
/// have a different type than this does.
- QualType IntegerType;
+ ///
+ /// If the underlying integer type was explicitly stated in the source
+ /// code, this is a TypeSourceInfo* for that type. Otherwise this type
+ /// was automatically deduced somehow, and this is a Type*.
+ ///
+ /// Normally if IsFixed(), this would contain a TypeSourceInfo*, but in
+ /// some cases it won't.
+ ///
+ /// The underlying type of an enumeration never has any qualifiers, so
+ /// we can get away with just storing a raw Type*, and thus save an
+ /// extra pointer when TypeSourceInfo is needed.
+
+ llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType;
/// PromotionType - The integer type that values of this type should
/// promote to. In C, enumerators are generally of an integer type
@@ -2022,11 +2230,16 @@ class EnumDecl : public TagDecl {
};
EnumDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
+ IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL,
+ bool Scoped, bool ScopedUsingClassTag, bool Fixed)
: TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
- IntegerType = QualType();
+ assert(Scoped || !ScopedUsingClassTag);
+ IntegerType = (const Type*)0;
NumNegativeBits = 0;
NumPositiveBits = 0;
+ IsScoped = Scoped;
+ IsScopedUsingClassTag = ScopedUsingClassTag;
+ IsFixed = Fixed;
}
public:
EnumDecl *getCanonicalDecl() {
@@ -2045,7 +2258,9 @@ public:
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
- SourceLocation TKL, EnumDecl *PrevDecl);
+ SourceLocation TKL, EnumDecl *PrevDecl,
+ bool IsScoped, bool IsScopedUsingClassTag,
+ bool IsFixed);
static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
/// completeDefinition - When created, the EnumDecl corresponds to a
@@ -2085,10 +2300,25 @@ public:
/// getIntegerType - Return the integer type this enum decl corresponds to.
/// This returns a null qualtype for an enum forward definition.
- QualType getIntegerType() const { return IntegerType; }
+ QualType getIntegerType() const {
+ if (!IntegerType)
+ return QualType();
+ if (const Type* T = IntegerType.dyn_cast<const Type*>())
+ return QualType(T, 0);
+ return IntegerType.get<TypeSourceInfo*>()->getType();
+ }
/// \brief Set the underlying integer type.
- void setIntegerType(QualType T) { IntegerType = T; }
+ void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); }
+
+ /// \brief Set the underlying integer type source info.
+ void setIntegerTypeSourceInfo(TypeSourceInfo* TInfo) { IntegerType = TInfo; }
+
+ /// \brief Return the type source info for the underlying integer type,
+ /// if no type source info exists, return 0.
+ TypeSourceInfo* getIntegerTypeSourceInfo() const {
+ return IntegerType.dyn_cast<TypeSourceInfo*>();
+ }
/// \brief Returns the width in bits requred to store all the
/// non-negative enumerators of this enum.
@@ -2116,6 +2346,27 @@ public:
NumNegativeBits = Num;
}
+ /// \brief Returns true if this is a C++0x scoped enumeration.
+ bool isScoped() const {
+ return IsScoped;
+ }
+
+ /// \brief Returns true if this is a C++0x scoped enumeration.
+ bool isScopedUsingClassTag() const {
+ return IsScopedUsingClassTag;
+ }
+
+ /// \brief Returns true if this is a C++0x enumeration with fixed underlying
+ /// type.
+ bool isFixed() const {
+ return IsFixed;
+ }
+
+ /// \brief Returns true if this can be considered a complete type.
+ bool isComplete() const {
+ return isDefinition() || isFixed();
+ }
+
/// \brief Returns the enumeration (declared within the template)
/// from which this enumeration type was instantiated, or NULL if
/// this enumeration was not instantiated from any template.
@@ -2128,6 +2379,8 @@ 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;
};
@@ -2151,17 +2404,24 @@ class RecordDecl : public TagDecl {
/// containing an object.
bool HasObjectMember : 1;
+ /// \brief Whether the field declarations of this record have been loaded
+ /// from external storage. To avoid unnecessary deserialization of
+ /// methods/nested types we allow deserialization of just the fields
+ /// when needed.
+ mutable bool LoadedFieldsFromExternalStorage : 1;
+ friend class DeclContext;
+
protected:
RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
RecordDecl *PrevDecl, SourceLocation TKL);
public:
- static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
+ static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
SourceLocation TKL = SourceLocation(),
RecordDecl* PrevDecl = 0);
- static RecordDecl *Create(ASTContext &C, EmptyShell Empty);
+ static RecordDecl *Create(const ASTContext &C, EmptyShell Empty);
const RecordDecl *getPreviousDeclaration() const {
return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
@@ -2190,11 +2450,6 @@ public:
AnonymousStructOrUnion = Anon;
}
- ValueDecl *getAnonymousStructOrUnionObject();
- const ValueDecl *getAnonymousStructOrUnionObject() const {
- return const_cast<RecordDecl*>(this)->getAnonymousStructOrUnionObject();
- }
-
bool hasObjectMember() const { return HasObjectMember; }
void setHasObjectMember (bool val) { HasObjectMember = val; }
@@ -2229,11 +2484,10 @@ public:
// data members, functions, constructors, destructors, etc.
typedef specific_decl_iterator<FieldDecl> field_iterator;
- field_iterator field_begin() const {
- return field_iterator(decls_begin());
- }
+ field_iterator field_begin() const;
+
field_iterator field_end() const {
- return field_iterator(decls_end());
+ return field_iterator(decl_iterator());
}
// field_empty - Whether there are any fields (non-static data
@@ -2244,13 +2498,17 @@ public:
/// completeDefinition - Notes that the definition of this type is
/// now complete.
- void completeDefinition();
+ 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;
}
+
+private:
+ /// \brief Deserialize just the fields.
+ void LoadFieldsFromExternalStorage() const;
};
class FileScopeAsmDecl : public Decl {
@@ -2275,8 +2533,49 @@ public:
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
///
class BlockDecl : public Decl, public DeclContext {
+public:
+ /// A class which contains all the information about a particular
+ /// captured value.
+ class Capture {
+ enum {
+ flag_isByRef = 0x1,
+ flag_isNested = 0x2
+ };
+
+ /// The variable being captured.
+ llvm::PointerIntPair<VarDecl*, 2> VariableAndFlags;
+
+ /// The copy expression, expressed in terms of a DeclRef (or
+ /// BlockDeclRef) to the captured variable. Only required if the
+ /// variable has a C++ class type.
+ Expr *CopyExpr;
+
+ public:
+ Capture(VarDecl *variable, bool byRef, bool nested, Expr *copy)
+ : VariableAndFlags(variable,
+ (byRef ? flag_isByRef : 0) | (nested ? flag_isNested : 0)),
+ CopyExpr(copy) {}
+
+ /// The variable being captured.
+ VarDecl *getVariable() const { return VariableAndFlags.getPointer(); }
+
+ /// Whether this is a "by ref" capture, i.e. a capture of a __block
+ /// variable.
+ bool isByRef() const { return VariableAndFlags.getInt() & flag_isByRef; }
+
+ /// Whether this is a nested capture, i.e. the variable captured
+ /// is not from outside the immediately enclosing function/block.
+ bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; }
+
+ bool hasCopyExpr() const { return CopyExpr != 0; }
+ Expr *getCopyExpr() const { return CopyExpr; }
+ void setCopyExpr(Expr *e) { CopyExpr = e; }
+ };
+
+private:
// FIXME: This can be packed into the bitfields in Decl.
bool IsVariadic : 1;
+ bool CapturesCXXThis : 1;
/// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals.
@@ -2286,11 +2585,15 @@ class BlockDecl : public Decl, public DeclContext {
Stmt *Body;
TypeSourceInfo *SignatureAsWritten;
+ Capture *Captures;
+ unsigned NumCaptures;
+
protected:
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
: Decl(Block, DC, CaretLoc), DeclContext(Block),
- IsVariadic(false), ParamInfo(0), NumParams(0), Body(0),
- SignatureAsWritten(0) {}
+ IsVariadic(false), CapturesCXXThis(false),
+ ParamInfo(0), NumParams(0), Body(0),
+ SignatureAsWritten(0), Captures(0), NumCaptures(0) {}
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
@@ -2319,7 +2622,7 @@ public:
param_const_iterator param_begin() const { return ParamInfo; }
param_const_iterator param_end() const { return ParamInfo+param_size(); }
- unsigned getNumParams() const;
+ unsigned getNumParams() const { return NumParams; }
const ParmVarDecl *getParamDecl(unsigned i) const {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
@@ -2330,6 +2633,30 @@ public:
}
void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
+ /// hasCaptures - True if this block (or its nested blocks) captures
+ /// anything of local storage from its enclosing scopes.
+ bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; }
+
+ /// getNumCaptures - Returns the number of captured variables.
+ /// Does not include an entry for 'this'.
+ unsigned getNumCaptures() const { return NumCaptures; }
+
+ typedef const Capture *capture_iterator;
+ typedef const Capture *capture_const_iterator;
+ capture_iterator capture_begin() { return Captures; }
+ capture_iterator capture_end() { return Captures + NumCaptures; }
+ capture_const_iterator capture_begin() const { return Captures; }
+ capture_const_iterator capture_end() const { return Captures + NumCaptures; }
+
+ bool capturesCXXThis() const { return CapturesCXXThis; }
+
+ void setCaptures(ASTContext &Context,
+ const Capture *begin,
+ const Capture *end,
+ bool capturesCXXThis);
+
+ virtual SourceRange getSourceRange() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const BlockDecl *D) { return true; }
@@ -2350,6 +2677,32 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
+template<typename decl_type>
+void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) {
+ // Note: This routine is implemented here because we need both NamedDecl
+ // and Redeclarable to be defined.
+
+ decl_type *First;
+
+ if (PrevDecl) {
+ // Point to previous. Make sure that this is actually the most recent
+ // redeclaration, or we can build invalid chains. If the most recent
+ // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
+ RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
+ PrevDecl->getMostRecentDeclaration()));
+ First = PrevDecl->getFirstDeclaration();
+ assert(First->RedeclLink.NextIsLatest() && "Expected first");
+ } else {
+ // Make this first.
+ First = static_cast<decl_type*>(this);
+ }
+
+ // First one will point to this one as latest.
+ First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this)))
+ ND->ClearLinkageCache();
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 1369c2b5955a..bf249cea9d5f 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -43,6 +43,7 @@ class DeclarationName;
class CompoundStmt;
class StoredDeclsMap;
class DependentDiagnostic;
+class ASTMutationListener;
}
namespace llvm {
@@ -197,25 +198,25 @@ private:
return DeclCtx.get<DeclContext*>();
}
- /// Loc - The location that this decl.
+ /// Loc - The location of this decl.
SourceLocation Loc;
/// DeclKind - This indicates which class this is.
- Kind DeclKind : 8;
+ unsigned DeclKind : 8;
/// InvalidDecl - This indicates a semantic error occurred.
- unsigned int InvalidDecl : 1;
+ unsigned InvalidDecl : 1;
/// HasAttrs - This indicates whether the decl has attributes or not.
- unsigned int HasAttrs : 1;
+ unsigned HasAttrs : 1;
/// Implicit - Whether this declaration was implicitly generated by
/// the implementation rather than explicitly written by the user.
- bool Implicit : 1;
+ unsigned Implicit : 1;
/// \brief Whether this declaration was "used", meaning that a definition is
/// required.
- bool Used : 1;
+ unsigned Used : 1;
protected:
/// Access - Used by C++ decls for the access specifier.
@@ -227,17 +228,24 @@ protected:
unsigned PCHLevel : 2;
/// ChangedAfterLoad - if this declaration has changed since being loaded
- bool ChangedAfterLoad : 1;
+ unsigned ChangedAfterLoad : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
- unsigned IdentifierNamespace : 15;
+ unsigned IdentifierNamespace : 12;
+ /// \brief Whether the \c CachedLinkage field is active.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned HasCachedLinkage : 1;
+
+ /// \brief If \c HasCachedLinkage, the linkage of this declaration.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned CachedLinkage : 2;
+
+
private:
-#ifndef NDEBUG
void CheckAccessDeclContext() const;
-#else
- void CheckAccessDeclContext() const { }
-#endif
protected:
@@ -246,7 +254,9 @@ protected:
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
- IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
if (Decl::CollectingStats()) add(DK);
}
@@ -254,7 +264,9 @@ protected:
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
- IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
if (Decl::CollectingStats()) add(DK);
}
@@ -272,7 +284,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- Kind getKind() const { return DeclKind; }
+ Kind getKind() const { return static_cast<Kind>(DeclKind); }
const char *getDeclKindName() const;
Decl *getNextDeclInContext() { return NextDeclInContext; }
@@ -298,17 +310,21 @@ public:
void setAccess(AccessSpecifier AS) {
Access = AS;
+#ifndef NDEBUG
CheckAccessDeclContext();
+#endif
}
AccessSpecifier getAccess() const {
+#ifndef NDEBUG
CheckAccessDeclContext();
+#endif
return AccessSpecifier(Access);
}
bool hasAttrs() const { return HasAttrs; }
void setAttrs(const AttrVec& Attrs);
- AttrVec& getAttrs() {
+ AttrVec &getAttrs() {
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
const AttrVec &getAttrs() const;
@@ -551,6 +567,9 @@ public:
/// template parameter pack.
bool isTemplateParameterPack() const;
+ /// \brief Whether this declaration is a parameter pack.
+ bool isParameterPack() const;
+
/// \brief Whether this declaration is a function or function template.
bool isFunctionOrFunctionTemplate() const;
@@ -621,10 +640,14 @@ public:
llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
void dump() const;
+ void dumpXML() const;
+ void dumpXML(llvm::raw_ostream &OS) const;
private:
const Attr *getAttrsImpl() const;
+protected:
+ ASTMutationListener *getASTMutationListener() const;
};
/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
@@ -681,23 +704,24 @@ public:
///
class DeclContext {
/// DeclKind - This indicates which class this is.
- Decl::Kind DeclKind : 8;
+ unsigned DeclKind : 8;
/// \brief Whether this declaration context also has some external
/// storage that contains additional declarations that are lexically
/// part of this context.
- mutable bool ExternalLexicalStorage : 1;
+ mutable unsigned ExternalLexicalStorage : 1;
/// \brief Whether this declaration context also has some external
/// storage that contains additional declarations that are visible
/// in this context.
- mutable bool ExternalVisibleStorage : 1;
+ mutable unsigned ExternalVisibleStorage : 1;
/// \brief Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context).
mutable StoredDeclsMap *LookupPtr;
+protected:
/// FirstDecl - The first declaration stored within this declaration
/// context.
mutable Decl *FirstDecl;
@@ -710,7 +734,12 @@ class DeclContext {
friend class ExternalASTSource;
-protected:
+ /// \brief Build up a chain of declarations.
+ ///
+ /// \returns the first/last pair of declarations.
+ static std::pair<Decl *, Decl *>
+ BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls);
+
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
@@ -720,7 +749,7 @@ public:
~DeclContext();
Decl::Kind getDeclKind() const {
- return DeclKind;
+ return static_cast<Decl::Kind>(DeclKind);
}
const char *getDeclKindName() const;
@@ -807,6 +836,10 @@ public:
/// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
+ /// \brief Determines whether this context is, or is nested within,
+ /// a C++ extern "C" linkage spec.
+ bool isExternCContext() const;
+
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(const DeclContext *DC) const {
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index a9802bfcaf4e..d11ee8f7fd64 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -35,6 +35,7 @@ class CXXMethodDecl;
class CXXRecordDecl;
class CXXMemberLookupCriteria;
class CXXFinalOverriderMap;
+class CXXIndirectPrimaryBaseSet;
class FriendDecl;
/// \brief Represents any kind of function declaration, whether it is a
@@ -112,6 +113,8 @@ class AccessSpecDecl : public Decl {
: Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) {
setAccess(AS);
}
+ AccessSpecDecl(EmptyShell Empty)
+ : Decl(AccessSpec, Empty) { }
public:
/// getAccessSpecifierLoc - The location of the access specifier.
SourceLocation getAccessSpecifierLoc() const { return getLocation(); }
@@ -132,6 +135,9 @@ public:
SourceLocation ColonLoc) {
return new (C) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
}
+ static AccessSpecDecl *Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) AccessSpecDecl(Empty);
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -162,6 +168,10 @@ class CXXBaseSpecifier {
/// specifier (if present).
SourceRange Range;
+ /// \brief The source location of the ellipsis, if this is a pack
+ /// expansion.
+ SourceLocation EllipsisLoc;
+
/// Virtual - Whether this is a virtual base class or not.
bool Virtual : 1;
@@ -177,6 +187,10 @@ class CXXBaseSpecifier {
/// VC++ bug.
unsigned Access : 2;
+ /// InheritConstructors - Whether the class contains a using declaration
+ /// to inherit the named class's constructors.
+ bool InheritConstructors : 1;
+
/// BaseTypeInfo - The type of the base class. This will be a class or struct
/// (or a typedef of such). The source code range does not include the
/// "virtual" or access specifier.
@@ -186,8 +200,9 @@ public:
CXXBaseSpecifier() { }
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
- TypeSourceInfo *TInfo)
- : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { }
+ TypeSourceInfo *TInfo, SourceLocation EllipsisLoc)
+ : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC),
+ Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { }
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
@@ -201,6 +216,22 @@ public:
/// with the 'class' keyword (vs. one declared with the 'struct' keyword).
bool isBaseOfClass() const { return BaseOfClass; }
+ /// \brief Determine whether this base specifier is a pack expansion.
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+
+ /// \brief Determine whether this base class's constructors get inherited.
+ bool getInheritConstructors() const { return InheritConstructors; }
+
+ /// \brief Set that this base class's constructors should be inherited.
+ void setInheritConstructors(bool Inherit = true) {
+ InheritConstructors = Inherit;
+ }
+
+ /// \brief For a pack expansion, determine the location of the ellipsis.
+ SourceLocation getEllipsisLoc() const {
+ return EllipsisLoc;
+ }
+
/// getAccessSpecifier - Returns the access specifier for this base
/// specifier. This is the actual base specifier as used for
/// semantic analysis, so the result can never be AS_none. To
@@ -336,20 +367,20 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Whether we have already declared a destructor within the class.
bool DeclaredDestructor : 1;
-
- /// Bases - Base classes of this class.
- /// FIXME: This is wasted space for a union.
- CXXBaseSpecifier *Bases;
/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
-
- /// VBases - direct and indirect virtual base classes of this class.
- CXXBaseSpecifier *VBases;
-
+
/// NumVBases - The number of virtual base class specifiers in VBases.
unsigned NumVBases;
+ /// Bases - Base classes of this class.
+ /// FIXME: This is wasted space for a union.
+ LazyCXXBaseSpecifiersPtr Bases;
+
+ /// VBases - direct and indirect virtual base classes of this class.
+ LazyCXXBaseSpecifiersPtr VBases;
+
/// Conversions - Overload set containing the conversion functions
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
@@ -371,6 +402,15 @@ class CXXRecordDecl : public RecordDecl {
/// in reverse order.
FriendDecl *FirstFriend;
+ /// \brief Retrieve the set of direct base classes.
+ CXXBaseSpecifier *getBases() const {
+ return Bases.get(Definition->getASTContext().getExternalSource());
+ }
+
+ /// \brief Retrieve the set of virtual base classes.
+ CXXBaseSpecifier *getVBases() const {
+ return VBases.get(Definition->getASTContext().getExternalSource());
+ }
} *DefinitionData;
struct DefinitionData &data() {
@@ -395,9 +435,17 @@ class CXXRecordDecl : public RecordDecl {
llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
TemplateOrInstantiation;
-#ifndef NDEBUG
- void CheckConversionFunction(NamedDecl *D);
-#endif
+ friend class DeclContext;
+
+ /// \brief Notify the class that member has been added.
+ ///
+ /// This routine helps maintain information about the class based on which
+ /// members have been added. It will be invoked by DeclContext::addDecl()
+ /// whenever a member is added to this record.
+ void addedMember(Decl *D);
+
+ void markedVirtualFunctionPure();
+ friend void FunctionDecl::setPure(bool);
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -445,12 +493,12 @@ public:
bool hasDefinition() const { return DefinitionData != 0; }
- static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
+ static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
SourceLocation TKL = SourceLocation(),
CXXRecordDecl* PrevDecl=0,
bool DelayTypeCreation = false);
- static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty);
+ static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty);
bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0;
@@ -463,8 +511,8 @@ public:
/// class.
unsigned getNumBases() const { return data().NumBases; }
- base_class_iterator bases_begin() { return data().Bases; }
- base_class_const_iterator bases_begin() const { return data().Bases; }
+ base_class_iterator bases_begin() { return data().getBases(); }
+ base_class_const_iterator bases_begin() const { return data().getBases(); }
base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
base_class_const_iterator bases_end() const {
return bases_begin() + data().NumBases;
@@ -486,8 +534,8 @@ public:
/// class.
unsigned getNumVBases() const { return data().NumVBases; }
- base_class_iterator vbases_begin() { return data().VBases; }
- base_class_const_iterator vbases_begin() const { return data().VBases; }
+ base_class_iterator vbases_begin() { return data().getVBases(); }
+ base_class_const_iterator vbases_begin() const { return data().getVBases(); }
base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; }
base_class_const_iterator vbases_end() const {
return vbases_begin() + data().NumVBases;
@@ -553,18 +601,12 @@ public:
return data().DeclaredDefaultConstructor;
}
- /// \brief Note whether this class has already had its default constructor
- /// implicitly declared or doesn't need one.
- void setDeclaredDefaultConstructor(bool DDC) {
- data().DeclaredDefaultConstructor = DDC;
- }
-
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
- bool hasConstCopyConstructor(ASTContext &Context) const;
+ bool hasConstCopyConstructor(const ASTContext &Context) const;
/// getCopyConstructor - Returns the copy constructor for this class
- CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
+ CXXConstructorDecl *getCopyConstructor(const ASTContext &Context,
unsigned TypeQuals) const;
/// \brief Retrieve the copy-assignment operator for this class, if available.
@@ -579,11 +621,6 @@ public:
/// a unique copy-assignment operator could not be found.
CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const;
- /// addedConstructor - Notify the class that another constructor has
- /// been added. This routine helps maintain information about the
- /// class based on which constructors have been added.
- void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
-
/// hasUserDeclaredConstructor - Whether this class has any
/// user-declared constructors. When true, a default constructor
/// will not be implicitly declared.
@@ -606,17 +643,6 @@ public:
return data().DeclaredCopyConstructor;
}
- /// \brief Note whether this class has already had its copy constructor
- /// declared.
- void setDeclaredCopyConstructor(bool DCC) {
- data().DeclaredCopyConstructor = DCC;
- }
-
- /// addedAssignmentOperator - Notify the class that another assignment
- /// operator has been added. This routine helps maintain information about the
- /// class based on which operators have been added.
- void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
-
/// hasUserDeclaredCopyAssignment - Whether this class has a
/// user-declared copy assignment operator. When false, a copy
/// assigment operator will be implicitly declared.
@@ -632,12 +658,6 @@ public:
return data().DeclaredCopyAssignment;
}
- /// \brief Note whether this class has already had its copy assignment
- /// operator declared.
- void setDeclaredCopyAssignment(bool DCA) {
- data().DeclaredCopyAssignment = DCA;
- }
-
/// hasUserDeclaredDestructor - Whether this class has a
/// user-declared destructor. When false, a destructor will be
/// implicitly declared.
@@ -645,26 +665,12 @@ public:
return data().UserDeclaredDestructor;
}
- /// setUserDeclaredDestructor - Set whether this class has a
- /// user-declared destructor. If not set by the time the class is
- /// fully defined, a destructor will be implicitly declared.
- void setUserDeclaredDestructor(bool UCD) {
- data().UserDeclaredDestructor = UCD;
- if (UCD)
- data().DeclaredDestructor = true;
- }
-
/// \brief Determine whether this class has had its destructor declared,
/// either via the user or via an implicit declaration.
///
/// This value is used for lazy creation of destructors.
bool hasDeclaredDestructor() const { return data().DeclaredDestructor; }
-
- /// \brief Note whether this class has already had its destructor declared.
- void setDeclaredDestructor(bool DD) {
- data().DeclaredDestructor = DD;
- }
-
+
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
UnresolvedSetImpl *getConversionFunctions() {
@@ -682,13 +688,6 @@ public:
return getConversionFunctions()->end();
}
- /// Replaces a conversion function with a new declaration.
- ///
- /// Returns true if the old conversion was found.
- bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
- return getConversionFunctions()->replace(Old, New);
- }
-
/// Removes a conversion function from this class. The conversion
/// function must currently be a member of this class. Furthermore,
/// this class must currently be in the process of being defined.
@@ -698,105 +697,52 @@ public:
/// in current class; including conversion function templates.
const UnresolvedSetImpl *getVisibleConversionFunctions();
- /// addConversionFunction - Registers a conversion function which
- /// this class declares directly.
- void addConversionFunction(NamedDecl *Decl) {
-#ifndef NDEBUG
- CheckConversionFunction(Decl);
-#endif
-
- // We intentionally don't use the decl's access here because it
- // hasn't been set yet. That's really just a misdesign in Sema.
- data().Conversions.addDecl(Decl);
- }
-
/// isAggregate - Whether this class is an aggregate (C++
/// [dcl.init.aggr]), which is a class with no user-declared
/// constructors, no private or protected non-static data members,
/// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
bool isAggregate() const { return data().Aggregate; }
- /// setAggregate - Set whether this class is an aggregate (C++
- /// [dcl.init.aggr]).
- void setAggregate(bool Agg) { data().Aggregate = Agg; }
-
- /// setMethodAsVirtual - Make input method virtual and set the necesssary
- /// special function bits and other bits accordingly.
- void setMethodAsVirtual(FunctionDecl *Method);
-
/// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
/// that is an aggregate that has no non-static non-POD data members, no
/// reference data members, no user-defined copy assignment operator and no
/// user-defined destructor.
bool isPOD() const { return data().PlainOldData; }
- /// setPOD - Set whether this class is a POD-type (C++ [class]p4).
- void setPOD(bool POD) { data().PlainOldData = POD; }
-
/// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
/// means it has a virtual function, virtual base, data member (other than
/// 0-width bit-field) or inherits from a non-empty class. Does NOT include
/// a check for union-ness.
bool isEmpty() const { return data().Empty; }
- /// Set whether this class is empty (C++0x [meta.unary.prop])
- void setEmpty(bool Emp) { data().Empty = Emp; }
-
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
/// which means that the class contains or inherits a virtual function.
bool isPolymorphic() const { return data().Polymorphic; }
- /// setPolymorphic - Set whether this class is polymorphic (C++
- /// [class.virtual]).
- void setPolymorphic(bool Poly) { data().Polymorphic = Poly; }
-
/// isAbstract - Whether this class is abstract (C++ [class.abstract]),
/// which means that the class contains or inherits a pure virtual function.
bool isAbstract() const { return data().Abstract; }
- /// setAbstract - Set whether this class is abstract (C++ [class.abstract])
- void setAbstract(bool Abs) { data().Abstract = Abs; }
-
// hasTrivialConstructor - Whether this class has a trivial constructor
// (C++ [class.ctor]p5)
bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
- // setHasTrivialConstructor - Set whether this class has a trivial constructor
- // (C++ [class.ctor]p5)
- void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; }
-
// hasTrivialCopyConstructor - Whether this class has a trivial copy
// constructor (C++ [class.copy]p6)
bool hasTrivialCopyConstructor() const {
return data().HasTrivialCopyConstructor;
}
- // setHasTrivialCopyConstructor - Set whether this class has a trivial
- // copy constructor (C++ [class.copy]p6)
- void setHasTrivialCopyConstructor(bool TC) {
- data().HasTrivialCopyConstructor = TC;
- }
-
// hasTrivialCopyAssignment - Whether this class has a trivial copy
// assignment operator (C++ [class.copy]p11)
bool hasTrivialCopyAssignment() const {
return data().HasTrivialCopyAssignment;
}
- // setHasTrivialCopyAssignment - Set whether this class has a
- // trivial copy assignment operator (C++ [class.copy]p11)
- void setHasTrivialCopyAssignment(bool TC) {
- data().HasTrivialCopyAssignment = TC;
- }
-
// hasTrivialDestructor - Whether this class has a trivial destructor
// (C++ [class.dtor]p3)
bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
- // setHasTrivialDestructor - Set whether this class has a trivial destructor
- // (C++ [class.dtor]p3)
- void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; }
-
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
@@ -854,9 +800,6 @@ public:
/// \brief Set the kind of specialization or template instantiation this is.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
-
- /// getDefaultConstructor - Returns the default constructor for this class
- CXXConstructorDecl *getDefaultConstructor();
/// getDestructor - Returns the destructor decl for this class.
CXXDestructorDecl *getDestructor() const;
@@ -880,7 +823,7 @@ public:
/// \param Base the base class we are searching for.
///
/// \returns true if this class is derived from Base, false otherwise.
- bool isDerivedFrom(CXXRecordDecl *Base) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base) const;
/// \brief Determine whether this class is derived from the type \p Base.
///
@@ -898,7 +841,7 @@ public:
///
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
/// tangling input and output in \p Paths
- bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
/// \brief Determine whether this class is virtually derived from
/// the class \p Base.
@@ -1034,6 +977,9 @@ public:
/// most-derived class in the class hierarchy.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const;
+ /// \brief Get the indirect primary bases for this class.
+ void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const;
+
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
@@ -1048,6 +994,27 @@ public:
return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
}
+ /// \brief Indicates that the definition of this class is now complete.
+ virtual void completeDefinition();
+
+ /// \brief Indicates that the definition of this class is now complete,
+ /// and provides a final overrider map to help determine
+ ///
+ /// \param FinalOverriders The final overrider map for this class, which can
+ /// be provided as an optimization for abstract-class checking. If NULL,
+ /// final overriders will be computed if they are needed to complete the
+ /// definition.
+ void completeDefinition(CXXFinalOverriderMap *FinalOverriders);
+
+ /// \brief Determine whether this class may end up being abstract, even though
+ /// it is not yet known to be abstract.
+ ///
+ /// \returns true if this class is not known to be abstract but has any
+ /// base classes that are abstract. In this case, \c completeDefinition()
+ /// will need to compute final overriders to determine whether the class is
+ /// actually abstract.
+ bool mayBeAbstract() const;
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
return K >= firstCXXRecord && K <= lastCXXRecord;
@@ -1059,6 +1026,8 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend class ASTReader;
+ friend class ASTWriter;
};
/// CXXMethodDecl - Represents a static or instance method of a
@@ -1139,6 +1108,20 @@ public:
return getType()->getAs<FunctionProtoType>()->getTypeQuals();
}
+ /// \brief Retrieve the ref-qualifier associated with this method.
+ ///
+ /// In the following example, \c f() has an lvalue ref-qualifier, \c g()
+ /// has an rvalue ref-qualifier, and \c h() has no ref-qualifier.
+ /// \code
+ /// struct X {
+ /// void f() &;
+ /// void g() &&;
+ /// void h();
+ /// };
+ RefQualifierKind getRefQualifier() const {
+ return getType()->getAs<FunctionProtoType>()->getRefQualifier();
+ }
+
bool hasInlineBody() const;
// Implement isa/cast/dyncast/etc.
@@ -1149,7 +1132,7 @@ public:
}
};
-/// CXXBaseOrMemberInitializer - Represents a C++ base or member
+/// CXXCtorInitializer - Represents a C++ base or member
/// initializer, which is part of a constructor initializer that
/// initializes one non-static member variable or one base class. For
/// example, in the following, both 'A(a)' and 'f(3.14159)' are member
@@ -1163,37 +1146,20 @@ public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
/// @endcode
-class CXXBaseOrMemberInitializer {
- /// \brief Either the base class name (stored as a TypeSourceInfo*) or the
- /// field being initialized.
- llvm::PointerUnion<TypeSourceInfo *, FieldDecl *> BaseOrMember;
+class CXXCtorInitializer {
+ /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal
+ /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being
+ /// initialized.
+ llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *>
+ Initializee;
- /// \brief The source location for the field name.
- SourceLocation MemberLocation;
+ /// \brief The source location for the field name or, for a base initializer
+ /// pack expansion, the location of the ellipsis.
+ SourceLocation MemberOrEllipsisLocation;
/// \brief The argument used to initialize the base or member, which may
/// end up constructing an object (when multiple arguments are involved).
Stmt *Init;
-
- /// \brief Stores either the constructor to call to initialize this base or
- /// member (a CXXConstructorDecl pointer), or stores the anonymous union of
- /// which the initialized value is a member.
- ///
- /// When the value is a FieldDecl pointer, 'BaseOrMember' is class's
- /// anonymous union data member, this field holds the FieldDecl for the
- /// member of the anonymous union being initialized.
- /// @code
- /// struct X {
- /// X() : au_i1(123) {}
- /// union {
- /// int au_i1;
- /// float au_f1;
- /// };
- /// };
- /// @endcode
- /// In above example, BaseOrMember holds the field decl. for anonymous union
- /// and AnonUnionMember holds field decl for au_i1.
- FieldDecl *AnonUnionMember;
/// LParenLoc - Location of the left paren of the ctor-initializer.
SourceLocation LParenLoc;
@@ -1208,6 +1174,7 @@ class CXXBaseOrMemberInitializer {
/// IsWritten - Whether or not the initializer is explicitly written
/// in the sources.
bool IsWritten : 1;
+
/// SourceOrderOrNumArrayIndices - If IsWritten is true, then this
/// number keeps track of the textual order of this initializer in the
/// original sources, counting from 0; otherwise, if IsWritten is false,
@@ -1215,50 +1182,62 @@ class CXXBaseOrMemberInitializer {
/// object in memory.
unsigned SourceOrderOrNumArrayIndices : 14;
- CXXBaseOrMemberInitializer(ASTContext &Context,
- FieldDecl *Member, SourceLocation MemberLoc,
- SourceLocation L,
- Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices);
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R, VarDecl **Indices, unsigned NumIndices);
public:
- /// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
+ /// CXXCtorInitializer - Creates a new base-class initializer.
explicit
- CXXBaseOrMemberInitializer(ASTContext &Context,
- TypeSourceInfo *TInfo, bool IsVirtual,
- SourceLocation L,
- Expr *Init,
- SourceLocation R);
+ CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual,
+ SourceLocation L, Expr *Init, SourceLocation R,
+ SourceLocation EllipsisLoc);
- /// CXXBaseOrMemberInitializer - Creates a new member initializer.
+ /// CXXCtorInitializer - Creates a new member initializer.
explicit
- CXXBaseOrMemberInitializer(ASTContext &Context,
- FieldDecl *Member, SourceLocation MemberLoc,
- SourceLocation L,
- Expr *Init,
- SourceLocation R);
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
+
+ explicit
+ CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
/// \brief Creates a new member initializer that optionally contains
/// array indices used to describe an elementwise initialization.
- static CXXBaseOrMemberInitializer *Create(ASTContext &Context,
- FieldDecl *Member,
- SourceLocation MemberLoc,
- SourceLocation L,
- Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices);
+ static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L,
+ Expr *Init, SourceLocation R,
+ VarDecl **Indices, unsigned NumIndices);
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
- bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
+ bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>(); }
/// isMemberInitializer - Returns true when this initializer is
/// initializing a non-static data member.
- bool isMemberInitializer() const { return BaseOrMember.is<FieldDecl*>(); }
+ bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); }
+
+ bool isAnyMemberInitializer() const {
+ return isMemberInitializer() || isIndirectMemberInitializer();
+ }
+ bool isIndirectMemberInitializer() const {
+ return Initializee.is<IndirectFieldDecl*>();
+ }
+
+ /// \brief Determine whether this initializer is a pack expansion.
+ bool isPackExpansion() const {
+ return isBaseInitializer() && MemberOrEllipsisLocation.isValid();
+ }
+
+ // \brief For a pack expansion, returns the location of the ellipsis.
+ SourceLocation getEllipsisLoc() const {
+ assert(isPackExpansion() && "Initializer is not a pack expansion");
+ return MemberOrEllipsisLocation;
+ }
+
/// If this is a base class initializer, returns the type of the
/// base class with location information. Otherwise, returns an NULL
/// type location.
@@ -1267,7 +1246,6 @@ public:
/// If this is a base class initializer, returns the type of the base class.
/// Otherwise, returns NULL.
const Type *getBaseClass() const;
- Type *getBaseClass();
/// Returns whether the base is virtual or not.
bool isBaseVirtual() const {
@@ -1278,7 +1256,7 @@ public:
/// \brief Returns the declarator information for a base class initializer.
TypeSourceInfo *getBaseClassInfo() const {
- return BaseOrMember.dyn_cast<TypeSourceInfo *>();
+ return Initializee.dyn_cast<TypeSourceInfo *>();
}
/// getMember - If this is a member initializer, returns the
@@ -1286,18 +1264,28 @@ public:
/// initialized. Otherwise, returns NULL.
FieldDecl *getMember() const {
if (isMemberInitializer())
- return BaseOrMember.get<FieldDecl*>();
+ return Initializee.get<FieldDecl*>();
+ else
+ return 0;
+ }
+ FieldDecl *getAnyMember() const {
+ if (isMemberInitializer())
+ return Initializee.get<FieldDecl*>();
+ else if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>()->getAnonField();
else
return 0;
}
- SourceLocation getMemberLocation() const {
- return MemberLocation;
+ IndirectFieldDecl *getIndirectMember() const {
+ if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>();
+ else
+ return 0;
}
- void setMember(FieldDecl *Member) {
- assert(isMemberInitializer());
- BaseOrMember = Member;
+ SourceLocation getMemberLocation() const {
+ return MemberOrEllipsisLocation;
}
/// \brief Determine the source location of the initializer.
@@ -1329,15 +1317,7 @@ public:
IsWritten = true;
SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos);
}
-
- FieldDecl *getAnonUnionMember() const {
- return AnonUnionMember;
- }
- void setAnonUnionMember(FieldDecl *anonMember) {
- AnonUnionMember = anonMember;
- }
-
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -1388,10 +1368,10 @@ class CXXConstructorDecl : public CXXMethodDecl {
bool ImplicitlyDefined : 1;
/// Support for base and member initializers.
- /// BaseOrMemberInitializers - The arguments used to initialize the base
+ /// CtorInitializers - The arguments used to initialize the base
/// or member.
- CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
- unsigned NumBaseOrMemberInitializers;
+ CXXCtorInitializer **CtorInitializers;
+ unsigned NumCtorInitializers;
CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
@@ -1400,7 +1380,7 @@ class CXXConstructorDecl : public CXXMethodDecl {
: CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false,
SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
- BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
+ CtorInitializers(0), NumCtorInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -1443,37 +1423,54 @@ public:
}
/// init_iterator - Iterates through the member/base initializer list.
- typedef CXXBaseOrMemberInitializer **init_iterator;
+ typedef CXXCtorInitializer **init_iterator;
/// init_const_iterator - Iterates through the memberbase initializer list.
- typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
+ typedef CXXCtorInitializer * const * init_const_iterator;
/// init_begin() - Retrieve an iterator to the first initializer.
- init_iterator init_begin() { return BaseOrMemberInitializers; }
+ init_iterator init_begin() { return CtorInitializers; }
/// begin() - Retrieve an iterator to the first initializer.
- init_const_iterator init_begin() const { return BaseOrMemberInitializers; }
+ init_const_iterator init_begin() const { return CtorInitializers; }
/// init_end() - Retrieve an iterator past the last initializer.
init_iterator init_end() {
- return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ return CtorInitializers + NumCtorInitializers;
}
/// end() - Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
- return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
+ return CtorInitializers + NumCtorInitializers;
+ }
+
+ typedef std::reverse_iterator<init_iterator> init_reverse_iterator;
+ typedef std::reverse_iterator<init_const_iterator> init_const_reverse_iterator;
+
+ init_reverse_iterator init_rbegin() {
+ return init_reverse_iterator(init_end());
+ }
+ init_const_reverse_iterator init_rbegin() const {
+ return init_const_reverse_iterator(init_end());
+ }
+
+ init_reverse_iterator init_rend() {
+ return init_reverse_iterator(init_begin());
+ }
+ init_const_reverse_iterator init_rend() const {
+ return init_const_reverse_iterator(init_begin());
}
/// getNumArgs - Determine the number of arguments used to
/// initialize the member or base.
- unsigned getNumBaseOrMemberInitializers() const {
- return NumBaseOrMemberInitializers;
+ unsigned getNumCtorInitializers() const {
+ return NumCtorInitializers;
}
- void setNumBaseOrMemberInitializers(unsigned numBaseOrMemberInitializers) {
- NumBaseOrMemberInitializers = numBaseOrMemberInitializers;
+ void setNumCtorInitializers(unsigned numCtorInitializers) {
+ NumCtorInitializers = numCtorInitializers;
}
- void setBaseOrMemberInitializers(CXXBaseOrMemberInitializer ** initializers) {
- BaseOrMemberInitializers = initializers;
+ void setCtorInitializers(CXXCtorInitializer ** initializers) {
+ CtorInitializers = initializers;
}
/// isDefaultConstructor - Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
@@ -1502,15 +1499,44 @@ public:
return isCopyConstructor(TypeQuals);
}
+ /// \brief Determine whether this constructor is a move constructor
+ /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ ///
+ /// \param TypeQuals If this constructor is a move constructor, will be set
+ /// to the type qualifiers on the referent of the first parameter's type.
+ bool isMoveConstructor(unsigned &TypeQuals) const;
+
+ /// \brief Determine whether this constructor is a move constructor
+ /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ bool isMoveConstructor() const;
+
+ /// \brief Determine whether this is a copy or move constructor.
+ ///
+ /// \param TypeQuals Will be set to the type qualifiers on the reference
+ /// parameter, if in fact this is a copy or move constructor.
+ bool isCopyOrMoveConstructor(unsigned &TypeQuals) const;
+
+ /// \brief Determine whether this a copy or move constructor.
+ bool isCopyOrMoveConstructor() const {
+ unsigned Quals;
+ return isCopyOrMoveConstructor(Quals);
+ }
+
/// isConvertingConstructor - Whether this constructor is a
/// converting constructor (C++ [class.conv.ctor]), which can be
/// used for user-defined conversions.
bool isConvertingConstructor(bool AllowExplicit) const;
/// \brief Determine whether this is a member template specialization that
- /// looks like a copy constructor. Such constructors are never used to copy
+ /// would copy the object to itself. Such constructors are never used to copy
/// an object.
- bool isCopyConstructorLikeSpecialization() const;
+ bool isSpecializationCopyingObject() const;
+
+ /// \brief Get the constructor that this inheriting constructor is based on.
+ const CXXConstructorDecl *getInheritedConstructor() const;
+
+ /// \brief Set the constructor that this inheriting constructor is based on.
+ void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -1542,8 +1568,9 @@ class CXXDestructorDecl : public CXXMethodDecl {
FunctionDecl *OperatorDelete;
CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
- QualType T, bool isInline, bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, TInfo, false,
SC_None, isInline),
ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
@@ -1553,7 +1580,8 @@ public:
static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
const DeclarationNameInfo &NameInfo,
- QualType T, bool isInline,
+ QualType T, TypeSourceInfo* TInfo,
+ bool isInline,
bool isImplicitlyDeclared);
/// isImplicitlyDefined - Whether this destructor was implicitly
@@ -1918,13 +1946,16 @@ class UsingShadowDecl : public NamedDecl {
/// The referenced declaration.
NamedDecl *Underlying;
- /// The using declaration which introduced this decl.
- UsingDecl *Using;
+ /// \brief The using declaration which introduced this decl or the next using
+ /// shadow declaration contained in the aforementioned using declaration.
+ NamedDecl *UsingOrNextShadow;
+ friend class UsingDecl;
UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
NamedDecl *Target)
: NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
- Underlying(Target), Using(Using) {
+ Underlying(Target),
+ UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
if (Target) {
setDeclName(Target->getDeclName());
IdentifierNamespace = Target->getIdentifierNamespace();
@@ -1952,15 +1983,20 @@ public:
}
/// \brief Gets the using declaration to which this declaration is tied.
- UsingDecl *getUsingDecl() const { return Using; }
+ UsingDecl *getUsingDecl() const;
- /// \brief Sets the using declaration that introduces this target
- /// declaration.
- void setUsingDecl(UsingDecl* UD) { Using = UD; }
+ /// \brief The next using shadow declaration contained in the shadow decl
+ /// chain of the using declaration which introduced this decl.
+ UsingShadowDecl *getNextUsingShadowDecl() const {
+ return dyn_cast_or_null<UsingShadowDecl>(UsingOrNextShadow);
+ }
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;
+ friend class ASTDeclWriter;
};
/// UsingDecl - Represents a C++ using-declaration. For example:
@@ -1980,10 +2016,9 @@ class UsingDecl : public NamedDecl {
/// declaration name embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
- /// \brief The collection of shadow declarations associated with
- /// this using declaration. This set can change as a class is
- /// processed.
- llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows;
+ /// \brief The first shadow declaration of the shadow decl chain associated
+ /// with this using declaration.
+ UsingShadowDecl *FirstUsingShadow;
// \brief Has 'typename' keyword.
bool IsTypeName;
@@ -1993,7 +2028,7 @@ class UsingDecl : public NamedDecl {
const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
- DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) {
+ DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) {
}
public:
@@ -2031,29 +2066,58 @@ public:
/// \brief Sets whether the using declaration has 'typename'.
void setTypeName(bool TN) { IsTypeName = TN; }
- typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator;
- shadow_iterator shadow_begin() const { return Shadows.begin(); }
- shadow_iterator shadow_end() const { return Shadows.end(); }
+ /// \brief Iterates through the using shadow declarations assosiated with
+ /// this using declaration.
+ class shadow_iterator {
+ /// \brief The current using shadow declaration.
+ UsingShadowDecl *Current;
+
+ public:
+ typedef UsingShadowDecl* value_type;
+ typedef UsingShadowDecl* reference;
+ typedef UsingShadowDecl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ shadow_iterator() : Current(0) { }
+ explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { }
- void addShadowDecl(UsingShadowDecl *S) {
- assert(S->getUsingDecl() == this);
- if (!Shadows.insert(S)) {
- assert(false && "declaration already in set");
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ shadow_iterator& operator++() {
+ Current = Current->getNextUsingShadowDecl();
+ return *this;
}
- }
- void removeShadowDecl(UsingShadowDecl *S) {
- assert(S->getUsingDecl() == this);
- if (!Shadows.erase(S)) {
- assert(false && "declaration not in set");
+
+ shadow_iterator operator++(int) {
+ shadow_iterator tmp(*this);
+ ++(*this);
+ return tmp;
}
+
+ friend bool operator==(shadow_iterator x, shadow_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(shadow_iterator x, shadow_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ shadow_iterator shadow_begin() const {
+ return shadow_iterator(FirstUsingShadow);
}
+ shadow_iterator shadow_end() const { return shadow_iterator(); }
/// \brief Return the number of shadowed declarations associated with this
/// using declaration.
- unsigned getNumShadowDecls() const {
- return Shadows.size();
+ unsigned shadow_size() const {
+ return std::distance(shadow_begin(), shadow_end());
}
+ void addShadowDecl(UsingShadowDecl *S);
+ void removeShadowDecl(UsingShadowDecl *S);
+
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
SourceRange NNR, SourceLocation UsingL,
NestedNameSpecifier* TargetNNS,
@@ -2145,6 +2209,9 @@ 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;
+ friend class ASTDeclWriter;
};
/// UnresolvedUsingTypenameDecl - Represents a dependent using
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 4b5e6fd48bb3..20d6da19b8ca 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -43,11 +43,16 @@ private:
FriendUnion Friend;
// A pointer to the next friend in the sequence.
- FriendDecl *NextFriend;
+ LazyDeclPtr NextFriend;
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
+ /// True if this 'friend' declaration is unsupported. Eventually we
+ /// will support every possible friend declaration, but for now we
+ /// silently ignore some and set this flag to authorize all access.
+ bool UnsupportedFriend;
+
friend class CXXRecordDecl::friend_iterator;
friend class CXXRecordDecl;
@@ -55,13 +60,19 @@ private:
SourceLocation FriendL)
: Decl(Decl::Friend, DC, L),
Friend(Friend),
- NextFriend(0),
- FriendLoc(FriendL) {
+ NextFriend(),
+ FriendLoc(FriendL),
+ UnsupportedFriend(false) {
}
explicit FriendDecl(EmptyShell Empty)
- : Decl(Decl::Friend, Empty), NextFriend(0) { }
+ : Decl(Decl::Friend, Empty), NextFriend() { }
+ FriendDecl *getNextFriend() {
+ return cast_or_null<FriendDecl>(
+ NextFriend.get(getASTContext().getExternalSource()));
+ }
+
public:
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
@@ -87,6 +98,14 @@ public:
return FriendLoc;
}
+ /// Determines if this friend kind is unsupported.
+ bool isUnsupportedFriend() const {
+ return UnsupportedFriend;
+ }
+ void setUnsupportedFriend(bool Unsupported) {
+ UnsupportedFriend = Unsupported;
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const FriendDecl *D) { return true; }
@@ -115,7 +134,7 @@ public:
friend_iterator &operator++() {
assert(Ptr && "attempt to increment past end of friend list");
- Ptr = Ptr->NextFriend;
+ Ptr = Ptr->getNextFriend();
return *this;
}
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index 030291ea7345..cb9e1681cc06 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace clang {
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index ad26748e1343..b3ca474fcc19 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -28,7 +28,7 @@ class ObjCProtocolDecl;
class ObjCCategoryDecl;
class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
-class CXXBaseOrMemberInitializer;
+class CXXCtorInitializer;
class ObjCListBase {
void operator=(const ObjCListBase &); // DO NOT IMPLEMENT
@@ -437,7 +437,7 @@ public:
class ObjCInterfaceDecl : public ObjCContainerDecl {
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
- mutable Type *TypeForDecl;
+ mutable const Type *TypeForDecl;
friend class ASTContext;
/// Class's super class.
@@ -449,8 +449,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// Protocols reference in both the @interface and class extensions.
ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
- /// List of categories defined for this class.
- /// FIXME: Why is this a linked list??
+ /// \brief List of categories and class extensions defined for this class.
+ ///
+ /// Categories are stored as a linked list in the AST, since the categories
+ /// and class extensions come long after the initial interface declaration,
+ /// and we avoid dynamically-resized arrays in the AST whereever possible.
ObjCCategoryDecl *CategoryList;
/// IvarList - List of all ivars defined by this class; including class
@@ -459,7 +462,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
bool ForwardDecl:1; // declared with @class.
bool InternalInterface:1; // true - no @interface for @implementation
-
+
+ /// \brief Indicates that the contents of this Objective-C class will be
+ /// completed by the external AST source when required.
+ mutable bool ExternallyCompleted : 1;
+
SourceLocation ClassLoc; // location of the class identifier.
SourceLocation SuperClassLoc; // location of the super class identifier.
SourceLocation EndLoc; // marks the '>', '}', or identifier.
@@ -467,6 +474,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal);
+ void LoadExternalDefinition() const;
public:
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
@@ -474,7 +482,16 @@ public:
SourceLocation ClassLoc = SourceLocation(),
bool ForwardDecl = false,
bool isInternal = false);
+
+ /// \brief Indicate that this Objective-C class is complete, but that
+ /// the external AST source will be responsible for filling in its contents
+ /// when a complete class is required.
+ void setExternallyCompleted();
+
const ObjCProtocolList &getReferencedProtocols() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols;
}
@@ -494,29 +511,47 @@ public:
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.begin();
}
protocol_iterator protocol_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.end();
}
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.loc_begin();
}
protocol_loc_iterator protocol_loc_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return ReferencedProtocols.loc_end();
}
typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
all_protocol_iterator all_referenced_protocol_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return AllReferencedProtocols.empty() ? protocol_begin()
: AllReferencedProtocols.begin();
}
all_protocol_iterator all_referenced_protocol_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
return AllReferencedProtocols.empty() ? protocol_end()
: AllReferencedProtocols.end();
}
@@ -551,10 +586,22 @@ public:
bool isForwardDecl() const { return ForwardDecl; }
void setForwardDecl(bool val) { ForwardDecl = val; }
- ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
+ ObjCInterfaceDecl *getSuperClass() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return SuperClass;
+ }
+
void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
- ObjCCategoryDecl* getCategoryList() const { return CategoryList; }
+ ObjCCategoryDecl* getCategoryList() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return CategoryList;
+ }
+
void setCategoryList(ObjCCategoryDecl *category) {
CategoryList = category;
}
@@ -595,7 +642,7 @@ public:
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
// Lookup a method in the classes implementation hierarchy.
- ObjCMethodDecl *lookupPrivateInstanceMethod(const Selector &Sel);
+ ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true);
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
@@ -621,8 +668,8 @@ public:
bool RHSIsQualifiedID = false);
// Low-level accessor
- Type *getTypeForDecl() const { return TypeForDecl; }
- void setTypeForDecl(Type *TD) const { TypeForDecl = TD; }
+ const Type *getTypeForDecl() const { return TypeForDecl; }
+ 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; }
@@ -991,6 +1038,7 @@ public:
void insertNextClassCategory() {
NextClassCategory = ClassInterface->getCategoryList();
ClassInterface->setCategoryList(this);
+ ClassInterface->setChangedSinceDeserialization(true);
}
bool IsClassExtension() const { return getIdentifier() == 0; }
@@ -1168,7 +1216,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
ObjCInterfaceDecl *SuperClass;
/// Support for ivar initialization.
/// IvarInitializers - The arguments used to initialize the ivars
- CXXBaseOrMemberInitializer **IvarInitializers;
+ CXXCtorInitializer **IvarInitializers;
unsigned NumIvarInitializers;
/// true of class extension has at least one bitfield ivar.
@@ -1187,10 +1235,10 @@ public:
ObjCInterfaceDecl *superDecl);
/// init_iterator - Iterates through the ivar initializer list.
- typedef CXXBaseOrMemberInitializer **init_iterator;
+ typedef CXXCtorInitializer **init_iterator;
/// init_const_iterator - Iterates through the ivar initializer list.
- typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
+ typedef CXXCtorInitializer * const * init_const_iterator;
/// init_begin() - Retrieve an iterator to the first initializer.
init_iterator init_begin() { return IvarInitializers; }
@@ -1215,7 +1263,7 @@ public:
}
void setIvarInitializers(ASTContext &C,
- CXXBaseOrMemberInitializer ** initializers,
+ CXXCtorInitializer ** initializers,
unsigned numInitializers);
bool hasSynthBitfield() const { return HasSynthBitfield; }
@@ -1322,7 +1370,8 @@ public:
OBJC_PR_retain = 0x10,
OBJC_PR_copy = 0x20,
OBJC_PR_nonatomic = 0x40,
- OBJC_PR_setter = 0x80
+ OBJC_PR_setter = 0x80,
+ OBJC_PR_atomic = 0x100
};
enum SetterKind { Assign, Retain, Copy };
@@ -1330,8 +1379,8 @@ public:
private:
SourceLocation AtLoc; // location of @property
TypeSourceInfo *DeclType;
- unsigned PropertyAttributes : 8;
- unsigned PropertyAttributesAsWritten : 8;
+ unsigned PropertyAttributes : 9;
+ unsigned PropertyAttributesAsWritten : 9;
// @required/@optional
unsigned PropertyImplementation : 2;
@@ -1429,6 +1478,10 @@ public:
return PropertyIvarDecl;
}
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, getLocation());
+ }
+
/// Lookup a property by name in the specified DeclContext.
static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
IdentifierInfo *propertyID);
@@ -1450,6 +1503,15 @@ public:
};
private:
SourceLocation AtLoc; // location of @synthesize or @dynamic
+
+ /// \brief For @synthesize, the location of the ivar, if it was written in
+ /// the source code.
+ ///
+ /// \code
+ /// @synthesize int a = b
+ /// \endcode
+ SourceLocation IvarLoc;
+
/// Property declaration being implemented
ObjCPropertyDecl *PropertyDecl;
@@ -1466,9 +1528,10 @@ private:
ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
ObjCPropertyDecl *property,
Kind PK,
- ObjCIvarDecl *ivarDecl)
+ ObjCIvarDecl *ivarDecl,
+ SourceLocation ivarLoc)
: Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
- PropertyDecl(property), PropertyIvarDecl(ivarDecl),
+ IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl),
GetterCXXConstructor(0), SetterCXXAssignment(0) {
assert (PK == Dynamic || PropertyIvarDecl);
}
@@ -1478,11 +1541,11 @@ public:
SourceLocation atLoc, SourceLocation L,
ObjCPropertyDecl *property,
Kind PK,
- ObjCIvarDecl *ivarDecl);
+ ObjCIvarDecl *ivarDecl,
+ SourceLocation ivarLoc);
- virtual SourceRange getSourceRange() const {
- return SourceRange(AtLoc, getLocation());
- }
+ virtual SourceRange getSourceRange() const;
+
SourceLocation getLocStart() const { return AtLoc; }
void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
@@ -1498,7 +1561,13 @@ public:
ObjCIvarDecl *getPropertyIvarDecl() const {
return PropertyIvarDecl;
}
- void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; }
+ SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; }
+
+ void setPropertyIvarDecl(ObjCIvarDecl *Ivar,
+ SourceLocation IvarLoc) {
+ PropertyIvarDecl = Ivar;
+ this->IvarLoc = IvarLoc;
+ }
Expr *getGetterCXXConstructor() const {
return GetterCXXConstructor;
@@ -1517,6 +1586,8 @@ 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;
};
} // end namespace clang
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index b532668242fd..176c6badae16 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -53,7 +53,7 @@ class TemplateParameterList {
SourceLocation RAngleLoc);
public:
- static TemplateParameterList *Create(ASTContext &C,
+ static TemplateParameterList *Create(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
NamedDecl **Params,
@@ -85,7 +85,7 @@ public:
return begin()[Idx];
}
- /// \btief Returns the minimum number of arguments needed to form a
+ /// \brief Returns the minimum number of arguments needed to form a
/// template specialization. This may be fewer than the number of
/// template parameters, if some of the parameters have default
/// arguments or if there is a parameter pack.
@@ -107,101 +107,57 @@ public:
}
};
-/// \brief A helper class for making template argument lists.
-class TemplateArgumentListBuilder {
- TemplateArgument *StructuredArgs;
- unsigned MaxStructuredArgs;
- unsigned NumStructuredArgs;
-
- llvm::SmallVector<TemplateArgument, 4> FlatArgs;
- unsigned MaxFlatArgs;
- unsigned NumFlatArgs;
-
- bool AddingToPack;
- unsigned PackBeginIndex;
-
-public:
- TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
- unsigned NumTemplateArgs)
- : StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
- NumStructuredArgs(0), FlatArgs(0),
- MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
- AddingToPack(false), PackBeginIndex(0) { }
-
- void Append(const TemplateArgument &Arg);
- void BeginPack();
- void EndPack();
-
- unsigned flatSize() const { return FlatArgs.size(); }
- const TemplateArgument *getFlatArguments() const { return FlatArgs.data(); }
-
- unsigned structuredSize() const {
- // If we don't have any structured args, just reuse the flat size.
- if (!StructuredArgs)
- return flatSize();
-
- return NumStructuredArgs;
- }
- const TemplateArgument *getStructuredArguments() const {
- // If we don't have any structured args, just reuse the flat args.
- if (!StructuredArgs)
- return getFlatArguments();
-
- return StructuredArgs;
- }
-};
-
/// \brief A template argument list.
-///
-/// FIXME: In the future, this class will be extended to support
-/// variadic templates and member templates, which will make some of
-/// the function names below make more sense.
class TemplateArgumentList {
/// \brief The template argument list.
///
/// The integer value will be non-zero to indicate that this
/// template argument list does own the pointer.
- llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
+ llvm::PointerIntPair<const TemplateArgument *, 1> Arguments;
/// \brief The number of template arguments in this template
/// argument list.
- unsigned NumFlatArguments;
-
- llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
- unsigned NumStructuredArguments;
+ unsigned NumArguments;
TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL
void operator=(const TemplateArgumentList &Other); // DO NOT IMPL
+
+ TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs,
+ bool Owned)
+ : Arguments(Args, Owned), NumArguments(NumArgs) { }
+
public:
- /// TemplateArgumentList - If this constructor is passed "true" for 'TakeArgs'
- /// it copies them into a locally new[]'d array. If passed "false", then it
- /// just references the array passed in. This is only safe if the builder
- /// outlives it, but saves a copy.
- TemplateArgumentList(ASTContext &Context,
- TemplateArgumentListBuilder &Builder,
- bool TakeArgs);
-
- /// TemplateArgumentList - It copies the template arguments into a locally
- /// new[]'d array.
- TemplateArgumentList(ASTContext &Context,
- const TemplateArgument *Args, unsigned NumArgs);
-
- /// Produces a shallow copy of the given template argument list. This
- /// assumes that the input argument list outlives it. This takes the list as
- /// a pointer to avoid looking like a copy constructor, since this really
- /// really isn't safe to use that way.
- explicit TemplateArgumentList(const TemplateArgumentList *Other);
-
- TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { }
-
- /// \brief Copies the template arguments into a locally new[]'d array.
- void init(ASTContext &Context,
- const TemplateArgument *Args, unsigned NumArgs);
+ /// \brief Type used to indicate that the template argument list itself is a
+ /// stack object. It does not own its template arguments.
+ enum OnStackType { OnStack };
+
+ /// \brief Create a new template argument list that copies the given set of
+ /// template arguments.
+ static TemplateArgumentList *CreateCopy(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Construct a new, temporary template argument list on the stack.
+ ///
+ /// The template argument list does not own the template arguments
+ /// provided.
+ explicit TemplateArgumentList(OnStackType,
+ const TemplateArgument *Args, unsigned NumArgs)
+ : Arguments(Args, false), NumArguments(NumArgs) { }
+
+ /// \brief Produces a shallow copy of the given template argument list.
+ ///
+ /// This operation assumes that the input argument list outlives it.
+ /// This takes the list as a pointer to avoid looking like a copy
+ /// constructor, since this really really isn't safe to use that
+ /// way.
+ explicit TemplateArgumentList(const TemplateArgumentList *Other)
+ : Arguments(Other->data(), false), NumArguments(Other->size()) { }
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &get(unsigned Idx) const {
- assert(Idx < NumFlatArguments && "Invalid template argument index");
- return getFlatArgumentList()[Idx];
+ assert(Idx < NumArguments && "Invalid template argument index");
+ return data()[Idx];
}
/// \brief Retrieve the template argument at a given index.
@@ -209,15 +165,11 @@ public:
/// \brief Retrieve the number of template arguments in this
/// template argument list.
- unsigned size() const { return NumFlatArguments; }
-
- /// \brief Retrieve the number of template arguments in the
- /// flattened template argument list.
- unsigned flat_size() const { return NumFlatArguments; }
+ unsigned size() const { return NumArguments; }
- /// \brief Retrieve the flattened template argument list.
- const TemplateArgument *getFlatArgumentList() const {
- return FlatArguments.getPointer();
+ /// \brief Retrieve a pointer to the template argument list.
+ const TemplateArgument *data() const {
+ return Arguments.getPointer();
}
};
@@ -292,7 +244,31 @@ public:
/// which is a FunctionDecl that has been explicitly specialization or
/// instantiated from a function template.
class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
+ FunctionTemplateSpecializationInfo(FunctionDecl *FD,
+ FunctionTemplateDecl *Template,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentList *TemplateArgs,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation POI)
+ : Function(FD),
+ Template(Template, TSK - 1),
+ TemplateArguments(TemplateArgs),
+ TemplateArgumentsAsWritten(TemplateArgsAsWritten),
+ PointOfInstantiation(POI) { }
+
public:
+ static FunctionTemplateSpecializationInfo *
+ Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentList *TemplateArgs,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation POI) {
+ return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
+ TemplateArgs,
+ TemplateArgsAsWritten,
+ POI);
+ }
+
/// \brief The function template specialization that this structure
/// describes.
FunctionDecl *Function;
@@ -345,8 +321,8 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, TemplateArguments->getFlatArgumentList(),
- TemplateArguments->flat_size(),
+ Profile(ID, TemplateArguments->data(),
+ TemplateArguments->size(),
Function->getASTContext());
}
@@ -441,11 +417,6 @@ class DependentFunctionTemplateSpecializationInfo {
return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
}
- const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc*>(
- &getTemplates()[getNumTemplates()]);
- }
-
public:
DependentFunctionTemplateSpecializationInfo(
const UnresolvedSetImpl &Templates,
@@ -463,6 +434,12 @@ public:
return getTemplates()[I];
}
+ /// \brief Returns the explicit template arguments that were given.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc*>(
+ &getTemplates()[getNumTemplates()]);
+ }
+
/// \brief Returns the number of explicit template arguments that were given.
unsigned getNumTemplateArgs() const {
return d.NumArgs;
@@ -584,7 +561,7 @@ protected:
/// for the common pointer.
CommonBase *getCommonPtr();
- virtual CommonBase *newCommon() = 0;
+ virtual CommonBase *newCommon(ASTContext &C) = 0;
// Construct a template decl with name, parameters, and templated element.
RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
@@ -789,19 +766,13 @@ protected:
TemplateParameterList *Params, NamedDecl *Decl)
: RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
- CommonBase *newCommon();
+ CommonBase *newCommon(ASTContext &C);
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}
- friend void FunctionDecl::setFunctionTemplateSpecialization(
- FunctionTemplateDecl *Template,
- const TemplateArgumentList *TemplateArgs,
- void *InsertPos,
- TemplateSpecializationKind TSK,
- const TemplateArgumentListInfo *TemplateArgsAsWritten,
- SourceLocation PointOfInstantiation);
+ friend class FunctionDecl;
/// \brief Retrieve the set of function template specializations of this
/// function template.
@@ -940,15 +911,15 @@ class TemplateTypeParmDecl : public TypeDecl {
bool Typename, QualType Type, bool ParameterPack)
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
- TypeForDecl = Type.getTypePtr();
+ TypeForDecl = Type.getTypePtrOrNull();
}
public:
- static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
+ static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack);
- static TemplateTypeParmDecl *Create(ASTContext &C, EmptyShell Empty);
+ static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty);
/// \brief Whether this template type parameter was declared with
/// the 'typename' keyword. If not, it was declared with the 'class'
@@ -1014,22 +985,54 @@ public:
/// template<int Size> class array { };
/// @endcode
class NonTypeTemplateParmDecl
- : public VarDecl, protected TemplateParmPosition {
+ : public DeclaratorDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any, and whether or not
/// it was inherited.
llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited;
+ // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
+ // down here to save memory.
+
+ /// \brief Whether this non-type template parameter is a parameter pack.
+ bool ParameterPack;
+
+ /// \brief Whether this non-type template parameter is an "expanded"
+ /// parameter pack, meaning that its type is a pack expansion and we
+ /// already know the set of types that expansion expands to.
+ bool ExpandedParameterPack;
+
+ /// \brief The number of types in an expanded parameter pack.
+ unsigned NumExpandedTypes;
+
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo)
- : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
- TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false)
+ bool ParameterPack, TypeSourceInfo *TInfo)
+ : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo),
+ TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
+ ParameterPack(ParameterPack), ExpandedParameterPack(false),
+ NumExpandedTypes(0)
{ }
+ NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo,
+ const QualType *ExpandedTypes,
+ unsigned NumExpandedTypes,
+ TypeSourceInfo **ExpandedTInfos);
+
+ friend class ASTDeclReader;
+
public:
static NonTypeTemplateParmDecl *
- Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
- unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo);
+ Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack,
+ TypeSourceInfo *TInfo);
+
+ static NonTypeTemplateParmDecl *
+ Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
+ const QualType *ExpandedTypes, unsigned NumExpandedTypes,
+ TypeSourceInfo **ExpandedTInfos);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::setDepth;
@@ -1037,6 +1040,9 @@ public:
using TemplateParmPosition::setPosition;
using TemplateParmPosition::getIndex;
+ SourceLocation getInnerLocStart() const;
+ SourceRange getSourceRange() const;
+
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const {
@@ -1071,6 +1077,65 @@ public:
DefaultArgumentAndInherited.setInt(false);
}
+ /// \brief Whether this parameter is a non-type template parameter pack.
+ ///
+ /// If the parameter is a parameter pack, the type may be a
+ /// \c PackExpansionType. In the following example, the \c Dims parameter
+ /// is a parameter pack (whose type is 'unsigned').
+ ///
+ /// \code
+ /// template<typename T, unsigned ...Dims> struct multi_array;
+ /// \endcode
+ bool isParameterPack() const { return ParameterPack; }
+
+ /// \brief Whether this parameter is a non-type template parameter pack
+ /// that has 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
+ /// has already been expanded. For example, given:
+ ///
+ /// \code
+ /// template<typename ...Types>
+ /// struct X {
+ /// template<Types ...Values>
+ /// struct Y { /* ... */ };
+ /// };
+ /// \endcode
+ ///
+ /// The parameter pack \c Values has a \c PackExpansionType as its type,
+ /// which expands \c Types. When \c Types is supplied with template arguments
+ /// by instantiating \c X, the instantiation of \c Values becomes an
+ /// expanded parameter pack. For example, instantiating
+ /// \c X<int, unsigned int> results in \c Values being an expanded parameter
+ /// pack with expansion types \c int and \c unsigned int.
+ ///
+ /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions
+ /// return the expansion types.
+ bool isExpandedParameterPack() const { return ExpandedParameterPack; }
+
+ /// \brief Retrieves the number of expansion types in an expanded parameter pack.
+ unsigned getNumExpansionTypes() const {
+ assert(ExpandedParameterPack && "Not an expansion parameter pack");
+ return NumExpandedTypes;
+ }
+
+ /// \brief Retrieve a particular expansion type within an expanded parameter
+ /// pack.
+ QualType getExpansionType(unsigned I) const {
+ assert(I < NumExpandedTypes && "Out-of-range expansion type index");
+ void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
+ return QualType::getFromOpaquePtr(TypesAndInfos[2*I]);
+ }
+
+ /// \brief Retrieve a particular expansion type source info within an
+ /// expanded parameter pack.
+ TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
+ assert(I < NumExpandedTypes && "Out-of-range expansion type index");
+ void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
+ return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]);
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
@@ -1092,24 +1157,36 @@ class TemplateTemplateParmDecl
/// Whether or not the default argument was inherited.
bool DefaultArgumentWasInherited;
+ /// \brief Whether this parameter is a parameter pack.
+ bool ParameterPack;
+
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
- unsigned D, unsigned P,
+ unsigned D, unsigned P, bool ParameterPack,
IdentifierInfo *Id, TemplateParameterList *Params)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
TemplateParmPosition(D, P), DefaultArgument(),
- DefaultArgumentWasInherited(false)
+ DefaultArgumentWasInherited(false), ParameterPack(ParameterPack)
{ }
public:
- static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
+ static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
- unsigned P, IdentifierInfo *Id,
+ unsigned P, bool ParameterPack,
+ IdentifierInfo *Id,
TemplateParameterList *Params);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
+ /// \brief Whether this template template parameter is a template
+ /// parameter pack.
+ ///
+ /// \code
+ /// template<template <class T> ...MetaFunctions> struct Apply;
+ /// \endcode
+ bool isParameterPack() const { return ParameterPack; }
+
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const {
@@ -1211,7 +1288,7 @@ class ClassTemplateSpecializationDecl
ExplicitSpecializationInfo *ExplicitInfo;
/// \brief The template arguments used to describe this specialization.
- TemplateArgumentList TemplateArgs;
+ TemplateArgumentList *TemplateArgs;
/// \brief The point where this template was instantiated (if any)
SourceLocation PointOfInstantiation;
@@ -1224,7 +1301,8 @@ protected:
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
DeclContext *DC, SourceLocation L,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
ClassTemplateSpecializationDecl *PrevDecl);
explicit ClassTemplateSpecializationDecl(Kind DK);
@@ -1233,7 +1311,8 @@ public:
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
ClassTemplateSpecializationDecl *PrevDecl);
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
@@ -1259,15 +1338,7 @@ public:
/// \brief Retrieve the template arguments of the class template
/// specialization.
const TemplateArgumentList &getTemplateArgs() const {
- return TemplateArgs;
- }
-
- /// \brief Initialize the template arguments of the class template
- /// specialization.
- void initTemplateArgs(TemplateArgument *Args, unsigned NumArgs) {
- assert(TemplateArgs.flat_size() == 0 &&
- "Template arguments already initialized!");
- TemplateArgs.init(getASTContext(), Args, NumArgs);
+ return *TemplateArgs;
}
/// \brief Determine the kind of specialization that this
@@ -1357,18 +1428,6 @@ public:
SpecializedTemplate = PS;
}
- /// \brief Note that this class template specialization is actually an
- /// instantiation of the given class template partial specialization whose
- /// template arguments have been deduced.
- void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
- TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
- ASTContext &Ctx = getASTContext();
- setInstantiationOf(PartialSpec,
- new (Ctx) TemplateArgumentList(Ctx, TemplateArgs,
- NumTemplateArgs));
- }
-
/// \brief Note that this class template specialization is an instantiation
/// of the given class template.
void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
@@ -1415,8 +1474,7 @@ public:
SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); }
void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(),
- getASTContext());
+ Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext());
}
static void
@@ -1440,6 +1498,9 @@ public:
static bool classof(const ClassTemplatePartialSpecializationDecl *) {
return true;
}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
class ClassTemplatePartialSpecializationDecl
@@ -1469,15 +1530,16 @@ class ClassTemplatePartialSpecializationDecl
DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
TemplateArgumentLoc *ArgInfos,
unsigned NumArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl,
unsigned SequenceNumber)
: ClassTemplateSpecializationDecl(Context,
ClassTemplatePartialSpecialization,
- TK, DC, L, SpecializedTemplate, Builder,
- PrevDecl),
+ TK, DC, L, SpecializedTemplate,
+ Args, NumArgs, PrevDecl),
TemplateParams(Params), ArgsAsWritten(ArgInfos),
NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
InstantiatedFromMember(0, false) { }
@@ -1493,7 +1555,8 @@ public:
Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
- TemplateArgumentListBuilder &Builder,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
const TemplateArgumentListInfo &ArgInfos,
QualType CanonInjectedType,
ClassTemplatePartialSpecializationDecl *PrevDecl,
@@ -1512,18 +1575,11 @@ public:
return TemplateParams;
}
- void initTemplateParameters(TemplateParameterList *Params) {
- assert(TemplateParams == 0 && "TemplateParams already set");
- TemplateParams = Params;
- }
-
/// Get the template arguments as written.
TemplateArgumentLoc *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
}
- void initTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgInfos);
-
/// Get the number of template arguments as written.
unsigned getNumTemplateArgsAsWritten() const {
return NumArgsAsWritten;
@@ -1532,8 +1588,7 @@ public:
/// \brief Get the sequence number for this class template partial
/// specialization.
unsigned getSequenceNumber() const { return SequenceNumber; }
- void setSequenceNumber(unsigned N) { SequenceNumber = N; }
-
+
/// \brief Retrieve the member class template partial specialization from
/// which this particular class template partial specialization was
/// instantiated.
@@ -1617,6 +1672,9 @@ public:
static bool classof(const ClassTemplatePartialSpecializationDecl *) {
return true;
}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// Declaration of a class template.
@@ -1630,6 +1688,8 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// class template.
struct Common : CommonBase {
+ Common() : LazySpecializations() { }
+
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@@ -1641,25 +1701,31 @@ protected:
/// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType;
+
+ /// \brief If non-null, points to an array of specializations (including
+ /// partial specializations) known ownly by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations/
+ /// partial specializations that follow.
+ uint32_t *LazySpecializations;
};
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations();
+
/// \brief Retrieve the set of specializations of this class template.
- llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
- return getCommonPtr()->Specializations;
- }
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations();
/// \brief Retrieve the set of partial specializations of this class
/// template.
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
- getPartialSpecializations() {
- return getCommonPtr()->PartialSpecializations;
- }
+ getPartialSpecializations();
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
- CommonBase *newCommon();
+ CommonBase *newCommon(ASTContext &C);
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
@@ -1693,9 +1759,7 @@ public:
/// \brief Insert the specified specialization knowing that it is not already
/// in. InsertPos must be obtained from findSpecialization.
- void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) {
- getSpecializations().InsertNode(D, InsertPos);
- }
+ void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
ClassTemplateDecl *getCanonicalDecl() {
return redeclarable_base::getCanonicalDecl();
@@ -1729,9 +1793,7 @@ public:
/// \brief Insert the specified partial specialization knowing that it is not
/// already in. InsertPos must be obtained from findPartialSpecialization.
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
- void *InsertPos) {
- getPartialSpecializations().InsertNode(D, InsertPos);
- }
+ void *InsertPos);
/// \brief Return the next partial specialization sequence number.
unsigned getNextPartialSpecSequenceNumber() {
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 8bb627597520..e54719b33d30 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -315,7 +315,7 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
/// retrieved using its member functions (e.g.,
/// getCXXConstructorName).
class DeclarationNameTable {
- ASTContext &Ctx;
+ const ASTContext &Ctx;
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
CXXOperatorIdName *CXXOperatorNames; // Operator names
void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
@@ -324,7 +324,7 @@ class DeclarationNameTable {
DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
public:
- DeclarationNameTable(ASTContext &C);
+ DeclarationNameTable(const ASTContext &C);
~DeclarationNameTable();
/// getIdentifier - Create a declaration name that is a simple
@@ -402,7 +402,7 @@ struct DeclarationNameLoc {
DeclarationNameLoc(DeclarationName Name);
// FIXME: this should go away once all DNLocs are properly initialized.
- DeclarationNameLoc() { NamedType.TInfo = 0; }
+ DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); }
}; // struct DeclarationNameLoc
@@ -492,6 +492,10 @@ public:
LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
}
+ /// \brief Determine whether this name contains an unexpanded
+ /// parameter pack.
+ bool containsUnexpandedParameterPack() const;
+
/// getAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
new file mode 100644
index 000000000000..035f57c12ea7
--- /dev/null
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -0,0 +1,82 @@
+//===--- EvaluatedExprVisitor.h - Evaluated expression visitor --*- 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 EvaluatedExprVisitor class template, which visits
+// the potentially-evaluated subexpressions of a potentially-evaluated
+// expression.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
+#define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+
+namespace clang {
+
+class ASTContext;
+
+/// \begin Given a potentially-evaluated expression, this visitor visits all
+/// of its potentially-evaluated subexpressions, recursively.
+template<typename ImplClass>
+class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
+ ASTContext &Context;
+
+public:
+ explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { }
+
+ // Expressions that have no potentially-evaluated subexpressions (but may have
+ // other sub-expressions).
+ void VisitDeclRefExpr(DeclRefExpr *E) { }
+ void VisitOffsetOfExpr(OffsetOfExpr *E) { }
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { }
+ void VisitBlockExpr(BlockExpr *E) { }
+ void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
+ void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }
+
+ void VisitMemberExpr(MemberExpr *E) {
+ // Only the base matters.
+ return this->Visit(E->getBase());
+ }
+
+ void VisitChooseExpr(ChooseExpr *E) {
+ // Only the selected subexpression matters; the other one is not evaluated.
+ return this->Visit(E->getChosenSubExpr(Context));
+ }
+
+ void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ // Only the actual initializer matters; the designators are all constant
+ // expressions.
+ return this->Visit(E->getInit());
+ }
+
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ // typeid(expression) is potentially evaluated when the argument is
+ // a glvalue of polymorphic type. (C++ 5.2.8p2-3)
+ if (!E->isTypeOperand() && E->Classify(Context).isGLValue())
+ if (const RecordType *Record
+ = E->getExprOperand()->getType()->template getAs<RecordType>())
+ if (cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic())
+ return this->Visit(E->getExprOperand());
+ }
+
+ /// \brief The basis case walks all of the children of the statement or
+ /// expression, assuming they are all potentially evaluated.
+ void VisitStmt(Stmt *S) {
+ for (Stmt::child_range C = S->children(); C; ++C)
+ if (*C)
+ this->Visit(*C);
+ }
+};
+
+}
+
+#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 48130becf3b5..a17205c2b6b9 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -25,6 +25,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include <cctype>
#include <vector>
namespace clang {
@@ -39,8 +40,10 @@ namespace clang {
class CXXBaseSpecifier;
class CXXOperatorCallExpr;
class CXXMemberCallExpr;
+ class ObjCPropertyRefExpr;
class TemplateArgumentLoc;
class TemplateArgumentListInfo;
+ class OpaqueValueExpr;
/// \brief A simple array of base specifiers.
typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
@@ -52,24 +55,14 @@ typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
class Expr : public Stmt {
QualType TR;
- virtual void ANCHOR(); // key function.
protected:
- /// TypeDependent - Whether this expression is type-dependent
- /// (C++ [temp.dep.expr]).
- bool TypeDependent : 1;
-
- /// ValueDependent - Whether this expression is value-dependent
- /// (C++ [temp.dep.constexpr]).
- bool ValueDependent : 1;
-
- /// ValueKind - The value classification of this expression.
- /// Only actually used by certain subclasses.
- unsigned ValueKind : 2;
-
- enum { BitsRemaining = 28 };
-
- Expr(StmtClass SC, QualType T, bool TD, bool VD)
- : Stmt(SC), TypeDependent(TD), ValueDependent(VD), ValueKind(0) {
+ Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
+ bool TD, bool VD, bool ContainsUnexpandedParameterPack) : Stmt(SC) {
+ ExprBits.TypeDependent = TD;
+ ExprBits.ValueDependent = VD;
+ ExprBits.ValueKind = VK;
+ ExprBits.ObjectKind = OK;
+ ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
setType(T);
}
@@ -77,15 +70,6 @@ protected:
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
public:
- /// \brief Increases the reference count for this expression.
- ///
- /// Invoke the Retain() operation when this expression
- /// is being shared by another owner.
- Expr *Retain() {
- Stmt::Retain();
- return this;
- }
-
QualType getType() const { return TR; }
void setType(QualType t) {
// In C++, the type of an expression is always adjusted so that it
@@ -108,10 +92,10 @@ public:
/// @code
/// template<int Size, char (&Chars)[Size]> struct meta_string;
/// @endcode
- bool isValueDependent() const { return ValueDependent; }
+ bool isValueDependent() const { return ExprBits.ValueDependent; }
/// \brief Set whether this expression is value-dependent or not.
- void setValueDependent(bool VD) { ValueDependent = VD; }
+ void setValueDependent(bool VD) { ExprBits.ValueDependent = VD; }
/// isTypeDependent - Determines whether this expression is
/// type-dependent (C++ [temp.dep.expr]), which means that its type
@@ -124,19 +108,38 @@ public:
/// x + y;
/// }
/// @endcode
- bool isTypeDependent() const { return TypeDependent; }
+ bool isTypeDependent() const { return ExprBits.TypeDependent; }
/// \brief Set whether this expression is type-dependent or not.
- void setTypeDependent(bool TD) { TypeDependent = TD; }
+ void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; }
+
+ /// \brief Whether this expression contains an unexpanded parameter
+ /// pack (for C++0x variadic templates).
+ ///
+ /// Given the following function template:
+ ///
+ /// \code
+ /// template<typename F, typename ...Types>
+ /// void forward(const F &f, Types &&...args) {
+ /// f(static_cast<Types&&>(args)...);
+ /// }
+ /// \endcode
+ ///
+ /// The expressions \c args and \c static_cast<Types&&>(args) both
+ /// contain parameter packs.
+ bool containsUnexpandedParameterPack() const {
+ return ExprBits.ContainsUnexpandedParameterPack;
+ }
- /// SourceLocation tokens are not useful in isolation - they are low level
- /// value objects created/interpreted by SourceManager. We assume AST
- /// clients will have a pointer to the respective SourceManager.
- virtual SourceRange getSourceRange() const = 0;
+ /// \brief Set the bit that describes whether this expression
+ /// contains an unexpanded parameter pack.
+ void setContainsUnexpandedParameterPack(bool PP = true) {
+ ExprBits.ContainsUnexpandedParameterPack = PP;
+ }
/// getExprLoc - Return the preferred location for the arrow when diagnosing
/// a problem with a generic expression.
- virtual SourceLocation getExprLoc() const { return getLocStart(); }
+ SourceLocation getExprLoc() const;
/// isUnusedResultAWarning - Return true if this immediate expression should
/// be warned about if the result is unused. If so, fill in Loc and Ranges
@@ -145,19 +148,25 @@ public:
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
SourceRange &R2, ASTContext &Ctx) const;
- /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
- /// incomplete type other than void. Nonarray expressions that can be lvalues:
- /// - name, where name must be a variable
- /// - e[i]
- /// - (e), where e must be an lvalue
- /// - e.name, where e must be an lvalue
- /// - e->name
- /// - *e, the type of e cannot be a function type
- /// - string-constant
- /// - reference type [C++ [expr]]
- /// - b ? x : y, where x and y are lvalues of suitable types [C++]
+ /// isLValue - True if this expression is an "l-value" according to
+ /// the rules of the current language. C and C++ give somewhat
+ /// different rules for this concept, but in general, the result of
+ /// an l-value expression identifies a specific object whereas the
+ /// result of an r-value expression is a value detached from any
+ /// specific storage.
///
- enum isLvalueResult {
+ /// C++0x divides the concept of "r-value" into pure r-values
+ /// ("pr-values") and so-called expiring values ("x-values"), which
+ /// identify specific objects that can be safely cannibalized for
+ /// their resources. This is an unfortunate abuse of terminology on
+ /// the part of the C++ committee. In Clang, when we say "r-value",
+ /// we generally mean a pr-value.
+ bool isLValue() const { return getValueKind() == VK_LValue; }
+ bool isRValue() const { return getValueKind() == VK_RValue; }
+ bool isXValue() const { return getValueKind() == VK_XValue; }
+ bool isGLValue() const { return getValueKind() != VK_RValue; }
+
+ enum LValueClassification {
LV_Valid,
LV_NotObjectType,
LV_IncompleteVoidType,
@@ -167,7 +176,8 @@ public:
LV_SubObjCPropertySetting,
LV_ClassTemporary
};
- isLvalueResult isLvalue(ASTContext &Ctx) const;
+ /// 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,
@@ -252,8 +262,14 @@ public:
bool isPRValue() const { return Kind >= CL_Function; }
bool isRValue() const { return Kind >= CL_XValue; }
bool isModifiable() const { return getModifiable() == CM_Modifiable; }
+
+ /// \brief Create a simple, modifiably lvalue
+ static Classification makeSimpleLValue() {
+ return Classification(CL_LValue, CM_Modifiable);
+ }
+
};
- /// \brief classify - Classify this expression according to the C++0x
+ /// \brief Classify - Classify this expression according to the C++0x
/// expression taxonomy.
///
/// C++0x defines ([basic.lval]) a new taxonomy of expressions to replace the
@@ -269,7 +285,7 @@ public:
return ClassifyImpl(Ctx, 0);
}
- /// \brief classifyModifiable - Classify this expression according to the
+ /// \brief ClassifyModifiable - Classify this expression according to the
/// C++0x expression taxonomy, and see if it is valid on the left side
/// of an assignment.
///
@@ -281,6 +297,40 @@ public:
return ClassifyImpl(Ctx, &Loc);
}
+ /// getValueKindForType - Given a formal return or parameter type,
+ /// give its value kind.
+ static ExprValueKind getValueKindForType(QualType T) {
+ if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ return (isa<LValueReferenceType>(RT)
+ ? VK_LValue
+ : (RT->getPointeeType()->isFunctionType()
+ ? VK_LValue : VK_XValue));
+ return VK_RValue;
+ }
+
+ /// getValueKind - The value kind that this expression produces.
+ ExprValueKind getValueKind() const {
+ return static_cast<ExprValueKind>(ExprBits.ValueKind);
+ }
+
+ /// getObjectKind - The object kind that this expression produces.
+ /// Object kinds are meaningful only for expressions that yield an
+ /// l-value or x-value.
+ ExprObjectKind getObjectKind() const {
+ return static_cast<ExprObjectKind>(ExprBits.ObjectKind);
+ }
+
+ bool isOrdinaryOrBitFieldObject() const {
+ ExprObjectKind OK = getObjectKind();
+ return (OK == OK_Ordinary || OK == OK_BitField);
+ }
+
+ /// setValueKind - Set the value kind produced by this expression.
+ void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }
+
+ /// setObjectKind - Set the object kind produced by this expression.
+ void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; }
+
private:
Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;
@@ -294,6 +344,10 @@ public:
return const_cast<Expr*>(this)->getBitField();
}
+ /// \brief If this expression is an l-value for an Objective C
+ /// property, find the underlying property reference expression.
+ const ObjCPropertyRefExpr *getObjCProperty() const;
+
/// \brief Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
@@ -355,33 +409,49 @@ public:
/// any crazy technique (that has nothing to do with language standards) that
/// we want to. If this function returns true, it returns the folded constant
/// in Result.
- bool Evaluate(EvalResult &Result, ASTContext &Ctx) const;
+ bool Evaluate(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsBooleanCondition - Return true if this is a constant
/// which we we can fold and convert to a boolean condition using
/// any crazy technique that we want to.
- bool EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const;
+ bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
/// isEvaluatable - Call Evaluate to see if this expression can be constant
/// folded, but discard the result.
- bool isEvaluatable(ASTContext &Ctx) const;
+ bool isEvaluatable(const ASTContext &Ctx) const;
/// HasSideEffects - This routine returns true for all those expressions
- /// which must be evaluated each time and must not be optimization away
+ /// which must be evaluated each time and must not be optimized away
/// or evaluated at compile time. Example is a function call, volatile
/// variable read.
- bool HasSideEffects(ASTContext &Ctx) const;
+ bool HasSideEffects(const ASTContext &Ctx) const;
/// EvaluateAsInt - Call Evaluate and return the folded integer. This
/// must be called on an expression that constant folds to an integer.
- llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const;
+ llvm::APSInt EvaluateAsInt(const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue
/// with link time known address.
- bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const;
+ bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue.
- bool EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const;
+ bool EvaluateAsAnyLValue(EvalResult &Result, const ASTContext &Ctx) const;
+
+ /// \brief Enumeration used to describe the kind of Null pointer constant
+ /// returned from \c isNullPointerConstant().
+ enum NullPointerConstantKind {
+ /// \brief Expression is not a Null pointer constant.
+ NPCK_NotNull = 0,
+
+ /// \brief Expression is a Null pointer constant built from a zero integer.
+ NPCK_ZeroInteger,
+
+ /// \brief Expression is a C++0X nullptr.
+ NPCK_CXX0X_nullptr,
+
+ /// \brief Expression is a GNU-style __null constant.
+ NPCK_GNUNull
+ };
/// \brief Enumeration used to describe how \c isNullPointerConstant()
/// should cope with value-dependent expressions.
@@ -398,16 +468,30 @@ public:
NPC_ValueDependentIsNotNull
};
- /// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an
- /// integer constant expression with the value zero, or if this is one that is
- /// cast to void*.
- bool isNullPointerConstant(ASTContext &Ctx,
- NullPointerConstantValueDependence NPC) const;
+ /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to
+ /// a Null pointer constant. The return value can further distinguish the
+ /// kind of NULL pointer constant that was detected.
+ NullPointerConstantKind isNullPointerConstant(
+ ASTContext &Ctx,
+ NullPointerConstantValueDependence NPC) const;
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
/// write barrier.
bool isOBJCGCCandidate(ASTContext &Ctx) const;
+ /// \brief Returns true if this expression is a bound member function.
+ bool isBoundMemberFunction(ASTContext &Ctx) const;
+
+ /// \brief Result type of CanThrow().
+ enum CanThrowResult {
+ CT_Cannot,
+ CT_Dependent,
+ CT_Can
+ };
+ /// \brief Test if this expression, if evaluated, might throw, according to
+ /// the rules of C++ [expr.unary.noexcept].
+ CanThrowResult CanThrow(ASTContext &C) const;
+
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
/// its subexpression. If that subexpression is also a ParenExpr,
/// then this method recursively returns its subexpression, and so forth.
@@ -422,6 +506,18 @@ public:
/// ParenExpr or ImplicitCastExprs, returning their operand.
Expr *IgnoreParenImpCasts();
+ const Expr *IgnoreParenImpCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenImpCasts();
+ }
+
+ /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and
+ /// CastExprs that represent lvalue casts, returning their operand.
+ Expr *IgnoreParenLValueCasts();
+
+ const Expr *IgnoreParenLValueCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenLValueCasts();
+ }
+
/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
/// value (including ptr->int casts of the same size). Strip off any
/// ParenExpr or CastExprs, returning their operand.
@@ -436,14 +532,9 @@ public:
/// the expression is a default argument.
bool isDefaultArgument() const;
- /// \brief Determine whether this expression directly creates a
- /// temporary object (of class type).
- bool isTemporaryObject() const { return getTemporaryObject() != 0; }
-
- /// \brief If this expression directly creates a temporary object of
- /// class type, return the expression that actually constructs that
- /// temporary object.
- const Expr *getTemporaryObject() const;
+ /// \brief Determine whether the result of this expression is a
+ /// temporary object of the given class type.
+ bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;
const Expr *IgnoreParens() const {
return const_cast<Expr*>(this)->IgnoreParens();
@@ -470,6 +561,63 @@ public:
// Primary Expressions.
//===----------------------------------------------------------------------===//
+/// OpaqueValueExpr - An expression referring to an opaque object of a
+/// fixed type and value class. These don't correspond to concrete
+/// syntax; instead they're used to express operations (usually copy
+/// operations) on values whose source is generally obvious from
+/// context.
+class OpaqueValueExpr : public Expr {
+ friend class ASTStmtReader;
+ Expr *SourceExpr;
+ SourceLocation Loc;
+
+public:
+ OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
+ ExprObjectKind OK = OK_Ordinary)
+ : Expr(OpaqueValueExprClass, T, VK, OK,
+ T->isDependentType(), T->isDependentType(), false),
+ SourceExpr(0), Loc(Loc) {
+ }
+
+ /// Given an expression which invokes a copy constructor --- i.e. a
+ /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups ---
+ /// find the OpaqueValueExpr that's the source of the construction.
+ static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);
+
+ explicit OpaqueValueExpr(EmptyShell Empty)
+ : Expr(OpaqueValueExprClass, Empty) { }
+
+ /// \brief Retrieve the location of this expression.
+ SourceLocation getLocation() const { return Loc; }
+
+ SourceRange getSourceRange() const {
+ if (SourceExpr) return SourceExpr->getSourceRange();
+ return Loc;
+ }
+ SourceLocation getExprLoc() const {
+ if (SourceExpr) return SourceExpr->getExprLoc();
+ return Loc;
+ }
+
+ child_range children() { return child_range(); }
+
+ /// The source expression of an opaque value expression is the
+ /// expression which originally generated the value. This is
+ /// provided as a convenience for analyses that don't wish to
+ /// precisely model the execution behavior of the program.
+ ///
+ /// The source expression is typically set when building the
+ /// expression which binds the opaque value expression in the first
+ /// place.
+ Expr *getSourceExpr() const { return SourceExpr; }
+ void setSourceExpr(Expr *e) { SourceExpr = e; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OpaqueValueExprClass;
+ }
+ static bool classof(const OpaqueValueExpr *) { return true; }
+};
+
/// \brief Represents the qualifier that may precede a C++ name, e.g., the
/// "std::" in "std::sort".
struct NameQualifier {
@@ -505,6 +653,8 @@ struct ExplicitTemplateArgumentList {
}
void initializeFrom(const TemplateArgumentListInfo &List);
+ void initializeFrom(const TemplateArgumentListInfo &List,
+ bool &Dependent, bool &ContainsUnexpandedParameterPack);
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
static std::size_t sizeFor(const TemplateArgumentListInfo &List);
@@ -551,12 +701,12 @@ class DeclRefExpr : public Expr {
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
ValueDecl *D, SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs,
- QualType T);
+ QualType T, ExprValueKind VK);
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
ValueDecl *D, const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
- QualType T);
+ QualType T, ExprValueKind VK);
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
@@ -567,8 +717,9 @@ class DeclRefExpr : public Expr {
void computeDependence();
public:
- DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) :
- Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) {
+ DeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l) :
+ Expr(DeclRefExprClass, t, VK, OK_Ordinary, false, false, false),
+ DecoratedD(d, 0), Loc(l) {
computeDependence();
}
@@ -577,7 +728,7 @@ public:
SourceRange QualifierRange,
ValueDecl *D,
SourceLocation NameLoc,
- QualType T,
+ QualType T, ExprValueKind VK,
const TemplateArgumentListInfo *TemplateArgs = 0);
static DeclRefExpr *Create(ASTContext &Context,
@@ -585,12 +736,14 @@ public:
SourceRange QualifierRange,
ValueDecl *D,
const DeclarationNameInfo &NameInfo,
- QualType T,
+ QualType T, ExprValueKind VK,
const TemplateArgumentListInfo *TemplateArgs = 0);
/// \brief Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(ASTContext &Context,
- bool HasQualifier, unsigned NumTemplateArgs);
+ bool HasQualifier,
+ bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
ValueDecl *getDecl() { return DecoratedD.getPointer(); }
const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }
@@ -602,7 +755,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
/// \brief Determine whether this declaration reference was preceded by a
/// C++ nested-name-specifier, e.g., \c N::foo.
@@ -706,8 +859,7 @@ public:
static bool classof(const DeclRefExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -730,8 +882,10 @@ private:
IdentType Type;
public:
PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
- : Expr(PredefinedExprClass, type, type->isDependentType(),
- type->isDependentType()), Loc(l), Type(IT) {}
+ : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
+ type->isDependentType(), type->isDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(l), Type(IT) {}
/// \brief Construct an empty predefined expression.
explicit PredefinedExpr(EmptyShell Empty)
@@ -745,7 +899,7 @@ public:
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == PredefinedExprClass;
@@ -753,8 +907,7 @@ public:
static bool classof(const PredefinedExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
@@ -817,7 +970,9 @@ public:
// or UnsignedLongLongTy
IntegerLiteral(ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type, false, false), Loc(l) {
+ : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
setValue(C, V);
}
@@ -829,7 +984,7 @@ public:
static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
llvm::APInt getValue() const { return Num.getValue(); }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
/// \brief Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
@@ -843,8 +998,7 @@ public:
static bool classof(const IntegerLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
class CharacterLiteral : public Expr {
@@ -854,8 +1008,9 @@ class CharacterLiteral : public Expr {
public:
// type should be IntTy
CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
- : Expr(CharacterLiteralClass, type, false, false), Value(value), Loc(l),
- IsWide(iswide) {
+ : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Value(value), Loc(l), IsWide(iswide) {
}
/// \brief Construct an empty character literal.
@@ -864,7 +1019,7 @@ public:
SourceLocation getLocation() const { return Loc; }
bool isWide() const { return IsWide; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
unsigned getValue() const { return Value; }
@@ -878,8 +1033,7 @@ public:
static bool classof(const CharacterLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
class FloatingLiteral : public Expr {
@@ -889,7 +1043,8 @@ class FloatingLiteral : public Expr {
FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type, false, false),
+ : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
+ false),
IsExact(isexact), Loc(L) {
setValue(C, V);
}
@@ -919,7 +1074,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == FloatingLiteralClass;
@@ -927,8 +1082,7 @@ public:
static bool classof(const FloatingLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ImaginaryLiteral - We support imaginary integer and floating point literals,
@@ -940,7 +1094,9 @@ class ImaginaryLiteral : public Expr {
Stmt *Val;
public:
ImaginaryLiteral(Expr *val, QualType Ty)
- : Expr(ImaginaryLiteralClass, Ty, false, false), Val(val) {}
+ : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Val(val) {}
/// \brief Build an empty imaginary literal.
explicit ImaginaryLiteral(EmptyShell Empty)
@@ -950,15 +1106,14 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- virtual SourceRange getSourceRange() const { return Val->getSourceRange(); }
+ SourceRange getSourceRange() const { return Val->getSourceRange(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImaginaryLiteralClass;
}
static bool classof(const ImaginaryLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Val, &Val+1); }
};
/// StringLiteral - This represents a string literal expression, e.g. "foo"
@@ -984,7 +1139,8 @@ class StringLiteral : public Expr {
unsigned NumConcatenated;
SourceLocation TokLocs[1];
- StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {}
+ StringLiteral(QualType Ty) :
+ Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false) {}
public:
/// This is the "fully general" constructor that allows representation of
@@ -1034,12 +1190,23 @@ public:
assert(TokNum < NumConcatenated && "Invalid tok number");
TokLocs[TokNum] = L;
}
+
+ /// getLocationOfByte - Return a source location that points to the specified
+ /// byte of this string literal.
+ ///
+ /// Strings are amazingly complex. They can be formed from multiple tokens
+ /// and can have escape sequences in them in addition to the usual trigraph
+ /// and escaped newline business. This routine handles this complexity.
+ ///
+ SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features,
+ const TargetInfo &Target) const;
typedef const SourceLocation *tokloc_iterator;
tokloc_iterator tokloc_begin() const { return TokLocs; }
tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
}
static bool classof(const Stmt *T) {
@@ -1048,8 +1215,7 @@ public:
static bool classof(const StringLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
@@ -1060,7 +1226,9 @@ class ParenExpr : public Expr {
public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(),
- val->isTypeDependent(), val->isValueDependent()),
+ val->getValueKind(), val->getObjectKind(),
+ val->isTypeDependent(), val->isValueDependent(),
+ val->containsUnexpandedParameterPack()),
L(l), R(r), Val(val) {}
/// \brief Construct an empty parenthesized expression.
@@ -1071,7 +1239,7 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- virtual SourceRange getSourceRange() const { return SourceRange(L, R); }
+ SourceRange getSourceRange() const { return SourceRange(L, R); }
/// \brief Get the location of the left parentheses '('.
SourceLocation getLParen() const { return L; }
@@ -1087,8 +1255,7 @@ public:
static bool classof(const ParenExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Val, &Val+1); }
};
@@ -1112,10 +1279,12 @@ private:
Stmt *Val;
public:
- UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
- : Expr(UnaryOperatorClass, type,
+ UnaryOperator(Expr *input, Opcode opc, QualType type,
+ ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
+ : Expr(UnaryOperatorClass, type, VK, OK,
input->isTypeDependent() || type->isDependentType(),
- input->isValueDependent()),
+ input->isValueDependent(),
+ input->containsUnexpandedParameterPack()),
Opc(opc), Loc(l), Val(input) {}
/// \brief Build an empty unary operator.
@@ -1137,7 +1306,7 @@ public:
return Op == UO_PostInc || Op == UO_PostDec;
}
- /// isPostfix - Return true if this is a prefix operation, like --x.
+ /// isPrefix - Return true if this is a prefix operation, like --x.
static bool isPrefix(Opcode Op) {
return Op == UO_PreInc || Op == UO_PreDec;
}
@@ -1167,13 +1336,13 @@ public:
/// the given unary opcode.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (isPostfix())
return SourceRange(Val->getLocStart(), Loc);
else
return SourceRange(Loc, Val->getLocEnd());
}
- virtual SourceLocation getExprLoc() const { return Loc; }
+ SourceLocation getExprLoc() const { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryOperatorClass;
@@ -1181,8 +1350,7 @@ public:
static bool classof(const UnaryOperator *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Val, &Val+1); }
};
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
@@ -1369,7 +1537,7 @@ public:
return NumExprs;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(OperatorLoc, RParenLoc);
}
@@ -1380,8 +1548,12 @@ public:
static bool classof(const OffsetOfExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ Stmt **begin =
+ reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
+ + NumComps);
+ return child_range(begin, begin + NumExprs);
+ }
};
/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of
@@ -1399,10 +1571,11 @@ public:
SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
- Expr(SizeOfAlignOfExprClass, resultType,
+ Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
- TInfo->getType()->isDependentType()),
+ TInfo->getType()->isDependentType(),
+ TInfo->getType()->containsUnexpandedParameterPack()),
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
Argument.Ty = TInfo;
}
@@ -1410,10 +1583,11 @@ public:
SizeOfAlignOfExpr(bool issizeof, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp) :
- Expr(SizeOfAlignOfExprClass, resultType,
+ Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
- E->isTypeDependent()),
+ E->isTypeDependent(),
+ E->containsUnexpandedParameterPack()),
isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
Argument.Ex = E;
}
@@ -1459,7 +1633,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(OpLoc, RParenLoc);
}
@@ -1469,8 +1643,7 @@ public:
static bool classof(const SizeOfAlignOfExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children();
};
//===----------------------------------------------------------------------===//
@@ -1484,10 +1657,13 @@ class ArraySubscriptExpr : public Expr {
SourceLocation RBracketLoc;
public:
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation rbracketloc)
- : Expr(ArraySubscriptExprClass, t,
+ : Expr(ArraySubscriptExprClass, t, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
- lhs->isValueDependent() || rhs->isValueDependent()),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
RBracketLoc(rbracketloc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -1530,14 +1706,14 @@ public:
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getLHS()->getLocStart(), RBracketLoc);
}
SourceLocation getRBracketLoc() const { return RBracketLoc; }
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
- virtual SourceLocation getExprLoc() const { return getBase()->getExprLoc(); }
+ SourceLocation getExprLoc() const { return getBase()->getExprLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ArraySubscriptExprClass;
@@ -1545,8 +1721,9 @@ public:
static bool classof(const ArraySubscriptExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
@@ -1557,19 +1734,36 @@ public:
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
/// "str1 + str2" to resolve to a function call.
class CallExpr : public Expr {
- enum { FN=0, ARGS_START=1 };
+ enum { FN=0, PREARGS_START=1 };
Stmt **SubExprs;
unsigned NumArgs;
SourceLocation RParenLoc;
protected:
- // This version of the constructor is for derived classes.
- CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs,
- QualType t, SourceLocation rparenloc);
+ // 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,
+ SourceLocation rparenloc);
+ CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty);
+
+ Stmt *getPreArg(unsigned i) {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ return SubExprs[PREARGS_START+i];
+ }
+ const Stmt *getPreArg(unsigned i) const {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ return SubExprs[PREARGS_START+i];
+ }
+ void setPreArg(unsigned i, Stmt *PreArg) {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ SubExprs[PREARGS_START+i] = PreArg;
+ }
+
+ unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
public:
CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
- SourceLocation rparenloc);
+ ExprValueKind VK, SourceLocation rparenloc);
/// \brief Build an empty call expression.
CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
@@ -1593,20 +1787,25 @@ public:
///
unsigned getNumArgs() const { return NumArgs; }
+ /// \brief Retrieve the call arguments.
+ Expr **getArgs() {
+ return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
+ }
+
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
}
const Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
}
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
- SubExprs[Arg+ARGS_START] = ArgExpr;
+ SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
}
/// setNumArgs - This changes the number of arguments present in this call.
@@ -1617,10 +1816,16 @@ public:
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
- arg_iterator arg_begin() { return SubExprs+ARGS_START; }
- arg_iterator arg_end() { return SubExprs+ARGS_START+getNumArgs(); }
- const_arg_iterator arg_begin() const { return SubExprs+ARGS_START; }
- const_arg_iterator arg_end() const { return SubExprs+ARGS_START+getNumArgs();}
+ arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); }
+ arg_iterator arg_end() {
+ return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ }
+ const_arg_iterator arg_begin() const {
+ return SubExprs+PREARGS_START+getNumPreArgs();
+ }
+ const_arg_iterator arg_end() const {
+ return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ }
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
@@ -1628,7 +1833,7 @@ public:
/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
/// not, return 0.
- unsigned isBuiltinCall(ASTContext &Context) const;
+ unsigned isBuiltinCall(const ASTContext &Context) const;
/// getCallReturnType - Get the return type of the call expr. This is not
/// always the type of the expr itself, if the return type is a reference
@@ -1638,7 +1843,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getCallee()->getLocStart(), RParenLoc);
}
@@ -1649,8 +1854,10 @@ public:
static bool classof(const CallExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0],
+ &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
+ }
};
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
@@ -1705,9 +1912,11 @@ class MemberExpr : public Expr {
public:
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
- const DeclarationNameInfo &NameInfo, QualType ty)
- : Expr(MemberExprClass, ty,
- base->isTypeDependent(), base->isValueDependent()),
+ const DeclarationNameInfo &NameInfo, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK,
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()),
MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {
@@ -1719,9 +1928,11 @@ public:
// (i.e., source locations for C++ operator names or type source info
// for constructors, destructors and conversion oeprators).
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
- SourceLocation l, QualType ty)
- : Expr(MemberExprClass, ty,
- base->isTypeDependent(), base->isValueDependent()),
+ SourceLocation l, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK,
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(),
IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
@@ -1731,7 +1942,7 @@ public:
ValueDecl *memberdecl, DeclAccessPair founddecl,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *targs,
- QualType ty);
+ QualType ty, ExprValueKind VK, ExprObjectKind OK);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
@@ -1866,7 +2077,7 @@ public:
SourceLocation getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
// If we have an implicit base (like a C++ implicit this),
// make sure not to return its location
SourceLocation EndLoc = (HasExplicitTemplateArgumentList)
@@ -1878,7 +2089,7 @@ public:
return SourceRange(BaseLoc, EndLoc);
}
- virtual SourceLocation getExprLoc() const { return MemberLoc; }
+ SourceLocation getExprLoc() const { return MemberLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == MemberExprClass;
@@ -1886,8 +2097,10 @@ public:
static bool classof(const MemberExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
+
+ friend class ASTReader;
+ friend class ASTStmtWriter;
};
/// CompoundLiteralExpr - [C99 6.5.2.5]
@@ -1904,11 +2117,12 @@ class CompoundLiteralExpr : public Expr {
Stmt *Init;
bool FileScope;
public:
- // FIXME: Can compound literals be value-dependent?
CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
- QualType T, Expr *init, bool fileScope)
- : Expr(CompoundLiteralExprClass, T,
- tinfo->getType()->isDependentType(), false),
+ QualType T, ExprValueKind VK, Expr *init, bool fileScope)
+ : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary,
+ tinfo->getType()->isDependentType(),
+ init->isValueDependent(),
+ init->containsUnexpandedParameterPack()),
LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {}
/// \brief Construct an empty compound literal.
@@ -1928,7 +2142,7 @@ public:
TypeSourceInfo *getTypeSourceInfo() const { return TInfo; }
void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
// FIXME: Init should never be null.
if (!Init)
return SourceRange();
@@ -1943,8 +2157,7 @@ public:
static bool classof(const CompoundLiteralExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Init, &Init+1); }
};
/// CastExpr - Base class for type casts, including both implicit
@@ -1956,11 +2169,9 @@ public:
typedef clang::CastKind CastKind;
private:
- unsigned Kind : 5;
- unsigned BasePathSize : BitsRemaining - 5;
Stmt *Op;
- void CheckBasePath() const {
+ void CheckCastConsistency() const {
#ifndef NDEBUG
switch (getCastKind()) {
case CK_DerivedToBase:
@@ -1972,16 +2183,13 @@ private:
break;
// These should not have an inheritance path.
- case CK_Unknown:
case CK_BitCast:
- case CK_LValueBitCast:
- case CK_NoOp:
case CK_Dynamic:
case CK_ToUnion:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_NullToMemberPointer:
- case CK_UserDefinedConversion:
+ case CK_NullToPointer:
case CK_ConstructorConversion:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
@@ -1991,10 +2199,32 @@ private:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
- case CK_MemberPointerToBoolean:
case CK_AnyPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
+ case CK_FloatingRealToComplex:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ assert(!getType()->isBooleanType() && "unheralded conversion to bool");
+ // fallthrough to check for null base path
+
+ case CK_Dependent:
+ case CK_LValueToRValue:
+ case CK_GetObjCProperty:
+ case CK_NoOp:
+ case CK_PointerToBoolean:
+ case CK_IntegralToBoolean:
+ case CK_FloatingToBoolean:
+ case CK_MemberPointerToBoolean:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToBoolean:
+ case CK_LValueBitCast: // -> bool&
+ case CK_UserDefinedConversion: // operator bool()
assert(path_empty() && "Cast kind should not have a base path!");
break;
}
@@ -2007,26 +2237,33 @@ private:
CXXBaseSpecifier **path_buffer();
protected:
- CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op,
- unsigned BasePathSize) :
- Expr(SC, ty,
+ CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+ const CastKind kind, Expr *op, unsigned BasePathSize) :
+ Expr(SC, ty, VK, OK_Ordinary,
// Cast expressions are type-dependent if the type is
// dependent (C++ [temp.dep.expr]p3).
ty->isDependentType(),
// Cast expressions are value-dependent if the type is
// dependent or if the subexpression is value-dependent.
- ty->isDependentType() || (op && op->isValueDependent())),
- Kind(kind), BasePathSize(BasePathSize), Op(op) {
- CheckBasePath();
+ ty->isDependentType() || (op && op->isValueDependent()),
+ (ty->containsUnexpandedParameterPack() ||
+ op->containsUnexpandedParameterPack())),
+ Op(op) {
+ assert(kind != CK_Invalid && "creating cast with invalid cast kind");
+ CastExprBits.Kind = kind;
+ CastExprBits.BasePathSize = BasePathSize;
+ CheckCastConsistency();
}
/// \brief Construct an empty cast.
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
- : Expr(SC, Empty), BasePathSize(BasePathSize) { }
+ : Expr(SC, Empty) {
+ CastExprBits.BasePathSize = BasePathSize;
+ }
public:
- CastKind getCastKind() const { return static_cast<CastKind>(Kind); }
- void setCastKind(CastKind K) { Kind = K; }
+ CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
+ void setCastKind(CastKind K) { CastExprBits.Kind = K; }
const char *getCastKindName() const;
Expr *getSubExpr() { return cast<Expr>(Op); }
@@ -2043,8 +2280,8 @@ public:
typedef CXXBaseSpecifier **path_iterator;
typedef const CXXBaseSpecifier * const *path_const_iterator;
- bool path_empty() const { return BasePathSize == 0; }
- unsigned path_size() const { return BasePathSize; }
+ bool path_empty() const { return CastExprBits.BasePathSize == 0; }
+ unsigned path_size() const { return CastExprBits.BasePathSize; }
path_iterator path_begin() { return path_buffer(); }
path_iterator path_end() { return path_buffer() + path_size(); }
path_const_iterator path_begin() const { return path_buffer(); }
@@ -2059,8 +2296,7 @@ public:
static bool classof(const CastExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Op, &Op+1); }
};
/// ImplicitCastExpr - Allows us to explicitly represent implicit type
@@ -2087,8 +2323,7 @@ class ImplicitCastExpr : public CastExpr {
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
- : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength) {
- ValueKind = VK;
+ : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
}
/// \brief Construct an empty implicit cast.
@@ -2099,8 +2334,7 @@ public:
enum OnStack_t { OnStack };
ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
ExprValueKind VK)
- : CastExpr(ImplicitCastExprClass, ty, kind, op, 0) {
- ValueKind = VK;
+ : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
}
static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
@@ -2110,18 +2344,10 @@ public:
static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return getSubExpr()->getSourceRange();
}
- /// getValueKind - The value kind that this cast produces.
- ExprValueKind getValueKind() const {
- return static_cast<ExprValueKind>(ValueKind);
- }
-
- /// setValueKind - Set the value kind this cast produces.
- void setValueKind(ExprValueKind Cat) { ValueKind = Cat; }
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
}
@@ -2150,9 +2376,10 @@ class ExplicitCastExpr : public CastExpr {
TypeSourceInfo *TInfo;
protected:
- ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
- Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy)
- : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {}
+ ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK,
+ CastKind kind, Expr *op, unsigned PathSize,
+ TypeSourceInfo *writtenTy)
+ : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
@@ -2182,10 +2409,10 @@ class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
- CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op,
+ CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op,
unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r)
- : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize,
+ : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
@@ -2193,7 +2420,8 @@ class CStyleCastExpr : public ExplicitCastExpr {
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
public:
- static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K,
+ static CStyleCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind K,
Expr *Op, const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation R);
@@ -2206,7 +2434,7 @@ public:
SourceLocation getRParenLoc() const { return RPLoc; }
void setRParenLoc(SourceLocation L) { RPLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd());
}
static bool classof(const Stmt *T) {
@@ -2246,10 +2474,13 @@ private:
public:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation opLoc)
- : Expr(BinaryOperatorClass, ResTy,
+ : Expr(BinaryOperatorClass, ResTy, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
- lhs->isValueDependent() || rhs->isValueDependent()),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
Opc(opc), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -2272,7 +2503,7 @@ public:
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd());
}
@@ -2291,6 +2522,7 @@ public:
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
/// predicates to categorize the respective opcodes.
+ bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
@@ -2312,13 +2544,24 @@ public:
static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
bool isLogicalOp() const { return isLogicalOp(getOpcode()); }
- bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; }
- bool isCompoundAssignmentOp() const {
+ static bool isAssignmentOp(Opcode Opc) {
+ return Opc >= BO_Assign && Opc <= BO_OrAssign;
+ }
+ bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); }
+
+ static bool isCompoundAssignmentOp(Opcode Opc) {
return Opc > BO_Assign && Opc <= BO_OrAssign;
}
- bool isShiftAssignOp() const {
+ bool isCompoundAssignmentOp() const {
+ return isCompoundAssignmentOp(getOpcode());
+ }
+
+ static bool isShiftAssignOp(Opcode Opc) {
return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
}
+ bool isShiftAssignOp() const {
+ return isShiftAssignOp(getOpcode());
+ }
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstBinaryOperatorConstant &&
@@ -2327,15 +2570,19 @@ public:
static bool classof(const BinaryOperator *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
protected:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation opLoc, bool dead)
- : Expr(CompoundAssignOperatorClass, ResTy,
+ : Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
- lhs->isValueDependent() || rhs->isValueDependent()),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
Opc(opc), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -2355,11 +2602,11 @@ class CompoundAssignOperator : public BinaryOperator {
QualType ComputationLHSType;
QualType ComputationResultType;
public:
- CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc,
- QualType ResType, QualType CompLHSType,
- QualType CompResultType,
+ CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
+ ExprValueKind VK, ExprObjectKind OK,
+ QualType CompLHSType, QualType CompResultType,
SourceLocation OpLoc)
- : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true),
+ : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true),
ComputationLHSType(CompLHSType),
ComputationResultType(CompResultType) {
assert(isCompoundAssignmentOp() &&
@@ -2385,75 +2632,97 @@ public:
}
};
-/// ConditionalOperator - The ?: operator. Note that LHS may be null when the
-/// GNU "missing LHS" extension is in use.
-///
-class ConditionalOperator : public Expr {
+/// AbstractConditionalOperator - An abstract base class for
+/// ConditionalOperator and BinaryConditionalOperator.
+class AbstractConditionalOperator : public Expr {
+ SourceLocation QuestionLoc, ColonLoc;
+ friend class ASTStmtReader;
+
+protected:
+ AbstractConditionalOperator(StmtClass SC, QualType T,
+ ExprValueKind VK, ExprObjectKind OK,
+ bool TD, bool VD,
+ bool ContainsUnexpandedParameterPack,
+ SourceLocation qloc,
+ SourceLocation cloc)
+ : Expr(SC, T, VK, OK, TD, VD, ContainsUnexpandedParameterPack),
+ QuestionLoc(qloc), ColonLoc(cloc) {}
+
+ AbstractConditionalOperator(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty) { }
+
+public:
+ // getCond - Return the expression representing the condition for
+ // the ?: operator.
+ Expr *getCond() const;
+
+ // getTrueExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to true.
+ Expr *getTrueExpr() const;
+
+ // getFalseExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to false. This is
+ // the same as getRHS.
+ Expr *getFalseExpr() const;
+
+ SourceLocation getQuestionLoc() const { return QuestionLoc; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConditionalOperatorClass ||
+ T->getStmtClass() == BinaryConditionalOperatorClass;
+ }
+ static bool classof(const AbstractConditionalOperator *) { return true; }
+};
+
+/// ConditionalOperator - The ?: ternary operator. The GNU "missing
+/// middle" extension is a BinaryConditionalOperator.
+class ConditionalOperator : public AbstractConditionalOperator {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
- Stmt* Save;
- SourceLocation QuestionLoc, ColonLoc;
+
+ friend class ASTStmtReader;
public:
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
- SourceLocation CLoc, Expr *rhs, Expr *save, QualType t)
- : Expr(ConditionalOperatorClass, t,
+ SourceLocation CLoc, Expr *rhs,
+ QualType t, ExprValueKind VK, ExprObjectKind OK)
+ : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK,
// FIXME: the type of the conditional operator doesn't
// depend on the type of the conditional, but the standard
// seems to imply that it could. File a bug!
- ((lhs && lhs->isTypeDependent()) || (rhs && rhs->isTypeDependent())),
- (cond->isValueDependent() ||
- (lhs && lhs->isValueDependent()) ||
- (rhs && rhs->isValueDependent()))),
- QuestionLoc(QLoc),
- ColonLoc(CLoc) {
+ (lhs->isTypeDependent() || rhs->isTypeDependent()),
+ (cond->isValueDependent() || lhs->isValueDependent() ||
+ rhs->isValueDependent()),
+ (cond->containsUnexpandedParameterPack() ||
+ lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack()),
+ QLoc, CLoc) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
- Save = save;
}
/// \brief Build an empty conditional operator.
explicit ConditionalOperator(EmptyShell Empty)
- : Expr(ConditionalOperatorClass, Empty) { }
+ : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
// getCond - Return the expression representing the condition for
- // the ?: operator.
+ // the ?: operator.
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
- void setCond(Expr *E) { SubExprs[COND] = E; }
- // getTrueExpr - Return the subexpression representing the value of the ?:
- // expression if the condition evaluates to true.
- Expr *getTrueExpr() const {
- return cast<Expr>(!Save ? SubExprs[LHS] : SubExprs[COND]);
- }
+ // getTrueExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to true.
+ Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); }
- // getFalseExpr - Return the subexpression representing the value of the ?:
- // expression if the condition evaluates to false. This is the same as getRHS.
+ // getFalseExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to false. This is
+ // the same as getRHS.
Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }
- // getSaveExpr - In most cases this value will be null. Except a GCC extension
- // allows the left subexpression to be omitted, and instead of that condition
- // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the
- // expression "x" is only evaluated once. Under this senario, this function
- // returns the original, non-converted condition expression for the ?:operator
- Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; }
-
- Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); }
- void setLHS(Expr *E) { SubExprs[LHS] = E; }
-
+ Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
- void setRHS(Expr *E) { SubExprs[RHS] = E; }
-
- Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; }
- void setSAVE(Expr *E) { Save = E; }
-
- SourceLocation getQuestionLoc() const { return QuestionLoc; }
- void setQuestionLoc(SourceLocation L) { QuestionLoc = L; }
- SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation L) { ColonLoc = L; }
-
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -2462,18 +2731,118 @@ public:
static bool classof(const ConditionalOperator *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+/// BinaryConditionalOperator - The GNU extension to the conditional
+/// operator which allows the middle operand to be omitted.
+///
+/// This is a different expression kind on the assumption that almost
+/// every client ends up needing to know that these are different.
+class BinaryConditionalOperator : public AbstractConditionalOperator {
+ enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS };
+
+ /// - the common condition/left-hand-side expression, which will be
+ /// evaluated as the opaque value
+ /// - the condition, expressed in terms of the opaque value
+ /// - the left-hand-side, expressed in terms of the opaque value
+ /// - the right-hand-side
+ Stmt *SubExprs[NUM_SUBEXPRS];
+ OpaqueValueExpr *OpaqueValue;
+
+ friend class ASTStmtReader;
+public:
+ BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue,
+ Expr *cond, Expr *lhs, Expr *rhs,
+ SourceLocation qloc, SourceLocation cloc,
+ QualType t, ExprValueKind VK, ExprObjectKind OK)
+ : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK,
+ (common->isTypeDependent() || rhs->isTypeDependent()),
+ (common->isValueDependent() || rhs->isValueDependent()),
+ (common->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack()),
+ qloc, cloc),
+ OpaqueValue(opaqueValue) {
+ SubExprs[COMMON] = common;
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+
+ OpaqueValue->setSourceExpr(common);
+ }
+
+ /// \brief Build an empty conditional operator.
+ explicit BinaryConditionalOperator(EmptyShell Empty)
+ : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { }
+
+ /// \brief getCommon - Return the common expression, written to the
+ /// left of the condition. The opaque value will be bound to the
+ /// result of this expression.
+ Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); }
+
+ /// \brief getOpaqueValue - Return the opaque value placeholder.
+ OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
+
+ /// \brief getCond - Return the condition expression; this is defined
+ /// in terms of the opaque value.
+ Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
+
+ /// \brief getTrueExpr - Return the subexpression which will be
+ /// evaluated if the condition evaluates to true; this is defined
+ /// in terms of the opaque value.
+ Expr *getTrueExpr() const {
+ return cast<Expr>(SubExprs[LHS]);
+ }
+
+ /// \brief getFalseExpr - Return the subexpression which will be
+ /// evaluated if the condnition evaluates to false; this is
+ /// defined in terms of the opaque value.
+ Expr *getFalseExpr() const {
+ return cast<Expr>(SubExprs[RHS]);
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryConditionalOperatorClass;
+ }
+ static bool classof(const BinaryConditionalOperator *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
+ }
};
+inline Expr *AbstractConditionalOperator::getCond() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getCond();
+ return cast<BinaryConditionalOperator>(this)->getCond();
+}
+
+inline Expr *AbstractConditionalOperator::getTrueExpr() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getTrueExpr();
+ return cast<BinaryConditionalOperator>(this)->getTrueExpr();
+}
+
+inline Expr *AbstractConditionalOperator::getFalseExpr() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getFalseExpr();
+ return cast<BinaryConditionalOperator>(this)->getFalseExpr();
+}
+
/// AddrLabelExpr - The GNU address of label extension, representing &&label.
class AddrLabelExpr : public Expr {
SourceLocation AmpAmpLoc, LabelLoc;
- LabelStmt *Label;
+ LabelDecl *Label;
public:
- AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L,
+ AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L,
QualType t)
- : Expr(AddrLabelExprClass, t, false, false),
+ : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false),
AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
/// \brief Build an empty address of a label expression.
@@ -2485,12 +2854,12 @@ public:
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AmpAmpLoc, LabelLoc);
}
- LabelStmt *getLabel() const { return Label; }
- void setLabel(LabelStmt *S) { Label = S; }
+ LabelDecl *getLabel() const { return Label; }
+ void setLabel(LabelDecl *L) { Label = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AddrLabelExprClass;
@@ -2498,13 +2867,15 @@ public:
static bool classof(const AddrLabelExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
/// The StmtExpr contains a single CompoundStmt node, which it evaluates and
/// takes the value of the last subexpression.
+///
+/// A StmtExpr is always an r-value; values "returned" out of a
+/// StmtExpr will be copied.
class StmtExpr : public Expr {
Stmt *SubStmt;
SourceLocation LParenLoc, RParenLoc;
@@ -2512,7 +2883,8 @@ public:
// FIXME: Does type-dependence need to be computed differently?
StmtExpr(CompoundStmt *substmt, QualType T,
SourceLocation lp, SourceLocation rp) :
- Expr(StmtExprClass, T, T->isDependentType(), false),
+ Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
+ T->isDependentType(), false, false),
SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
/// \brief Build an empty statement expression.
@@ -2522,7 +2894,7 @@ public:
const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); }
void setSubStmt(CompoundStmt *S) { SubStmt = S; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LParenLoc, RParenLoc);
}
@@ -2537,55 +2909,9 @@ public:
static bool classof(const StmtExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
};
-/// TypesCompatibleExpr - GNU builtin-in function __builtin_types_compatible_p.
-/// This AST node represents a function that returns 1 if two *types* (not
-/// expressions) are compatible. The result of this built-in function can be
-/// used in integer constant expressions.
-class TypesCompatibleExpr : public Expr {
- TypeSourceInfo *TInfo1;
- TypeSourceInfo *TInfo2;
- SourceLocation BuiltinLoc, RParenLoc;
-public:
- TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
- TypeSourceInfo *tinfo1, TypeSourceInfo *tinfo2,
- SourceLocation RP) :
- Expr(TypesCompatibleExprClass, ReturnType, false, false),
- TInfo1(tinfo1), TInfo2(tinfo2), BuiltinLoc(BLoc), RParenLoc(RP) {}
-
- /// \brief Build an empty __builtin_type_compatible_p expression.
- explicit TypesCompatibleExpr(EmptyShell Empty)
- : Expr(TypesCompatibleExprClass, Empty) { }
-
- TypeSourceInfo *getArgTInfo1() const { return TInfo1; }
- void setArgTInfo1(TypeSourceInfo *TInfo) { TInfo1 = TInfo; }
- TypeSourceInfo *getArgTInfo2() const { return TInfo2; }
- void setArgTInfo2(TypeSourceInfo *TInfo) { TInfo2 = TInfo; }
-
- QualType getArgType1() const { return TInfo1->getType(); }
- QualType getArgType2() const { return TInfo2->getType(); }
-
- SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
- void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
-
- SourceLocation getRParenLoc() const { return RParenLoc; }
- void setRParenLoc(SourceLocation L) { RParenLoc = L; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(BuiltinLoc, RParenLoc);
- }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == TypesCompatibleExprClass;
- }
- static bool classof(const TypesCompatibleExpr *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-};
/// ShuffleVectorExpr - clang-specific builtin-in function
/// __builtin_shufflevector.
@@ -2604,18 +2930,9 @@ class ShuffleVectorExpr : public Expr {
unsigned NumExprs;
public:
- // FIXME: Can a shufflevector be value-dependent? Does type-dependence need
- // to be computed differently?
ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
QualType Type, SourceLocation BLoc,
- SourceLocation RP) :
- Expr(ShuffleVectorExprClass, Type, Type->isDependentType(), false),
- BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) {
-
- SubExprs = new (C) Stmt*[nexpr];
- for (unsigned i = 0; i < nexpr; i++)
- SubExprs[i] = args[i];
- }
+ SourceLocation RP);
/// \brief Build an empty vector-shuffle expression.
explicit ShuffleVectorExpr(EmptyShell Empty)
@@ -2627,7 +2944,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -2640,6 +2957,9 @@ public:
/// pointers.
unsigned getNumSubExprs() const { return NumExprs; }
+ /// \brief Retrieve the array of expressions.
+ Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
+
/// getExpr - Return the Expr at the specified index.
Expr *getExpr(unsigned Index) {
assert((Index < NumExprs) && "Arg access out of range!");
@@ -2658,8 +2978,9 @@ public:
}
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
+ }
};
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
@@ -2676,9 +2997,13 @@ class ChooseExpr : public Expr {
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
SourceLocation BuiltinLoc, RParenLoc;
public:
- ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t,
+ ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
+ QualType t, ExprValueKind VK, ExprObjectKind OK,
SourceLocation RP, bool TypeDependent, bool ValueDependent)
- : Expr(ChooseExprClass, t, TypeDependent, ValueDependent),
+ : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
+ (cond->containsUnexpandedParameterPack() ||
+ lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
BuiltinLoc(BLoc), RParenLoc(RP) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
@@ -2690,11 +3015,11 @@ public:
/// isConditionTrue - Return whether the condition is true (i.e. not
/// equal to zero).
- bool isConditionTrue(ASTContext &C) const;
+ bool isConditionTrue(const ASTContext &C) const;
/// getChosenSubExpr - Return the subexpression chosen according to the
/// condition.
- Expr *getChosenSubExpr(ASTContext &C) const {
+ Expr *getChosenSubExpr(const ASTContext &C) const {
return isConditionTrue(C) ? getLHS() : getRHS();
}
@@ -2711,7 +3036,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -2720,8 +3045,9 @@ public:
static bool classof(const ChooseExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
/// GNUNullExpr - Implements the GNU __null extension, which is a name
@@ -2736,7 +3062,8 @@ class GNUNullExpr : public Expr {
public:
GNUNullExpr(QualType Ty, SourceLocation Loc)
- : Expr(GNUNullExprClass, Ty, false, false), TokenLoc(Loc) { }
+ : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false),
+ TokenLoc(Loc) { }
/// \brief Build an empty GNU __null expression.
explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
@@ -2745,7 +3072,7 @@ public:
SourceLocation getTokenLocation() const { return TokenLoc; }
void setTokenLocation(SourceLocation L) { TokenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(TokenLoc);
}
static bool classof(const Stmt *T) {
@@ -2754,8 +3081,7 @@ public:
static bool classof(const GNUNullExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// VAArgExpr, used for the builtin function __builtin_va_arg.
@@ -2766,7 +3092,10 @@ class VAArgExpr : public Expr {
public:
VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
SourceLocation RPLoc, QualType t)
- : Expr(VAArgExprClass, t, t->isDependentType(), false),
+ : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary,
+ t->isDependentType(), false,
+ (TInfo->getType()->containsUnexpandedParameterPack() ||
+ e->containsUnexpandedParameterPack())),
Val(e), TInfo(TInfo),
BuiltinLoc(BLoc),
RParenLoc(RPLoc) { }
@@ -2787,7 +3116,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -2796,8 +3125,7 @@ public:
static bool classof(const VAArgExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Val, &Val+1); }
};
/// @brief Describes an C or C++ initializer list.
@@ -2866,12 +3194,15 @@ public:
unsigned getNumInits() const { return InitExprs.size(); }
- const Expr* getInit(unsigned Init) const {
+ /// \brief Retrieve the set of initializers.
+ Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
+
+ const Expr *getInit(unsigned Init) const {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
}
- Expr* getInit(unsigned Init) {
+ Expr *getInit(unsigned Init) {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
}
@@ -2933,17 +3264,18 @@ public:
HadArrayRangeDesignator = ARD;
}
- virtual SourceRange getSourceRange() const {
- return SourceRange(LBraceLoc, RBraceLoc);
- }
+ SourceRange getSourceRange() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == InitListExprClass;
}
static bool classof(const InitListExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (InitExprs.empty()) return child_range();
+ return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
+ }
typedef InitExprsTy::iterator iterator;
typedef InitExprsTy::const_iterator const_iterator;
@@ -3182,6 +3514,15 @@ public:
return Designators + NumDesignators;
}
+ typedef std::reverse_iterator<designators_iterator>
+ reverse_designators_iterator;
+ reverse_designators_iterator designators_rbegin() {
+ return reverse_designators_iterator(designators_end());
+ }
+ reverse_designators_iterator designators_rend() {
+ return reverse_designators_iterator(designators_begin());
+ }
+
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
void setDesignators(ASTContext &C, const Designator *Desigs,
@@ -3235,7 +3576,7 @@ public:
void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First,
const Designator *Last);
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == DesignatedInitExprClass;
@@ -3243,8 +3584,10 @@ public:
static bool classof(const DesignatedInitExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt**>(this + 1);
+ return child_range(begin, begin + NumSubExprs);
+ }
};
/// \brief Represents an implicitly-generated value initialization of
@@ -3258,7 +3601,8 @@ public:
class ImplicitValueInitExpr : public Expr {
public:
explicit ImplicitValueInitExpr(QualType ty)
- : Expr(ImplicitValueInitExprClass, ty, false, false) { }
+ : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, false, false) { }
/// \brief Construct an empty implicit value initialization.
explicit ImplicitValueInitExpr(EmptyShell Empty)
@@ -3269,13 +3613,12 @@ public:
}
static bool classof(const ImplicitValueInitExpr *) { return true; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange();
}
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
@@ -3308,7 +3651,7 @@ public:
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LParenLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -3317,8 +3660,9 @@ public:
static bool classof(const ParenListExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0]+NumExprs);
+ }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -3342,10 +3686,12 @@ class ExtVectorElementExpr : public Expr {
IdentifierInfo *Accessor;
SourceLocation AccessorLoc;
public:
- ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor,
- SourceLocation loc)
- : Expr(ExtVectorElementExprClass, ty, base->isTypeDependent(),
- base->isValueDependent()),
+ ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base,
+ IdentifierInfo &accessor, SourceLocation loc)
+ : Expr(ExtVectorElementExprClass, ty, VK,
+ (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent),
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
/// \brief Build an empty vector element expression.
@@ -3373,7 +3719,7 @@ public:
/// aggregate Constant of ConstantInt(s).
void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const;
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), AccessorLoc);
}
@@ -3387,8 +3733,7 @@ public:
static bool classof(const ExtVectorElementExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
};
@@ -3397,11 +3742,11 @@ public:
class BlockExpr : public Expr {
protected:
BlockDecl *TheBlock;
- bool HasBlockDeclRefExprs;
public:
- BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs)
- : Expr(BlockExprClass, ty, ty->isDependentType(), false),
- TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {}
+ BlockExpr(BlockDecl *BD, QualType ty)
+ : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary,
+ ty->isDependentType(), false, false),
+ TheBlock(BD) {}
/// \brief Build an empty block expression.
explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { }
@@ -3415,58 +3760,46 @@ public:
const Stmt *getBody() const;
Stmt *getBody();
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getCaretLocation(), getBody()->getLocEnd());
}
/// getFunctionType - Return the underlying function type for this block.
const FunctionType *getFunctionType() const;
- /// hasBlockDeclRefExprs - Return true iff the block has BlockDeclRefExpr
- /// inside of the block that reference values outside the block.
- bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; }
- void setHasBlockDeclRefExprs(bool BDRE) { HasBlockDeclRefExprs = BDRE; }
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == BlockExprClass;
}
static bool classof(const BlockExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
-/// BlockDeclRefExpr - A reference to a declared variable, function,
-/// enum, etc.
+/// BlockDeclRefExpr - A reference to a local variable declared in an
+/// enclosing scope.
class BlockDeclRefExpr : public Expr {
- ValueDecl *D;
+ VarDecl *D;
SourceLocation Loc;
bool IsByRef : 1;
bool ConstQualAdded : 1;
- Stmt *CopyConstructorVal;
public:
- // FIXME: Fix type/value dependence!
- BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
- bool constAdded = false,
- Stmt *copyConstructorVal = 0)
- : Expr(BlockDeclRefExprClass, t, (!t.isNull() && t->isDependentType()),false),
- D(d), Loc(l), IsByRef(ByRef),
- ConstQualAdded(constAdded), CopyConstructorVal(copyConstructorVal) {}
+ BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
+ SourceLocation l, bool ByRef, bool constAdded = false);
// \brief Build an empty reference to a declared variable in a
// block.
explicit BlockDeclRefExpr(EmptyShell Empty)
: Expr(BlockDeclRefExprClass, Empty) { }
- ValueDecl *getDecl() { return D; }
- const ValueDecl *getDecl() const { return D; }
- void setDecl(ValueDecl *VD) { D = VD; }
+ VarDecl *getDecl() { return D; }
+ const VarDecl *getDecl() const { return D; }
+ void setDecl(VarDecl *VD) { D = VD; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
bool isByRef() const { return IsByRef; }
void setByRef(bool BR) { IsByRef = BR; }
@@ -3474,20 +3807,13 @@ public:
bool isConstQualAdded() const { return ConstQualAdded; }
void setConstQualAdded(bool C) { ConstQualAdded = C; }
- const Expr *getCopyConstructorExpr() const
- { return cast_or_null<Expr>(CopyConstructorVal); }
- Expr *getCopyConstructorExpr()
- { return cast_or_null<Expr>(CopyConstructorVal); }
- void setCopyConstructorExpr(Expr *E) { CopyConstructorVal = E; }
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == BlockDeclRefExprClass;
}
static bool classof(const BlockDeclRefExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
} // end namespace clang
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 0a9435479d93..85ce9621d928 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -21,11 +21,11 @@
namespace clang {
- class CXXConstructorDecl;
- class CXXDestructorDecl;
- class CXXMethodDecl;
- class CXXTemporary;
- class TemplateArgumentListInfo;
+class CXXConstructorDecl;
+class CXXDestructorDecl;
+class CXXMethodDecl;
+class CXXTemporary;
+class TemplateArgumentListInfo;
//===--------------------------------------------------------------------===//
// C++ Expressions.
@@ -51,8 +51,9 @@ class CXXOperatorCallExpr : public CallExpr {
public:
CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
Expr **args, unsigned numargs, QualType t,
- SourceLocation operatorloc)
- : CallExpr(C, CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc),
+ ExprValueKind VK, SourceLocation operatorloc)
+ : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK,
+ operatorloc),
Operator(Op) {}
explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
CallExpr(C, CXXOperatorCallExprClass, Empty) { }
@@ -70,7 +71,7 @@ public:
/// bracket.
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXOperatorCallExprClass;
@@ -89,8 +90,8 @@ public:
class CXXMemberCallExpr : public CallExpr {
public:
CXXMemberCallExpr(ASTContext &C, Expr *fn, Expr **args, unsigned numargs,
- QualType t, SourceLocation rparenloc)
- : CallExpr(C, CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) {}
+ QualType t, ExprValueKind VK, SourceLocation RP)
+ : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, numargs, t, VK, RP) {}
CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
: CallExpr(C, CXXMemberCallExprClass, Empty) { }
@@ -100,7 +101,14 @@ public:
/// operation would return "x".
Expr *getImplicitObjectArgument();
- virtual SourceRange getSourceRange() const;
+ /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of
+ /// the implicit object argument. Note that this is may not be the same
+ /// declaration as that of the class context of the CXXMethodDecl which this
+ /// function is calling.
+ /// FIXME: Returns 0 for member pointer call exprs.
+ CXXRecordDecl *getRecordDecl();
+
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
@@ -108,6 +116,35 @@ public:
static bool classof(const CXXMemberCallExpr *) { return true; }
};
+/// CUDAKernelCallExpr - Represents a call to a CUDA kernel function.
+class CUDAKernelCallExpr : public CallExpr {
+private:
+ enum { CONFIG, END_PREARG };
+
+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) {
+ setConfig(Config);
+ }
+
+ CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty)
+ : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { }
+
+ const CallExpr *getConfig() const {
+ return cast_or_null<CallExpr>(getPreArg(CONFIG));
+ }
+ CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); }
+ void setConfig(CallExpr *E) { setPreArg(CONFIG, E); }
+
+ 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"
/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
/// const_cast.
@@ -118,26 +155,33 @@ public:
class CXXNamedCastExpr : public ExplicitCastExpr {
private:
SourceLocation Loc; // the location of the casting op
-
+ SourceLocation RParenLoc; // the location of the right parenthesis
+
protected:
- CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
- unsigned PathSize, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {}
+ CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+ CastKind kind, Expr *op, unsigned PathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
+ RParenLoc(RParenLoc) {}
explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(SC, Shell, PathSize) { }
+ friend class ASTStmtReader;
+
public:
const char *getCastName() const;
/// \brief Retrieve the location of the cast operator keyword, e.g.,
/// "static_cast".
SourceLocation getOperatorLoc() const { return Loc; }
- void setOperatorLoc(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
+ /// \brief Retrieve the location of the closing parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Loc, RParenLoc);
}
static bool classof(const Stmt *T) {
switch (T->getStmtClass()) {
@@ -158,20 +202,21 @@ public:
/// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
- CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
+ CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
unsigned pathSize, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize,
- writtenTy, l) {}
+ SourceLocation l, SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
+ writtenTy, l, RParenLoc) {}
explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
public:
static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
- CastKind K, Expr *Op,
+ ExprValueKind VK, CastKind K, Expr *Op,
const CXXCastPath *Path,
- TypeSourceInfo *Written, SourceLocation L);
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
unsigned PathSize);
@@ -188,20 +233,21 @@ public:
/// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
- CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
- unsigned pathSize, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize,
- writtenTy, l) {}
+ CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
+ Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
+ writtenTy, l, RParenLoc) {}
explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
public:
static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
- CastKind Kind, Expr *Op,
+ ExprValueKind VK, CastKind Kind, Expr *Op,
const CXXCastPath *Path,
- TypeSourceInfo *Written, SourceLocation L);
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
unsigned pathSize);
@@ -219,20 +265,22 @@ public:
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
- CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
- unsigned pathSize,
- TypeSourceInfo *writtenTy, SourceLocation l)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize,
- writtenTy, l) {}
+ CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
+ Expr *op, unsigned pathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
+ pathSize, writtenTy, l, RParenLoc) {}
CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
public:
static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
- CastKind Kind, Expr *Op,
- const CXXCastPath *Path,
- TypeSourceInfo *WrittenTy, SourceLocation L);
+ ExprValueKind VK, CastKind Kind,
+ Expr *Op, const CXXCastPath *Path,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
unsigned pathSize);
@@ -248,17 +296,20 @@ public:
/// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
- CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
- SourceLocation l)
- : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op,
- 0, writtenTy, l) {}
+ CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
+ 0, writtenTy, l, RParenLoc) {}
explicit CXXConstCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
public:
- static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op,
- TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXConstCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, Expr *Op,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc);
static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
static bool classof(const Stmt *T) {
@@ -274,7 +325,9 @@ class CXXBoolLiteralExpr : public Expr {
SourceLocation Loc;
public:
CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
- Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {}
+ Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Value(val), Loc(l) {}
explicit CXXBoolLiteralExpr(EmptyShell Empty)
: Expr(CXXBoolLiteralExprClass, Empty) { }
@@ -282,7 +335,7 @@ public:
bool getValue() const { return Value; }
void setValue(bool V) { Value = V; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@@ -293,8 +346,7 @@ public:
static bool classof(const CXXBoolLiteralExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal
@@ -302,12 +354,14 @@ class CXXNullPtrLiteralExpr : public Expr {
SourceLocation Loc;
public:
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
- Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {}
+ Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Loc(l) {}
explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
: Expr(CXXNullPtrLiteralExprClass, Empty) { }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@@ -317,8 +371,7 @@ public:
}
static bool classof(const CXXNullPtrLiteralExpr *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
@@ -333,19 +386,21 @@ private:
public:
CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
- : Expr(CXXTypeidExprClass, Ty,
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
// typeid is never type-dependent (C++ [temp.dep.expr]p4)
false,
// typeid is value-dependent if the type or expression are dependent
- Operand->getType()->isDependentType()),
+ Operand->getType()->isDependentType(),
+ Operand->getType()->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) { }
CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R)
- : Expr(CXXTypeidExprClass, Ty,
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
// typeid is never type-dependent (C++ [temp.dep.expr]p4)
- false,
+ false,
// typeid is value-dependent if the type or expression are dependent
- Operand->isTypeDependent() || Operand->isValueDependent()),
+ Operand->isTypeDependent() || Operand->isValueDependent(),
+ Operand->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) { }
CXXTypeidExpr(EmptyShell Empty, bool isExpr)
@@ -383,7 +438,7 @@ public:
Operand = E;
}
- virtual SourceRange getSourceRange() const { return Range; }
+ SourceRange getSourceRange() const { return Range; }
void setSourceRange(SourceRange R) { Range = R; }
static bool classof(const Stmt *T) {
@@ -392,8 +447,84 @@ public:
static bool classof(const CXXTypeidExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (isTypeOperand()) return child_range();
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
+};
+
+/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
+/// the _GUID that corresponds to the supplied type or expression.
+///
+/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr)
+class CXXUuidofExpr : public Expr {
+private:
+ llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
+ SourceRange Range;
+
+public:
+ CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
+ : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
+ false, Operand->getType()->isDependentType(),
+ Operand->getType()->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R)
+ : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
+ false, Operand->isTypeDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXUuidofExpr(EmptyShell Empty, bool isExpr)
+ : Expr(CXXUuidofExprClass, Empty) {
+ if (isExpr)
+ Operand = (Expr*)0;
+ else
+ Operand = (TypeSourceInfo*)0;
+ }
+
+ bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
+
+ /// \brief Retrieves the type operand of this __uuidof() expression after
+ /// various required adjustments (removing reference types, cv-qualifiers).
+ QualType getTypeOperand() const;
+
+ /// \brief Retrieve source information for the type operand.
+ TypeSourceInfo *getTypeOperandSourceInfo() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ return Operand.get<TypeSourceInfo *>();
+ }
+
+ void setTypeOperandSourceInfo(TypeSourceInfo *TSI) {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ Operand = TSI;
+ }
+
+ Expr *getExprOperand() const {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
+ return static_cast<Expr*>(Operand.get<Stmt *>());
+ }
+
+ void setExprOperand(Expr *E) {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
+ Operand = E;
+ }
+
+ SourceRange getSourceRange() const { return Range; }
+ void setSourceRange(SourceRange R) { Range = R; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUuidofExprClass;
+ }
+ static bool classof(const CXXUuidofExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (isTypeOperand()) return child_range();
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
};
/// CXXThisExpr - Represents the "this" expression in C++, which is a
@@ -413,10 +544,11 @@ class CXXThisExpr : public Expr {
public:
CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit)
- : Expr(CXXThisExprClass, Type,
+ : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary,
// 'this' is type-dependent if the class type of the enclosing
// member function is dependent (C++ [temp.dep.expr]p2)
- Type->isDependentType(), Type->isDependentType()),
+ Type->isDependentType(), Type->isDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
Loc(L), Implicit(isImplicit) { }
CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
@@ -424,7 +556,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
bool isImplicit() const { return Implicit; }
void setImplicit(bool I) { Implicit = I; }
@@ -435,8 +567,7 @@ public:
static bool classof(const CXXThisExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles
@@ -451,7 +582,9 @@ public:
// exepression. The l is the location of the throw keyword. expr
// can by null, if the optional expression to throw isn't present.
CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) :
- Expr(CXXThrowExprClass, Ty, false, false), Op(expr), ThrowLoc(l) {}
+ Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ expr && expr->containsUnexpandedParameterPack()),
+ Op(expr), ThrowLoc(l) {}
CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}
const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); }
@@ -461,7 +594,7 @@ public:
SourceLocation getThrowLoc() const { return ThrowLoc; }
void setThrowLoc(SourceLocation L) { ThrowLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (getSubExpr() == 0)
return SourceRange(ThrowLoc, ThrowLoc);
return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd());
@@ -473,8 +606,9 @@ public:
static bool classof(const CXXThrowExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Op, Op ? &Op+1 : &Op);
+ }
};
/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a
@@ -497,12 +631,16 @@ class CXXDefaultArgExpr : public Expr {
param->hasUnparsedDefaultArg()
? param->getType().getNonReferenceType()
: param->getDefaultArg()->getType(),
- false, false),
+ param->getDefaultArg()->getValueKind(),
+ param->getDefaultArg()->getObjectKind(), false, false, false),
Param(param, false), Loc(Loc) { }
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param,
Expr *SubExpr)
- : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) {
+ : Expr(SC, SubExpr->getType(),
+ SubExpr->getValueKind(), SubExpr->getObjectKind(),
+ false, false, false),
+ Param(param, true), Loc(Loc) {
*reinterpret_cast<Expr **>(this + 1) = SubExpr;
}
@@ -544,7 +682,7 @@ public:
/// used.
SourceLocation getUsedLocation() const { return Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
// Default argument expressions have no representation in the
// source, so they have an empty source range.
return SourceRange();
@@ -556,8 +694,7 @@ public:
static bool classof(const CXXDefaultArgExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -597,9 +734,12 @@ class CXXBindTemporaryExpr : public Expr {
Stmt *SubExpr;
- CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
- : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false),
- Temp(temp), SubExpr(subexpr) { }
+ CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr)
+ : Expr(CXXBindTemporaryExprClass, SubExpr->getType(),
+ VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(),
+ SubExpr->isValueDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ Temp(temp), SubExpr(SubExpr) { }
public:
CXXBindTemporaryExpr(EmptyShell Empty)
@@ -616,7 +756,7 @@ public:
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SubExpr->getSourceRange();
}
@@ -627,8 +767,7 @@ public:
static bool classof(const CXXBindTemporaryExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
/// CXXConstructExpr - Represents a call to a C++ constructor.
@@ -644,6 +783,7 @@ private:
CXXConstructorDecl *Constructor;
SourceLocation Loc;
+ SourceRange ParenRange;
bool Elidable : 1;
bool ZeroInitialization : 1;
unsigned ConstructKind : 2;
@@ -656,7 +796,8 @@ protected:
CXXConstructorDecl *d, bool elidable,
Expr **args, unsigned numargs,
bool ZeroInitialization = false,
- ConstructionKind ConstructKind = CK_Complete);
+ ConstructionKind ConstructKind = CK_Complete,
+ SourceRange ParenRange = SourceRange());
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
@@ -675,7 +816,8 @@ public:
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
bool ZeroInitialization = false,
- ConstructionKind ConstructKind = CK_Complete);
+ ConstructionKind ConstructKind = CK_Complete,
+ SourceRange ParenRange = SourceRange());
CXXConstructorDecl* getConstructor() const { return Constructor; }
@@ -731,7 +873,8 @@ public:
Args[Arg] = ArgExpr;
}
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
+ SourceRange getParenRange() const { return ParenRange; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstructExprClass ||
@@ -740,8 +883,9 @@ public:
static bool classof(const CXXConstructExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Args[0], &Args[0]+NumArgs);
+ }
friend class ASTStmtReader;
};
@@ -753,12 +897,13 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
- CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
+ CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
+ TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
Expr *castExpr, unsigned pathSize,
SourceLocation rParenLoc)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
- pathSize, writtenTy),
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
+ castExpr, pathSize, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
@@ -766,6 +911,7 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr {
public:
static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
TypeSourceInfo *Written,
SourceLocation TyBeginLoc,
CastKind Kind, Expr *Op,
@@ -779,7 +925,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -804,24 +950,21 @@ public:
/// };
/// @endcode
class CXXTemporaryObjectExpr : public CXXConstructExpr {
- SourceLocation TyBeginLoc;
- SourceLocation RParenLoc;
+ TypeSourceInfo *Type;
public:
CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons,
- QualType writtenTy, SourceLocation tyBeginLoc,
+ TypeSourceInfo *Type,
Expr **Args,unsigned NumArgs,
- SourceLocation rParenLoc,
+ SourceRange parenRange,
bool ZeroInitialization = false);
explicit CXXTemporaryObjectExpr(EmptyShell Empty)
- : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { }
+ : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { }
- SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
- SourceLocation getRParenLoc() const { return RParenLoc; }
+ TypeSourceInfo *getTypeSourceInfo() const { return Type; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(TyBeginLoc, RParenLoc);
- }
+ SourceRange getSourceRange() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTemporaryObjectExprClass;
}
@@ -835,32 +978,31 @@ public:
/// T, which is a non-class type.
///
class CXXScalarValueInitExpr : public Expr {
- SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
+ TypeSourceInfo *TypeInfo;
+ friend class ASTStmtReader;
+
public:
- CXXScalarValueInitExpr(QualType ty, SourceLocation tyBeginLoc,
- SourceLocation rParenLoc ) :
- Expr(CXXScalarValueInitExprClass, ty, false, false),
- TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+ /// \brief Create an explicitly-written scalar-value initialization
+ /// expression.
+ CXXScalarValueInitExpr(QualType Type,
+ TypeSourceInfo *TypeInfo,
+ SourceLocation rParenLoc ) :
+ Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
+ false, false, false),
+ RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
+
explicit CXXScalarValueInitExpr(EmptyShell Shell)
: Expr(CXXScalarValueInitExprClass, Shell) { }
- SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
- SourceLocation getRParenLoc() const { return RParenLoc; }
-
- void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
- void setRParenLoc(SourceLocation L) { RParenLoc = L; }
-
- /// @brief Whether this initialization expression was
- /// implicitly-generated.
- bool isImplicit() const {
- return TyBeginLoc.isInvalid() && RParenLoc.isInvalid();
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TypeInfo;
}
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
- virtual SourceRange getSourceRange() const {
- return SourceRange(TyBeginLoc, RParenLoc);
- }
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXScalarValueInitExprClass;
@@ -868,8 +1010,7 @@ public:
static bool classof(const CXXScalarValueInitExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// CXXNewExpr - A new expression for memory allocation and constructor calls,
@@ -882,8 +1023,11 @@ class CXXNewExpr : public Expr {
bool Initializer : 1;
// Do we allocate an array? If so, the first SubExpr is the size expression.
bool Array : 1;
+ // If this is an array allocation, does the usual deallocation
+ // function for the allocated type want to know the allocated size?
+ bool UsualArrayDeleteWantsSize : 1;
// The number of placement new arguments.
- unsigned NumPlacementArgs : 15;
+ unsigned NumPlacementArgs : 14;
// The number of constructor arguments. This may be 1 even for non-class
// types; use the pseudo copy constructor.
unsigned NumConstructorArgs : 14;
@@ -900,12 +1044,17 @@ class CXXNewExpr : public Expr {
// Must be null for all other types.
CXXConstructorDecl *Constructor;
+ /// \brief The allocated type-source information, as written in the source.
+ TypeSourceInfo *AllocatedTypeInfo;
+
/// \brief If the allocated type was expressed as a parenthesized type-id,
/// the source range covering the parenthesized type-id.
SourceRange TypeIdParens;
SourceLocation StartLoc;
SourceLocation EndLoc;
+ SourceLocation ConstructorLParen;
+ SourceLocation ConstructorRParen;
friend class ASTStmtReader;
public:
@@ -914,8 +1063,11 @@ public:
SourceRange TypeIdParens,
Expr *arraySize, CXXConstructorDecl *constructor, bool initializer,
Expr **constructorArgs, unsigned numConsArgs,
- FunctionDecl *operatorDelete, QualType ty,
- SourceLocation startLoc, SourceLocation endLoc);
+ FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,
+ QualType ty, TypeSourceInfo *AllocatedTypeInfo,
+ SourceLocation startLoc, SourceLocation endLoc,
+ SourceLocation constructorLParen,
+ SourceLocation constructorRParen);
explicit CXXNewExpr(EmptyShell Shell)
: Expr(CXXNewExprClass, Shell), SubExprs(0) { }
@@ -927,6 +1079,10 @@ public:
return getType()->getAs<PointerType>()->getPointeeType();
}
+ TypeSourceInfo *getAllocatedTypeSourceInfo() const {
+ return AllocatedTypeInfo;
+ }
+
FunctionDecl *getOperatorNew() const { return OperatorNew; }
void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
@@ -943,6 +1099,10 @@ public:
}
unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+ Expr **getPlacementArgs() {
+ return reinterpret_cast<Expr **>(SubExprs + Array);
+ }
+
Expr *getPlacementArg(unsigned i) {
assert(i < NumPlacementArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + i]);
@@ -956,11 +1116,21 @@ public:
SourceRange getTypeIdParens() const { return TypeIdParens; }
bool isGlobalNew() const { return GlobalNew; }
- void setGlobalNew(bool V) { GlobalNew = V; }
bool hasInitializer() const { return Initializer; }
- void setHasInitializer(bool V) { Initializer = V; }
+
+ /// Answers whether the usual array deallocation function for the
+ /// allocated type expects the size of the allocation as a
+ /// parameter.
+ bool doesUsualArrayDeleteWantSize() const {
+ return UsualArrayDeleteWantsSize;
+ }
unsigned getNumConstructorArgs() const { return NumConstructorArgs; }
+
+ Expr **getConstructorArgs() {
+ return reinterpret_cast<Expr **>(SubExprs + Array + NumPlacementArgs);
+ }
+
Expr *getConstructorArg(unsigned i) {
assert(i < NumConstructorArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
@@ -1007,13 +1177,13 @@ public:
const_arg_iterator raw_arg_begin() const { return SubExprs; }
const_arg_iterator raw_arg_end() const { return constructor_arg_end(); }
-
SourceLocation getStartLoc() const { return StartLoc; }
- void setStartLoc(SourceLocation L) { StartLoc = L; }
SourceLocation getEndLoc() const { return EndLoc; }
- void setEndLoc(SourceLocation L) { EndLoc = L; }
-
- virtual SourceRange getSourceRange() const {
+
+ SourceLocation getConstructorLParen() const { return ConstructorLParen; }
+ SourceLocation getConstructorRParen() const { return ConstructorRParen; }
+
+ SourceRange getSourceRange() const {
return SourceRange(StartLoc, EndLoc);
}
@@ -1023,8 +1193,11 @@ public:
static bool classof(const CXXNewExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0],
+ &SubExprs[0] + Array + getNumPlacementArgs()
+ + getNumConstructorArgs());
+ }
};
/// CXXDeleteExpr - A delete expression for memory deallocation and destructor
@@ -1034,6 +1207,13 @@ class CXXDeleteExpr : public Expr {
bool GlobalDelete : 1;
// Is this the array form of delete, i.e. "delete[]"?
bool ArrayForm : 1;
+ // ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied
+ // to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm
+ // will be true).
+ bool ArrayFormAsWritten : 1;
+ // Does the usual deallocation function for the element type require
+ // a size_t argument?
+ bool UsualArrayDeleteWantsSize : 1;
// Points to the operator delete overload that is used. Could be a member.
FunctionDecl *OperatorDelete;
// The pointer expression to be deleted.
@@ -1042,30 +1222,42 @@ class CXXDeleteExpr : public Expr {
SourceLocation Loc;
public:
CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
+ bool arrayFormAsWritten, bool usualArrayDeleteWantsSize,
FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
- : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete),
- ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg),
- Loc(loc) { }
+ : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false,
+ arg->containsUnexpandedParameterPack()),
+ GlobalDelete(globalDelete),
+ ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize),
+ OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { }
explicit CXXDeleteExpr(EmptyShell Shell)
: Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { }
bool isGlobalDelete() const { return GlobalDelete; }
bool isArrayForm() const { return ArrayForm; }
-
- void setGlobalDelete(bool V) { GlobalDelete = V; }
- void setArrayForm(bool V) { ArrayForm = V; }
+ bool isArrayFormAsWritten() const { return ArrayFormAsWritten; }
+
+ /// Answers whether the usual array deallocation function for the
+ /// allocated type expects the size of the allocation as a
+ /// parameter. This can be true even if the actual deallocation
+ /// function that we're using doesn't want a size.
+ bool doesUsualArrayDeleteWantSize() const {
+ return UsualArrayDeleteWantsSize;
+ }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
- void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; }
Expr *getArgument() { return cast<Expr>(Argument); }
const Expr *getArgument() const { return cast<Expr>(Argument); }
- void setArgument(Expr *E) { Argument = E; }
- virtual SourceRange getSourceRange() const {
+ /// \brief Retrieve the type being destroyed. If the type being
+ /// destroyed is a dependent type which may or may not be a pointer,
+ /// return an invalid type.
+ QualType getDestroyedType() const;
+
+ SourceRange getSourceRange() const {
return SourceRange(Loc, Argument->getLocEnd());
}
- void setStartLoc(SourceLocation L) { Loc = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDeleteExprClass;
@@ -1073,8 +1265,9 @@ public:
static bool classof(const CXXDeleteExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Argument, &Argument+1); }
+
+ friend class ASTStmtReader;
};
/// \brief Structure used to store the type being destroyed by a
@@ -1171,21 +1364,7 @@ public:
TypeSourceInfo *ScopeType,
SourceLocation ColonColonLoc,
SourceLocation TildeLoc,
- PseudoDestructorTypeStorage DestroyedType)
- : Expr(CXXPseudoDestructorExprClass,
- Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
- false, 0, false,
- false, 0, 0,
- FunctionType::ExtInfo())),
- /*isTypeDependent=*/(Base->isTypeDependent() ||
- (DestroyedType.getTypeSourceInfo() &&
- DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
- /*isValueDependent=*/Base->isValueDependent()),
- Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
- OperatorLoc(OperatorLoc), Qualifier(Qualifier),
- QualifierRange(QualifierRange),
- ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
- DestroyedType(DestroyedType) { }
+ PseudoDestructorTypeStorage DestroyedType);
explicit CXXPseudoDestructorExpr(EmptyShell Shell)
: Expr(CXXPseudoDestructorExprClass, Shell),
@@ -1278,7 +1457,7 @@ public:
DestroyedType = PseudoDestructorTypeStorage(Info);
}
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXPseudoDestructorExprClass;
@@ -1286,8 +1465,7 @@ public:
static bool classof(const CXXPseudoDestructorExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base + 1); }
};
/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
@@ -1296,8 +1474,10 @@ public:
/// __is_pod(int) == true
/// __is_enum(std::string) == false
class UnaryTypeTraitExpr : public Expr {
- /// UTT - The trait.
- UnaryTypeTrait UTT;
+ /// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned.
+ unsigned UTT : 31;
+ /// The value of the type trait. Unspecified if dependent.
+ bool Value : 1;
/// Loc - The location of the type trait keyword.
SourceLocation Loc;
@@ -1305,25 +1485,31 @@ class UnaryTypeTraitExpr : public Expr {
/// RParen - The location of the closing paren.
SourceLocation RParen;
- /// QueriedType - The type we're testing.
- QualType QueriedType;
+ /// The type being queried.
+ TypeSourceInfo *QueriedType;
public:
- UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried,
+ UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt,
+ TypeSourceInfo *queried, bool value,
SourceLocation rparen, QualType ty)
- : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()),
- UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { }
+ : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, queried->getType()->isDependentType(),
+ queried->getType()->containsUnexpandedParameterPack()),
+ UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { }
explicit UnaryTypeTraitExpr(EmptyShell Empty)
- : Expr(UnaryTypeTraitExprClass, Empty), UTT((UnaryTypeTrait)0) { }
+ : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false),
+ QueriedType() { }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
+ SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
- UnaryTypeTrait getTrait() const { return UTT; }
+ UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); }
- QualType getQueriedType() const { return QueriedType; }
+ QualType getQueriedType() const { return QueriedType->getType(); }
- bool EvaluateTrait(ASTContext&) const;
+ TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; }
+
+ bool getValue() const { return Value; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryTypeTraitExprClass;
@@ -1331,8 +1517,74 @@ public:
static bool classof(const UnaryTypeTraitExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+};
+
+/// BinaryTypeTraitExpr - A GCC or MS binary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+/// __is_base_of(Base, Derived) == true
+class BinaryTypeTraitExpr : public Expr {
+ /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned.
+ unsigned BTT : 8;
+
+ /// The value of the type trait. Unspecified if dependent.
+ bool Value : 1;
+
+ /// Loc - The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// RParen - The location of the closing paren.
+ SourceLocation RParen;
+
+ /// The lhs type being queried.
+ TypeSourceInfo *LhsType;
+
+ /// The rhs type being queried.
+ TypeSourceInfo *RhsType;
+
+public:
+ BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt,
+ TypeSourceInfo *lhsType, TypeSourceInfo *rhsType,
+ bool value, SourceLocation rparen, QualType ty)
+ : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false,
+ lhsType->getType()->isDependentType() ||
+ rhsType->getType()->isDependentType(),
+ (lhsType->getType()->containsUnexpandedParameterPack() ||
+ rhsType->getType()->containsUnexpandedParameterPack())),
+ BTT(btt), Value(value), Loc(loc), RParen(rparen),
+ LhsType(lhsType), RhsType(rhsType) { }
+
+
+ explicit BinaryTypeTraitExpr(EmptyShell Empty)
+ : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false),
+ LhsType(), RhsType() { }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Loc, RParen);
+ }
+
+ BinaryTypeTrait getTrait() const {
+ return static_cast<BinaryTypeTrait>(BTT);
+ }
+
+ QualType getLhsType() const { return LhsType->getType(); }
+ QualType getRhsType() const { return RhsType->getType(); }
+
+ TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; }
+ TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; }
+
+ bool getValue() const { assert(!isTypeDependent()); return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryTypeTraitExprClass;
+ }
+ static bool classof(const BinaryTypeTraitExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
friend class ASTStmtReader;
};
@@ -1360,23 +1612,23 @@ protected:
/// True if the name was a template-id.
bool HasExplicitTemplateArgs;
- OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent,
+ OverloadExpr(StmtClass K, ASTContext &C,
NestedNameSpecifier *Qualifier, SourceRange QRange,
const DeclarationNameInfo &NameInfo,
- bool HasTemplateArgs,
- UnresolvedSetIterator Begin, UnresolvedSetIterator End);
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End,
+ bool KnownDependent = false,
+ bool KnownContainsUnexpandedParameterPack = false);
OverloadExpr(StmtClass K, EmptyShell Empty)
: Expr(K, Empty), Results(0), NumResults(0),
Qualifier(0), HasExplicitTemplateArgs(false) { }
-public:
- /// Computes whether an unresolved lookup on the given declarations
- /// and optional template arguments is type- and value-dependent.
- static bool ComputeDependence(UnresolvedSetIterator Begin,
- UnresolvedSetIterator End,
- const TemplateArgumentListInfo *Args);
+ void initializeResults(ASTContext &C,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
+public:
struct FindResult {
OverloadExpr *Expression;
bool IsAddressOfOperand;
@@ -1420,9 +1672,6 @@ public:
return UnresolvedSetIterator(Results + NumResults);
}
- void initializeResults(ASTContext &C,
- UnresolvedSetIterator Begin,UnresolvedSetIterator End);
-
/// Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; }
@@ -1469,6 +1718,9 @@ public:
T->getStmtClass() == UnresolvedMemberExprClass;
}
static bool classof(const OverloadExpr *) { return true; }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// \brief A reference to a name which we were able to look up during
@@ -1498,14 +1750,15 @@ class UnresolvedLookupExpr : public OverloadExpr {
/// against the qualified-lookup bits.
CXXRecordDecl *NamingClass;
- UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent,
+ UnresolvedLookupExpr(ASTContext &C,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, SourceRange QRange,
const DeclarationNameInfo &NameInfo,
- bool RequiresADL, bool Overloaded, bool HasTemplateArgs,
+ bool RequiresADL, bool Overloaded,
+ const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End)
- : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier,
- QRange, NameInfo, HasTemplateArgs, Begin, End),
+ : OverloadExpr(UnresolvedLookupExprClass, C, Qualifier, QRange, NameInfo,
+ TemplateArgs, Begin, End),
RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
{}
@@ -1516,7 +1769,6 @@ class UnresolvedLookupExpr : public OverloadExpr {
public:
static UnresolvedLookupExpr *Create(ASTContext &C,
- bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
@@ -1524,16 +1776,12 @@ public:
bool ADL, bool Overloaded,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
- return new(C) UnresolvedLookupExpr(C,
- Dependent ? C.DependentTy : C.OverloadTy,
- Dependent, NamingClass,
- Qualifier, QualifierRange, NameInfo,
- ADL, Overloaded, false,
- Begin, End);
+ return new(C) UnresolvedLookupExpr(C, NamingClass, Qualifier,
+ QualifierRange, NameInfo, ADL,
+ Overloaded, 0, Begin, End);
}
static UnresolvedLookupExpr *Create(ASTContext &C,
- bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
@@ -1544,6 +1792,7 @@ public:
UnresolvedSetIterator End);
static UnresolvedLookupExpr *CreateEmpty(ASTContext &C,
+ bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// True if this declaration should be extended by
@@ -1606,15 +1855,14 @@ public:
return getExplicitTemplateArgs().NumTemplateArgs;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range(getNameInfo().getSourceRange());
if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
return Range;
}
- virtual StmtIterator child_begin();
- virtual StmtIterator child_end();
+ child_range children() { return child_range(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedLookupExprClass;
@@ -1655,11 +1903,7 @@ class DependentScopeDeclRefExpr : public Expr {
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
const DeclarationNameInfo &NameInfo,
- bool HasExplicitTemplateArgs)
- : Expr(DependentScopeDeclRefExprClass, T, true, true),
- NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier),
- HasExplicitTemplateArgs(HasExplicitTemplateArgs)
- {}
+ const TemplateArgumentListInfo *Args);
public:
static DependentScopeDeclRefExpr *Create(ASTContext &C,
@@ -1669,6 +1913,7 @@ public:
const TemplateArgumentListInfo *TemplateArgs = 0);
static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
+ bool HasExplicitTemplateArgs,
unsigned NumTemplateArgs);
/// \brief Retrieve the name that this expression refers to.
@@ -1740,7 +1985,7 @@ public:
return getExplicitTemplateArgs().NumTemplateArgs;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range(QualifierRange.getBegin(), getLocation());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
@@ -1752,25 +1997,32 @@ public:
}
static bool classof(const DependentScopeDeclRefExpr *) { return true; }
- virtual StmtIterator child_begin();
- virtual StmtIterator child_end();
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
-class CXXExprWithTemporaries : public Expr {
+/// Represents an expression --- generally a full-expression --- which
+/// introduces cleanups to be run at the end of the sub-expression's
+/// evaluation. The most common source of expression-introduced
+/// cleanups is temporary objects in C++, but several other C++
+/// expressions can create cleanups.
+class ExprWithCleanups : public Expr {
Stmt *SubExpr;
CXXTemporary **Temps;
unsigned NumTemps;
- CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps,
- unsigned NumTemps);
-
+ ExprWithCleanups(ASTContext &C, Expr *SubExpr,
+ CXXTemporary **Temps, unsigned NumTemps);
+
public:
- CXXExprWithTemporaries(EmptyShell Empty)
- : Expr(CXXExprWithTemporariesClass, Empty),
+ ExprWithCleanups(EmptyShell Empty)
+ : Expr(ExprWithCleanupsClass, Empty),
SubExpr(0), Temps(0), NumTemps(0) {}
- static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
+ static ExprWithCleanups *Create(ASTContext &C, Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps);
@@ -1782,7 +2034,7 @@ public:
return Temps[i];
}
const CXXTemporary *getTemporary(unsigned i) const {
- return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i);
+ return const_cast<ExprWithCleanups*>(this)->getTemporary(i);
}
void setTemporary(unsigned i, CXXTemporary *T) {
assert(i < NumTemps && "Index out of range");
@@ -1793,19 +2045,18 @@ public:
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SubExpr->getSourceRange();
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXExprWithTemporariesClass;
+ return T->getStmtClass() == ExprWithCleanupsClass;
}
- static bool classof(const CXXExprWithTemporaries *) { return true; }
+ static bool classof(const ExprWithCleanups *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
};
/// \brief Describes an explicit type conversion that uses functional
@@ -1830,12 +2081,9 @@ public:
/// constructor call, conversion function call, or some kind of type
/// conversion.
class CXXUnresolvedConstructExpr : public Expr {
- /// \brief The starting location of the type
- SourceLocation TyBeginLoc;
-
/// \brief The type being constructed.
- QualType Type;
-
+ TypeSourceInfo *Type;
+
/// \brief The location of the left parentheses ('(').
SourceLocation LParenLoc;
@@ -1845,20 +2093,20 @@ class CXXUnresolvedConstructExpr : public Expr {
/// \brief The number of arguments used to construct the type.
unsigned NumArgs;
- CXXUnresolvedConstructExpr(SourceLocation TyBegin,
- QualType T,
+ CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
Expr **Args,
unsigned NumArgs,
SourceLocation RParenLoc);
CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
- : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) { }
+ : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { }
+ friend class ASTStmtReader;
+
public:
static CXXUnresolvedConstructExpr *Create(ASTContext &C,
- SourceLocation TyBegin,
- QualType T,
+ TypeSourceInfo *Type,
SourceLocation LParenLoc,
Expr **Args,
unsigned NumArgs,
@@ -1867,15 +2115,14 @@ public:
static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C,
unsigned NumArgs);
- /// \brief Retrieve the source location where the type begins.
- SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
- void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
-
/// \brief Retrieve the type that is being constructed, as specified
/// in the source code.
- QualType getTypeAsWritten() const { return Type; }
- void setTypeAsWritten(QualType T) { Type = T; }
+ QualType getTypeAsWritten() const { return Type->getType(); }
+ /// \brief Retrieve the type source information for the type being
+ /// constructed.
+ TypeSourceInfo *getTypeSourceInfo() const { return Type; }
+
/// \brief Retrieve the location of the left parentheses ('(') that
/// precedes the argument list.
SourceLocation getLParenLoc() const { return LParenLoc; }
@@ -1916,17 +2163,18 @@ public:
*(arg_begin() + I) = E;
}
- virtual SourceRange getSourceRange() const {
- return SourceRange(TyBeginLoc, RParenLoc);
- }
+ SourceRange getSourceRange() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXUnresolvedConstructExprClass;
}
static bool classof(const CXXUnresolvedConstructExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt**>(this+1);
+ return child_range(begin, begin + NumArgs);
+ }
};
/// \brief Represents a C++ member access expression where the actual
@@ -1987,19 +2235,13 @@ class CXXDependentScopeMemberExpr : public Expr {
public:
CXXDependentScopeMemberExpr(ASTContext &C,
- Expr *Base, QualType BaseType,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- NamedDecl *FirstQualifierFoundInScope,
- DeclarationNameInfo MemberNameInfo)
- : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
- Base(Base), BaseType(BaseType), IsArrow(IsArrow),
- HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc),
- Qualifier(Qualifier), QualifierRange(QualifierRange),
- FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- MemberNameInfo(MemberNameInfo) { }
+ Expr *Base, QualType BaseType,
+ bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo);
static CXXDependentScopeMemberExpr *
Create(ASTContext &C,
@@ -2012,7 +2254,8 @@ public:
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
- CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
+ CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
/// \brief True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
@@ -2147,7 +2390,7 @@ public:
return getExplicitTemplateArgs().RAngleLoc;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range;
if (!isImplicitAccess())
Range.setBegin(Base->getSourceRange().getBegin());
@@ -2169,8 +2412,13 @@ public:
static bool classof(const CXXDependentScopeMemberExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (isImplicitAccess()) return child_range();
+ return child_range(&Base, &Base + 1);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// \brief Represents a C++ member access expression for which lookup
@@ -2206,8 +2454,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
- UnresolvedMemberExpr(ASTContext &C, QualType T, bool Dependent,
- bool HasUnresolvedUsing,
+ UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@@ -2222,7 +2469,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
public:
static UnresolvedMemberExpr *
- Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing,
+ Create(ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@@ -2232,7 +2479,8 @@ public:
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
static UnresolvedMemberExpr *
- CreateEmpty(ASTContext &C, unsigned NumTemplateArgs);
+ CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
/// \brief True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
@@ -2337,7 +2585,7 @@ public:
return getExplicitTemplateArgs().RAngleLoc;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
SourceRange Range = getMemberNameInfo().getSourceRange();
if (!isImplicitAccess())
Range.setBegin(Base->getSourceRange().getBegin());
@@ -2355,10 +2603,130 @@ public:
static bool classof(const UnresolvedMemberExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (isImplicitAccess()) return child_range();
+ return child_range(&Base, &Base + 1);
+ }
+};
+
+/// \brief Represents a C++0x noexcept expression (C++ [expr.unary.noexcept]).
+///
+/// The noexcept expression tests whether a given expression might throw. Its
+/// result is a boolean constant.
+class CXXNoexceptExpr : public Expr {
+ bool Value : 1;
+ Stmt *Operand;
+ SourceRange Range;
+
+ friend class ASTStmtReader;
+
+public:
+ CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val,
+ SourceLocation Keyword, SourceLocation RParen)
+ : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary,
+ /*TypeDependent*/false,
+ /*ValueDependent*/Val == CT_Dependent,
+ Operand->containsUnexpandedParameterPack()),
+ Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen)
+ { }
+
+ CXXNoexceptExpr(EmptyShell Empty)
+ : Expr(CXXNoexceptExprClass, Empty)
+ { }
+
+ Expr *getOperand() const { return static_cast<Expr*>(Operand); }
+
+ SourceRange getSourceRange() const { return Range; }
+
+ bool getValue() const { return Value; }
+
+ 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); }
};
+/// \brief Represents a C++0x pack expansion that produces a sequence of
+/// expressions.
+///
+/// A pack expansion expression contains a pattern (which itself is an
+/// expression) followed by an ellipsis. For example:
+///
+/// \code
+/// template<typename F, typename ...Types>
+/// void forward(F f, Types &&...args) {
+/// f(static_cast<Types&&>(args)...);
+/// }
+/// \endcode
+///
+/// Here, the argument to the function object \c f is a pack expansion whose
+/// pattern is \c static_cast<Types&&>(args). When the \c forward function
+/// template is instantiated, the pack expansion will instantiate to zero or
+/// or more function arguments to the function object \c f.
+class PackExpansionExpr : public Expr {
+ SourceLocation EllipsisLoc;
+
+ /// \brief The number of expansions that will be produced by this pack
+ /// expansion expression, if known.
+ ///
+ /// When zero, the number of expansions is not known. Otherwise, this value
+ /// is the number of expansions + 1.
+ unsigned NumExpansions;
+
+ Stmt *Pattern;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions)
+ : Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
+ Pattern->getObjectKind(), /*TypeDependent=*/true,
+ /*ValueDependent=*/true, /*ContainsUnexpandedParameterPack=*/false),
+ EllipsisLoc(EllipsisLoc),
+ NumExpansions(NumExpansions? *NumExpansions + 1 : 0),
+ Pattern(Pattern) { }
+
+ PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { }
+
+ /// \brief Retrieve the pattern of the pack expansion.
+ Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); }
+
+ /// \brief Retrieve the pattern of the pack expansion.
+ const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); }
+
+ /// \brief Retrieve the location of the ellipsis that describes this pack
+ /// expansion.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// \brief Determine the number of expansions that will be produced when
+ /// this pack expansion is instantiated, if already known.
+ llvm::Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Pattern->getLocStart(), EllipsisLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PackExpansionExprClass;
+ }
+ static bool classof(const PackExpansionExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Pattern, &Pattern + 1);
+ }
+};
+
inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
if (isa<UnresolvedLookupExpr>(this))
return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs();
@@ -2366,6 +2734,159 @@ inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs();
}
+/// \brief Represents an expression that computes the length of a parameter
+/// pack.
+///
+/// \code
+/// template<typename ...Types>
+/// struct count {
+/// static const unsigned value = sizeof...(Types);
+/// };
+/// \endcode
+class SizeOfPackExpr : public Expr {
+ /// \brief The location of the 'sizeof' keyword.
+ SourceLocation OperatorLoc;
+
+ /// \brief The location of the name of the parameter pack.
+ SourceLocation PackLoc;
+
+ /// \brief The location of the closing parenthesis.
+ SourceLocation RParenLoc;
+
+ /// \brief The length of the parameter pack, if known.
+ ///
+ /// When this expression is value-dependent, the length of the parameter pack
+ /// is unknown. When this expression is not value-dependent, the length is
+ /// known.
+ unsigned Length;
+
+ /// \brief The parameter pack itself.
+ NamedDecl *Pack;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ /// \brief Creates a value-dependent expression that computes the length of
+ /// the given parameter pack.
+ SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc, SourceLocation RParenLoc)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/true,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(0), Pack(Pack) { }
+
+ /// \brief Creates an expression that computes the length of
+ /// the given parameter pack, which is already known.
+ SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc, SourceLocation RParenLoc,
+ unsigned Length)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(Length), Pack(Pack) { }
+
+ /// \brief Create an empty expression.
+ SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { }
+
+ /// \brief Determine the location of the 'sizeof' keyword.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+
+ /// \brief Determine the location of the parameter pack.
+ SourceLocation getPackLoc() const { return PackLoc; }
+
+ /// \brief Determine the location of the right parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ /// \brief Retrieve the parameter pack.
+ NamedDecl *getPack() const { return Pack; }
+
+ /// \brief Retrieve the length of the parameter pack.
+ ///
+ /// This routine may only be invoked when the expression is not
+ /// value-dependent.
+ unsigned getPackLength() const {
+ assert(!isValueDependent() &&
+ "Cannot get the length of a value-dependent pack size expression");
+ return Length;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(OperatorLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SizeOfPackExprClass;
+ }
+ static bool classof(const SizeOfPackExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// \brief Represents a reference to a non-type template parameter pack that
+/// has been substituted with a non-template argument pack.
+///
+/// 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 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
+/// that pack expansion (e.g., when all template parameters have corresponding
+/// arguments), this type will be replaced with the appropriate underlying
+/// expression at the current pack substitution index.
+class SubstNonTypeTemplateParmPackExpr : public Expr {
+ /// \brief The non-type template parameter pack itself.
+ NonTypeTemplateParmDecl *Param;
+
+ /// \brief A pointer to the set of template arguments that this
+ /// parameter pack is instantiated with.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in \c Arguments.
+ unsigned NumArguments;
+
+ /// \brief The location of the non-type template parameter pack reference.
+ SourceLocation NameLoc;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ SubstNonTypeTemplateParmPackExpr(QualType T,
+ NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc,
+ const TemplateArgument &ArgPack);
+
+ SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { }
+
+ /// \brief Retrieve the non-type template parameter pack being substituted.
+ NonTypeTemplateParmDecl *getParameterPack() const { return Param; }
+
+ /// \brief Retrieve the location of the parameter pack name.
+ SourceLocation getParameterPackLocation() const { return NameLoc; }
+
+ /// \brief Retrieve the template argument pack containing the substituted
+ /// template arguments.
+ TemplateArgument getArgumentPack() const;
+
+ SourceRange getSourceRange() const { return NameLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass;
+ }
+ static bool classof(const SubstNonTypeTemplateParmPackExpr *) {
+ return true;
+ }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 8a09f4e9a6a9..285efb757bbb 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -14,14 +14,13 @@
#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
namespace clang {
class IdentifierInfo;
class ASTContext;
- class ObjCMethodDecl;
- class ObjCPropertyDecl;
/// ObjCStringLiteral, used for Objective-C string literals
/// i.e. @"foo".
@@ -30,7 +29,9 @@ class ObjCStringLiteral : public Expr {
SourceLocation AtLoc;
public:
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
- : Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {}
+ : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ String(SL), AtLoc(L) {}
explicit ObjCStringLiteral(EmptyShell Empty)
: Expr(ObjCStringLiteralClass, Empty) {}
@@ -41,7 +42,7 @@ public:
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, String->getLocEnd());
}
@@ -51,8 +52,7 @@ public:
static bool classof(const ObjCStringLiteral *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&String, &String+1); }
};
/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
@@ -64,8 +64,10 @@ class ObjCEncodeExpr : public Expr {
public:
ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCEncodeExprClass, T, EncodedType->getType()->isDependentType(),
- EncodedType->getType()->isDependentType()),
+ : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->containsUnexpandedParameterPack()),
EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
@@ -83,7 +85,7 @@ public:
EncodedType = EncType;
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
@@ -93,8 +95,7 @@ public:
static bool classof(const ObjCEncodeExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ObjCSelectorExpr used for @selector in Objective-C.
@@ -104,8 +105,9 @@ class ObjCSelectorExpr : public Expr {
public:
ObjCSelectorExpr(QualType T, Selector selInfo,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at),
- RParenLoc(rp){}
+ : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ SelName(selInfo), AtLoc(at), RParenLoc(rp){}
explicit ObjCSelectorExpr(EmptyShell Empty)
: Expr(ObjCSelectorExprClass, Empty) {}
@@ -117,7 +119,7 @@ public:
void setAtLoc(SourceLocation L) { AtLoc = L; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
@@ -130,8 +132,7 @@ public:
static bool classof(const ObjCSelectorExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used
@@ -144,8 +145,9 @@ class ObjCProtocolExpr : public Expr {
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol),
- AtLoc(at), RParenLoc(rp) {}
+ : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {}
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
@@ -157,7 +159,7 @@ public:
void setAtLoc(SourceLocation L) { AtLoc = L; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
@@ -167,8 +169,7 @@ public:
static bool classof(const ObjCProtocolExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
@@ -180,13 +181,13 @@ class ObjCIvarRefExpr : public Expr {
bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
public:
- ObjCIvarRefExpr(ObjCIvarDecl *d,
- QualType t, SourceLocation l, Expr *base,
+ ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
+ SourceLocation l, Expr *base,
bool arrow = false, bool freeIvar = false) :
- Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false,
- base->isValueDependent()), D(d),
- Loc(l), Base(base), IsArrow(arrow),
- IsFreeIvar(freeIvar) {}
+ Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {}
explicit ObjCIvarRefExpr(EmptyShell Empty)
: Expr(ObjCIvarRefExprClass, Empty) {}
@@ -207,7 +208,7 @@ public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return isFreeIvar() ? SourceRange(Loc)
: SourceRange(getBase()->getLocStart(), Loc);
}
@@ -218,8 +219,7 @@ public:
static bool classof(const ObjCIvarRefExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
};
/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
@@ -227,32 +227,127 @@ public:
///
class ObjCPropertyRefExpr : public Expr {
private:
- ObjCPropertyDecl *AsProperty;
+ /// If the bool is true, this is an implicit property reference; the
+ /// pointer is an (optional) ObjCMethodDecl and Setter may be set.
+ /// if the bool is false, this is an explicit property reference;
+ /// the pointer is an ObjCPropertyDecl and Setter is always null.
+ llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
+ ObjCMethodDecl *Setter;
+
SourceLocation IdLoc;
- Stmt *Base;
+
+ /// \brief When the receiver in property access is 'super', this is
+ /// the location of the 'super' keyword. When it's an interface,
+ /// this is that interface.
+ SourceLocation ReceiverLoc;
+ llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver;
+
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, Expr *base)
- : Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false,
- base->isValueDependent()),
- AsProperty(PD), IdLoc(l), Base(base) {
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), Setter(0),
+ IdLoc(l), ReceiverLoc(), Receiver(base) {
+ }
+
+ ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation l, SourceLocation sl, QualType st)
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, false,
+ st->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), Setter(0),
+ IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc, Expr *Base)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
+ Base->isValueDependent(),
+ Base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc,
+ SourceLocation SuperLoc, QualType SuperTy)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc,
+ SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
}
explicit ObjCPropertyRefExpr(EmptyShell Empty)
: Expr(ObjCPropertyRefExprClass, Empty) {}
- ObjCPropertyDecl *getProperty() const { return AsProperty; }
- void setProperty(ObjCPropertyDecl *D) { AsProperty = D; }
+ bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
+ bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
- const Expr *getBase() const { return cast<Expr>(Base); }
- Expr *getBase() { return cast<Expr>(Base); }
- void setBase(Expr *base) { Base = base; }
+ ObjCPropertyDecl *getExplicitProperty() const {
+ assert(!isImplicitProperty());
+ return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
+ }
+
+ ObjCMethodDecl *getImplicitPropertyGetter() const {
+ assert(isImplicitProperty());
+ return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
+ }
+
+ ObjCMethodDecl *getImplicitPropertySetter() const {
+ assert(isImplicitProperty());
+ return Setter;
+ }
+
+ Selector getGetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertyGetter()->getSelector();
+ return getExplicitProperty()->getGetterName();
+ }
+
+ Selector getSetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertySetter()->getSelector();
+ return getExplicitProperty()->getSetterName();
+ }
+
+ const Expr *getBase() const {
+ return cast<Expr>(Receiver.get<Stmt*>());
+ }
+ Expr *getBase() {
+ return cast<Expr>(Receiver.get<Stmt*>());
+ }
SourceLocation getLocation() const { return IdLoc; }
- void setLocation(SourceLocation L) { IdLoc = L; }
+
+ SourceLocation getReceiverLocation() const { return ReceiverLoc; }
+ QualType getSuperReceiverType() const {
+ return QualType(Receiver.get<const Type*>(), 0);
+ }
+ ObjCInterfaceDecl *getClassReceiver() const {
+ return Receiver.get<ObjCInterfaceDecl*>();
+ }
+ bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
+ bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
+ bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
- virtual SourceRange getSourceRange() const {
- return SourceRange(getBase()->getLocStart(), IdLoc);
+ SourceRange getSourceRange() const {
+ return SourceRange((isObjectReceiver() ? getBase()->getLocStart()
+ : getReceiverLocation()),
+ IdLoc);
}
static bool classof(const Stmt *T) {
@@ -261,89 +356,32 @@ public:
static bool classof(const ObjCPropertyRefExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-};
-
-/// ObjCImplicitSetterGetterRefExpr - A dot-syntax expression to access two
-/// methods; one to set a value to an 'ivar' (Setter) and the other to access
-/// an 'ivar' (Setter).
-/// An example for use of this AST is:
-/// @code
-/// @interface Test { }
-/// - (Test *)crash;
-/// - (void)setCrash: (Test*)value;
-/// @end
-/// void foo(Test *p1, Test *p2)
-/// {
-/// p2.crash = p1.crash; // Uses ObjCImplicitSetterGetterRefExpr AST
-/// }
-/// @endcode
-class ObjCImplicitSetterGetterRefExpr : public Expr {
- /// Setter - Setter method user declared for setting its 'ivar' to a value
- ObjCMethodDecl *Setter;
- /// Getter - Getter method user declared for accessing 'ivar' it controls.
- ObjCMethodDecl *Getter;
- /// Location of the member in the dot syntax notation. This is location
- /// of the getter method.
- SourceLocation MemberLoc;
- // FIXME: Swizzle these into a single pointer.
- Stmt *Base;
- ObjCInterfaceDecl *InterfaceDecl;
- /// Location of the receiver class in the dot syntax notation
- /// used to call a class method setter/getter.
- SourceLocation ClassLoc;
-
-public:
- ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
- QualType t,
- ObjCMethodDecl *setter,
- SourceLocation l, Expr *base)
- : Expr(ObjCImplicitSetterGetterRefExprClass, t, /*TypeDependent=*/false,
- base->isValueDependent()),
- Setter(setter), Getter(getter), MemberLoc(l), Base(base),
- InterfaceDecl(0), ClassLoc(SourceLocation()) {
- }
- ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
- QualType t,
- ObjCMethodDecl *setter,
- SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL)
- : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false),
- Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C),
- ClassLoc(CL) {
+ child_range children() {
+ if (Receiver.is<Stmt*>()) {
+ Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
+ return child_range(begin, begin+1);
}
- explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty)
- : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){}
-
- ObjCMethodDecl *getGetterMethod() const { return Getter; }
- ObjCMethodDecl *getSetterMethod() const { return Setter; }
- ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; }
- void setGetterMethod(ObjCMethodDecl *D) { Getter = D; }
- void setSetterMethod(ObjCMethodDecl *D) { Setter = D; }
- void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; }
-
- virtual SourceRange getSourceRange() const {
- if (Base)
- return SourceRange(getBase()->getLocStart(), MemberLoc);
- return SourceRange(ClassLoc, MemberLoc);
- }
- const Expr *getBase() const { return cast_or_null<Expr>(Base); }
- Expr *getBase() { return cast_or_null<Expr>(Base); }
- void setBase(Expr *base) { Base = base; }
-
- SourceLocation getLocation() const { return MemberLoc; }
- void setLocation(SourceLocation L) { MemberLoc = L; }
- SourceLocation getClassLoc() const { return ClassLoc; }
- void setClassLoc(SourceLocation L) { ClassLoc = L; }
+ return child_range();
+ }
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass;
+private:
+ friend class ASTStmtReader;
+ void setExplicitProperty(ObjCPropertyDecl *D) {
+ PropertyOrGetter.setPointer(D);
+ PropertyOrGetter.setInt(false);
+ Setter = 0;
+ }
+ void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter) {
+ PropertyOrGetter.setPointer(Getter);
+ PropertyOrGetter.setInt(true);
+ this->Setter = Setter;
}
- static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; }
+ void setBase(Expr *Base) { Receiver = Base; }
+ void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
+ void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ void setLocation(SourceLocation L) { IdLoc = L; }
+ void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
};
/// \brief An expression that sends a message to the given Objective-C
@@ -396,6 +434,9 @@ class ObjCMessageExpr : public Expr {
/// referring to the method that we type-checked against.
uintptr_t SelectorOrMethod;
+ /// \brief Location of the selector.
+ SourceLocation SelectorLoc;
+
/// \brief The source locations of the open and close square
/// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc;
@@ -404,26 +445,29 @@ class ObjCMessageExpr : public Expr {
: Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0),
HasMethod(0), SelectorOrMethod(0) { }
- ObjCMessageExpr(QualType T,
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
SourceLocation SuperLoc,
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
- ObjCMessageExpr(QualType T,
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
- ObjCMessageExpr(QualType T,
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -458,6 +502,10 @@ public:
///
/// \param T The result type of this message.
///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
/// \param LBrac The location of the open square bracket '['.
///
/// \param SuperLoc The location of the "super" keyword.
@@ -475,12 +523,14 @@ public:
/// \param NumArgs The number of arguments.
///
/// \param RBracLoc The location of the closing square bracket ']'.
- static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
SourceLocation LBracLoc,
SourceLocation SuperLoc,
bool IsInstanceSuper,
QualType SuperType,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -491,6 +541,10 @@ public:
///
/// \param T The result type of this message.
///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
/// \param LBrac The location of the open square bracket '['.
///
/// \param Receiver The type of the receiver, including
@@ -507,9 +561,11 @@ public:
///
/// \param RBracLoc The location of the closing square bracket ']'.
static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -520,6 +576,10 @@ public:
///
/// \param T The result type of this message.
///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
/// \param LBrac The location of the open square bracket '['.
///
/// \param Receiver The expression used to produce the object that
@@ -536,9 +596,11 @@ public:
///
/// \param RBracLoc The location of the closing square bracket ']'.
static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
Selector Sel,
+ SourceLocation SelLoc,
ObjCMethodDecl *Method,
Expr **Args, unsigned NumArgs,
SourceLocation RBracLoc);
@@ -556,6 +618,9 @@ public:
/// sent to.
ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
+ /// \brief Source range of the receiver.
+ SourceRange getReceiverRange() const;
+
/// \brief Determine whether this is an instance message to either a
/// computed object or to super.
bool isInstanceMessage() const {
@@ -682,11 +747,11 @@ public:
/// \brief Retrieve the arguments to this message, not including the
/// receiver.
- Stmt **getArgs() {
- return reinterpret_cast<Stmt **>(this + 1) + 1;
+ Expr **getArgs() {
+ return reinterpret_cast<Expr **>(this + 1) + 1;
}
- const Stmt * const *getArgs() const {
- return reinterpret_cast<const Stmt * const *>(this + 1) + 1;
+ const Expr * const *getArgs() const {
+ return reinterpret_cast<const Expr * const *>(this + 1) + 1;
}
/// getArg - Return the specified argument.
@@ -706,15 +771,13 @@ public:
SourceLocation getLeftLoc() const { return LBracLoc; }
SourceLocation getRightLoc() const { return RBracLoc; }
-
- void setLeftLoc(SourceLocation L) { LBracLoc = L; }
- void setRightLoc(SourceLocation L) { RBracLoc = L; }
+ SourceLocation getSelectorLoc() const { return SelectorLoc; }
void setSourceRange(SourceRange R) {
LBracLoc = R.getBegin();
RBracLoc = R.getEnd();
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LBracLoc, RBracLoc);
}
@@ -724,43 +787,24 @@ public:
static bool classof(const ObjCMessageExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children();
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
- arg_iterator arg_begin() { return getArgs(); }
- arg_iterator arg_end() { return getArgs() + NumArgs; }
- const_arg_iterator arg_begin() const { return getArgs(); }
- const_arg_iterator arg_end() const { return getArgs() + NumArgs; }
-};
-
-/// ObjCSuperExpr - Represents the "super" expression in Objective-C,
-/// which refers to the object on which the current method is executing.
-///
-/// FIXME: This class is intended for removal, once its remaining
-/// clients have been altered to represent "super" internally.
-class ObjCSuperExpr : public Expr {
- SourceLocation Loc;
-public:
- ObjCSuperExpr(SourceLocation L, QualType Type)
- : Expr(ObjCSuperExprClass, Type, false, false), Loc(L) { }
- explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {}
-
- SourceLocation getLoc() const { return Loc; }
- void setLoc(SourceLocation L) { Loc = L; }
-
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == ObjCSuperExprClass;
+ arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
+ arg_iterator arg_end() {
+ return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
+ }
+ const_arg_iterator arg_begin() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs());
+ }
+ const_arg_iterator arg_end() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
}
- static bool classof(const ObjCSuperExpr *) { return true; }
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
@@ -776,8 +820,9 @@ class ObjCIsaExpr : public Expr {
bool IsArrow;
public:
ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
- : Expr(ObjCIsaExprClass, ty, /*TypeDependent=*/false,
- base->isValueDependent()),
+ : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ /*ContainsUnexpandedParameterPack=*/false),
Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}
/// \brief Build an empty expression.
@@ -794,11 +839,11 @@ public:
SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), IsaMemberLoc);
}
- virtual SourceLocation getExprLoc() const { return IsaMemberLoc; }
+ SourceLocation getExprLoc() const { return IsaMemberLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCIsaExprClass;
@@ -806,8 +851,7 @@ public:
static bool classof(const ObjCIsaExpr *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Base, &Base+1); }
};
} // end namespace clang
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index a8ef0053a442..7b23766b0714 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#include "clang/AST/DeclBase.h"
#include <cassert>
#include <vector>
@@ -24,6 +25,7 @@ template <class T> class SmallVectorImpl;
namespace clang {
class ASTConsumer;
+class CXXBaseSpecifier;
class Decl;
class DeclContext;
class DeclContextLookupResult;
@@ -32,6 +34,7 @@ class ExternalSemaSource; // layering violation required for downcasting
class NamedDecl;
class Selector;
class Stmt;
+class TagDecl;
/// \brief Abstract interface for external sources of AST nodes.
///
@@ -91,6 +94,10 @@ public:
/// FunctionDecl::setLazyBody when building decls.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0;
+ /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// stream into an array of specifiers.
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0;
+
/// \brief Finds all declarations with the given name in the
/// given context.
///
@@ -110,12 +117,44 @@ public:
virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0;
/// \brief Finds all declarations lexically contained within the given
- /// DeclContext.
+ /// 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 true if an error occurred
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
- llvm::SmallVectorImpl<Decl*> &Result) = 0;
+ bool (*isKindWeWant)(Decl::Kind),
+ llvm::SmallVectorImpl<Decl*> &Result) = 0;
+
+ /// \brief Finds all declarations lexically contained within the given
+ /// DeclContext.
+ ///
+ /// \return true if an error occurred
+ bool FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::SmallVectorImpl<Decl*> &Result) {
+ return FindExternalLexicalDecls(DC, 0, Result);
+ }
+
+ template <typename DeclTy>
+ bool FindExternalLexicalDeclsBy(const DeclContext *DC,
+ llvm::SmallVectorImpl<Decl*> &Result) {
+ return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
+ }
+
+ /// \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 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.
@@ -227,6 +266,11 @@ typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
+/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
+typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
+ &ExternalASTSource::GetExternalCXXBaseSpecifiers>
+ LazyCXXBaseSpecifiersPtr;
+
} // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h
deleted file mode 100644
index 6ceefed8a63a..000000000000
--- a/include/clang/AST/FullExpr.h
+++ /dev/null
@@ -1,88 +0,0 @@
-//===--- FullExpr.h - C++ full expression class -----------------*- 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 FullExpr interface, to be used for type safe handling
-// of full expressions.
-//
-// Full expressions are described in C++ [intro.execution]p12.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_FULLEXPR_H
-#define LLVM_CLANG_AST_FULLEXPR_H
-
-#include "llvm/ADT/PointerUnion.h"
-
-namespace clang {
- class ASTContext;
- class CXXTemporary;
- class Expr;
-
-class FullExpr {
- struct ExprAndTemporaries {
- Expr *SubExpr;
-
- unsigned NumTemps;
-
- typedef CXXTemporary** temps_iterator;
-
- temps_iterator temps_begin() {
- return reinterpret_cast<CXXTemporary **>(this + 1);
- }
- temps_iterator temps_end() {
- return temps_begin() + NumTemps;
- }
- };
-
- typedef llvm::PointerUnion<Expr *, ExprAndTemporaries *> SubExprTy;
- SubExprTy SubExpr;
-
- FullExpr() { }
-
-public:
- static FullExpr Create(ASTContext &Context, Expr *SubExpr,
- CXXTemporary **Temps, unsigned NumTemps);
-
- Expr *getExpr() {
- if (Expr *E = SubExpr.dyn_cast<Expr *>())
- return E;
-
- return SubExpr.get<ExprAndTemporaries *>()->SubExpr;
- }
-
- const Expr *getExpr() const {
- return const_cast<FullExpr*>(this)->getExpr();
- }
-
- typedef CXXTemporary** temps_iterator;
-
- temps_iterator temps_begin() {
- if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
- return ET->temps_begin();
-
- return 0;
- }
- temps_iterator temps_end() {
- if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
- return ET->temps_end();
-
- return 0;
- }
-
- void *getAsOpaquePtr() const { return SubExpr.getOpaqueValue(); }
-
- static FullExpr getFromOpaquePtr(void *Ptr) {
- FullExpr E;
- E.SubExpr = SubExprTy::getFromOpaqueValue(Ptr);
- return E;
- }
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
new file mode 100644
index 000000000000..7af7702027a4
--- /dev/null
+++ b/include/clang/AST/Mangle.h
@@ -0,0 +1,150 @@
+//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the C++ name mangling interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MANGLE_H
+#define LLVM_CLANG_AST_MANGLE_H
+
+#include "clang/AST/Type.h"
+#include "clang/Basic/ABI.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+ class ASTContext;
+ class BlockDecl;
+ class CXXConstructorDecl;
+ class CXXDestructorDecl;
+ class CXXMethodDecl;
+ class FunctionDecl;
+ class NamedDecl;
+ class ObjCMethodDecl;
+ class VarDecl;
+ struct ThisAdjustment;
+ struct ThunkInfo;
+
+/// MangleBuffer - a convenient class for storing a name which is
+/// either the result of a mangling or is a constant string with
+/// external memory ownership.
+class MangleBuffer {
+public:
+ void setString(llvm::StringRef Ref) {
+ String = Ref;
+ }
+
+ llvm::SmallVectorImpl<char> &getBuffer() {
+ return Buffer;
+ }
+
+ llvm::StringRef getString() const {
+ if (!String.empty()) return String;
+ return Buffer.str();
+ }
+
+ operator llvm::StringRef() const {
+ return getString();
+ }
+
+private:
+ llvm::StringRef String;
+ llvm::SmallString<256> Buffer;
+};
+
+/// MangleContext - Context for tracking state which persists across multiple
+/// calls to the C++ name mangler.
+class MangleContext {
+ ASTContext &Context;
+ Diagnostic &Diags;
+
+ llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
+ llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
+
+public:
+ explicit MangleContext(ASTContext &Context,
+ Diagnostic &Diags)
+ : Context(Context), Diags(Diags) { }
+
+ virtual ~MangleContext() { }
+
+ ASTContext &getASTContext() const { return Context; }
+
+ Diagnostic &getDiags() const { return Diags; }
+
+ virtual void startNewFunction() { LocalBlockIds.clear(); }
+
+ unsigned getBlockId(const BlockDecl *BD, bool Local) {
+ llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
+ = Local? LocalBlockIds : GlobalBlockIds;
+ std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
+ Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
+ return Result.first->second;
+ }
+
+ /// @name Mangler Entry Points
+ /// @{
+
+ virtual bool shouldMangleDeclName(const NamedDecl *D) = 0;
+ virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &)=0;
+ virtual void mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleReferenceTemporary(const VarDecl *D,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXVTable(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXVTT(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &) = 0;
+ virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &) = 0;
+ virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ llvm::raw_ostream &) = 0;
+
+ void mangleGlobalBlock(const BlockDecl *BD,
+ llvm::raw_ostream &Out);
+ void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
+ const BlockDecl *BD, llvm::raw_ostream &Out);
+ void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
+ const BlockDecl *BD, llvm::raw_ostream &Out);
+ void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
+ llvm::raw_ostream &Out);
+ // Do the right thing.
+ void mangleBlock(const BlockDecl *BD, llvm::raw_ostream &Out);
+
+ void mangleObjCMethodName(const ObjCMethodDecl *MD,
+ llvm::raw_ostream &);
+
+ // This is pretty lame.
+ virtual void mangleItaniumGuardVariable(const VarDecl *D,
+ llvm::raw_ostream &) {
+ assert(0 && "Target does not support mangling guard variables");
+ }
+ /// @}
+};
+
+MangleContext *createItaniumMangleContext(ASTContext &Context,
+ Diagnostic &Diags);
+MangleContext *createMicrosoftMangleContext(ASTContext &Context,
+ Diagnostic &Diags);
+
+}
+
+#endif
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 3b25f3bb403f..99cc1f268fb2 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -90,7 +90,7 @@ private:
/// \brief Either find or insert the given nested name specifier
/// mockup in the given context.
- static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
+ static NestedNameSpecifier *FindOrInsert(const ASTContext &Context,
const NestedNameSpecifier &Mockup);
public:
@@ -99,19 +99,19 @@ public:
/// The prefix must be dependent, since nested name specifiers
/// referencing an identifier are only permitted when the identifier
/// cannot be resolved.
- static NestedNameSpecifier *Create(ASTContext &Context,
+ static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
IdentifierInfo *II);
/// \brief Builds a nested name specifier that names a namespace.
- static NestedNameSpecifier *Create(ASTContext &Context,
+ static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceDecl *NS);
/// \brief Builds a nested name specifier that names a type.
- static NestedNameSpecifier *Create(ASTContext &Context,
+ static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
- bool Template, Type *T);
+ bool Template, const Type *T);
/// \brief Builds a specifier that consists of just an identifier.
///
@@ -119,11 +119,12 @@ public:
/// prefix because the prefix is implied by something outside of the
/// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
/// type.
- static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II);
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ IdentifierInfo *II);
/// \brief Returns the nested name specifier representing the global
/// scope.
- static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
+ static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
/// \brief Return the prefix of this nested name specifier.
///
@@ -160,10 +161,10 @@ public:
}
/// \brief Retrieve the type stored in this nested name specifier.
- Type *getAsType() const {
+ const Type *getAsType() const {
if (Prefix.getInt() == TypeSpec ||
Prefix.getInt() == TypeSpecWithTemplate)
- return (Type *)Specifier;
+ return (const Type *)Specifier;
return 0;
}
@@ -172,6 +173,10 @@ public:
/// type or not.
bool isDependent() const;
+ /// \brief Whether this nested-name-specifier contains an unexpanded
+ /// parameter pack (for C++0x variadic templates).
+ bool containsUnexpandedParameterPack() const;
+
/// \brief Print this nested name specifier to the given output
/// stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index 804531192971..35c72c45ce7c 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -17,107 +17,238 @@
namespace clang {
-/// CastKind - the kind of cast this represents.
+/// CastKind - The kind of operation required for a conversion.
enum CastKind {
- /// CK_Unknown - Unknown cast kind.
- /// FIXME: The goal is to get rid of this and make all casts have a
- /// kind so that the AST client doesn't have to try to figure out what's
- /// going on.
- CK_Unknown,
+ /// CK_Dependent - A conversion which cannot yet be analyzed because
+ /// either the expression or target type is dependent. These are
+ /// created only for explicit casts; dependent ASTs aren't required
+ /// to even approximately type-check.
+ /// (T*) malloc(sizeof(T))
+ /// reinterpret_cast<intptr_t>(A<T>::alloc());
+ CK_Dependent,
- /// CK_BitCast - Used for reinterpret_cast.
+ /// CK_BitCast - A conversion which causes a bit pattern of one type
+ /// to be reinterpreted as a bit pattern of another type. Generally
+ /// the operands must have equivalent size and unrelated types.
+ ///
+ /// The pointer conversion char* -> int* is a bitcast. Many other
+ /// pointer conversions which are "physically" bitcasts are given
+ /// special cast kinds.
+ ///
+ /// Vector coercions are bitcasts.
CK_BitCast,
- /// CK_LValueBitCast - Used for reinterpret_cast of expressions to
- /// a reference type.
+ /// CK_LValueBitCast - A conversion which reinterprets the address of
+ /// an l-value as an l-value of a different kind. Used for
+ /// reinterpret_casts of l-value expressions to reference types.
+ /// bool b; reinterpret_cast<char&>(b) = 'a';
CK_LValueBitCast,
+
+ /// CK_LValueToRValue - A conversion which causes the extraction of
+ /// an r-value from the operand gl-value. The result of an r-value
+ /// conversion is always unqualified.
+ CK_LValueToRValue,
+
+ /// CK_GetObjCProperty - A conversion which calls an Objective-C
+ /// property getter. The operand is an OK_ObjCProperty l-value; the
+ /// result will generally be an r-value, but could be an ordinary
+ /// gl-value if the property reference is to an implicit property
+ /// for a method that returns a reference type.
+ CK_GetObjCProperty,
- /// CK_NoOp - Used for const_cast.
+ /// CK_NoOp - A conversion which does not affect the type other than
+ /// (possibly) adding qualifiers.
+ /// int -> int
+ /// char** -> const char * const *
CK_NoOp,
- /// CK_BaseToDerived - Base to derived class casts.
+ /// CK_BaseToDerived - A conversion from a C++ class pointer/reference
+ /// to a derived class pointer/reference.
+ /// B *b = static_cast<B*>(a);
CK_BaseToDerived,
- /// CK_DerivedToBase - Derived to base class casts.
+ /// CK_DerivedToBase - A conversion from a C++ class pointer
+ /// to a base class pointer.
+ /// A *a = new B();
CK_DerivedToBase,
- /// CK_UncheckedDerivedToBase - Derived to base class casts that
- /// assume that the derived pointer is not null.
+ /// CK_UncheckedDerivedToBase - A conversion from a C++ class
+ /// pointer/reference to a base class that can assume that the
+ /// derived pointer is not null.
+ /// const A &a = B();
+ /// b->method_from_a();
CK_UncheckedDerivedToBase,
- /// CK_Dynamic - Dynamic cast.
+ /// CK_Dynamic - A C++ dynamic_cast.
CK_Dynamic,
- /// CK_ToUnion - Cast to union (GCC extension).
+ /// CK_ToUnion - The GCC cast-to-union extension.
+ /// int -> union { int x; float y; }
+ /// float -> union { int x; float y; }
CK_ToUnion,
/// CK_ArrayToPointerDecay - Array to pointer decay.
+ /// int[10] -> int*
+ /// char[5][6] -> char(*)[6]
CK_ArrayToPointerDecay,
- // CK_FunctionToPointerDecay - Function to pointer decay.
+ /// CK_FunctionToPointerDecay - Function to pointer decay.
+ /// void(int) -> void(*)(int)
CK_FunctionToPointerDecay,
- /// CK_NullToMemberPointer - Null pointer to member pointer.
+ /// CK_NullToPointer - Null pointer constant to pointer, ObjC
+ /// pointer, or block pointer.
+ /// (void*) 0
+ /// void (^block)() = 0;
+ CK_NullToPointer,
+
+ /// CK_NullToMemberPointer - Null pointer constant to member pointer.
+ /// int A::*mptr = 0;
+ /// int (A::*fptr)(int) = nullptr;
CK_NullToMemberPointer,
/// CK_BaseToDerivedMemberPointer - Member pointer in base class to
/// member pointer in derived class.
+ /// int B::*mptr = &A::member;
CK_BaseToDerivedMemberPointer,
/// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
/// member pointer in base class.
+ /// int A::*mptr = static_cast<int A::*>(&B::member);
CK_DerivedToBaseMemberPointer,
+ /// CK_MemberPointerToBoolean - Member pointer to boolean. A check
+ /// against the null member pointer.
+ CK_MemberPointerToBoolean,
+
/// CK_UserDefinedConversion - Conversion using a user defined type
/// conversion function.
+ /// struct A { operator int(); }; int i = int(A());
CK_UserDefinedConversion,
- /// CK_ConstructorConversion - Conversion by constructor
+ /// CK_ConstructorConversion - Conversion by constructor.
+ /// struct A { A(int); }; A a = A(10);
CK_ConstructorConversion,
- /// CK_IntegralToPointer - Integral to pointer
+ /// CK_IntegralToPointer - Integral to pointer. A special kind of
+ /// reinterpreting conversion. Applies to normal, ObjC, and block
+ /// pointers.
+ /// (char*) 0x1001aab0
+ /// reinterpret_cast<int*>(0)
CK_IntegralToPointer,
- /// CK_PointerToIntegral - Pointer to integral
+ /// CK_PointerToIntegral - Pointer to integral. A special kind of
+ /// reinterpreting conversion. Applies to normal, ObjC, and block
+ /// pointers.
+ /// (intptr_t) "help!"
CK_PointerToIntegral,
+
+ /// CK_PointerToBoolean - Pointer to boolean conversion. A check
+ /// against null. Applies to normal, ObjC, and block pointers.
+ CK_PointerToBoolean,
- /// CK_ToVoid - Cast to void.
+ /// CK_ToVoid - Cast to void, discarding the computed value.
+ /// (void) malloc(2048)
CK_ToVoid,
- /// CK_VectorSplat - Casting from an integer/floating type to an extended
- /// vector type with the same element type as the src type. Splats the
- /// src expression into the destination expression.
+ /// CK_VectorSplat - A conversion from an arithmetic type to a
+ /// vector of that element type. Fills all elements ("splats") with
+ /// the source value.
+ /// __attribute__((ext_vector_type(4))) int v = 5;
CK_VectorSplat,
- /// CK_IntegralCast - Casting between integral types of different size.
+ /// CK_IntegralCast - A cast between integral types (other than to
+ /// boolean). Variously a bitcast, a truncation, a sign-extension,
+ /// or a zero-extension.
+ /// long l = 5;
+ /// (unsigned) i
CK_IntegralCast,
+ /// CK_IntegralToBoolean - Integral to boolean. A check against zero.
+ /// (bool) i
+ CK_IntegralToBoolean,
+
/// CK_IntegralToFloating - Integral to floating point.
+ /// float f = i;
CK_IntegralToFloating,
- /// CK_FloatingToIntegral - Floating point to integral.
+ /// CK_FloatingToIntegral - Floating point to integral. Rounds
+ /// towards zero, discarding any fractional component.
+ /// (int) f
CK_FloatingToIntegral,
+
+ /// CK_FloatingToBoolean - Floating point to boolean.
+ /// (bool) f
+ CK_FloatingToBoolean,
/// CK_FloatingCast - Casting between floating types of different size.
+ /// (double) f
+ /// (float) ld
CK_FloatingCast,
- /// CK_MemberPointerToBoolean - Member pointer to boolean
- CK_MemberPointerToBoolean,
-
- /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
- /// pointer
+ /// CK_AnyPointerToObjCPointerCast - Casting any other pointer kind
+ /// to an Objective-C pointer.
CK_AnyPointerToObjCPointerCast,
- /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
- /// pointer
+ /// CK_AnyPointerToBlockPointerCast - Casting any other pointer kind
+ /// to a block pointer.
CK_AnyPointerToBlockPointerCast,
/// \brief Converting between two Objective-C object types, which
/// can occur when performing reference binding to an Objective-C
/// object.
- CK_ObjCObjectLValueCast
+ CK_ObjCObjectLValueCast,
+
+ /// \brief A conversion of a floating point real to a floating point
+ /// complex of the original type. Injects the value as the real
+ /// component with a zero imaginary component.
+ /// float -> _Complex float
+ CK_FloatingRealToComplex,
+
+ /// \brief Converts a floating point complex to floating point real
+ /// of the source's element type. Just discards the imaginary
+ /// component.
+ /// _Complex long double -> long double
+ CK_FloatingComplexToReal,
+
+ /// \brief Converts a floating point complex to bool by comparing
+ /// against 0+0i.
+ CK_FloatingComplexToBoolean,
+
+ /// \brief Converts between different floating point complex types.
+ /// _Complex float -> _Complex double
+ CK_FloatingComplexCast,
+
+ /// \brief Converts from a floating complex to an integral complex.
+ /// _Complex float -> _Complex int
+ CK_FloatingComplexToIntegralComplex,
+
+ /// \brief Converts from an integral real to an integral complex
+ /// whose element type matches the source. Injects the value as
+ /// the real component with a zero imaginary component.
+ /// long -> _Complex long
+ CK_IntegralRealToComplex,
+
+ /// \brief Converts an integral complex to an integral real of the
+ /// source's element type by discarding the imaginary component.
+ /// _Complex short -> short
+ CK_IntegralComplexToReal,
+
+ /// \brief Converts an integral complex to bool by comparing against
+ /// 0+0i.
+ CK_IntegralComplexToBoolean,
+
+ /// \brief Converts between different integral complex types.
+ /// _Complex char -> _Complex long long
+ /// _Complex unsigned int -> _Complex signed int
+ CK_IntegralComplexCast,
+
+ /// \brief Converts from an integral complex to a floating complex.
+ /// _Complex unsigned -> _Complex float
+ CK_IntegralComplexToFloatingComplex
};
+#define CK_Invalid ((CastKind) -1)
enum BinaryOperatorKind {
// Operators listed in order of precedence.
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index f826e1117b66..9ea5a0930d32 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -24,8 +24,14 @@ public:
ParentMap(Stmt* ASTRoot);
~ParentMap();
+ /// \brief Adds and/or updates the parent/child-relations of the complete
+ /// stmt tree of S. All children of S including indirect descendants are
+ /// visited and updated or inserted but not the parents of S.
+ void addStmt(Stmt* S);
+
Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const;
+ Stmt *getParentIgnoreParenCasts(Stmt *) const;
const Stmt *getParent(const Stmt* S) const {
return getParent(const_cast<Stmt*>(S));
@@ -35,6 +41,10 @@ public:
return getParentIgnoreParens(const_cast<Stmt*>(S));
}
+ const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
+ return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
+ }
+
bool hasParent(Stmt* S) const {
return getParent(S) != 0;
}
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 70d65d35fef8..a59c302ffc1e 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
#define LLVM_CLANG_AST_PRETTY_PRINTER_H
+#include "clang/Basic/LangOptions.h"
+
namespace llvm {
class raw_ostream;
}
@@ -44,7 +46,7 @@ struct PrintingPolicy {
unsigned Indentation : 8;
/// \brief What language we're printing.
- const LangOptions &LangOpts;
+ const LangOptions LangOpts;
/// \brief Whether we should suppress printing of the actual specifiers for
/// the given type or declaration.
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 2b3229e8fae9..d7bab80afc5e 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -14,8 +14,9 @@
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
#define LLVM_CLANG_AST_LAYOUTINFO_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
namespace clang {
@@ -32,93 +33,41 @@ namespace clang {
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
/// These objects are managed by ASTContext.
class ASTRecordLayout {
- /// Size - Size of record in bits.
- uint64_t Size;
+ /// Size - Size of record in characters.
+ CharUnits Size;
- /// DataSize - Size of record in bits without tail padding.
- uint64_t DataSize;
+ /// DataSize - Size of record in characters without tail padding.
+ CharUnits DataSize;
/// FieldOffsets - Array of field offsets in bits.
uint64_t *FieldOffsets;
- // Alignment - Alignment of record in bits.
- unsigned Alignment;
+ // Alignment - Alignment of record in characters.
+ CharUnits Alignment;
// FieldCount - Number of fields.
unsigned FieldCount;
-public:
- /// PrimaryBaseInfo - Contains info about a primary base.
- struct PrimaryBaseInfo {
- PrimaryBaseInfo() {}
-
- PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual)
- : Value(Base, Base && IsVirtual) {}
-
- /// Value - Points to the primary base. The single-bit value
- /// will be non-zero when the primary base is virtual.
- llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Value;
-
- /// getBase - Returns the primary base.
- const CXXRecordDecl *getBase() const { return Value.getPointer(); }
-
- /// isVirtual - Returns whether the primary base is virtual or not.
- bool isVirtual() const { return Value.getInt(); }
-
- friend bool operator==(const PrimaryBaseInfo &X, const PrimaryBaseInfo &Y) {
- return X.Value == Y.Value;
- }
- };
-
- /// primary_base_info_iterator - An iterator for iterating the primary base
- /// class chain.
- class primary_base_info_iterator {
- /// Current - The current base class info.
- PrimaryBaseInfo Current;
-
- public:
- primary_base_info_iterator() {}
- primary_base_info_iterator(PrimaryBaseInfo Info) : Current(Info) {}
-
- const PrimaryBaseInfo &operator*() const { return Current; }
-
- primary_base_info_iterator& operator++() {
- const CXXRecordDecl *RD = Current.getBase();
- Current = RD->getASTContext().getASTRecordLayout(RD).getPrimaryBaseInfo();
- return *this;
- }
-
- friend bool operator==(const primary_base_info_iterator &X,
- const primary_base_info_iterator &Y) {
- return X.Current == Y.Current;
- }
- friend bool operator!=(const primary_base_info_iterator &X,
- const primary_base_info_iterator &Y) {
- return !(X == Y);
- }
- };
-
-private:
/// CXXRecordLayoutInfo - Contains C++ specific layout information.
struct CXXRecordLayoutInfo {
- /// NonVirtualSize - The non-virtual size (in bits) of an object, which is
+ /// NonVirtualSize - The non-virtual size (in chars) of an object, which is
/// the size of the object without virtual bases.
- uint64_t NonVirtualSize;
+ CharUnits NonVirtualSize;
- /// NonVirtualAlign - The non-virtual alignment (in bits) of an object,
+ /// NonVirtualAlign - The non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
- uint64_t NonVirtualAlign;
+ CharUnits NonVirtualAlign;
/// SizeOfLargestEmptySubobject - The size of the largest empty subobject
/// (either a base or a member). Will be zero if the class doesn't contain
/// any empty subobjects.
- uint64_t SizeOfLargestEmptySubobject;
+ CharUnits SizeOfLargestEmptySubobject;
/// PrimaryBase - The primary base info for this record.
- PrimaryBaseInfo PrimaryBase;
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
- typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsetsMapTy;
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
/// BaseOffsets - Contains a map from base classes to their offset.
BaseOffsetsMapTy BaseOffsets;
@@ -133,35 +82,35 @@ private:
friend class ASTContext;
- ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment,
- unsigned datasize, const uint64_t *fieldoffsets,
+ ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+ CharUnits datasize, const uint64_t *fieldoffsets,
unsigned fieldcount);
// Constructor for C++ records.
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
- ASTRecordLayout(ASTContext &Ctx,
- uint64_t size, unsigned alignment, uint64_t datasize,
+ ASTRecordLayout(const ASTContext &Ctx,
+ CharUnits size, CharUnits alignment, CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
- uint64_t nonvirtualsize, unsigned nonvirtualalign,
- uint64_t SizeOfLargestEmptySubobject,
+ CharUnits nonvirtualsize, CharUnits nonvirtualalign,
+ CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
- bool PrimaryBaseIsVirtual,
+ bool IsPrimaryBaseVirtual,
const BaseOffsetsMapTy& BaseOffsets,
const BaseOffsetsMapTy& VBaseOffsets);
~ASTRecordLayout() {}
void Destroy(ASTContext &Ctx);
-
+
ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
public:
- /// getAlignment - Get the record alignment in bits.
- unsigned getAlignment() const { return Alignment; }
+ /// getAlignment - Get the record alignment in characters.
+ CharUnits getAlignment() const { return Alignment; }
- /// getSize - Get the record size in bits.
- uint64_t getSize() const { return Size; }
+ /// getSize - Get the record size in characters.
+ CharUnits getSize() const { return Size; }
/// getFieldCount - Get the number of fields in the layout.
unsigned getFieldCount() const { return FieldCount; }
@@ -174,75 +123,81 @@ public:
}
/// getDataSize() - Get the record data size, which is the record size
- /// without tail padding, in bits.
- uint64_t getDataSize() const {
+ /// without tail padding, in characters.
+ CharUnits getDataSize() const {
return DataSize;
}
- /// getNonVirtualSize - Get the non-virtual size (in bits) of an object,
+ /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
/// which is the size of the object without virtual bases.
- uint64_t getNonVirtualSize() const {
+ CharUnits getNonVirtualSize() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->NonVirtualSize;
}
- /// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object,
+ /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
- unsigned getNonVirtualAlign() const {
+ CharUnits getNonVirtualAlign() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->NonVirtualAlign;
}
- /// getPrimaryBaseInfo - Get the primary base info.
- const PrimaryBaseInfo &getPrimaryBaseInfo() const {
+ /// getPrimaryBase - Get the primary base for this record.
+ const CXXRecordDecl *getPrimaryBase() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
- return CXXInfo->PrimaryBase;
+ return CXXInfo->PrimaryBase.getPointer();
}
- // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
- const CXXRecordDecl *getPrimaryBase() const {
- return getPrimaryBaseInfo().getBase();
- }
+ /// isPrimaryBaseVirtual - Get whether the primary base for this record
+ /// is virtual or not.
+ bool isPrimaryBaseVirtual() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
- // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
- bool getPrimaryBaseWasVirtual() const {
- return getPrimaryBaseInfo().isVirtual();
+ return CXXInfo->PrimaryBase.getInt();
}
- /// getBaseClassOffset - Get the offset, in bits, for the given base class.
- uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const {
+ /// getBaseClassOffset - Get the offset, in chars, for the given base class.
+ CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
return CXXInfo->BaseOffsets[Base];
}
- /// getVBaseClassOffset - Get the offset, in bits, for the given base class.
- uint64_t getVBaseClassOffset(const CXXRecordDecl *VBase) const {
+ /// getVBaseClassOffset - Get the offset, in chars, for the given base class.
+ CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
return CXXInfo->VBaseOffsets[VBase];
}
-
- uint64_t getSizeOfLargestEmptySubobject() const {
+
+ /// getBaseClassOffsetInBits - Get the offset, in bits, for the given
+ /// base class.
+ uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
- return CXXInfo->SizeOfLargestEmptySubobject;
+ assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
+
+ return getBaseClassOffset(Base).getQuantity() *
+ Base->getASTContext().getCharWidth();
}
- primary_base_info_iterator primary_base_begin() const {
+ /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given
+ /// base class.
+ uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
-
- return primary_base_info_iterator(getPrimaryBaseInfo());
+ assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
+
+ return getVBaseClassOffset(VBase).getQuantity() *
+ VBase->getASTContext().getCharWidth();
}
- primary_base_info_iterator primary_base_end() const {
+ CharUnits getSizeOfLargestEmptySubobject() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
-
- return primary_base_info_iterator();
+ return CXXInfo->SizeOfLargestEmptySubobject;
}
};
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 232e47b03ae5..921b799b94b5 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -143,6 +143,10 @@ public:
/// \brief Return whether this visitor should recurse into
/// template instantiations.
bool shouldVisitTemplateInstantiations() const { return false; }
+
+ /// \brief Return whether this visitor should recurse into the types of
+ /// TypeLocs.
+ bool shouldWalkTypesOfTypeLocs() const { return true; }
/// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
@@ -211,7 +215,7 @@ public:
/// be overridden for clients that need access to the name.
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseConstructorInitializer(CXXBaseOrMemberInitializer *Init);
+ bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
// ---- Methods on Stmts ----
@@ -368,7 +372,7 @@ private:
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
- bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+ bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count);
bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
bool TraverseRecordHelper(RecordDecl *D);
@@ -393,7 +397,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
- case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
+ case BO_##NAME: DISPATCH(Bin##NAME, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
@@ -438,7 +442,8 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, BASE)
#define TYPE(CLASS, BASE) \
- case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, T.getTypePtr());
+ case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, \
+ const_cast<Type*>(T.getTypePtr()));
#include "clang/AST/TypeNodes.def"
}
@@ -531,7 +536,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
return getDerived().TraverseType(Arg.getAsType());
case TemplateArgument::Template:
- return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(Arg.getAsExpr());
@@ -566,7 +573,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
}
case TemplateArgument::Template:
- return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
@@ -592,7 +601,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
- CXXBaseOrMemberInitializer *Init) {
+ CXXCtorInitializer *Init) {
// FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()?
if (Init->isWritten())
TRY_TO(TraverseStmt(Init->getInit()));
@@ -706,10 +715,15 @@ DEF_TRAVERSE_TYPE(DecltypeType, {
TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
})
+DEF_TRAVERSE_TYPE(AutoType, {
+ TRY_TO(TraverseType(T->getDeducedType()));
+ })
+
DEF_TRAVERSE_TYPE(RecordType, { })
DEF_TRAVERSE_TYPE(EnumType, { })
DEF_TRAVERSE_TYPE(TemplateTypeParmType, { })
DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { })
DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
TRY_TO(TraverseTemplateName(T->getTemplateName()));
@@ -718,6 +732,14 @@ DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
+DEF_TRAVERSE_TYPE(AttributedType, {
+ TRY_TO(TraverseType(T->getModifiedType()));
+ })
+
+DEF_TRAVERSE_TYPE(ParenType, {
+ TRY_TO(TraverseType(T->getInnerType()));
+ })
+
DEF_TRAVERSE_TYPE(ElaboratedType, {
if (T->getQualifier()) {
TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
@@ -734,6 +756,10 @@ DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
})
+DEF_TRAVERSE_TYPE(PackExpansionType, {
+ TRY_TO(TraverseType(T->getPattern()));
+ })
+
DEF_TRAVERSE_TYPE(ObjCInterfaceType, { })
DEF_TRAVERSE_TYPE(ObjCObjectType, {
@@ -752,14 +778,15 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType, {
// ----------------- TypeLoc traversal -----------------
// This macro makes available a variable TL, the passed-in TypeLoc.
-// It calls WalkUpFrom* for the Type in the given TypeLoc, in addition
-// to WalkUpFrom* for the TypeLoc itself, such that existing clients
-// that override the WalkUpFrom*Type() and/or Visit*Type() methods
+// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc,
+// in addition to WalkUpFrom* for the TypeLoc itself, such that existing
+// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods
// continue to work.
#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
template<typename Derived> \
bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
- TRY_TO(WalkUpFrom##TYPE(TL.getTypePtr())); \
+ if (getDerived().shouldWalkTypesOfTypeLocs()) \
+ TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE*>(TL.getTypePtr()))); \
TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
{ CODE; } \
return true; \
@@ -867,22 +894,16 @@ DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, {
TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
})
-// FIXME: location of arguments, exception specifications (attributes?)
-// Note that we have the ParmVarDecl's here. Do we want to use them?
+// FIXME: location of exception specifications (attributes?)
DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
- FunctionProtoType *T = TL.getTypePtr();
-/*
+ const FunctionProtoType *T = TL.getTypePtr();
+
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
TRY_TO(TraverseDecl(TL.getArg(I)));
}
-*/
- for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
- AEnd = T->arg_type_end();
- A != AEnd; ++A) {
- TRY_TO(TraverseType(*A));
- }
+
for (FunctionProtoType::exception_iterator E = T->exception_begin(),
EEnd = T->exception_end();
E != EEnd; ++E) {
@@ -906,10 +927,15 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, {
TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
})
+DEF_TRAVERSE_TYPELOC(AutoType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
+ })
+
DEF_TRAVERSE_TYPELOC(RecordType, { })
DEF_TRAVERSE_TYPELOC(EnumType, { })
DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { })
DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { })
// FIXME: use the loc for the template name?
DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
@@ -921,6 +947,14 @@ DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { })
+DEF_TRAVERSE_TYPELOC(ParenType, {
+ TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(AttributedType, {
+ TRY_TO(TraverseTypeLoc(TL.getModifiedLoc()));
+ })
+
// FIXME: use the sourceloc on qualifier?
DEF_TRAVERSE_TYPELOC(ElaboratedType, {
if (TL.getTypePtr()->getQualifier()) {
@@ -941,6 +975,10 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
}
})
+DEF_TRAVERSE_TYPELOC(PackExpansionType, {
+ TRY_TO(TraverseTypeLoc(TL.getPatternLoc()));
+ })
+
DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { })
DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
@@ -1001,11 +1039,18 @@ DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
})
DEF_TRAVERSE_DECL(FriendDecl, {
- TRY_TO(TraverseDecl(D->getFriendDecl()));
+ // Friend is either decl or a type.
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
})
DEF_TRAVERSE_DECL(FriendTemplateDecl, {
- TRY_TO(TraverseDecl(D->getFriendDecl()));
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
TemplateParameterList *TPL = D->getTemplateParameterList(I);
for (TemplateParameterList::iterator ITPL = TPL->begin(),
@@ -1051,6 +1096,11 @@ DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
return true;
})
+DEF_TRAVERSE_DECL(LabelDecl, {
+ // There is no code in a LabelDecl.
+})
+
+
DEF_TRAVERSE_DECL(NamespaceDecl, {
// Code in an unnamed namespace shows up automatically in
// decls_begin()/decls_end(). Thus we don't need to recurse on
@@ -1082,7 +1132,9 @@ DEF_TRAVERSE_DECL(ObjCProtocolDecl, {
})
DEF_TRAVERSE_DECL(ObjCMethodDecl, {
- // FIXME: implement
+ // We don't traverse nodes in param_begin()/param_end(), as they
+ // appear in decls_begin()/decls_end() and thus are handled.
+ TRY_TO(TraverseStmt(D->getBody()));
})
DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
@@ -1175,7 +1227,7 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
if (D->isThisDeclarationADefinition())
TRY_TO(TraverseClassInstantiations(D, D));
}
-
+
// Note that getInstantiatedFromMemberTemplate() is just a link
// from a template instantiation back to the template from which
// it was instantiated, and thus should not be traversed.
@@ -1208,10 +1260,10 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
assert(false && "Unknown specialization kind.");
}
}
-
+
return true;
}
-
+
DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
@@ -1251,7 +1303,7 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
})
DEF_TRAVERSE_DECL(TypedefDecl, {
- TRY_TO(TraverseType(D->getUnderlyingType()));
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the typedef, not something that was written in the
// source.
@@ -1282,11 +1334,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(
RecordDecl *D) {
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type, not something that was written in the source.
- //
- // The anonymous struct or union object is the variable or field
- // whose type is the anonymous struct or union. We shouldn't
- // traverse D->getAnonymousStructOrUnionObject(), as it's not
- // something that is explicitly written in the source.
+
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
return true;
}
@@ -1380,6 +1428,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
})
+DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
+
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
@@ -1412,47 +1462,11 @@ template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
- // Visit the function type itself, which can be either
- // FunctionNoProtoType or FunctionProtoType, or a typedef. If it's
- // not a Function*ProtoType, then it can't have a body or arguments,
- // so we have to do less work.
- Type *FuncType = D->getType().getTypePtr();
- if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
- if (D->isThisDeclarationADefinition()) {
- // Don't call Traverse*, or the result type and parameter types
- // will be double counted.
- TRY_TO(WalkUpFromFunctionProtoType(FuncProto));
- } else {
- // This works around a bug in Clang that does not add the parameters
- // to decls_begin/end for function declarations (as opposed to
- // definitions):
- // http://llvm.org/PR7442
- // We work around this here by traversing the function type.
- // This isn't perfect because we don't traverse the default
- // values, if any. It also may not interact great with
- // templates. But it's the best we can do until the bug is
- // fixed.
- // FIXME: replace the entire 'if' statement with
- // TRY_TO(WalkUpFromFunctionProtoType(FuncProto));
- // when the bug is fixed.
- TRY_TO(TraverseFunctionProtoType(FuncProto));
- return true;
- }
- } else if (FunctionNoProtoType *FuncNoProto =
- dyn_cast<FunctionNoProtoType>(FuncType)) {
- // Don't call Traverse*, or the result type will be double
- // counted.
- TRY_TO(WalkUpFromFunctionNoProtoType(FuncNoProto));
- } else { // a typedef type, or who knows what
- assert(!D->isThisDeclarationADefinition() && "Unexpected function type");
- TRY_TO(TraverseType(D->getType()));
- return true;
- }
-
- TRY_TO(TraverseType(D->getResultType()));
-
// If we're an explicit template specialization, iterate over the
- // template args that were explicitly specified.
+ // template args that were explicitly specified. If we were doing
+ // this in typing order, we'd do it between the return type and
+ // the function args, but both are handled by the FunctionTypeLoc
+ // above, so we have to choose one side. I've decided to do before.
if (const FunctionTemplateSpecializationInfo *FTSI =
D->getTemplateSpecializationInfo()) {
if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
@@ -1467,28 +1481,11 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
}
}
- for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
-
- if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
- if (D->isThisDeclarationADefinition()) {
- // This would be visited if we called TraverseType(D->getType())
- // above, but we don't (at least, not in the
- // declaration-is-a-definition case), in order to avoid duplicate
- // visiting for parameters. (We need to check parameters here,
- // rather than letting D->getType() do it, so we visit default
- // parameter values). So we need to re-do some of the work the
- // type would do.
- for (FunctionProtoType::exception_iterator
- E = FuncProto->exception_begin(),
- EEnd = FuncProto->exception_end();
- E != EEnd; ++E) {
- TRY_TO(TraverseType(*E));
- }
- }
- }
+ // Visit the function type itself, which can be either
+ // FunctionNoProtoType or FunctionProtoType, or a typedef. This
+ // also covers the return type and the function parameters,
+ // including exception specifications.
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers.
@@ -1554,7 +1551,7 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, {
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
- TRY_TO(TraverseVarHelper(D));
+ TRY_TO(TraverseDeclaratorHelper(D));
TRY_TO(TraverseStmt(D->getDefaultArgument()));
})
@@ -1577,12 +1574,11 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
// ----------------- Stmt traversal -----------------
//
// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
-// over the children defined in child_begin/child_end (every stmt
-// defines these, though sometimes the range is empty). Each
-// individual Traverse* method only needs to worry about children
-// other than those. To see what child_begin()/end() does for a given
-// class, see, e.g.,
-// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
+// over the children defined in children() (every stmt defines these,
+// though sometimes the range is empty). Each individual Traverse*
+// method only needs to worry about children other than those. To see
+// what children() does for a given class, see, e.g.,
+// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
// This macro makes available a variable S, the passed-in stmt.
#define DEF_TRAVERSE_STMT(STMT, CODE) \
@@ -1590,9 +1586,8 @@ template<typename Derived> \
bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \
TRY_TO(WalkUpFrom##STMT(S)); \
{ CODE; } \
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end(); \
- C != CEnd; ++C) { \
- TRY_TO(TraverseStmt(*C)); \
+ for (Stmt::child_range range = S->children(); range; ++range) { \
+ TRY_TO(TraverseStmt(*range)); \
} \
return true; \
}
@@ -1608,12 +1603,12 @@ DEF_TRAVERSE_STMT(AsmStmt, {
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
TRY_TO(TraverseStmt(S->getClobber(I)));
}
- // child_begin()/end() iterates over inputExpr and outputExpr.
+ // children() iterates over inputExpr and outputExpr.
})
DEF_TRAVERSE_STMT(CXXCatchStmt, {
TRY_TO(TraverseDecl(S->getExceptionDecl()));
- // child_begin()/end() iterates over the handler block.
+ // children() iterates over the handler block.
})
DEF_TRAVERSE_STMT(DeclStmt, {
@@ -1621,11 +1616,11 @@ DEF_TRAVERSE_STMT(DeclStmt, {
I != E; ++I) {
TRY_TO(TraverseDecl(*I));
}
- // Suppress the default iteration over child_begin/end by
+ // Suppress the default iteration over children() by
// returning. Here's why: A DeclStmt looks like 'type var [=
// initializer]'. The decls above already traverse over the
// initializers, so we don't have to do it again (which
- // child_begin/end would do).
+ // children() would do).
return true;
})
@@ -1652,17 +1647,16 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
DEF_TRAVERSE_STMT(ReturnStmt, { })
-DEF_TRAVERSE_STMT(SwitchCase, { })
DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(WhileStmt, { })
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
if (S->hasExplicitTemplateArgs()) {
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getTemplateArgs(), S->getNumTemplateArgs()));
}
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
})
DEF_TRAVERSE_STMT(DeclRefExpr, {
@@ -1695,27 +1689,27 @@ DEF_TRAVERSE_STMT(ImplicitCastExpr, {
})
DEF_TRAVERSE_STMT(CStyleCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXConstCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
- TRY_TO(TraverseType(S->getTypeAsWritten()));
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
// InitListExpr is a tricky one, because we want to do all our work on
@@ -1729,9 +1723,8 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
S = Syn;
TRY_TO(WalkUpFromInitListExpr(S));
// All we need are the default actions. FIXME: use a helper function.
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
- C != CEnd; ++C) {
- TRY_TO(TraverseStmt(*C));
+ for (Stmt::child_range range = S->children(); range; ++range) {
+ TRY_TO(TraverseStmt(*range));
}
return true;
}
@@ -1739,12 +1732,12 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
// This is called for code like 'return T()' where T is a built-in
// (i.e. non-class) type.
- if (!S->isImplicit())
- TRY_TO(TraverseType(S->getType()));
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXNewExpr, {
- TRY_TO(TraverseType(S->getAllocatedType()));
+ // The child-iterator will pick up the other arguments.
+ TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(OffsetOfExpr, {
@@ -1769,15 +1762,43 @@ DEF_TRAVERSE_STMT(CXXTypeidExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
})
-DEF_TRAVERSE_STMT(TypesCompatibleExpr, {
- TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc()));
- TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc()));
+DEF_TRAVERSE_STMT(CXXUuidofExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
- TRY_TO(TraverseType(S->getQueriedType()));
+ TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc()));
+ TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(VAArgExpr, {
+ // The child-iterator will pick up the expression argument.
+ TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
})
+DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
+ // This is called for code like 'return T()' where T is a class type.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
+ // This is called for code like 'T()', where T is a template argument.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+// These expressions all might take explicit template arguments.
+// We traverse those if so. FIXME: implement these.
+DEF_TRAVERSE_STMT(CXXConstructExpr, { })
+DEF_TRAVERSE_STMT(CallExpr, { })
+DEF_TRAVERSE_STMT(CXXMemberCallExpr, { })
+
// These exprs (most of them), do not need any action except iterating
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@@ -1790,53 +1811,64 @@ DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
-DEF_TRAVERSE_STMT(CXXExprWithTemporaries, { })
+DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
-DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { })
+DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
+ TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
+ if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
+ TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(CXXThisExpr, { })
DEF_TRAVERSE_STMT(CXXThrowExpr, { })
-DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { })
DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
DEF_TRAVERSE_STMT(GNUNullExpr, { })
DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { })
DEF_TRAVERSE_STMT(ObjCEncodeExpr, { })
-DEF_TRAVERSE_STMT(ObjCImplicitSetterGetterRefExpr, { })
DEF_TRAVERSE_STMT(ObjCIsaExpr, { })
DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { })
DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
-DEF_TRAVERSE_STMT(ObjCSuperExpr, { })
DEF_TRAVERSE_STMT(ParenExpr, { })
DEF_TRAVERSE_STMT(ParenListExpr, { })
DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { })
-DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { })
-DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { })
-DEF_TRAVERSE_STMT(VAArgExpr, {
- // The child-iterator will pick up the expression argument.
- TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
- })
-DEF_TRAVERSE_STMT(CXXConstructExpr, { })
-
-DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
- // This is called for code like 'return T()' where T is a class type.
- TRY_TO(TraverseType(S->getType()));
- })
+DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
-DEF_TRAVERSE_STMT(CallExpr, { })
-DEF_TRAVERSE_STMT(CXXMemberCallExpr, { })
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
+DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
+DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { })
// These operators (all of them) do not need any action except
// iterating over the children.
+DEF_TRAVERSE_STMT(BinaryConditionalOperator, { })
DEF_TRAVERSE_STMT(ConditionalOperator, { })
DEF_TRAVERSE_STMT(UnaryOperator, { })
DEF_TRAVERSE_STMT(BinaryOperator, { })
DEF_TRAVERSE_STMT(CompoundAssignOperator, { })
+DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
+DEF_TRAVERSE_STMT(PackExpansionExpr, { })
+DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
+DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, { })
@@ -1861,7 +1893,6 @@ DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
// http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html
// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
-// http://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html
// Every class that has getQualifier.
#undef DEF_TRAVERSE_STMT
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index ba778293ba2d..e87ca78d635a 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -109,25 +109,7 @@ public:
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
/// first and only declaration.
- void setPreviousDeclaration(decl_type *PrevDecl) {
- decl_type *First;
-
- if (PrevDecl) {
- // Point to previous. Make sure that this is actually the most recent
- // redeclaration, or we can build invalid chains. If the most recent
- // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
- RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
- PrevDecl->getMostRecentDeclaration()));
- First = PrevDecl->getFirstDeclaration();
- assert(First->RedeclLink.NextIsLatest() && "Expected first");
- } else {
- // Make this first.
- First = static_cast<decl_type*>(this);
- }
-
- // First one will point to this one as latest.
- First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
- }
+ void setPreviousDeclaration(decl_type *PrevDecl);
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 62a6b6463df5..7ede9ce323f4 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -20,7 +20,6 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtIterator.h"
#include "clang/AST/DeclGroup.h"
-#include "clang/AST/FullExpr.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/AST/ASTContext.h"
#include <string>
@@ -104,13 +103,7 @@ public:
first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class
#define ABSTRACT_STMT(STMT)
#include "clang/AST/StmtNodes.inc"
-};
-private:
- /// \brief The statement class.
- const unsigned sClass : 8;
-
- /// \brief The reference count for this statement.
- unsigned RefCount : 24;
+ };
// Make vanilla 'new' and 'delete' illegal for Stmts.
protected:
@@ -122,6 +115,77 @@ protected:
assert(0 && "Stmts cannot be released with regular 'delete'.");
}
+ class StmtBitfields {
+ friend class Stmt;
+
+ /// \brief The statement class.
+ unsigned sClass : 8;
+ };
+ enum { NumStmtBits = 8 };
+
+ class CompoundStmtBitfields {
+ friend class CompoundStmt;
+ unsigned : NumStmtBits;
+
+ unsigned NumStmts : 32 - NumStmtBits;
+ };
+
+ class ExprBitfields {
+ friend class Expr;
+ friend class DeclRefExpr; // computeDependence
+ friend class InitListExpr; // ctor
+ friend class DesignatedInitExpr; // ctor
+ friend class BlockDeclRefExpr; // ctor
+ friend class ASTStmtReader; // deserialization
+ friend class CXXNewExpr; // ctor
+ friend class DependentScopeDeclRefExpr; // ctor
+ friend class CXXConstructExpr; // ctor
+ friend class CallExpr; // ctor
+ friend class OffsetOfExpr; // ctor
+ friend class ObjCMessageExpr; // ctor
+ friend class ShuffleVectorExpr; // ctor
+ friend class ParenListExpr; // ctor
+ friend class CXXUnresolvedConstructExpr; // ctor
+ friend class CXXDependentScopeMemberExpr; // ctor
+ friend class OverloadExpr; // ctor
+ unsigned : NumStmtBits;
+
+ unsigned ValueKind : 2;
+ unsigned ObjectKind : 2;
+ unsigned TypeDependent : 1;
+ unsigned ValueDependent : 1;
+ unsigned ContainsUnexpandedParameterPack : 1;
+ };
+ enum { NumExprBits = 15 };
+
+ class CastExprBitfields {
+ friend class CastExpr;
+ unsigned : NumExprBits;
+
+ unsigned Kind : 6;
+ unsigned BasePathSize : 32 - 6 - NumExprBits;
+ };
+
+ class CallExprBitfields {
+ friend class CallExpr;
+ unsigned : NumExprBits;
+
+ unsigned NumPreArgs : 1;
+ };
+
+ union {
+ // FIXME: this is wasteful on 64-bit platforms.
+ void *Aligner;
+
+ StmtBitfields StmtBits;
+ CompoundStmtBitfields CompoundStmtBits;
+ ExprBitfields ExprBits;
+ CastExprBitfields CastExprBits;
+ CallExprBitfields CallExprBits;
+ };
+
+ friend class ASTStmtReader;
+
public:
// Only allow allocation of Stmts using the allocator in ASTContext
// or by doing a placement new.
@@ -152,44 +216,27 @@ public:
protected:
/// \brief Construct an empty statement.
- explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
+ explicit Stmt(StmtClass SC, EmptyShell) {
+ StmtBits.sClass = SC;
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
public:
- Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
+ Stmt(StmtClass SC) {
+ StmtBits.sClass = SC;
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
- virtual ~Stmt() {}
-
-#ifndef NDEBUG
- /// \brief True if this statement's refcount is in a valid state.
- /// Should be used only in assertions.
- bool isRetained() const {
- return (RefCount >= 1);
- }
-#endif
-
- /// \brief Increases the reference count for this statement.
- ///
- /// Invoke the Retain() operation when this statement or expression
- /// is being shared by another owner.
- Stmt *Retain() {
- assert(RefCount >= 1);
- ++RefCount;
- return this;
- }
StmtClass getStmtClass() const {
- assert(RefCount >= 1 && "Referencing already-destroyed statement!");
- return (StmtClass)sClass;
+ return static_cast<StmtClass>(StmtBits.sClass);
}
const char *getStmtClassName() const;
/// SourceLocation tokens are not useful in isolation - they are low level
/// value objects created/interpreted by SourceManager. We assume AST
/// clients will have a pointer to the respective SourceManager.
- virtual SourceRange getSourceRange() const = 0;
+ SourceRange getSourceRange() const;
+
SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
@@ -236,22 +283,25 @@ public:
/// within CFGs.
bool hasImplicitControlFlow() const;
- /// Child Iterators: All subclasses must implement child_begin and child_end
- /// to permit easy iteration over the substatements/subexpessions of an
- /// AST node. This permits easy iteration over all nodes in the AST.
+ /// Child Iterators: All subclasses must implement 'children'
+ /// to permit easy iteration over the substatements/subexpessions of an
+ /// AST node. This permits easy iteration over all nodes in the AST.
typedef StmtIterator child_iterator;
typedef ConstStmtIterator const_child_iterator;
- virtual child_iterator child_begin() = 0;
- virtual child_iterator child_end() = 0;
+ typedef StmtRange child_range;
+ typedef ConstStmtRange const_child_range;
- const_child_iterator child_begin() const {
- return const_child_iterator(const_cast<Stmt*>(this)->child_begin());
+ child_range children();
+ const_child_range children() const {
+ return const_cast<Stmt*>(this)->children();
}
- const_child_iterator child_end() const {
- return const_child_iterator(const_cast<Stmt*>(this)->child_end());
- }
+ child_iterator child_begin() { return children().first; }
+ child_iterator child_end() { return children().second; }
+
+ const_child_iterator child_begin() const { return children().first; }
+ const_child_iterator child_end() const { return children().second; }
/// \brief Produce a unique representation of the given statement.
///
@@ -265,7 +315,7 @@ public:
/// parameters are identified by index/level rather than their
/// declaration pointers) or the exact representation of the statement as
/// written in the source.
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
bool Canonical);
};
@@ -314,8 +364,10 @@ public:
static bool classof(const DeclStmt *) { return true; }
// Iterators over subexpressions.
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(child_iterator(DG.begin(), DG.end()),
+ child_iterator(DG.end(), DG.end()));
+ }
typedef DeclGroupRef::iterator decl_iterator;
typedef DeclGroupRef::const_iterator const_decl_iterator;
@@ -330,8 +382,16 @@ public:
///
class NullStmt : public Stmt {
SourceLocation SemiLoc;
+
+ /// \brief Whether the null statement was preceded by an empty macro, e.g:
+ /// @code
+ /// #define CALL(x)
+ /// CALL(0);
+ /// @endcode
+ bool LeadingEmptyMacro;
public:
- NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {}
+ NullStmt(SourceLocation L, bool LeadingEmptyMacro = false)
+ : Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {}
/// \brief Build an empty null statement.
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
@@ -339,55 +399,66 @@ public:
SourceLocation getSemiLoc() const { return SemiLoc; }
void setSemiLoc(SourceLocation L) { SemiLoc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
+ bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro; }
+
+ SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == NullStmtClass;
}
static bool classof(const NullStmt *) { return true; }
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// CompoundStmt - This represents a group of statements like { stmt stmt }.
///
class CompoundStmt : public Stmt {
Stmt** Body;
- unsigned NumStmts;
SourceLocation LBracLoc, RBracLoc;
public:
- CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts,
- SourceLocation LB, SourceLocation RB)
- : Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) {
+ CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned NumStmts,
+ SourceLocation LB, SourceLocation RB)
+ : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) {
+ CompoundStmtBits.NumStmts = NumStmts;
+
if (NumStmts == 0) {
Body = 0;
return;
}
Body = new (C) Stmt*[NumStmts];
- memcpy(Body, StmtStart, numStmts * sizeof(*Body));
+ memcpy(Body, StmtStart, NumStmts * sizeof(*Body));
}
// \brief Build an empty compound statement.
explicit CompoundStmt(EmptyShell Empty)
- : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { }
+ : Stmt(CompoundStmtClass, Empty), Body(0) {
+ CompoundStmtBits.NumStmts = 0;
+ }
void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
- bool body_empty() const { return NumStmts == 0; }
- unsigned size() const { return NumStmts; }
+ bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
+ unsigned size() const { return CompoundStmtBits.NumStmts; }
typedef Stmt** body_iterator;
body_iterator body_begin() { return Body; }
- body_iterator body_end() { return Body + NumStmts; }
- Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; }
+ body_iterator body_end() { return Body + size(); }
+ Stmt *body_back() { return !body_empty() ? Body[size()-1] : 0; }
+
+ void setLastStmt(Stmt *S) {
+ assert(!body_empty() && "setLastStmt");
+ Body[size()-1] = S;
+ }
typedef Stmt* const * const_body_iterator;
const_body_iterator body_begin() const { return Body; }
- const_body_iterator body_end() const { return Body + NumStmts; }
- const Stmt *body_back() const { return NumStmts ? Body[NumStmts-1] : 0; }
+ const_body_iterator body_end() const { return Body + size(); }
+ const Stmt *body_back() const { return !body_empty() ? Body[size()-1] : 0; }
typedef std::reverse_iterator<body_iterator> reverse_body_iterator;
reverse_body_iterator body_rbegin() {
@@ -408,7 +479,7 @@ public:
return const_reverse_body_iterator(body_begin());
}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(LBracLoc, RBracLoc);
}
@@ -423,8 +494,9 @@ public:
static bool classof(const CompoundStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts);
+ }
};
// SwitchCase is the base class for CaseStmt and DefaultStmt,
@@ -443,17 +515,15 @@ public:
void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
- Stmt *getSubStmt() { return v_getSubStmt(); }
+ Stmt *getSubStmt();
- virtual SourceRange getSourceRange() const { return SourceRange(); }
+ SourceRange getSourceRange() const { return SourceRange(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CaseStmtClass ||
- T->getStmtClass() == DefaultStmtClass;
+ T->getStmtClass() == DefaultStmtClass;
}
static bool classof(const SwitchCase *) { return true; }
-protected:
- virtual Stmt* v_getSubStmt() = 0;
};
class CaseStmt : public SwitchCase {
@@ -463,8 +533,6 @@ class CaseStmt : public SwitchCase {
SourceLocation CaseLoc;
SourceLocation EllipsisLoc;
SourceLocation ColonLoc;
-
- virtual Stmt* v_getSubStmt() { return getSubStmt(); }
public:
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
SourceLocation ellipsisLoc, SourceLocation colonLoc)
@@ -504,7 +572,7 @@ public:
void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
// Handle deeply nested case statements with iteration instead of recursion.
const CaseStmt *CS = this;
while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
@@ -518,15 +586,15 @@ public:
static bool classof(const CaseStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
};
class DefaultStmt : public SwitchCase {
Stmt* SubStmt;
SourceLocation DefaultLoc;
SourceLocation ColonLoc;
- virtual Stmt* v_getSubStmt() { return getSubStmt(); }
public:
DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL),
@@ -544,7 +612,7 @@ public:
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation L) { ColonLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(DefaultLoc, SubStmt->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -553,42 +621,43 @@ public:
static bool classof(const DefaultStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
};
+
+/// LabelStmt - Represents a label, which has a substatement. For example:
+/// foo: return;
+///
class LabelStmt : public Stmt {
- IdentifierInfo *Label;
+ LabelDecl *TheDecl;
Stmt *SubStmt;
SourceLocation IdentLoc;
public:
- LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
- : Stmt(LabelStmtClass), Label(label),
- SubStmt(substmt), IdentLoc(IL) {}
+ LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
+ : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt), IdentLoc(IL) {
+ }
// \brief Build an empty label statement.
explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
SourceLocation getIdentLoc() const { return IdentLoc; }
- IdentifierInfo *getID() const { return Label; }
- void setID(IdentifierInfo *II) { Label = II; }
+ LabelDecl *getDecl() const { return TheDecl; }
+ void setDecl(LabelDecl *D) { TheDecl = D; }
const char *getName() const;
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
void setIdentLoc(SourceLocation L) { IdentLoc = L; }
void setSubStmt(Stmt *SS) { SubStmt = SS; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(IdentLoc, SubStmt->getLocEnd());
}
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == LabelStmtClass;
}
static bool classof(const LabelStmt *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
};
@@ -635,22 +704,23 @@ public:
SourceLocation getElseLoc() const { return ElseLoc; }
void setElseLoc(SourceLocation L) { ElseLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (SubExprs[ELSE])
return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
else
return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd());
}
+ // Iterators over subexpressions. The iterators will include iterating
+ // over the initialization expression referenced by the condition variable.
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == IfStmtClass;
}
static bool classof(const IfStmt *) { return true; }
-
- // Iterators over subexpressions. The iterators will include iterating
- // over the initialization expression referenced by the condition variable.
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
};
/// SwitchStmt - This represents a 'switch' stmt.
@@ -662,6 +732,11 @@ class SwitchStmt : public Stmt {
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
+ /// If the SwitchStmt is a switch on an enum value, this records whether
+ /// all the enum values were covered by CaseStmts. This value is meant to
+ /// be a hint for possible clients.
+ unsigned AllEnumCasesCovered : 1;
+
public:
SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
@@ -705,21 +780,34 @@ public:
}
void addSwitchCase(SwitchCase *SC) {
assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
- SC->Retain();
SC->setNextSwitchCase(FirstCase);
FirstCase = SC;
}
- virtual SourceRange getSourceRange() const {
+
+ /// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
+ /// switch over an enum value then all cases have been explicitly covered.
+ void setAllEnumCasesCovered() {
+ AllEnumCasesCovered = 1;
+ }
+
+ /// Returns true if the SwitchStmt is a switch of an enum value and all cases
+ /// have been explicitly covered.
+ bool isAllEnumCasesCovered() const {
+ return (bool) AllEnumCasesCovered;
+ }
+
+ SourceRange getSourceRange() const {
return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
}
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == SwitchStmtClass;
}
static bool classof(const SwitchStmt *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
};
@@ -757,7 +845,7 @@ public:
SourceLocation getWhileLoc() const { return WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -766,14 +854,15 @@ public:
static bool classof(const WhileStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
/// DoStmt - This represents a 'do/while' stmt.
///
class DoStmt : public Stmt {
- enum { COND, BODY, END_EXPR };
+ enum { BODY, COND, END_EXPR };
Stmt* SubExprs[END_EXPR];
SourceLocation DoLoc;
SourceLocation WhileLoc;
@@ -805,7 +894,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(DoLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
@@ -814,8 +903,9 @@ public:
static bool classof(const DoStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
@@ -870,7 +960,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -879,32 +969,33 @@ public:
static bool classof(const ForStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
};
/// GotoStmt - This represents a direct goto.
///
class GotoStmt : public Stmt {
- LabelStmt *Label;
+ LabelDecl *Label;
SourceLocation GotoLoc;
SourceLocation LabelLoc;
public:
- GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
+ GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL)
: Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
/// \brief Build an empty goto statement.
explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
- LabelStmt *getLabel() const { return Label; }
- void setLabel(LabelStmt *S) { Label = S; }
+ LabelDecl *getLabel() const { return Label; }
+ void setLabel(LabelDecl *D) { Label = D; }
SourceLocation getGotoLoc() const { return GotoLoc; }
void setGotoLoc(SourceLocation L) { GotoLoc = L; }
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(GotoLoc, LabelLoc);
}
static bool classof(const Stmt *T) {
@@ -913,8 +1004,7 @@ public:
static bool classof(const GotoStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// IndirectGotoStmt - This represents an indirect goto.
@@ -938,11 +1028,18 @@ public:
void setStarLoc(SourceLocation L) { StarLoc = L; }
SourceLocation getStarLoc() const { return StarLoc; }
- Expr *getTarget();
- const Expr *getTarget() const;
+ Expr *getTarget() { return reinterpret_cast<Expr*>(Target); }
+ const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);}
void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
- virtual SourceRange getSourceRange() const {
+ /// getConstantTarget - Returns the fixed target of this indirect
+ /// goto, if one exists.
+ LabelDecl *getConstantTarget();
+ const LabelDecl *getConstantTarget() const {
+ return const_cast<IndirectGotoStmt*>(this)->getConstantTarget();
+ }
+
+ SourceRange getSourceRange() const {
return SourceRange(GotoLoc, Target->getLocEnd());
}
@@ -952,8 +1049,7 @@ public:
static bool classof(const IndirectGotoStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Target, &Target+1); }
};
@@ -970,7 +1066,7 @@ public:
SourceLocation getContinueLoc() const { return ContinueLoc; }
void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(ContinueLoc);
}
@@ -980,8 +1076,7 @@ public:
static bool classof(const ContinueStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
/// BreakStmt - This represents a break.
@@ -997,7 +1092,7 @@ public:
SourceLocation getBreakLoc() const { return BreakLoc; }
void setBreakLoc(SourceLocation L) { BreakLoc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
+ SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == BreakStmtClass;
@@ -1005,8 +1100,7 @@ public:
static bool classof(const BreakStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(); }
};
@@ -1050,7 +1144,7 @@ public:
const VarDecl *getNRVOCandidate() const { return NRVOCandidate; }
void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; }
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == ReturnStmtClass;
@@ -1058,8 +1152,10 @@ public:
static bool classof(const ReturnStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
+ return child_range();
+ }
};
/// AsmStmt - This represents a GNU inline-assembly statement extension.
@@ -1257,7 +1353,7 @@ public:
StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AsmLoc, RParenLoc);
}
@@ -1304,10 +1400,9 @@ public:
return &Exprs[0] + NumOutputs;
}
- // Child iterators
-
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs);
+ }
};
} // end namespace clang
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 0508f35e48e8..f08815fd562d 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -37,7 +37,7 @@ public:
CXXCatchStmt(EmptyShell Empty)
: Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
}
@@ -51,8 +51,7 @@ public:
}
static bool classof(const CXXCatchStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); }
friend class ASTStmtReader;
};
@@ -84,7 +83,7 @@ public:
static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
unsigned numHandlers);
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(getTryLoc(), getEndLoc());
}
@@ -113,8 +112,9 @@ public:
}
static bool classof(const CXXTryStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
+ }
friend class ASTStmtReader;
};
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index 4da2e3474b1c..851c001adc54 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -1,4 +1,4 @@
-//===--- StmtIterator.h - Iterators for Statements ------------------------===//
+//===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstddef>
#include <iterator>
@@ -51,11 +51,11 @@ protected:
return (RawVAPtr & Flags) == 0;
}
- VariableArrayType* getVAPtr() const {
- return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
+ const VariableArrayType *getVAPtr() const {
+ return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
}
- void setVAPtr(VariableArrayType* P) {
+ void setVAPtr(const VariableArrayType *P) {
assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
@@ -68,7 +68,7 @@ protected:
StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
StmtIteratorBase(Decl *d, Stmt **s);
- StmtIteratorBase(VariableArrayType *t);
+ StmtIteratorBase(const VariableArrayType *t);
StmtIteratorBase(Decl **dgi, Decl **dge);
StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
};
@@ -86,7 +86,7 @@ public:
StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
- StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
+ StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
DERIVED& operator++() {
if (inDecl() || inDeclGroup()) {
@@ -130,7 +130,7 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
StmtIterator(Decl** dgi, Decl** dge)
: StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
- StmtIterator(VariableArrayType* t)
+ StmtIterator(const VariableArrayType *t)
: StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
StmtIterator(Decl* D, Stmt **s = 0)
@@ -146,6 +146,86 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
+/// A range of statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (StmtRange range = stmt->children(); range; ++range)
+struct StmtRange : std::pair<StmtIterator,StmtIterator> {
+ StmtRange() {}
+ StmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<StmtIterator,StmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ Stmt *operator->() const { return first.operator->(); }
+ Stmt *&operator*() const { return first.operator*(); }
+
+ StmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
+
+ StmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ StmtRange copy = *this;
+ ++first;
+ return copy;
+ }
+
+ friend const StmtIterator &begin(const StmtRange &range) {
+ return range.first;
+ }
+ friend const StmtIterator &end(const StmtRange &range) {
+ return range.second;
+ }
+};
+
+/// A range of const statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (ConstStmtRange range = stmt->children(); range; ++range)
+struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
+ ConstStmtRange() {}
+ ConstStmtRange(const ConstStmtIterator &begin,
+ const ConstStmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+ ConstStmtRange(const StmtRange &range)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
+ {}
+ ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ const Stmt *operator->() const { return first.operator->(); }
+ const Stmt *operator*() const { return first.operator*(); }
+
+ ConstStmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
+
+ ConstStmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ ConstStmtRange copy = *this;
+ ++first;
+ return copy;
+ }
+
+ friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
+ return range.first;
+ }
+ friend const ConstStmtIterator &end(const ConstStmtRange &range) {
+ return range.second;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index 269aa4c6dab2..1800a71f9154 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/include/clang/AST/StmtObjC.h
@@ -55,7 +55,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -64,8 +64,9 @@ public:
static bool classof(const ObjCForCollectionStmt *) { return true; }
// Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
};
/// ObjCAtCatchStmt - This represents objective-c's @catch statement.
@@ -102,7 +103,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtCatchLoc, Body->getLocEnd());
}
@@ -113,8 +114,7 @@ public:
}
static bool classof(const ObjCAtCatchStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Body, &Body + 1); }
};
/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
@@ -133,7 +133,7 @@ public:
Stmt *getFinallyBody() { return AtFinallyStmt; }
void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd());
}
@@ -145,8 +145,9 @@ public:
}
static bool classof(const ObjCAtFinallyStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&AtFinallyStmt, &AtFinallyStmt+1);
+ }
};
/// ObjCAtTryStmt - This represent objective-c's over-all
@@ -239,15 +240,17 @@ public:
getStmts()[1 + NumCatchStmts] = S;
}
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtTryStmtClass;
}
static bool classof(const ObjCAtTryStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(getStmts(),
+ getStmts() + 1 + NumCatchStmts + HasFinally);
+ }
};
/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement.
@@ -291,7 +294,7 @@ public:
}
void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd());
}
@@ -300,8 +303,9 @@ public:
}
static bool classof(const ObjCAtSynchronizedStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() {
+ return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR);
+ }
};
/// ObjCAtThrowStmt - This represents objective-c's @throw statement.
@@ -323,7 +327,7 @@ public:
SourceLocation getThrowLoc() { return AtThrowLoc; }
void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
- virtual SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const {
if (Throw)
return SourceRange(AtThrowLoc, Throw->getLocEnd());
else
@@ -335,8 +339,7 @@ public:
}
static bool classof(const ObjCAtThrowStmt *) { return true; }
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ child_range children() { return child_range(&Throw, &Throw+1); }
};
} // end namespace clang
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 7d5123fb0449..a4e074e083f6 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -23,6 +23,7 @@
namespace llvm {
class FoldingSetNodeID;
+ class raw_ostream;
}
namespace clang {
@@ -30,26 +31,14 @@ namespace clang {
class Decl;
class DiagnosticBuilder;
class Expr;
+struct PrintingPolicy;
class TypeSourceInfo;
/// \brief Represents a template argument within a class template
/// specialization.
class TemplateArgument {
- union {
- uintptr_t TypeOrValue;
- struct {
- char Value[sizeof(llvm::APSInt)];
- void *Type;
- } Integer;
- struct {
- TemplateArgument *Args;
- unsigned NumArgs;
- bool CopyArgs;
- } Args;
- };
-
public:
- /// \brief The type of template argument we're storing.
+ /// \brief The kind of template argument we're storing.
enum ArgKind {
/// \brief Represents an empty template argument, e.g., one that has not
/// been deduced.
@@ -66,16 +55,42 @@ public:
/// The template argument is a template name that was provided for a
/// template template parameter.
Template,
+ /// The template argument is a pack expansion of a template name that was
+ /// provided for a template template parameter.
+ TemplateExpansion,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
Expression,
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
Pack
- } Kind;
+ };
+
+private:
+ /// \brief The kind of template argument we're storing.
+ unsigned Kind;
+ union {
+ uintptr_t TypeOrValue;
+ struct {
+ char Value[sizeof(llvm::APSInt)];
+ void *Type;
+ } Integer;
+ struct {
+ const TemplateArgument *Args;
+ unsigned NumArgs;
+ } Args;
+ struct {
+ void *Name;
+ unsigned NumExpansions;
+ } TemplateArg;
+ };
+
+ TemplateArgument(TemplateName, bool); // DO NOT USE
+
+public:
/// \brief Construct an empty, invalid template argument.
- TemplateArgument() : TypeOrValue(0), Kind(Null) { }
+ TemplateArgument() : Kind(Null), TypeOrValue(0) { }
/// \brief Construct a template type argument.
TemplateArgument(QualType T) : Kind(Type) {
@@ -92,6 +107,8 @@ public:
/// \brief Construct an integral constant template argument.
TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
+ // FIXME: Large integral values will get leaked. Do something
+ // similar to what we did with IntegerLiteral.
new (Integer.Value) llvm::APSInt(Value);
Integer.Type = Type.getAsOpaquePtr();
}
@@ -102,10 +119,35 @@ public:
/// parameters. However, the template name could be a dependent template
/// name that ends up being instantiated to a function template whose address
/// is taken.
- TemplateArgument(TemplateName Name) : Kind(Template) {
- TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+ ///
+ /// \param Name The template name.
+ TemplateArgument(TemplateName Name) : Kind(Template)
+ {
+ TemplateArg.Name = Name.getAsVoidPointer();
+ TemplateArg.NumExpansions = 0;
}
-
+
+ /// \brief Construct a template argument that is a template pack expansion.
+ ///
+ /// This form of template argument is generally used for template template
+ /// parameters. However, the template name could be a dependent template
+ /// name that ends up being instantiated to a function template whose address
+ /// is taken.
+ ///
+ /// \param Name The template name.
+ ///
+ /// \param NumExpansions The number of expansions that will be generated by
+ /// instantiating
+ TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
+ : Kind(TemplateExpansion)
+ {
+ TemplateArg.Name = Name.getAsVoidPointer();
+ if (NumExpansions)
+ TemplateArg.NumExpansions = *NumExpansions + 1;
+ else
+ TemplateArg.NumExpansions = 0;
+ }
+
/// \brief Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
@@ -115,46 +157,59 @@ public:
TypeOrValue = reinterpret_cast<uintptr_t>(E);
}
+ /// \brief Construct a template argument that is a template argument pack.
+ ///
+ /// We assume that storage for the template arguments provided
+ /// outlives the TemplateArgument itself.
+ TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
+ this->Args.Args = Args;
+ this->Args.NumArgs = NumArgs;
+ }
+
/// \brief Copy constructor for a template argument.
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
+ // FIXME: Large integral values will get leaked. Do something
+ // similar to what we did with IntegerLiteral.
if (Kind == Integral) {
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
Integer.Type = Other.Integer.Type;
} else if (Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
- Args.Args = new TemplateArgument[Args.NumArgs];
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I] = Other.Args.Args[I];
- }
- else
+ Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
+ } else
TypeOrValue = Other.TypeOrValue;
}
TemplateArgument& operator=(const TemplateArgument& Other) {
- // FIXME: Does not provide the strong guarantee for exception
- // safety.
using llvm::APSInt;
- // FIXME: Handle Packs
- assert(Kind != Pack && "FIXME: Handle packs");
- assert(Other.Kind != Pack && "FIXME: Handle packs");
-
if (Kind == Other.Kind && Kind == Integral) {
// Copy integral values.
*this->getAsIntegral() = *Other.getAsIntegral();
Integer.Type = Other.Integer.Type;
- } else {
- // Destroy the current integral value, if that's what we're holding.
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
+ return *this;
+ }
+
+ // Destroy the current integral value, if that's what we're holding.
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
- Kind = Other.Kind;
+ Kind = Other.Kind;
- if (Other.Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else
- TypeOrValue = Other.TypeOrValue;
+ if (Other.Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else if (Other.Kind == Pack) {
+ Args.NumArgs = Other.Args.NumArgs;
+ Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
+ } else {
+ TypeOrValue = Other.TypeOrValue;
}
return *this;
@@ -165,16 +220,31 @@ public:
if (Kind == Integral)
getAsIntegral()->~APSInt();
- else if (Kind == Pack && Args.CopyArgs)
- delete[] Args.Args;
}
+ /// \brief Create a new template argument pack by copying the given set of
+ /// template arguments.
+ static TemplateArgument CreatePackCopy(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
/// \brief Return the kind of stored template argument.
- ArgKind getKind() const { return Kind; }
+ ArgKind getKind() const { return (ArgKind)Kind; }
/// \brief Determine whether this template argument has no value.
bool isNull() const { return Kind == Null; }
+ /// \brief Whether this template argument is dependent on a template
+ /// parameter.
+ bool isDependent() const;
+
+ /// \brief Whether this template argument contains an unexpanded
+ /// parameter pack.
+ bool containsUnexpandedParameterPack() const;
+
+ /// \brief Determine whether this template argument is a pack expansion.
+ bool isPackExpansion() const;
+
/// \brief Retrieve the template argument as a type.
QualType getAsType() const {
if (Kind != Type)
@@ -195,9 +265,21 @@ public:
if (Kind != Template)
return TemplateName();
- return TemplateName::getFromVoidPointer(
- reinterpret_cast<void *> (TypeOrValue));
+ 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();
+
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
+
+ /// \brief Retrieve the number of expansions that a template template argument
+ /// expansion will produce, if known.
+ llvm::Optional<unsigned> getNumTemplateExpansions() const;
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
@@ -260,11 +342,17 @@ public:
/// same.
bool structurallyEquals(const TemplateArgument &Other) const;
- /// \brief Construct a template argument pack.
- void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+ /// \brief When the template argument is a pack expansion, returns
+ /// the pattern of the pack expansion.
+ ///
+ /// \param Ellipsis Will be set to the location of the ellipsis.
+ TemplateArgument getPackExpansionPattern() const;
+ /// \brief Print this template argument to the given output stream.
+ void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
+
/// \brief Used to insert TemplateArguments into FoldingSets.
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
};
/// Location information for a TemplateArgument.
@@ -276,95 +364,48 @@ private:
struct {
unsigned QualifierRange[2];
unsigned TemplateNameLoc;
+ unsigned EllipsisLoc;
} Template;
};
-#ifndef NDEBUG
- enum Kind {
- K_None,
- K_TypeSourceInfo,
- K_Expression,
- K_Template
- } Kind;
-#endif
-
public:
- TemplateArgumentLocInfo()
- : Expression(0)
-#ifndef NDEBUG
- , Kind(K_None)
-#endif
- {}
+ TemplateArgumentLocInfo();
- TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
- : Declarator(TInfo)
-#ifndef NDEBUG
- , Kind(K_TypeSourceInfo)
-#endif
- {}
+ TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
- TemplateArgumentLocInfo(Expr *E)
- : Expression(E)
-#ifndef NDEBUG
- , Kind(K_Expression)
-#endif
- {}
+ TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
TemplateArgumentLocInfo(SourceRange QualifierRange,
- SourceLocation TemplateNameLoc)
-#ifndef NDEBUG
- : Kind(K_Template)
-#endif
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc)
{
Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+ Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
}
TypeSourceInfo *getAsTypeSourceInfo() const {
- assert(Kind == K_TypeSourceInfo);
return Declarator;
}
Expr *getAsExpr() const {
- assert(Kind == K_Expression);
return Expression;
}
SourceRange getTemplateQualifierRange() const {
- assert(Kind == K_Template);
return SourceRange(
SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
}
SourceLocation getTemplateNameLoc() const {
- assert(Kind == K_Template);
return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
}
-#ifndef NDEBUG
- void validateForArgument(const TemplateArgument &Arg) {
- switch (Arg.getKind()) {
- case TemplateArgument::Type:
- assert(Kind == K_TypeSourceInfo);
- break;
- case TemplateArgument::Expression:
- case TemplateArgument::Declaration:
- assert(Kind == K_Expression);
- break;
- case TemplateArgument::Template:
- assert(Kind == K_Template);
- break;
- case TemplateArgument::Integral:
- case TemplateArgument::Pack:
- assert(Kind == K_None);
- break;
- case TemplateArgument::Null:
- llvm_unreachable("source info for null template argument?");
- }
+ SourceLocation getTemplateEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
}
-#endif
};
/// Location wrapper for a TemplateArgument. TemplateArgument is to
@@ -393,14 +434,18 @@ public:
TemplateArgumentLoc(const TemplateArgument &Argument,
SourceRange QualifierRange,
- SourceLocation TemplateNameLoc)
- : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
- assert(Argument.getKind() == TemplateArgument::Template);
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc = SourceLocation())
+ : Argument(Argument),
+ LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
}
/// \brief - Fetches the primary location of the argument.
SourceLocation getLocation() const {
- if (Argument.getKind() == TemplateArgument::Template)
+ if (Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion)
return getTemplateNameLoc();
return getSourceRange().getBegin();
@@ -433,14 +478,32 @@ public:
}
SourceRange getTemplateQualifierRange() const {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateQualifierRange();
}
SourceLocation getTemplateNameLoc() const {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateNameLoc();
}
+
+ SourceLocation getTemplateEllipsisLoc() const {
+ assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
+ return LocInfo.getTemplateEllipsisLoc();
+ }
+
+ /// \brief When the template argument is a pack expansion, returns
+ /// the pattern of the pack expansion.
+ ///
+ /// \param Ellipsis Will be set to the location of the ellipsis.
+ ///
+ /// \param NumExpansions Will be set to the number of expansions that will
+ /// be generated from this pack expansion, if known a priori.
+ TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
+ llvm::Optional<unsigned> &NumExpansions,
+ ASTContext &Context) const;
};
/// A convenient class for passing around template argument
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index ddfac712734b..1721973e8229 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -23,43 +23,119 @@ namespace llvm {
}
namespace clang {
-
+
+class ASTContext;
class DependentTemplateName;
class DiagnosticBuilder;
class IdentifierInfo;
class NestedNameSpecifier;
+class OverloadedTemplateStorage;
struct PrintingPolicy;
class QualifiedTemplateName;
class NamedDecl;
+class SubstTemplateTemplateParmPackStorage;
+class TemplateArgument;
class TemplateDecl;
-
-/// \brief A structure for storing the information associated with an
-/// overloaded template name.
-class OverloadedTemplateStorage {
+class TemplateTemplateParmDecl;
+
+/// \brief Implementation class used to describe either a set of overloaded
+/// template names or an already-substituted template template parameter pack.
+class UncommonTemplateNameStorage {
+protected:
union {
- unsigned Size;
- NamedDecl *Storage[1];
+ struct {
+ /// \brief If true, this is an OverloadedTemplateStorage instance;
+ /// otherwise, it's a SubstTemplateTemplateParmPackStorage instance.
+ unsigned IsOverloadedStorage : 1;
+
+ /// \brief The number of stored templates or template arguments,
+ /// depending on which subclass we have.
+ unsigned Size : 31;
+ } Bits;
+
+ void *PointerAlignment;
};
-
+
+ UncommonTemplateNameStorage(unsigned Size, bool OverloadedStorage) {
+ Bits.IsOverloadedStorage = OverloadedStorage;
+ Bits.Size = Size;
+ }
+
+public:
+ unsigned size() const { return Bits.Size; }
+
+ OverloadedTemplateStorage *getAsOverloadedStorage() {
+ return Bits.IsOverloadedStorage
+ ? reinterpret_cast<OverloadedTemplateStorage *>(this)
+ : 0;
+ }
+
+ SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
+ return Bits.IsOverloadedStorage
+ ? 0
+ : reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) ;
+ }
+};
+
+/// \brief A structure for storing the information associated with an
+/// overloaded template name.
+class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext;
- OverloadedTemplateStorage(unsigned Size) : Size(Size) {}
+ OverloadedTemplateStorage(unsigned Size)
+ : UncommonTemplateNameStorage(Size, true) { }
NamedDecl **getStorage() {
- return &Storage[1];
+ return reinterpret_cast<NamedDecl **>(this + 1);
}
NamedDecl * const *getStorage() const {
- return &Storage[1];
+ return reinterpret_cast<NamedDecl *const *>(this + 1);
}
public:
typedef NamedDecl *const *iterator;
- unsigned size() const { return Size; }
-
iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); }
};
+
+
+/// \brief A structure for storing an already-substituted template template
+/// parameter pack.
+///
+/// This kind of template names occurs when the parameter pack has been
+/// provided with a template template argument pack in a context where its
+/// enclosing pack expansion could not be fully expanded.
+class SubstTemplateTemplateParmPackStorage
+ : public UncommonTemplateNameStorage, public llvm::FoldingSetNode
+{
+ ASTContext &Context;
+ TemplateTemplateParmDecl *Parameter;
+ const TemplateArgument *Arguments;
+
+public:
+ SubstTemplateTemplateParmPackStorage(ASTContext &Context,
+ TemplateTemplateParmDecl *Parameter,
+ unsigned Size,
+ const TemplateArgument *Arguments)
+ : UncommonTemplateNameStorage(Size, false), Context(Context),
+ Parameter(Parameter), Arguments(Arguments) { }
+
+ /// \brief Retrieve the template template parameter pack being substituted.
+ TemplateTemplateParmDecl *getParameterPack() const {
+ return Parameter;
+ }
+
+ /// \brief Retrieve the template template argument pack with which this
+ /// parameter was substituted.
+ TemplateArgument getArgumentPack() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+
+ static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ TemplateTemplateParmDecl *Parameter,
+ const TemplateArgument &ArgPack);
+};
/// \brief Represents a C++ template name within the type system.
///
@@ -90,7 +166,7 @@ public:
/// only be understood in the context of
class TemplateName {
typedef llvm::PointerUnion4<TemplateDecl *,
- OverloadedTemplateStorage *,
+ UncommonTemplateNameStorage *,
QualifiedTemplateName *,
DependentTemplateName *> StorageType;
@@ -103,16 +179,28 @@ class TemplateName {
public:
// \brief Kind of name that is actually stored.
enum NameKind {
+ /// \brief A single template declaration.
Template,
+ /// \brief A set of overloaded template declarations.
OverloadedTemplate,
+ /// \brief A qualified template name, where the qualification is kept
+ /// to describe the source code as written.
QualifiedTemplate,
- DependentTemplate
+ /// \brief A dependent template name that has not been resolved to a
+ /// template (or set of templates).
+ DependentTemplate,
+ /// \brief A template template parameter pack that has been substituted for
+ /// a template template argument pack, but has not yet been expanded into
+ /// individual arguments.
+ SubstTemplateTemplateParmPack
};
TemplateName() : Storage() { }
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
explicit TemplateName(OverloadedTemplateStorage *Storage)
: Storage(Storage) { }
+ explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
+ : Storage(Storage) { }
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
@@ -122,7 +210,7 @@ public:
// \brief Get the kind of name that is actually stored.
NameKind getKind() const;
- /// \brief Retrieve the the underlying template declaration that
+ /// \brief Retrieve the underlying template declaration that
/// this template name refers to, if known.
///
/// \returns The template declaration that this template name refers
@@ -131,7 +219,7 @@ public:
/// set of function templates, returns NULL.
TemplateDecl *getAsTemplateDecl() const;
- /// \brief Retrieve the the underlying, overloaded function template
+ /// \brief Retrieve the underlying, overloaded function template
// declarations that this template name refers to, if known.
///
/// \returns The set of overloaded function templates that this template
@@ -139,7 +227,25 @@ public:
/// specific set of function templates because it is a dependent name or
/// refers to a single template, returns NULL.
OverloadedTemplateStorage *getAsOverloadedTemplate() const {
- return Storage.dyn_cast<OverloadedTemplateStorage *>();
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsOverloadedStorage();
+
+ return 0;
+ }
+
+ /// \brief Retrieve the substituted template template parameter pack, if
+ /// known.
+ ///
+ /// \returns The storage for the substituted template template parameter pack,
+ /// if known. Otherwise, returns NULL.
+ SubstTemplateTemplateParmPackStorage *
+ getAsSubstTemplateTemplateParmPack() const {
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsSubstTemplateTemplateParmPack();
+
+ return 0;
}
/// \brief Retrieve the underlying qualified template name
@@ -157,6 +263,10 @@ public:
/// \brief Determines whether this is a dependent template name.
bool isDependent() const;
+ /// \brief Determines whether this template name contains an
+ /// unexpanded parameter pack (for C++0x variadic templates).
+ bool containsUnexpandedParameterPack() const;
+
/// \brief Print the template name.
///
/// \param OS the output stream to which the template name will be
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 92e62a58d42c..9b177cceed96 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -18,12 +18,14 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/Visibility.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/type_traits.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
@@ -34,7 +36,7 @@ using llvm::dyn_cast;
using llvm::dyn_cast_or_null;
namespace clang {
enum {
- TypeAlignmentInBits = 3,
+ TypeAlignmentInBits = 4,
TypeAlignment = 1 << TypeAlignmentInBits
};
class Type;
@@ -91,8 +93,9 @@ namespace clang {
class TemplateArgument;
class TemplateArgumentLoc;
class TemplateArgumentListInfo;
- class Type;
class ElaboratedType;
+ class ExtQuals;
+ class ExtQualsTypeCommonBase;
struct PrintingPolicy;
template <typename> class CanQual;
@@ -128,7 +131,7 @@ public:
MaxAddressSpace = 0xffffffu,
/// The width of the "fast" qualifier mask.
- FastWidth = 2,
+ FastWidth = 3,
/// The fast qualifier mask.
FastMask = (1 << FastWidth) - 1
@@ -271,6 +274,25 @@ public:
}
}
+ /// \brief Add the qualifiers from the given set to this set, given that
+ /// they don't conflict.
+ void addConsistentQualifiers(Qualifiers qs) {
+ assert(getAddressSpace() == qs.getAddressSpace() ||
+ !hasAddressSpace() || !qs.hasAddressSpace());
+ assert(getObjCGCAttr() == qs.getObjCGCAttr() ||
+ !hasObjCGCAttr() || !qs.hasObjCGCAttr());
+ Mask |= qs.Mask;
+ }
+
+ /// \brief Determines if these qualifiers compatibly include another set.
+ /// Generally this answers the question of whether an object with the other
+ /// qualifiers can be safely used as an object with these qualifiers.
+ bool compatiblyIncludes(Qualifiers other) const {
+ // Non-CVR qualifiers must match exactly. CVR qualifiers may subset.
+ return ((Mask & ~CVRMask) == (other.Mask & ~CVRMask)) &&
+ (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
+ }
+
bool isSupersetOf(Qualifiers Other) const;
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
@@ -325,85 +347,6 @@ private:
static const uint32_t AddressSpaceShift = 5;
};
-
-/// ExtQuals - We can encode up to three bits in the low bits of a
-/// type pointer, but there are many more type qualifiers that we want
-/// to be able to apply to an arbitrary type. Therefore we have this
-/// struct, intended to be heap-allocated and used by QualType to
-/// store qualifiers.
-///
-/// The current design tags the 'const' and 'restrict' qualifiers in
-/// two low bits on the QualType pointer; a third bit records whether
-/// the pointer is an ExtQuals node. 'const' was chosen because it is
-/// orders of magnitude more common than the other two qualifiers, in
-/// both library and user code. It's relatively rare to see
-/// 'restrict' in user code, but many standard C headers are saturated
-/// with 'restrict' declarations, so that representing them efficiently
-/// is a critical goal of this representation.
-class ExtQuals : public llvm::FoldingSetNode {
- // NOTE: changing the fast qualifiers should be straightforward as
- // long as you don't make 'const' non-fast.
- // 1. Qualifiers:
- // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ).
- // Fast qualifiers must occupy the low-order bits.
- // b) Update Qualifiers::FastWidth and FastMask.
- // 2. QualType:
- // a) Update is{Volatile,Restrict}Qualified(), defined inline.
- // b) Update remove{Volatile,Restrict}, defined near the end of
- // this header.
- // 3. ASTContext:
- // a) Update get{Volatile,Restrict}Type.
-
- /// Context - the context to which this set belongs. We save this
- /// here so that QualifierCollector can use it to reapply extended
- /// qualifiers to an arbitrary type without requiring a context to
- /// be pushed through every single API dealing with qualifiers.
- ASTContext& Context;
-
- /// BaseType - the underlying type that this qualifies
- const Type *BaseType;
-
- /// Quals - the immutable set of qualifiers applied by this
- /// node; always contains extended qualifiers.
- Qualifiers Quals;
-
-public:
- ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals)
- : Context(Context), BaseType(Base), Quals(Quals)
- {
- assert(Quals.hasNonFastQualifiers()
- && "ExtQuals created with no fast qualifiers");
- assert(!Quals.hasFastQualifiers()
- && "ExtQuals created with fast qualifiers");
- }
-
- Qualifiers getQualifiers() const { return Quals; }
-
- bool hasVolatile() const { return Quals.hasVolatile(); }
-
- bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); }
- Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); }
-
- bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
- unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
-
- const Type *getBaseType() const { return BaseType; }
-
- ASTContext &getContext() const { return Context; }
-
-public:
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, getBaseType(), Quals);
- }
- static void Profile(llvm::FoldingSetNodeID &ID,
- const Type *BaseType,
- Qualifiers Quals) {
- assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!");
- ID.AddPointer(BaseType);
- Quals.Profile(ID);
- }
-};
-
/// CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
CC_Default,
@@ -414,6 +357,7 @@ enum CallingConv {
CC_X86Pascal // __attribute__((pascal))
};
+typedef std::pair<const Type*, Qualifiers> SplitQualType;
/// QualType - For efficiency, we don't store CV-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
@@ -440,8 +384,14 @@ class QualType {
return Value.getPointer().get<const Type*>();
}
- QualType getUnqualifiedTypeSlow() const;
-
+ const ExtQualsTypeCommonBase *getCommonPtr() const {
+ assert(!isNull() && "Cannot retrieve a NULL type pointer");
+ uintptr_t CommonPtrVal
+ = reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
+ CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1);
+ return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal);
+ }
+
friend class QualifierCollector;
public:
QualType() {}
@@ -457,24 +407,29 @@ public:
/// Retrieves a pointer to the underlying (unqualified) type.
/// This should really return a const Type, but it's not worth
/// changing all the users right now.
- Type *getTypePtr() const {
- if (hasLocalNonFastQualifiers())
- return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
- return const_cast<Type*>(getTypePtrUnsafe());
- }
+ ///
+ /// This function requires that the type not be NULL. If the type might be
+ /// NULL, use the (slightly less efficient) \c getTypePtrOrNull().
+ const Type *getTypePtr() const;
+
+ const Type *getTypePtrOrNull() const;
+
+ /// Divides a QualType into its unqualified type and a set of local
+ /// qualifiers.
+ SplitQualType split() const;
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
- static QualType getFromOpaquePtr(void *Ptr) {
+ static QualType getFromOpaquePtr(const void *Ptr) {
QualType T;
- T.Value.setFromOpaqueValue(Ptr);
+ T.Value.setFromOpaqueValue(const_cast<void*>(Ptr));
return T;
}
- Type &operator*() const {
+ const Type &operator*() const {
return *getTypePtr();
}
- Type *operator->() const {
+ const Type *operator->() const {
return getTypePtr();
}
@@ -510,7 +465,7 @@ public:
/// "volatile" qualifier set, without looking through typedefs that may have
/// added "volatile" at a different level.
bool isLocalVolatileQualified() const {
- return (hasLocalNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
+ return (getLocalFastQualifiers() & Qualifiers::Volatile);
}
/// \brief Determine whether this type is volatile-qualified.
@@ -536,13 +491,7 @@ public:
/// \brief Retrieve the set of qualifiers local to this particular QualType
/// instance, not including any qualifiers acquired through typedefs or
/// other sugar.
- Qualifiers getLocalQualifiers() const {
- Qualifiers Quals;
- if (hasLocalNonFastQualifiers())
- Quals = getExtQualsUnsafe()->getQualifiers();
- Quals.addFastQualifiers(getLocalFastQualifiers());
- return Quals;
- }
+ Qualifiers getLocalQualifiers() const;
/// \brief Retrieve the set of qualifiers applied to this type.
Qualifiers getQualifiers() const;
@@ -551,21 +500,13 @@ public:
/// local to this particular QualType instance, not including any qualifiers
/// acquired through typedefs or other sugar.
unsigned getLocalCVRQualifiers() const {
- unsigned CVR = getLocalFastQualifiers();
- if (isLocalVolatileQualified())
- CVR |= Qualifiers::Volatile;
- return CVR;
+ return getLocalFastQualifiers();
}
/// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
/// applied to this type.
unsigned getCVRQualifiers() const;
- /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
- /// applied to this type, looking through any number of unqualified array
- /// types to their element types' qualifiers.
- unsigned getCVRQualifiersThroughArrayTypes() const;
-
bool isConstant(ASTContext& Ctx) const {
return QualType::isConstant(*this, Ctx);
}
@@ -587,16 +528,13 @@ public:
Value.setInt(Value.getInt() | TQs);
}
- // FIXME: The remove* functions are semantically broken, because they might
- // not remove a qualifier stored on a typedef. Most of the with* functions
- // have the same problem.
- void removeConst();
- void removeVolatile();
- void removeRestrict();
- void removeCVRQualifiers(unsigned Mask);
+ void removeLocalConst();
+ void removeLocalVolatile();
+ void removeLocalRestrict();
+ void removeLocalCVRQualifiers(unsigned Mask);
- void removeFastQualifiers() { Value.setInt(0); }
- void removeFastQualifiers(unsigned Mask) {
+ void removeLocalFastQualifiers() { Value.setInt(0); }
+ void removeLocalFastQualifiers(unsigned Mask) {
assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers");
Value.setInt(Value.getInt() & ~Mask);
}
@@ -611,31 +549,54 @@ public:
// Creates a type with exactly the given fast qualifiers, removing
// any existing fast qualifiers.
- QualType withExactFastQualifiers(unsigned TQs) const {
- return withoutFastQualifiers().withFastQualifiers(TQs);
+ QualType withExactLocalFastQualifiers(unsigned TQs) const {
+ return withoutLocalFastQualifiers().withFastQualifiers(TQs);
}
// Removes fast qualifiers, but leaves any extended qualifiers in place.
- QualType withoutFastQualifiers() const {
+ QualType withoutLocalFastQualifiers() const {
QualType T = *this;
- T.removeFastQualifiers();
+ T.removeLocalFastQualifiers();
return T;
}
+ QualType getCanonicalType() const;
+
/// \brief Return this type with all of the instance-specific qualifiers
/// removed, but without removing any qualifiers that may have been applied
/// through typedefs.
QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); }
- /// \brief Return the unqualified form of the given type, which might be
- /// desugared to eliminate qualifiers introduced via typedefs.
- QualType getUnqualifiedType() const {
- QualType T = getLocalUnqualifiedType();
- if (!T.hasQualifiers())
- return T;
-
- return getUnqualifiedTypeSlow();
- }
+ /// \brief Retrieve the unqualified variant of the given type,
+ /// removing as little sugar as possible.
+ ///
+ /// This routine looks through various kinds of sugar to find the
+ /// least-desugared type that is unqualified. For example, given:
+ ///
+ /// \code
+ /// typedef int Integer;
+ /// typedef const Integer CInteger;
+ /// typedef CInteger DifferenceType;
+ /// \endcode
+ ///
+ /// Executing \c getUnqualifiedType() on the type \c DifferenceType will
+ /// desugar until we hit the type \c Integer, which has no qualifiers on it.
+ ///
+ /// The resulting type might still be qualified if it's an array
+ /// type. To strip qualifiers even from within an array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline QualType getUnqualifiedType() const;
+
+ /// getSplitUnqualifiedType - Retrieve the unqualified variant of the
+ /// given type, removing as little sugar as possible.
+ ///
+ /// Like getUnqualifiedType(), but also returns the set of
+ /// qualifiers that were built up.
+ ///
+ /// The resulting type might still be qualified if it's an array
+ /// type. To strip qualifiers even from within an array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline SplitQualType getSplitUnqualifiedType() const;
bool isMoreQualifiedThan(QualType Other) const;
bool isAtLeastAsQualifiedAs(QualType Other) const;
@@ -659,8 +620,20 @@ public:
/// concrete.
///
/// Qualifiers are left in place.
- QualType getDesugaredType() const {
- return QualType::getDesugaredType(*this);
+ QualType getDesugaredType(const ASTContext &Context) const {
+ return getDesugaredType(*this, Context);
+ }
+
+ SplitQualType getSplitDesugaredType() const {
+ return getSplitDesugaredType(*this);
+ }
+
+ /// IgnoreParens - Returns the specified type after dropping any
+ /// outer-level parentheses.
+ QualType IgnoreParens() const {
+ if (isa<ParenType>(*this))
+ return QualType::IgnoreParens(*this);
+ return *this;
}
/// operator==/!= - Indicate whether the specified types and qualifiers are
@@ -671,7 +644,13 @@ public:
friend bool operator!=(const QualType &LHS, const QualType &RHS) {
return LHS.Value != RHS.Value;
}
- std::string getAsString() const;
+ std::string getAsString() const {
+ return getAsString(split());
+ }
+ static std::string getAsString(SplitQualType split) {
+ return getAsString(split.first, split.second);
+ }
+ static std::string getAsString(const Type *ty, Qualifiers qs);
std::string getAsString(const PrintingPolicy &Policy) const {
std::string S;
@@ -679,7 +658,16 @@ public:
return S;
}
void getAsStringInternal(std::string &Str,
- const PrintingPolicy &Policy) const;
+ const PrintingPolicy &Policy) const {
+ return getAsStringInternal(split(), Str, Policy);
+ }
+ static void getAsStringInternal(SplitQualType split, std::string &out,
+ const PrintingPolicy &policy) {
+ return getAsStringInternal(split.first, split.second, out, policy);
+ }
+ static void getAsStringInternal(const Type *ty, Qualifiers qs,
+ std::string &out,
+ const PrintingPolicy &policy);
void dump(const char *s) const;
void dump() const;
@@ -704,12 +692,29 @@ public:
return getObjCGCAttr() == Qualifiers::Strong;
}
+ enum DestructionKind {
+ DK_none,
+ DK_cxx_destructor
+ };
+
+ /// isDestructedType - nonzero if objects of this type require
+ /// non-trivial work to clean up after. Non-zero because it's
+ /// conceivable that qualifiers (objc_gc(weak)?) could make
+ /// something require destruction.
+ DestructionKind isDestructedType() const {
+ return isDestructedTypeImpl(*this);
+ }
+
private:
// These methods are implemented in a separate translation unit;
// "static"-ize them to avoid creating temporary QualTypes in the
// caller.
static bool isConstant(QualType T, ASTContext& Ctx);
- static QualType getDesugaredType(QualType T);
+ static QualType getDesugaredType(QualType T, const ASTContext &Context);
+ static SplitQualType getSplitDesugaredType(QualType T);
+ static SplitQualType getSplitUnqualifiedTypeImpl(QualType type);
+ static QualType IgnoreParens(QualType T);
+ static DestructionKind isDestructedTypeImpl(QualType type);
};
} // end clang.
@@ -718,7 +723,7 @@ namespace llvm {
/// Implement simplify_type for QualType, so that we can dyn_cast from QualType
/// to a specific Type class.
template<> struct simplify_type<const ::clang::QualType> {
- typedef ::clang::Type* SimpleType;
+ typedef const ::clang::Type *SimpleType;
static SimpleType getSimplifiedValue(const ::clang::QualType &Val) {
return Val.getTypePtr();
}
@@ -744,6 +749,106 @@ public:
namespace clang {
+/// \brief Base class that is common to both the \c ExtQuals and \c Type
+/// classes, which allows \c QualType to access the common fields between the
+/// two.
+///
+class ExtQualsTypeCommonBase {
+ ExtQualsTypeCommonBase(const Type *baseType, QualType canon)
+ : BaseType(baseType), CanonicalType(canon) {}
+
+ /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or
+ /// a self-referential pointer (for \c Type).
+ ///
+ /// This pointer allows an efficient mapping from a QualType to its
+ /// underlying type pointer.
+ const Type *const BaseType;
+
+ /// \brief The canonical type of this type. A QualType.
+ QualType CanonicalType;
+
+ friend class QualType;
+ friend class Type;
+ friend class ExtQuals;
+};
+
+/// ExtQuals - We can encode up to four bits in the low bits of a
+/// type pointer, but there are many more type qualifiers that we want
+/// to be able to apply to an arbitrary type. Therefore we have this
+/// struct, intended to be heap-allocated and used by QualType to
+/// store qualifiers.
+///
+/// The current design tags the 'const', 'restrict', and 'volatile' qualifiers
+/// in three low bits on the QualType pointer; a fourth bit records whether
+/// the pointer is an ExtQuals node. The extended qualifiers (address spaces,
+/// Objective-C GC attributes) are much more rare.
+class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode {
+ // NOTE: changing the fast qualifiers should be straightforward as
+ // long as you don't make 'const' non-fast.
+ // 1. Qualifiers:
+ // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ).
+ // Fast qualifiers must occupy the low-order bits.
+ // b) Update Qualifiers::FastWidth and FastMask.
+ // 2. QualType:
+ // a) Update is{Volatile,Restrict}Qualified(), defined inline.
+ // b) Update remove{Volatile,Restrict}, defined near the end of
+ // this header.
+ // 3. ASTContext:
+ // a) Update get{Volatile,Restrict}Type.
+
+ /// Quals - the immutable set of qualifiers applied by this
+ /// node; always contains extended qualifiers.
+ Qualifiers Quals;
+
+ ExtQuals *this_() { return this; }
+
+public:
+ ExtQuals(const Type *baseType, QualType canon, Qualifiers quals)
+ : ExtQualsTypeCommonBase(baseType,
+ canon.isNull() ? QualType(this_(), 0) : canon),
+ Quals(quals)
+ {
+ assert(Quals.hasNonFastQualifiers()
+ && "ExtQuals created with no fast qualifiers");
+ assert(!Quals.hasFastQualifiers()
+ && "ExtQuals created with fast qualifiers");
+ }
+
+ Qualifiers getQualifiers() const { return Quals; }
+
+ bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); }
+ Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); }
+
+ bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
+ unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+
+ const Type *getBaseType() const { return BaseType; }
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, getBaseType(), Quals);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const Type *BaseType,
+ Qualifiers Quals) {
+ assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!");
+ ID.AddPointer(BaseType);
+ Quals.Profile(ID);
+ }
+};
+
+/// \brief The kind of C++0x ref-qualifier associated with a function type,
+/// which determines whether a member function's "this" object can be an
+/// lvalue, rvalue, or neither.
+enum RefQualifierKind {
+ /// \brief No ref-qualifier was provided.
+ RQ_None = 0,
+ /// \brief An lvalue ref-qualifier was provided (\c &).
+ RQ_LValue,
+ /// \brief An rvalue ref-qualifier was provided (\c &&).
+ RQ_RValue
+};
+
/// Type - This is the base class of the type hierarchy. A central concept
/// with types is that each type always has a canonical type. A canonical type
/// is the type with any typedef names stripped out of it or the types it
@@ -769,7 +874,7 @@ namespace clang {
///
/// Types, once created, are immutable.
///
-class Type {
+class Type : public ExtQualsTypeCommonBase {
public:
enum TypeClass {
#define TYPE(Class, Base) Class,
@@ -783,53 +888,249 @@ private:
Type(const Type&); // DO NOT IMPLEMENT.
void operator=(const Type&); // DO NOT IMPLEMENT.
- QualType CanonicalType;
+ /// Bitfields required by the Type class.
+ class TypeBitfields {
+ friend class Type;
+ template <class T> friend class TypePropertyCache;
- /// TypeClass bitfield - Enum that specifies what subclass this belongs to.
- unsigned TC : 8;
+ /// TypeClass bitfield - Enum that specifies what subclass this belongs to.
+ unsigned TC : 8;
- /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
- /// Note that this should stay at the end of the ivars for Type so that
- /// subclasses can pack their bitfields into the same word.
- bool Dependent : 1;
+ /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
+ /// Note that this should stay at the end of the ivars for Type so that
+ /// subclasses can pack their bitfields into the same word.
+ unsigned Dependent : 1;
- /// \brief Whether the linkage of this type is already known.
- mutable bool LinkageKnown : 1;
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ unsigned VariablyModified : 1;
+
+ /// \brief Whether this type contains an unexpanded parameter pack
+ /// (for C++0x variadic templates).
+ unsigned ContainsUnexpandedParameterPack : 1;
+
+ /// \brief Nonzero if the cache (i.e. the bitfields here starting
+ /// with 'Cache') is valid. If so, then this is a
+ /// LangOptions::VisibilityMode+1.
+ mutable unsigned CacheValidAndVisibility : 2;
+
+ /// \brief Linkage of this type.
+ mutable unsigned CachedLinkage : 2;
+
+ /// \brief Whether this type involves and local or unnamed types.
+ mutable unsigned CachedLocalOrUnnamed : 1;
- /// \brief Linkage of this type.
- mutable unsigned CachedLinkage : 2;
+ /// \brief FromAST - Whether this type comes from an AST file.
+ mutable unsigned FromAST : 1;
+
+ bool isCacheValid() const {
+ return (CacheValidAndVisibility != 0);
+ }
+ Visibility getVisibility() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return static_cast<Visibility>(CacheValidAndVisibility-1);
+ }
+ Linkage getLinkage() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return static_cast<Linkage>(CachedLinkage);
+ }
+ bool hasLocalOrUnnamedType() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return CachedLocalOrUnnamed;
+ }
+ };
+ enum { NumTypeBits = 17 };
+
+protected:
+ // These classes allow subclasses to somewhat cleanly pack bitfields
+ // into Type.
+
+ class ArrayTypeBitfields {
+ friend class ArrayType;
+
+ unsigned : NumTypeBits;
+
+ /// IndexTypeQuals - CVR qualifiers from declarations like
+ /// 'int X[static restrict 4]'. For function parameters only.
+ unsigned IndexTypeQuals : 3;
+
+ /// SizeModifier - storage class qualifiers from declarations like
+ /// 'int X[static restrict 4]'. For function parameters only.
+ /// Actually an ArrayType::ArraySizeModifier.
+ unsigned SizeModifier : 3;
+ };
+
+ class BuiltinTypeBitfields {
+ friend class BuiltinType;
+
+ unsigned : NumTypeBits;
+
+ /// The kind (BuiltinType::Kind) of builtin type this is.
+ unsigned Kind : 8;
+ };
+
+ class FunctionTypeBitfields {
+ friend class FunctionType;
+
+ unsigned : NumTypeBits;
+
+ /// Extra information which affects how the function is called, like
+ /// regparm and the calling convention.
+ unsigned ExtInfo : 8;
+
+ /// Whether the function is variadic. Only used by FunctionProtoType.
+ unsigned Variadic : 1;
+
+ /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
+ /// other bitfields.
+ /// The qualifiers are part of FunctionProtoType because...
+ ///
+ /// C++ 8.3.5p4: The return type, the parameter type list and the
+ /// cv-qualifier-seq, [...], are part of the function type.
+ unsigned TypeQuals : 3;
+
+ /// \brief The ref-qualifier associated with a \c FunctionProtoType.
+ ///
+ /// This is a value of type \c RefQualifierKind.
+ unsigned RefQualifier : 2;
+ };
+
+ class ObjCObjectTypeBitfields {
+ friend class ObjCObjectType;
+
+ unsigned : NumTypeBits;
+
+ /// NumProtocols - The number of protocols stored directly on this
+ /// object type.
+ unsigned NumProtocols : 32 - NumTypeBits;
+ };
+
+ class ReferenceTypeBitfields {
+ friend class ReferenceType;
+
+ unsigned : NumTypeBits;
+
+ /// True if the type was originally spelled with an lvalue sigil.
+ /// This is never true of rvalue references but can also be false
+ /// on lvalue references because of C++0x [dcl.typedef]p9,
+ /// as follows:
+ ///
+ /// typedef int &ref; // lvalue, spelled lvalue
+ /// typedef int &&rvref; // rvalue
+ /// ref &a; // lvalue, inner ref, spelled lvalue
+ /// ref &&a; // lvalue, inner ref
+ /// rvref &a; // lvalue, inner ref, spelled lvalue
+ /// rvref &&a; // rvalue, inner ref
+ unsigned SpelledAsLValue : 1;
+
+ /// True if the inner type is a reference type. This only happens
+ /// in non-canonical forms.
+ unsigned InnerRef : 1;
+ };
+
+ class TypeWithKeywordBitfields {
+ friend class TypeWithKeyword;
+
+ unsigned : NumTypeBits;
+
+ /// An ElaboratedTypeKeyword. 8 bits for efficient access.
+ unsigned Keyword : 8;
+ };
+
+ class VectorTypeBitfields {
+ friend class VectorType;
+
+ unsigned : NumTypeBits;
+
+ /// VecKind - The kind of vector, either a generic vector type or some
+ /// target-specific vector type such as for AltiVec or Neon.
+ unsigned VecKind : 3;
+
+ /// NumElements - The number of elements in the vector.
+ unsigned NumElements : 29 - NumTypeBits;
+ };
+
+ class AttributedTypeBitfields {
+ friend class AttributedType;
- /// \brief FromAST - Whether this type comes from an AST file.
- mutable bool FromAST : 1;
+ unsigned : NumTypeBits;
+ /// AttrKind - an AttributedType::Kind
+ unsigned AttrKind : 32 - NumTypeBits;
+ };
+
+ union {
+ TypeBitfields TypeBits;
+ ArrayTypeBitfields ArrayTypeBits;
+ AttributedTypeBitfields AttributedTypeBits;
+ BuiltinTypeBitfields BuiltinTypeBits;
+ FunctionTypeBitfields FunctionTypeBits;
+ ObjCObjectTypeBitfields ObjCObjectTypeBits;
+ ReferenceTypeBitfields ReferenceTypeBits;
+ TypeWithKeywordBitfields TypeWithKeywordBits;
+ VectorTypeBitfields VectorTypeBits;
+ };
+
+private:
/// \brief Set whether this type comes from an AST file.
void setFromAST(bool V = true) const {
- FromAST = V;
+ TypeBits.FromAST = V;
}
-protected:
- /// \brief Compute the linkage of this type.
- virtual Linkage getLinkageImpl() const;
-
- enum { BitsRemainingInType = 19 };
+ template <class T> friend class TypePropertyCache;
+protected:
// silence VC++ warning C4355: 'this' : used in base member initializer list
Type *this_() { return this; }
- Type(TypeClass tc, QualType Canonical, bool dependent)
- : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
- TC(tc), Dependent(dependent), LinkageKnown(false),
- CachedLinkage(NoLinkage), FromAST(false) {}
- virtual ~Type();
+ Type(TypeClass tc, QualType canon, bool Dependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : ExtQualsTypeCommonBase(this,
+ canon.isNull() ? QualType(this_(), 0) : canon) {
+ TypeBits.TC = tc;
+ TypeBits.Dependent = Dependent;
+ TypeBits.VariablyModified = VariablyModified;
+ TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ TypeBits.CacheValidAndVisibility = 0;
+ TypeBits.CachedLocalOrUnnamed = false;
+ TypeBits.CachedLinkage = NoLinkage;
+ TypeBits.FromAST = false;
+ }
friend class ASTContext;
+ void setDependent(bool D = true) { TypeBits.Dependent = D; }
+ void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; }
+ void setContainsUnexpandedParameterPack(bool PP = true) {
+ TypeBits.ContainsUnexpandedParameterPack = PP;
+ }
+
public:
- TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
+ TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); }
/// \brief Whether this type comes from an AST file.
- bool isFromAST() const { return FromAST; }
+ bool isFromAST() const { return TypeBits.FromAST; }
+
+ /// \brief Whether this type is or contains an unexpanded parameter
+ /// pack, used to support C++0x variadic templates.
+ ///
+ /// A type that contains a parameter pack shall be expanded by the
+ /// ellipsis operator at some point. For example, the typedef in the
+ /// following example contains an unexpanded parameter pack 'T':
+ ///
+ /// \code
+ /// template<typename ...T>
+ /// struct X {
+ /// typedef T* pointer_types; // ill-formed; T is a parameter pack.
+ /// };
+ /// \endcode
+ ///
+ /// Note that this routine does not specify which
+ bool containsUnexpandedParameterPack() const {
+ return TypeBits.ContainsUnexpandedParameterPack;
+ }
+ /// Determines if this type would be canonical if it had no further
+ /// qualification.
bool isCanonicalUnqualified() const {
- return CanonicalType.getTypePtr() == this;
+ return CanonicalType == QualType(this, 0);
}
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
@@ -846,6 +1147,14 @@ public:
bool isIncompleteOrObjectType() const {
return !isFunctionType();
}
+
+ /// \brief Determine whether this type is an object type.
+ bool isObjectType() const {
+ // C++ [basic.types]p8:
+ // An object type is a (possibly cv-qualified) type that is not a
+ // function type, not a reference type, and not a void type.
+ return !isReferenceType() && !isFunctionType() && !isVoidType();
+ }
/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
bool isPODType() const;
@@ -854,10 +1163,6 @@ public:
/// (C++0x [basic.types]p10)
bool isLiteralType() const;
- /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
- /// types that have a non-constant expression. This does not include "[]".
- bool isVariablyModifiedType() const;
-
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs and qualifiers.
@@ -867,6 +1172,12 @@ public:
/// isSpecificBuiltinType - Test for a particular builtin type.
bool isSpecificBuiltinType(unsigned K) const;
+ /// isPlaceholderType - Test for a type which does not represent an
+ /// actual type-system type but is instead used as a placeholder for
+ /// various convenient purposes within Clang. All such types are
+ /// BuiltinTypes.
+ bool isPlaceholderType() const;
+
/// isIntegerType() does *not* include complex integers (a GCC extension).
/// isComplexIntegerType() can be used to test for complex integers.
bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum)
@@ -879,6 +1190,9 @@ public:
/// \brief Determine whether this type is an integral or enumeration type.
bool isIntegralOrEnumerationType() const;
+ /// \brief Determine whether this type is an integral or unscoped enumeration
+ /// type.
+ bool isIntegralOrUnscopedEnumerationType() const;
/// Floating point categories.
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
@@ -938,10 +1252,33 @@ public:
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
+ enum ScalarTypeKind {
+ STK_Pointer,
+ STK_MemberPointer,
+ STK_Bool,
+ STK_Integral,
+ STK_Floating,
+ STK_IntegralComplex,
+ STK_FloatingComplex
+ };
+ /// getScalarTypeKind - Given that this is a scalar type, classify it.
+ ScalarTypeKind getScalarTypeKind() const;
+
/// isDependentType - Whether this type is a dependent type, meaning
/// that its definition somehow depends on a template parameter
/// (C++ [temp.dep.type]).
- bool isDependentType() const { return Dependent; }
+ bool isDependentType() const { return TypeBits.Dependent; }
+
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ bool isVariablyModifiedType() const { return TypeBits.VariablyModified; }
+
+ /// \brief Whether this type involves a variable-length array type
+ /// with a definite size.
+ bool hasSizedVLAType() const;
+
+ /// \brief Whether this type is or contains a local or unnamed type.
+ bool hasUnnamedOrLocalType() const;
+
bool isOverloadableType() const;
/// \brief Determine wither this type is a C++ elaborated-type-specifier.
@@ -991,15 +1328,41 @@ public:
/// 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;
+
+ /// \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.
+ AutoType *getContainedAutoType() const;
- // Member-template getAs<specific type>'. Look through sugar for
- // an instance of <specific type>. This scheme will eventually
- // replace the specific getAsXXXX methods above.
- //
- // There are some specializations of this member template listed
- // immediately following this class.
+ /// Member-template getAs<specific type>'. Look through sugar for
+ /// an instance of <specific type>. This scheme will eventually
+ /// replace the specific getAsXXXX methods above.
+ ///
+ /// There are some specializations of this member template listed
+ /// immediately following this class.
template <typename T> const T *getAs() const;
+ /// A variant of getAs<> for array types which silently discards
+ /// qualifiers from the outermost type.
+ const ArrayType *getAsArrayTypeUnsafe() const;
+
+ /// Member-template castAs<specific type>. Look through sugar for
+ /// the underlying instance of <specific type>.
+ ///
+ /// This method has the same relationship to getAs<T> as cast<T> has
+ /// to dyn_cast<T>; which is to say, the underlying type *must*
+ /// have the intended type, and this method will never return null.
+ template <typename T> const T *castAs() const;
+
+ /// A variant of castAs<> for array type which silently discards
+ /// qualifiers from the outermost type.
+ const ArrayType *castAsArrayTypeUnsafe() const;
+
+ /// getBaseElementTypeUnsafe - Get the base element type of this
+ /// type, potentially discarding type qualifiers. This method
+ /// should never be used when type qualifiers are meaningful.
+ const Type *getBaseElementTypeUnsafe() const;
+
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@@ -1040,6 +1403,12 @@ public:
/// \brief Determine the linkage of this type.
Linkage getLinkage() const;
+
+ /// \brief Determine the visibility of this type.
+ Visibility getVisibility() const;
+
+ /// \brief Determine the linkage and visibility of this type.
+ std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
/// \brief Note that the linkage is no longer known.
void ClearLinkageCache();
@@ -1067,6 +1436,9 @@ template <> inline const TypedefType *Type::getAs() const {
#define LEAF_TYPE(Class) \
template <> inline const Class##Type *Type::getAs() const { \
return dyn_cast<Class##Type>(CanonicalType); \
+} \
+template <> inline const Class##Type *Type::castAs() const { \
+ return cast<Class##Type>(CanonicalType); \
}
#include "clang/AST/TypeNodes.def"
@@ -1081,6 +1453,7 @@ public:
Bool, // This is bool and/or _Bool.
Char_U, // This is 'char' for targets where char is unsigned.
UChar, // This is explicitly qualified unsigned char.
+ WChar_U, // This is 'wchar_t' for C++, when unsigned.
Char16, // This is 'char16_t' for C++.
Char32, // This is 'char32_t' for C++.
UShort,
@@ -1091,7 +1464,7 @@ public:
Char_S, // This is 'char' for targets where char is signed.
SChar, // This is explicitly qualified signed char.
- WChar, // This is 'wchar_t' for C++.
+ WChar_S, // This is 'wchar_t' for C++, when signed.
Short,
Int,
Long,
@@ -1102,11 +1475,13 @@ public:
NullPtr, // This is the type of C++0x 'nullptr'.
- Overload, // This represents the type of an overloaded function declaration.
- Dependent, // This represents the type of a type-dependent expression.
+ /// This represents the type of an expression whose type is
+ /// totally unknown, e.g. 'T::foo'. It is permitted for this to
+ /// appear in situations where the structure of the type is
+ /// theoretically deducible.
+ Dependent,
- UndeducedAuto, // In C++0x, this represents the type of an auto variable
- // that has not been deduced yet.
+ Overload, // This represents the type of an overloaded function declaration.
/// The primitive Objective C 'id' type. The type pointed to by the
/// user-visible 'id' type. Only ever shows up in an AST as the base
@@ -1120,37 +1495,42 @@ public:
ObjCSel // This represents the ObjC 'SEL' type.
};
-private:
- Kind TypeKind;
-
-protected:
- virtual Linkage getLinkageImpl() const;
-
+
public:
BuiltinType(Kind K)
- : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)),
- TypeKind(K) {}
+ : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
+ /*VariablyModified=*/false,
+ /*Unexpanded paramter pack=*/false) {
+ BuiltinTypeBits.Kind = K;
+ }
- Kind getKind() const { return TypeKind; }
+ Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
const char *getName(const LangOptions &LO) const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
bool isInteger() const {
- return TypeKind >= Bool && TypeKind <= Int128;
+ return getKind() >= Bool && getKind() <= Int128;
}
bool isSignedInteger() const {
- return TypeKind >= Char_S && TypeKind <= Int128;
+ return getKind() >= Char_S && getKind() <= Int128;
}
bool isUnsignedInteger() const {
- return TypeKind >= Bool && TypeKind <= UInt128;
+ return getKind() >= Bool && getKind() <= UInt128;
}
bool isFloatingPoint() const {
- return TypeKind >= Float && TypeKind <= LongDouble;
+ return getKind() >= Float && getKind() <= LongDouble;
+ }
+
+ /// Determines whether this type is a "forbidden" placeholder type,
+ /// i.e. a type which cannot appear in arbitrary positions in a
+ /// fully-formed expression.
+ bool isPlaceholderType() const {
+ return getKind() == Overload;
}
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
@@ -1163,14 +1543,13 @@ public:
class ComplexType : public Type, public llvm::FoldingSetNode {
QualType ElementType;
ComplexType(QualType Element, QualType CanonicalPtr) :
- Type(Complex, CanonicalPtr, Element->isDependentType()),
+ Type(Complex, CanonicalPtr, Element->isDependentType(),
+ Element->isVariablyModifiedType(),
+ Element->containsUnexpandedParameterPack()),
ElementType(Element) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getElementType() const { return ElementType; }
@@ -1188,19 +1567,50 @@ public:
static bool classof(const ComplexType *) { return true; }
};
+/// ParenType - Sugar for parentheses used when specifying types.
+///
+class ParenType : public Type, public llvm::FoldingSetNode {
+ QualType Inner;
+
+ ParenType(QualType InnerType, QualType CanonType) :
+ Type(Paren, CanonType, InnerType->isDependentType(),
+ InnerType->isVariablyModifiedType(),
+ InnerType->containsUnexpandedParameterPack()),
+ Inner(InnerType) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getInnerType() const { return Inner; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getInnerType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getInnerType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) {
+ Inner.Profile(ID);
+ }
+
+ 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.
///
class PointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
PointerType(QualType Pointee, QualType CanonicalPtr) :
- Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) {
+ Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getPointeeType() const { return PointeeType; }
@@ -1226,14 +1636,13 @@ public:
class BlockPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType; // Block is some kind of pointer type
BlockPointerType(QualType Pointee, QualType CanonicalCls) :
- Type(BlockPointer, CanonicalCls, Pointee->isDependentType()),
+ Type(BlockPointer, CanonicalCls, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
PointeeType(Pointee) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
// Get the pointee type. Pointee is required to always be a function type.
@@ -1260,48 +1669,33 @@ public:
class ReferenceType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
- /// True if the type was originally spelled with an lvalue sigil.
- /// This is never true of rvalue references but can also be false
- /// on lvalue references because of C++0x [dcl.typedef]p9,
- /// as follows:
- ///
- /// typedef int &ref; // lvalue, spelled lvalue
- /// typedef int &&rvref; // rvalue
- /// ref &a; // lvalue, inner ref, spelled lvalue
- /// ref &&a; // lvalue, inner ref
- /// rvref &a; // lvalue, inner ref, spelled lvalue
- /// rvref &&a; // rvalue, inner ref
- bool SpelledAsLValue;
-
- /// True if the inner type is a reference type. This only happens
- /// in non-canonical forms.
- bool InnerRef;
-
protected:
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
bool SpelledAsLValue) :
- Type(tc, CanonicalRef, Referencee->isDependentType()),
- PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue),
- InnerRef(Referencee->isReferenceType()) {
+ Type(tc, CanonicalRef, Referencee->isDependentType(),
+ Referencee->isVariablyModifiedType(),
+ Referencee->containsUnexpandedParameterPack()),
+ PointeeType(Referencee)
+ {
+ ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue;
+ ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
}
- virtual Linkage getLinkageImpl() const;
-
public:
- bool isSpelledAsLValue() const { return SpelledAsLValue; }
- bool isInnerRef() const { return InnerRef; }
+ bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; }
+ bool isInnerRef() const { return ReferenceTypeBits.InnerRef; }
QualType getPointeeTypeAsWritten() const { return PointeeType; }
QualType getPointeeType() const {
// FIXME: this might strip inner qualifiers; okay?
const ReferenceType *T = this;
- while (T->InnerRef)
- T = T->PointeeType->getAs<ReferenceType>();
+ while (T->isInnerRef())
+ T = T->PointeeType->castAs<ReferenceType>();
return T->PointeeType;
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, PointeeType, SpelledAsLValue);
+ Profile(ID, PointeeType, isSpelledAsLValue());
}
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Referencee,
@@ -1362,14 +1756,14 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) :
Type(MemberPointer, CanonicalPtr,
- Cls->isDependentType() || Pointee->isDependentType()),
+ Cls->isDependentType() || Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ (Cls->containsUnexpandedParameterPack() ||
+ Pointee->containsUnexpandedParameterPack())),
PointeeType(Pointee), Class(Cls) {
}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getPointeeType() const { return PointeeType; }
@@ -1420,14 +1814,6 @@ private:
/// ElementType - The element type of the array.
QualType ElementType;
- // NOTE: VC++ treats enums as signed, avoid using the ArraySizeModifier enum
- /// NOTE: These fields are packed into the bitfields space in the Type class.
- unsigned SizeModifier : 2;
-
- /// IndexTypeQuals - Capture qualifiers in declarations like:
- /// 'int X[static restrict 4]'. For function parameters only.
- unsigned IndexTypeQuals : 3;
-
protected:
// C++ [temp.dep.type]p1:
// A type is dependent if it is...
@@ -1435,23 +1821,29 @@ protected:
// size is specified by a constant expression that is
// value-dependent,
ArrayType(TypeClass tc, QualType et, QualType can,
- ArraySizeModifier sm, unsigned tq)
- : Type(tc, can, et->isDependentType() || tc == DependentSizedArray),
- ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {}
+ ArraySizeModifier sm, unsigned tq,
+ bool ContainsUnexpandedParameterPack)
+ : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
+ (tc == VariableArray || et->isVariablyModifiedType()),
+ ContainsUnexpandedParameterPack),
+ ElementType(et) {
+ ArrayTypeBits.IndexTypeQuals = tq;
+ ArrayTypeBits.SizeModifier = sm;
+ }
friend class ASTContext; // ASTContext creates these.
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getElementType() const { return ElementType; }
ArraySizeModifier getSizeModifier() const {
- return ArraySizeModifier(SizeModifier);
+ return ArraySizeModifier(ArrayTypeBits.SizeModifier);
}
Qualifiers getIndexTypeQualifiers() const {
- return Qualifiers::fromCVRMask(IndexTypeQuals);
+ return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers());
+ }
+ unsigned getIndexTypeCVRQualifiers() const {
+ return ArrayTypeBits.IndexTypeQuals;
}
- unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray ||
@@ -1471,12 +1863,14 @@ class ConstantArrayType : public ArrayType {
ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
ArraySizeModifier sm, unsigned tq)
- : ArrayType(ConstantArray, et, can, sm, tq),
+ : ArrayType(ConstantArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
Size(size) {}
protected:
ConstantArrayType(TypeClass tc, QualType et, QualType can,
const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
- : ArrayType(tc, et, can, sm, tq), Size(size) {}
+ : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
+ Size(size) {}
friend class ASTContext; // ASTContext creates these.
public:
const llvm::APInt &getSize() const { return Size; }
@@ -1519,7 +1913,8 @@ class IncompleteArrayType : public ArrayType {
IncompleteArrayType(QualType et, QualType can,
ArraySizeModifier sm, unsigned tq)
- : ArrayType(IncompleteArray, et, can, sm, tq) {}
+ : ArrayType(IncompleteArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()) {}
friend class ASTContext; // ASTContext creates these.
public:
bool isSugared() const { return false; }
@@ -1570,7 +1965,8 @@ class VariableArrayType : public ArrayType {
VariableArrayType(QualType et, QualType can, Expr *e,
ArraySizeModifier sm, unsigned tq,
SourceRange brackets)
- : ArrayType(VariableArray, et, can, sm, tq),
+ : ArrayType(VariableArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
@@ -1613,7 +2009,7 @@ public:
/// until template instantiation occurs, at which point this will
/// become either a ConstantArrayType or a VariableArrayType.
class DependentSizedArrayType : public ArrayType {
- ASTContext &Context;
+ const ASTContext &Context;
/// \brief An assignment expression that will instantiate to the
/// size of the array.
@@ -1625,11 +2021,10 @@ class DependentSizedArrayType : public ArrayType {
/// Brackets - The left and right array brackets.
SourceRange Brackets;
- DependentSizedArrayType(ASTContext &Context, QualType et, QualType can,
+ DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can,
Expr *e, ArraySizeModifier sm, unsigned tq,
- SourceRange brackets)
- : ArrayType(DependentSizedArray, et, can, sm, tq),
- Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
+ SourceRange brackets);
+
friend class ASTContext; // ASTContext creates these.
public:
@@ -1658,7 +2053,7 @@ public:
getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType ET, ArraySizeModifier SizeMod,
unsigned TypeQuals, Expr *E);
};
@@ -1672,17 +2067,15 @@ public:
/// }
/// @endcode
class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
- ASTContext &Context;
+ const ASTContext &Context;
Expr *SizeExpr;
/// ElementType - The element type of the array.
QualType ElementType;
SourceLocation loc;
- DependentSizedExtVectorType(ASTContext &Context, QualType ElementType,
- QualType can, Expr *SizeExpr, SourceLocation loc)
- : Type (DependentSizedExtVector, can, true),
- Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
- loc(loc) {}
+ DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType,
+ QualType can, Expr *SizeExpr, SourceLocation loc);
+
friend class ASTContext;
public:
@@ -1702,7 +2095,7 @@ public:
Profile(ID, Context, getElementType(), getSizeExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType ElementType, Expr *SizeExpr);
};
@@ -1714,53 +2107,49 @@ public:
/// client is responsible for converting the size into the number of elements.
class VectorType : public Type, public llvm::FoldingSetNode {
public:
- enum AltiVecSpecific {
- NotAltiVec, // is not AltiVec vector
- AltiVec, // is AltiVec vector
- Pixel, // is AltiVec 'vector Pixel'
- Bool // is AltiVec 'vector bool ...'
+ enum VectorKind {
+ GenericVector, // not a target-specific vector type
+ AltiVecVector, // is AltiVec vector
+ AltiVecPixel, // is AltiVec 'vector Pixel'
+ AltiVecBool, // is AltiVec 'vector bool ...'
+ NeonVector, // is ARM Neon vector
+ NeonPolyVector // is ARM Neon polynomial vector
};
protected:
/// ElementType - The element type of the vector.
QualType ElementType;
- /// NumElements - The number of elements in the vector.
- unsigned NumElements;
-
- AltiVecSpecific AltiVecSpec;
-
VectorType(QualType vecType, unsigned nElements, QualType canonType,
- AltiVecSpecific altiVecSpec) :
- Type(Vector, canonType, vecType->isDependentType()),
- ElementType(vecType), NumElements(nElements), AltiVecSpec(altiVecSpec) {}
+ VectorKind vecKind);
+
VectorType(TypeClass tc, QualType vecType, unsigned nElements,
- QualType canonType, AltiVecSpecific altiVecSpec)
- : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType),
- NumElements(nElements), AltiVecSpec(altiVecSpec) {}
+ QualType canonType, VectorKind vecKind);
+
friend class ASTContext; // ASTContext creates these.
- virtual Linkage getLinkageImpl() const;
-
public:
QualType getElementType() const { return ElementType; }
- unsigned getNumElements() const { return NumElements; }
+ unsigned getNumElements() const { return VectorTypeBits.NumElements; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- AltiVecSpecific getAltiVecSpecific() const { return AltiVecSpec; }
+ VectorKind getVectorKind() const {
+ return VectorKind(VectorTypeBits.VecKind);
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getElementType(), getNumElements(), getTypeClass(), AltiVecSpec);
+ Profile(ID, getElementType(), getNumElements(),
+ getTypeClass(), getVectorKind());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType,
unsigned NumElements, TypeClass TypeClass,
- unsigned AltiVecSpec) {
+ VectorKind VecKind) {
ID.AddPointer(ElementType.getAsOpaquePtr());
ID.AddInteger(NumElements);
ID.AddInteger(TypeClass);
- ID.AddInteger(AltiVecSpec);
+ ID.AddInteger(VecKind);
}
static bool classof(const Type *T) {
@@ -1776,7 +2165,7 @@ public:
/// points, colors, and textures (modeled after OpenGL Shading Language).
class ExtVectorType : public VectorType {
ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
- VectorType(ExtVector, vecType, nElements, canonType, NotAltiVec) {}
+ VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
friend class ASTContext; // ASTContext creates these.
public:
static int getPointAccessorIdx(char c) {
@@ -1823,7 +2212,7 @@ public:
bool isAccessorWithinNumElements(char c) const {
if (int idx = getAccessorIdx(c)+1)
- return unsigned(idx-1) < NumElements;
+ return unsigned(idx-1) < getNumElements();
return false;
}
bool isSugared() const { return false; }
@@ -1839,40 +2228,20 @@ public:
/// class of FunctionNoProtoType and FunctionProtoType.
///
class FunctionType : public Type {
- virtual void ANCHOR(); // Key function for FunctionType.
-
- /// SubClassData - This field is owned by the subclass, put here to pack
- /// tightly with the ivars in Type.
- bool SubClassData : 1;
-
- /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
- /// other bitfields.
- /// The qualifiers are part of FunctionProtoType because...
- ///
- /// C++ 8.3.5p4: The return type, the parameter type list and the
- /// cv-qualifier-seq, [...], are part of the function type.
- ///
- unsigned TypeQuals : 3;
-
- /// NoReturn - Indicates if the function type is attribute noreturn.
- unsigned NoReturn : 1;
-
- /// RegParm - How many arguments to pass inreg.
- unsigned RegParm : 3;
-
- /// CallConv - The calling convention used by the function.
- unsigned CallConv : 3;
-
// The type returned by the function.
QualType ResultType;
public:
- // This class is used for passing arround the information needed to
- // construct a call. It is not actually used for storage, just for
- // factoring together common arguments.
- // If you add a field (say Foo), other than the obvious places (both, constructors,
- // compile failures), what you need to update is
- // * Operetor==
+ /// ExtInfo - A class which abstracts out some details necessary for
+ /// making a call.
+ ///
+ /// It is not actually used directly for storing this information in
+ /// a FunctionType, although FunctionType does currently use the
+ /// same bit-pattern.
+ ///
+ // If you add a field (say Foo), other than the obvious places (both,
+ // constructors, compile failures), what you need to update is
+ // * Operator==
// * getFoo
// * withFoo
// * functionType. Add Foo, getFoo.
@@ -1883,76 +2252,100 @@ class FunctionType : public Type {
// * TypePrinter::PrintFunctionProto
// * AST read and write
// * Codegen
-
class ExtInfo {
+ // Feel free to rearrange or add bits, but if you go over 8,
+ // you'll need to adjust both the Bits field below and
+ // Type::FunctionTypeBitfields.
+
+ // | CC |noreturn|regparm
+ // |0 .. 2| 3 |4 .. 6
+ enum { CallConvMask = 0x7 };
+ enum { NoReturnMask = 0x8 };
+ enum { RegParmMask = ~(CallConvMask | NoReturnMask),
+ RegParmOffset = 4 };
+
+ unsigned char Bits;
+
+ ExtInfo(unsigned Bits) : Bits(static_cast<unsigned char>(Bits)) {}
+
+ friend class FunctionType;
+
public:
// Constructor with no defaults. Use this when you know that you
// have all the elements (when reading an AST file for example).
- ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) :
- NoReturn(noReturn), RegParm(regParm), CC(cc) {}
+ ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) {
+ Bits = ((unsigned) cc) |
+ (noReturn ? NoReturnMask : 0) |
+ (regParm << RegParmOffset);
+ }
// Constructor with all defaults. Use when for example creating a
// function know to use defaults.
- ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {}
+ ExtInfo() : Bits(0) {}
- bool getNoReturn() const { return NoReturn; }
- unsigned getRegParm() const { return RegParm; }
- CallingConv getCC() const { return CC; }
+ bool getNoReturn() const { return Bits & NoReturnMask; }
+ unsigned getRegParm() const { return Bits >> RegParmOffset; }
+ CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
- bool operator==(const ExtInfo &Other) const {
- return getNoReturn() == Other.getNoReturn() &&
- getRegParm() == Other.getRegParm() &&
- getCC() == Other.getCC();
+ bool operator==(ExtInfo Other) const {
+ return Bits == Other.Bits;
}
- bool operator!=(const ExtInfo &Other) const {
- return !(*this == Other);
+ bool operator!=(ExtInfo Other) const {
+ return Bits != Other.Bits;
}
// Note that we don't have setters. That is by design, use
// the following with methods instead of mutating these objects.
ExtInfo withNoReturn(bool noReturn) const {
- return ExtInfo(noReturn, getRegParm(), getCC());
+ if (noReturn)
+ return ExtInfo(Bits | NoReturnMask);
+ else
+ return ExtInfo(Bits & ~NoReturnMask);
}
ExtInfo withRegParm(unsigned RegParm) const {
- return ExtInfo(getNoReturn(), RegParm, getCC());
+ return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset));
}
ExtInfo withCallingConv(CallingConv cc) const {
- return ExtInfo(getNoReturn(), getRegParm(), cc);
+ return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc);
}
- private:
- // True if we have __attribute__((noreturn))
- bool NoReturn;
- // The value passed to __attribute__((regparm(x)))
- unsigned RegParm;
- // The calling convention as specified via
- // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal))
- CallingConv CC;
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Bits);
+ }
};
protected:
- FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
- unsigned typeQuals, QualType Canonical, bool Dependent,
- const ExtInfo &Info)
- : Type(tc, Canonical, Dependent),
- SubClassData(SubclassInfo), TypeQuals(typeQuals),
- NoReturn(Info.getNoReturn()),
- RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {}
- bool getSubClassData() const { return SubClassData; }
- unsigned getTypeQuals() const { return TypeQuals; }
+ FunctionType(TypeClass tc, QualType res, bool variadic,
+ unsigned typeQuals, RefQualifierKind RefQualifier,
+ QualType Canonical, bool Dependent,
+ bool VariablyModified, bool ContainsUnexpandedParameterPack,
+ ExtInfo Info)
+ : Type(tc, Canonical, Dependent, VariablyModified,
+ ContainsUnexpandedParameterPack),
+ ResultType(res) {
+ FunctionTypeBits.ExtInfo = Info.Bits;
+ FunctionTypeBits.Variadic = variadic;
+ FunctionTypeBits.TypeQuals = typeQuals;
+ FunctionTypeBits.RefQualifier = static_cast<unsigned>(RefQualifier);
+ }
+ bool isVariadic() const { return FunctionTypeBits.Variadic; }
+ unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
+
+ RefQualifierKind getRefQualifier() const {
+ return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
+ }
+
public:
QualType getResultType() const { return ResultType; }
- unsigned getRegParmType() const { return RegParm; }
- bool getNoReturnAttr() const { return NoReturn; }
- CallingConv getCallConv() const { return (CallingConv)CallConv; }
- ExtInfo getExtInfo() const {
- return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv);
- }
+ unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
+ bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
+ CallingConv getCallConv() const { return getExtInfo().getCC(); }
+ ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
/// \brief Determine the type of an expression that calls a function of
/// this type.
@@ -1972,15 +2365,13 @@ public:
/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
- FunctionNoProtoType(QualType Result, QualType Canonical,
- const ExtInfo &Info)
- : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
- /*Dependent=*/false, Info) {}
+ FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
+ : FunctionType(FunctionNoProto, Result, false, 0, RQ_None, Canonical,
+ /*Dependent=*/false, Result->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false, Info) {}
+
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
// No additional state past what FunctionType provides.
@@ -1991,10 +2382,8 @@ public:
Profile(ID, getResultType(), getExtInfo());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
- const ExtInfo &Info) {
- ID.AddInteger(Info.getCC());
- ID.AddInteger(Info.getRegParm());
- ID.AddInteger(Info.getNoReturn());
+ ExtInfo Info) {
+ Info.Profile(ID);
ID.AddPointer(ResultType.getAsOpaquePtr());
}
@@ -2010,36 +2399,37 @@ public:
/// exception specification, but this specification is not part of the canonical
/// type.
class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
- /// hasAnyDependentType - Determine whether there are any dependent
- /// types within the arguments passed in.
- static bool hasAnyDependentType(const QualType *ArgArray, unsigned numArgs) {
+public:
+ /// ExtProtoInfo - Extra information about a function prototype.
+ struct ExtProtoInfo {
+ ExtProtoInfo() :
+ Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false),
+ TypeQuals(0), RefQualifier(RQ_None), NumExceptions(0), Exceptions(0) {}
+
+ FunctionType::ExtInfo ExtInfo;
+ bool Variadic;
+ bool HasExceptionSpec;
+ bool HasAnyExceptionSpec;
+ unsigned char TypeQuals;
+ RefQualifierKind RefQualifier;
+ unsigned NumExceptions;
+ const QualType *Exceptions;
+ };
+
+private:
+ /// \brief Determine whether there are any argument types that
+ /// contain an unexpanded parameter pack.
+ static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray,
+ unsigned numArgs) {
for (unsigned Idx = 0; Idx < numArgs; ++Idx)
- if (ArgArray[Idx]->isDependentType())
- return true;
+ if (ArgArray[Idx]->containsUnexpandedParameterPack())
+ return true;
return false;
}
- FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
- bool isVariadic, unsigned typeQuals, bool hasExs,
- bool hasAnyExs, const QualType *ExArray,
- unsigned numExs, QualType Canonical,
- const ExtInfo &Info)
- : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
- (Result->isDependentType() ||
- hasAnyDependentType(ArgArray, numArgs)),
- Info),
- NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
- AnyExceptionSpec(hasAnyExs) {
- // Fill in the trailing argument array.
- QualType *ArgInfo = reinterpret_cast<QualType*>(this+1);
- for (unsigned i = 0; i != numArgs; ++i)
- ArgInfo[i] = ArgArray[i];
- // Fill in the exception array.
- QualType *Ex = ArgInfo + numArgs;
- for (unsigned i = 0; i != numExs; ++i)
- Ex[i] = ExArray[i];
- }
+ FunctionProtoType(QualType result, const QualType *args, unsigned numArgs,
+ QualType canonical, const ExtProtoInfo &epi);
/// NumArgs - The number of arguments this function has, not counting '...'.
unsigned NumArgs : 20;
@@ -2048,10 +2438,10 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
unsigned NumExceptions : 10;
/// HasExceptionSpec - Whether this function has an exception spec at all.
- bool HasExceptionSpec : 1;
+ unsigned HasExceptionSpec : 1;
- /// AnyExceptionSpec - Whether this function has a throw(...) spec.
- bool AnyExceptionSpec : 1;
+ /// HasAnyExceptionSpec - Whether this function has a throw(...) spec.
+ unsigned HasAnyExceptionSpec : 1;
/// ArgInfo - There is an variable size array after the class in memory that
/// holds the argument types.
@@ -2061,9 +2451,6 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
unsigned getNumArgs() const { return NumArgs; }
QualType getArgType(unsigned i) const {
@@ -2071,8 +2458,21 @@ public:
return arg_type_begin()[i];
}
+ ExtProtoInfo getExtProtoInfo() const {
+ ExtProtoInfo EPI;
+ EPI.ExtInfo = getExtInfo();
+ EPI.Variadic = isVariadic();
+ EPI.HasExceptionSpec = hasExceptionSpec();
+ EPI.HasAnyExceptionSpec = hasAnyExceptionSpec();
+ EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
+ EPI.RefQualifier = getRefQualifier();
+ EPI.NumExceptions = NumExceptions;
+ EPI.Exceptions = exception_begin();
+ return EPI;
+ }
+
bool hasExceptionSpec() const { return HasExceptionSpec; }
- bool hasAnyExceptionSpec() const { return AnyExceptionSpec; }
+ bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; }
unsigned getNumExceptions() const { return NumExceptions; }
QualType getExceptionType(unsigned i) const {
assert(i < NumExceptions && "Invalid exception number!");
@@ -2083,9 +2483,24 @@ public:
getNumExceptions() == 0;
}
- bool isVariadic() const { return getSubClassData(); }
+ using FunctionType::isVariadic;
+
+ /// \brief Determines whether this function prototype contains a
+ /// parameter pack at the end.
+ ///
+ /// A function template whose last parameter is a parameter pack can be
+ /// called with an arbitrary number of arguments, much like a variadic
+ /// function. However,
+ bool isTemplateVariadic() const;
+
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
+
+ /// \brief Retrieve the ref-qualifier associated with this function type.
+ RefQualifierKind getRefQualifier() const {
+ return FunctionType::getRefQualifier();
+ }
+
typedef const QualType *arg_type_iterator;
arg_type_iterator arg_type_begin() const {
return reinterpret_cast<const QualType *>(this+1);
@@ -2112,10 +2527,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys, unsigned NumArgs,
- bool isVariadic, unsigned TypeQuals,
- bool hasExceptionSpec, bool anyExceptionSpec,
- unsigned NumExceptions, exception_iterator Exs,
- const ExtInfo &ExtInfo);
+ const ExtProtoInfo &EPI);
};
@@ -2127,7 +2539,8 @@ class UnresolvedUsingType : public Type {
UnresolvedUsingTypenameDecl *Decl;
UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D)
- : Type(UnresolvedUsing, QualType(), true),
+ : Type(UnresolvedUsing, QualType(), true, false,
+ /*ContainsUnexpandedParameterPack=*/false),
Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
public:
@@ -2156,7 +2569,8 @@ class TypedefType : public Type {
TypedefDecl *Decl;
protected:
TypedefType(TypeClass tc, const TypedefDecl *D, QualType can)
- : Type(tc, can, can->isDependentType()),
+ : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
Decl(const_cast<TypedefDecl*>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
@@ -2165,14 +2579,6 @@ public:
TypedefDecl *getDecl() const { return Decl; }
- /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
- /// potentially looking through *all* consecutive typedefs. This returns the
- /// sum of the type qualifiers, so if you have:
- /// typedef const int A;
- /// typedef volatile A B;
- /// looking through the typedefs for B will give you "const volatile A".
- QualType LookThroughTypedefs() const;
-
bool isSugared() const { return true; }
QualType desugar() const;
@@ -2208,10 +2614,10 @@ public:
/// of this class via TypeOfExprType nodes.
class DependentTypeOfExprType
: public TypeOfExprType, public llvm::FoldingSetNode {
- ASTContext &Context;
+ const ASTContext &Context;
public:
- DependentTypeOfExprType(ASTContext &Context, Expr *E)
+ DependentTypeOfExprType(const ASTContext &Context, Expr *E)
: TypeOfExprType(E), Context(Context) { }
bool isSugared() const { return false; }
@@ -2221,7 +2627,7 @@ public:
Profile(ID, Context, getUnderlyingExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
Expr *E);
};
@@ -2229,7 +2635,9 @@ public:
class TypeOfType : public Type {
QualType TOType;
TypeOfType(QualType T, QualType can)
- : Type(TypeOf, can, T->isDependentType()), TOType(T) {
+ : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType(),
+ T->containsUnexpandedParameterPack()),
+ TOType(T) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
friend class ASTContext; // ASTContext creates these.
@@ -2279,10 +2687,10 @@ public:
/// canonical, dependent types, only. Clients will only see instances
/// of this class via DecltypeType nodes.
class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
- ASTContext &Context;
+ const ASTContext &Context;
public:
- DependentDecltypeType(ASTContext &Context, Expr *E);
+ DependentDecltypeType(const ASTContext &Context, Expr *E);
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2291,7 +2699,7 @@ public:
Profile(ID, Context, getUnderlyingExpr());
}
- static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
Expr *E);
};
@@ -2303,8 +2711,6 @@ class TagType : public Type {
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
- virtual Linkage getLinkageImpl() const;
-
public:
TagDecl *getDecl() const;
@@ -2340,10 +2746,6 @@ public:
// const, it needs to return false.
bool hasConstFields() const { return false; }
- // FIXME: RecordType needs to check when it is created that all fields are in
- // the same address space, and return that.
- unsigned getAddressSpace() const { return 0; }
-
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2376,20 +2778,107 @@ public:
static bool classof(const EnumType *) { return true; }
};
+/// AttributedType - An attributed type is a type to which a type
+/// attribute has been applied. The "modified type" is the
+/// fully-sugared type to which the attributed type was applied;
+/// generally it is not canonically equivalent to the attributed type.
+/// The "equivalent type" is the minimally-desugared type which the
+/// type is canonically equivalent to.
+///
+/// For example, in the following attributed type:
+/// int32_t __attribute__((vector_size(16)))
+/// - the modified type is the TypedefType for int32_t
+/// - the equivalent type is VectorType(16, int32_t)
+/// - the canonical type is VectorType(16, int)
+class AttributedType : public Type, public llvm::FoldingSetNode {
+public:
+ // It is really silly to have yet another attribute-kind enum, but
+ // clang::attr::Kind doesn't currently cover the pure type attrs.
+ enum Kind {
+ // Expression operand.
+ attr_address_space,
+ attr_regparm,
+ attr_vector_size,
+ attr_neon_vector_type,
+ attr_neon_polyvector_type,
+
+ FirstExprOperandKind = attr_address_space,
+ LastExprOperandKind = attr_neon_polyvector_type,
+
+ // Enumerated operand (string or keyword).
+ attr_objc_gc,
+
+ FirstEnumOperandKind = attr_objc_gc,
+ LastEnumOperandKind = attr_objc_gc,
+
+ // No operand.
+ attr_noreturn,
+ attr_cdecl,
+ attr_fastcall,
+ attr_stdcall,
+ attr_thiscall,
+ attr_pascal
+ };
+
+private:
+ QualType ModifiedType;
+ QualType EquivalentType;
+
+ friend class ASTContext; // creates these
+
+ AttributedType(QualType canon, Kind attrKind,
+ QualType modified, QualType equivalent)
+ : Type(Attributed, canon, canon->isDependentType(),
+ canon->isVariablyModifiedType(),
+ canon->containsUnexpandedParameterPack()),
+ ModifiedType(modified), EquivalentType(equivalent) {
+ AttributedTypeBits.AttrKind = attrKind;
+ }
+
+public:
+ Kind getAttrKind() const {
+ return static_cast<Kind>(AttributedTypeBits.AttrKind);
+ }
+
+ QualType getModifiedType() const { return ModifiedType; }
+ QualType getEquivalentType() const { return EquivalentType; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getEquivalentType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
+ QualType modified, QualType equivalent) {
+ ID.AddInteger(attrKind);
+ ID.AddPointer(modified.getAsOpaquePtr());
+ ID.AddPointer(equivalent.getAsOpaquePtr());
+ }
+
+ 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 {
unsigned Depth : 15;
- unsigned Index : 16;
unsigned ParameterPack : 1;
+ unsigned Index : 16;
IdentifierInfo *Name;
TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N,
QualType Canon)
- : Type(TemplateTypeParm, Canon, /*Dependent=*/true),
- Depth(D), Index(I), ParameterPack(PP), Name(N) { }
+ : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
+ /*VariablyModified=*/false, PP),
+ Depth(D), ParameterPack(PP), Index(I), Name(N) { }
TemplateTypeParmType(unsigned D, unsigned I, bool PP)
- : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true),
- Depth(D), Index(I), ParameterPack(PP), Name(0) { }
+ : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true,
+ /*VariablyModified=*/false, PP),
+ Depth(D), ParameterPack(PP), Index(I), Name(0) { }
friend class ASTContext; // ASTContext creates these
@@ -2433,7 +2922,9 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
const TemplateTypeParmType *Replaced;
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
- : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()),
+ : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
+ Canon->isVariablyModifiedType(),
+ Canon->containsUnexpandedParameterPack()),
Replaced(Param) { }
friend class ASTContext;
@@ -2471,6 +2962,101 @@ public:
static bool classof(const SubstTemplateTypeParmType *T) { return true; }
};
+/// \brief Represents the result of substituting a set of types for a template
+/// type parameter pack.
+///
+/// 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 type node is used to represent a template type
+/// 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
+/// that pack expansion (e.g., when all template parameters have corresponding
+/// arguments), this type will be replaced with the \c SubstTemplateTypeParmType
+/// at the current pack substitution index.
+class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
+ /// \brief The original type parameter.
+ const TemplateTypeParmType *Replaced;
+
+ /// \brief A pointer to the set of template arguments that this
+ /// parameter pack is instantiated with.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in \c Arguments.
+ unsigned NumArguments;
+
+ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
+ QualType Canon,
+ const TemplateArgument &ArgPack);
+
+ friend class ASTContext;
+
+public:
+ IdentifierInfo *getName() const { return Replaced->getName(); }
+
+ /// Gets the template parameter that was substituted for.
+ const TemplateTypeParmType *getReplacedParameter() const {
+ return Replaced;
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ TemplateArgument getArgumentPack() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack);
+
+ 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.
+///
+/// These types are usually a placeholder for a deduced type. However, within
+/// templates and before the initializer is attached, there is no deduced type
+/// and an auto type is type-dependent and canonical.
+class AutoType : public Type, public llvm::FoldingSetNode {
+ AutoType(QualType DeducedType)
+ : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
+ /*Dependent=*/DeducedType.isNull(),
+ /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
+ assert((DeducedType.isNull() || !DeducedType->isDependentType()) &&
+ "deduced a dependent type for auto");
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ bool isSugared() const { return isDeduced(); }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
+ QualType getDeducedType() const {
+ return isDeduced() ? getCanonicalTypeInternal() : QualType();
+ }
+ bool isDeduced() const {
+ return !isDependentType();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDeducedType());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ QualType Deduced) {
+ ID.AddPointer(Deduced.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Auto;
+ }
+ static bool classof(const AutoType *T) { return true; }
+};
+
/// \brief Represents the type of a template specialization as written
/// in the source code.
///
@@ -2516,7 +3102,8 @@ public:
/// enclosing the template arguments.
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs,
- const PrintingPolicy &Policy);
+ const PrintingPolicy &Policy,
+ bool SkipBrackets = false);
static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args,
unsigned NumArgs,
@@ -2556,14 +3143,14 @@ public:
}
QualType desugar() const { return getCanonicalTypeInternal(); }
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Ctx) {
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
Profile(ID, Template, getArgs(), NumArgs, Ctx);
}
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs,
- ASTContext &Context);
+ const ASTContext &Context);
static bool classof(const Type *T) {
return T->getTypeClass() == TemplateSpecialization;
@@ -2607,7 +3194,9 @@ class InjectedClassNameType : public Type {
// currently suitable for AST reading, too much
// interdependencies.
InjectedClassNameType(CXXRecordDecl *D, QualType TST)
- : Type(InjectedClassName, QualType(), true),
+ : Type(InjectedClassName, QualType(), /*Dependent=*/true,
+ /*VariablyModified=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
Decl(D), InjectedType(TST) {
assert(isa<TemplateSpecializationType>(TST));
assert(!TST.hasQualifiers());
@@ -2666,19 +3255,18 @@ enum ElaboratedTypeKeyword {
/// Also provides a few static helpers for converting and printing
/// elaborated type keyword and tag type kind enumerations.
class TypeWithKeyword : public Type {
- /// Keyword - Encodes an ElaboratedTypeKeyword enumeration constant.
- unsigned Keyword : 3;
-
protected:
TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc,
- QualType Canonical, bool dependent)
- : Type(tc, Canonical, dependent), Keyword(Keyword) {}
+ QualType Canonical, bool Dependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : Type(tc, Canonical, Dependent, VariablyModified,
+ ContainsUnexpandedParameterPack) {
+ TypeWithKeywordBits.Keyword = Keyword;
+ }
public:
- virtual ~TypeWithKeyword(); // pin vtable to Type.cpp
-
ElaboratedTypeKeyword getKeyword() const {
- return static_cast<ElaboratedTypeKeyword>(Keyword);
+ return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword);
}
/// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST)
@@ -2730,7 +3318,9 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
QualType NamedType, QualType CanonType)
: TypeWithKeyword(Keyword, Elaborated, CanonType,
- NamedType->isDependentType()),
+ NamedType->isDependentType(),
+ NamedType->isVariablyModifiedType(),
+ NamedType->containsUnexpandedParameterPack()),
NNS(NNS), NamedType(NamedType) {
assert(!(Keyword == ETK_None && NNS == 0) &&
"ElaboratedType cannot have elaborated type keyword "
@@ -2790,7 +3380,9 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, QualType CanonType)
- : TypeWithKeyword(Keyword, DependentName, CanonType, true),
+ : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true,
+ /*VariablyModified=*/false,
+ NNS->containsUnexpandedParameterPack()),
NNS(NNS), Name(Name) {
assert(NNS->isDependent() &&
"DependentNameType requires a dependent nested-name-specifier");
@@ -2799,8 +3391,6 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
public:
- virtual ~DependentNameType();
-
/// \brief Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
@@ -2867,8 +3457,6 @@ class DependentTemplateSpecializationType :
friend class ASTContext; // ASTContext creates these
public:
- virtual ~DependentTemplateSpecializationType();
-
NestedNameSpecifier *getQualifier() const { return NNS; }
const IdentifierInfo *getIdentifier() const { return Name; }
@@ -2889,12 +3477,12 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) {
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs());
}
static void Profile(llvm::FoldingSetNodeID &ID,
- ASTContext &Context,
+ const ASTContext &Context,
ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *Qualifier,
const IdentifierInfo *Name,
@@ -2909,6 +3497,88 @@ public:
}
};
+/// \brief Represents a pack expansion of types.
+///
+/// Pack expansions are part of C++0x variadic templates. A pack
+/// expansion contains a pattern, which itself contains one or more
+/// "unexpanded" parameter packs. When instantiated, a pack expansion
+/// produces a series of types, each instantiated from the pattern of
+/// the expansion, where the Ith instantiation of the pattern uses the
+/// Ith arguments bound to each of the unexpanded parameter packs. The
+/// pack expansion is considered to "expand" these unexpanded
+/// parameter packs.
+///
+/// \code
+/// template<typename ...Types> struct tuple;
+///
+/// template<typename ...Types>
+/// struct tuple_of_references {
+/// typedef tuple<Types&...> type;
+/// };
+/// \endcode
+///
+/// Here, the pack expansion \c Types&... is represented via a
+/// PackExpansionType whose pattern is Types&.
+class PackExpansionType : public Type, public llvm::FoldingSetNode {
+ /// \brief The pattern of the pack expansion.
+ QualType Pattern;
+
+ /// \brief The number of expansions that this pack expansion will
+ /// generate when substituted (+1), or indicates that
+ ///
+ /// This field will only have a non-zero value when some of the parameter
+ /// packs that occur within the pattern have been substituted but others have
+ /// not.
+ unsigned NumExpansions;
+
+ PackExpansionType(QualType Pattern, QualType Canon,
+ llvm::Optional<unsigned> NumExpansions)
+ : Type(PackExpansion, Canon, /*Dependent=*/true,
+ /*VariableModified=*/Pattern->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Pattern(Pattern),
+ NumExpansions(NumExpansions? *NumExpansions + 1: 0) { }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Retrieve the pattern of this pack expansion, which is the
+ /// type that will be repeatedly instantiated when instantiating the
+ /// pack expansion itself.
+ QualType getPattern() const { return Pattern; }
+
+ /// \brief Retrieve the number of expansions that this pack expansion will
+ /// generate, if known.
+ llvm::Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPattern(), getNumExpansions());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions) {
+ ID.AddPointer(Pattern.getAsOpaquePtr());
+ ID.AddBoolean(NumExpansions);
+ if (NumExpansions)
+ ID.AddInteger(*NumExpansions);
+ }
+
+ 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.
/// Every Objective C type is a combination of a base type and a
/// list of protocols.
@@ -2930,19 +3600,15 @@ public:
/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
/// this should get its own sugar class to better represent the source.
class ObjCObjectType : public Type {
- // Pad the bit count up so that NumProtocols is 2-byte aligned
- unsigned : BitsRemainingInType - 16;
-
- /// \brief The number of protocols stored after the
- /// ObjCObjectPointerType node.
- ///
- /// These protocols are those written directly on the type. If
- /// protocol qualifiers ever become additive, the iterators will
- /// get kindof complicated.
- ///
- /// In the canonical object type, these are sorted alphabetically
- /// and uniqued.
- unsigned NumProtocols : 16;
+ // ObjCObjectType.NumProtocols - the number of protocols stored
+ // after the ObjCObjectPointerType node.
+ //
+ // These protocols are those written directly on the type. If
+ // protocol qualifiers ever become additive, the iterators will need
+ // to get kindof complicated.
+ //
+ // In the canonical object type, these are sorted alphabetically
+ // and uniqued.
/// Either a BuiltinType or an InterfaceType or sugar for either.
QualType BaseType;
@@ -2959,13 +3625,11 @@ protected:
enum Nonce_ObjCInterface { Nonce_ObjCInterface };
ObjCObjectType(enum Nonce_ObjCInterface)
- : Type(ObjCInterface, QualType(), false),
- NumProtocols(0),
- BaseType(QualType(this_(), 0)) {}
+ : Type(ObjCInterface, QualType(), false, false, false),
+ BaseType(QualType(this_(), 0)) {
+ ObjCObjectTypeBits.NumProtocols = 0;
+ }
-protected:
- Linkage getLinkageImpl() const; // key function
-
public:
/// getBaseType - Gets the base type of this object type. This is
/// always (possibly sugar for) one of:
@@ -3006,7 +3670,7 @@ public:
/// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none.
- unsigned getNumProtocols() const { return NumProtocols; }
+ unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; }
/// \brief Fetch a protocol by index.
ObjCProtocolDecl *getProtocol(unsigned I) const {
@@ -3072,6 +3736,7 @@ class ObjCInterfaceType : public ObjCObjectType {
: ObjCObjectType(Nonce_ObjCInterface),
Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
+
public:
/// getDecl - Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
@@ -3117,13 +3782,10 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
- : Type(ObjCObjectPointer, Canonical, false),
+ : Type(ObjCObjectPointer, Canonical, false, false, false),
PointeeType(Pointee) {}
friend class ASTContext; // ASTContext creates these.
-protected:
- virtual Linkage getLinkageImpl() const;
-
public:
/// getPointeeType - Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof.
@@ -3152,7 +3814,7 @@ public:
/// would return 'A1P<Q>' (and we'd have to make iterating over
/// qualifiers more complicated).
const ObjCObjectType *getObjectType() const {
- return PointeeType->getAs<ObjCObjectType>();
+ return PointeeType->castAs<ObjCObjectType>();
}
/// getInterfaceType - If this pointer points to an Objective C
@@ -3238,177 +3900,154 @@ public:
/// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers {
- ASTContext *Context;
-
public:
- QualifierCollector(Qualifiers Qs = Qualifiers())
- : Qualifiers(Qs), Context(0) {}
- QualifierCollector(ASTContext &Context, Qualifiers Qs = Qualifiers())
- : Qualifiers(Qs), Context(&Context) {}
-
- void setContext(ASTContext &C) { Context = &C; }
+ QualifierCollector(Qualifiers Qs = Qualifiers()) : Qualifiers(Qs) {}
/// Collect any qualifiers on the given type and return an
- /// unqualified type.
- const Type *strip(QualType QT) {
- addFastQualifiers(QT.getLocalFastQualifiers());
- if (QT.hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = QT.getExtQualsUnsafe();
- Context = &EQ->getContext();
- addQualifiers(EQ->getQualifiers());
- return EQ->getBaseType();
- }
- return QT.getTypePtrUnsafe();
+ /// unqualified type. The qualifiers are assumed to be consistent
+ /// with those already in the type.
+ const Type *strip(QualType type) {
+ addFastQualifiers(type.getLocalFastQualifiers());
+ if (!type.hasLocalNonFastQualifiers())
+ return type.getTypePtrUnsafe();
+
+ const ExtQuals *extQuals = type.getExtQualsUnsafe();
+ addConsistentQualifiers(extQuals->getQualifiers());
+ return extQuals->getBaseType();
}
/// Apply the collected qualifiers to the given type.
- QualType apply(QualType QT) const;
+ QualType apply(const ASTContext &Context, QualType QT) const;
/// Apply the collected qualifiers to the given type.
- QualType apply(const Type* T) const;
-
+ QualType apply(const ASTContext &Context, const Type* T) const;
};
// Inline function definitions.
+inline const Type *QualType::getTypePtr() const {
+ return getCommonPtr()->BaseType;
+}
+
+inline const Type *QualType::getTypePtrOrNull() const {
+ return (isNull() ? 0 : getCommonPtr()->BaseType);
+}
+
+inline SplitQualType QualType::split() const {
+ if (!hasLocalNonFastQualifiers())
+ return SplitQualType(getTypePtrUnsafe(),
+ Qualifiers::fromFastMask(getLocalFastQualifiers()));
+
+ const ExtQuals *eq = getExtQualsUnsafe();
+ Qualifiers qs = eq->getQualifiers();
+ qs.addFastQualifiers(getLocalFastQualifiers());
+ return SplitQualType(eq->getBaseType(), qs);
+}
+
+inline Qualifiers QualType::getLocalQualifiers() const {
+ Qualifiers Quals;
+ if (hasLocalNonFastQualifiers())
+ Quals = getExtQualsUnsafe()->getQualifiers();
+ Quals.addFastQualifiers(getLocalFastQualifiers());
+ return Quals;
+}
+
+inline Qualifiers QualType::getQualifiers() const {
+ Qualifiers quals = getCommonPtr()->CanonicalType.getLocalQualifiers();
+ quals.addFastQualifiers(getLocalFastQualifiers());
+ return quals;
+}
+
+inline unsigned QualType::getCVRQualifiers() const {
+ unsigned cvr = getCommonPtr()->CanonicalType.getLocalCVRQualifiers();
+ cvr |= getLocalCVRQualifiers();
+ return cvr;
+}
+
+inline QualType QualType::getCanonicalType() const {
+ QualType canon = getCommonPtr()->CanonicalType;
+ return canon.withFastQualifiers(getLocalFastQualifiers());
+}
+
inline bool QualType::isCanonical() const {
- const Type *T = getTypePtr();
- if (hasLocalQualifiers())
- return T->isCanonicalUnqualified() && !isa<ArrayType>(T);
- return T->isCanonicalUnqualified();
+ return getTypePtr()->isCanonicalUnqualified();
}
inline bool QualType::isCanonicalAsParam() const {
+ if (!isCanonical()) return false;
if (hasLocalQualifiers()) return false;
+
const Type *T = getTypePtr();
- return T->isCanonicalUnqualified() &&
- !isa<FunctionType>(T) && !isa<ArrayType>(T);
+ if (T->isVariablyModifiedType() && T->hasSizedVLAType())
+ return false;
+
+ return !isa<FunctionType>(T) && !isa<ArrayType>(T);
}
inline bool QualType::isConstQualified() const {
return isLocalConstQualified() ||
- getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified();
+ getCommonPtr()->CanonicalType.isLocalConstQualified();
}
inline bool QualType::isRestrictQualified() const {
return isLocalRestrictQualified() ||
- getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified();
+ getCommonPtr()->CanonicalType.isLocalRestrictQualified();
}
inline bool QualType::isVolatileQualified() const {
return isLocalVolatileQualified() ||
- getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified();
+ getCommonPtr()->CanonicalType.isLocalVolatileQualified();
}
inline bool QualType::hasQualifiers() const {
return hasLocalQualifiers() ||
- getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers();
-}
-
-inline Qualifiers QualType::getQualifiers() const {
- Qualifiers Quals = getLocalQualifiers();
- Quals.addQualifiers(
- getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers());
- return Quals;
-}
-
-inline unsigned QualType::getCVRQualifiers() const {
- return getLocalCVRQualifiers() |
- getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers();
+ getCommonPtr()->CanonicalType.hasLocalQualifiers();
}
-/// getCVRQualifiersThroughArrayTypes - If there are CVR qualifiers for this
-/// type, returns them. Otherwise, if this is an array type, recurses
-/// on the element type until some qualifiers have been found or a non-array
-/// type reached.
-inline unsigned QualType::getCVRQualifiersThroughArrayTypes() const {
- if (unsigned Quals = getCVRQualifiers())
- return Quals;
- QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
- return AT->getElementType().getCVRQualifiersThroughArrayTypes();
- return 0;
+inline QualType QualType::getUnqualifiedType() const {
+ if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
+ return QualType(getTypePtr(), 0);
+
+ return QualType(getSplitUnqualifiedTypeImpl(*this).first, 0);
}
-inline void QualType::removeConst() {
- removeFastQualifiers(Qualifiers::Const);
+inline SplitQualType QualType::getSplitUnqualifiedType() const {
+ if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
+ return split();
+
+ return getSplitUnqualifiedTypeImpl(*this);
+}
+
+inline void QualType::removeLocalConst() {
+ removeLocalFastQualifiers(Qualifiers::Const);
}
-inline void QualType::removeRestrict() {
- removeFastQualifiers(Qualifiers::Restrict);
+inline void QualType::removeLocalRestrict() {
+ removeLocalFastQualifiers(Qualifiers::Restrict);
}
-inline void QualType::removeVolatile() {
- QualifierCollector Qc;
- const Type *Ty = Qc.strip(*this);
- if (Qc.hasVolatile()) {
- Qc.removeVolatile();
- *this = Qc.apply(Ty);
- }
+inline void QualType::removeLocalVolatile() {
+ removeLocalFastQualifiers(Qualifiers::Volatile);
}
-inline void QualType::removeCVRQualifiers(unsigned Mask) {
+inline void QualType::removeLocalCVRQualifiers(unsigned Mask) {
assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits");
+ assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask);
// Fast path: we don't need to touch the slow qualifiers.
- if (!(Mask & ~Qualifiers::FastMask)) {
- removeFastQualifiers(Mask);
- return;
- }
-
- QualifierCollector Qc;
- const Type *Ty = Qc.strip(*this);
- Qc.removeCVRQualifiers(Mask);
- *this = Qc.apply(Ty);
+ removeLocalFastQualifiers(Mask);
}
/// getAddressSpace - Return the address space of this type.
inline unsigned QualType::getAddressSpace() const {
- if (hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = getExtQualsUnsafe();
- if (EQ->hasAddressSpace())
- return EQ->getAddressSpace();
- }
-
- QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (CT.hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = CT.getExtQualsUnsafe();
- if (EQ->hasAddressSpace())
- return EQ->getAddressSpace();
- }
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
- return AT->getElementType().getAddressSpace();
- if (const RecordType *RT = dyn_cast<RecordType>(CT))
- return RT->getAddressSpace();
- return 0;
+ return getQualifiers().getAddressSpace();
}
/// getObjCGCAttr - Return the gc attribute of this type.
inline Qualifiers::GC QualType::getObjCGCAttr() const {
- if (hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = getExtQualsUnsafe();
- if (EQ->hasObjCGCAttr())
- return EQ->getObjCGCAttr();
- }
-
- QualType CT = getTypePtr()->getCanonicalTypeInternal();
- if (CT.hasLocalNonFastQualifiers()) {
- const ExtQuals *EQ = CT.getExtQualsUnsafe();
- if (EQ->hasObjCGCAttr())
- return EQ->getObjCGCAttr();
- }
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
- return AT->getElementType().getObjCGCAttr();
- if (const ObjCObjectPointerType *PT = CT->getAs<ObjCObjectPointerType>())
- return PT->getPointeeType().getObjCGCAttr();
- // We most look at all pointer types, not just pointer to interface types.
- if (const PointerType *PT = CT->getAs<PointerType>())
- return PT->getPointeeType().getObjCGCAttr();
- return Qualifiers::GCNone;
+ return getQualifiers().getObjCGCAttr();
}
inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
@@ -3436,26 +4075,18 @@ inline bool Qualifiers::isSupersetOf(Qualifiers Other) const {
/// is more qualified than "const int", "volatile int", and
/// "int". However, it is not more qualified than "const volatile
/// int".
-inline bool QualType::isMoreQualifiedThan(QualType Other) const {
- // FIXME: work on arbitrary qualifiers
- unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes();
- unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes();
- if (getAddressSpace() != Other.getAddressSpace())
- return false;
- return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals;
+inline bool QualType::isMoreQualifiedThan(QualType other) const {
+ Qualifiers myQuals = getQualifiers();
+ Qualifiers otherQuals = other.getQualifiers();
+ return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals));
}
/// isAtLeastAsQualifiedAs - Determine whether this type is at last
/// as qualified as the Other type. For example, "const volatile
/// int" is at least as qualified as "const int", "volatile int",
/// "int", and "const volatile int".
-inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const {
- // FIXME: work on arbitrary qualifiers
- unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes();
- unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes();
- if (getAddressSpace() != Other.getAddressSpace())
- return false;
- return (MyQuals | OtherQuals) == MyQuals;
+inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const {
+ return getQualifiers().compatiblyIncludes(other.getQualifiers());
}
/// getNonReferenceType - If Type is a reference type (e.g., const
@@ -3496,7 +4127,7 @@ inline bool Type::isRValueReferenceType() const {
return isa<RValueReferenceType>(CanonicalType);
}
inline bool Type::isFunctionPointerType() const {
- if (const PointerType* T = getAs<PointerType>())
+ if (const PointerType *T = getAs<PointerType>())
return T->getPointeeType()->isFunctionType();
else
return false;
@@ -3531,9 +4162,15 @@ inline bool Type::isVariableArrayType() const {
inline bool Type::isDependentSizedArrayType() const {
return isa<DependentSizedArrayType>(CanonicalType);
}
+inline bool Type::isBuiltinType() const {
+ return isa<BuiltinType>(CanonicalType);
+}
inline bool Type::isRecordType() const {
return isa<RecordType>(CanonicalType);
}
+inline bool Type::isEnumeralType() const {
+ return isa<EnumType>(CanonicalType);
+}
inline bool Type::isAnyComplexType() const {
return isa<ComplexType>(CanonicalType);
}
@@ -3586,10 +4223,6 @@ inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType);
}
-inline bool Type::isBuiltinType() const {
- return getAs<BuiltinType>();
-}
-
inline bool Type::isSpecificBuiltinType(unsigned K) const {
if (const BuiltinType *BT = getAs<BuiltinType>())
if (BT->getKind() == (BuiltinType::Kind) K)
@@ -3597,6 +4230,12 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const {
return false;
}
+inline bool Type::isPlaceholderType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>())
+ return BT->isPlaceholderType();
+ return false;
+}
+
/// \brief Determines whether this is a type for which one can define
/// an overloaded operator.
inline bool Type::isOverloadableType() const {
@@ -3612,6 +4251,13 @@ inline bool Type::hasObjCPointerRepresentation() const {
return isObjCObjectPointerType();
}
+inline const Type *Type::getBaseElementTypeUnsafe() const {
+ const Type *type = this;
+ while (const ArrayType *arrayType = type->getAsArrayTypeUnsafe())
+ type = arrayType->getElementType().getTypePtr();
+ return type;
+}
+
/// Insertion operator for diagnostics. This allows sending QualType's into a
/// diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -3658,6 +4304,35 @@ template <typename T> const T *Type::getAs() const {
return cast<T>(getUnqualifiedDesugaredType());
}
+inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
+ // If this is directly an array type, return it.
+ if (const ArrayType *arr = dyn_cast<ArrayType>(this))
+ return arr;
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<ArrayType>(CanonicalType))
+ return 0;
+
+ // If this is a typedef for the type, strip the typedef off without
+ // losing all typedef information.
+ return cast<ArrayType>(getUnqualifiedDesugaredType());
+}
+
+template <typename T> const T *Type::castAs() const {
+ ArrayType_cannot_be_used_with_getAs<T> at;
+ (void) at;
+
+ assert(isa<T>(CanonicalType));
+ if (const T *ty = dyn_cast<T>(this)) return ty;
+ return cast<T>(getUnqualifiedDesugaredType());
+}
+
+inline const ArrayType *Type::castAsArrayTypeUnsafe() const {
+ assert(isa<ArrayType>(CanonicalType));
+ if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr;
+ return cast<ArrayType>(getUnqualifiedDesugaredType());
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index f1c64bd95977..c7f5ee76330c 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -20,6 +20,7 @@
#include "clang/Basic/Specifiers.h"
namespace clang {
+ class ASTContext;
class ParmVarDecl;
class TypeSourceInfo;
class UnqualTypeLoc;
@@ -38,7 +39,7 @@ class TypeLoc {
protected:
// The correctness of this relies on the property that, for Type *Ty,
// QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty
- void *Ty;
+ const void *Ty;
void *Data;
public:
@@ -56,7 +57,7 @@ public:
TypeLoc() : Ty(0), Data(0) { }
TypeLoc(QualType ty, void *opaqueData)
: Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
- TypeLoc(Type *ty, void *opaqueData)
+ TypeLoc(const Type *ty, void *opaqueData)
: Ty(ty), Data(opaqueData) { }
TypeLocClass getTypeLocClass() const {
@@ -76,7 +77,7 @@ public:
return QualType::getFromOpaquePtr(Ty);
}
- Type *getTypePtr() const {
+ const Type *getTypePtr() const {
return QualType::getFromOpaquePtr(Ty).getTypePtr();
}
@@ -115,13 +116,36 @@ public:
/// \brief Skips past any qualifiers, if this is qualified.
UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header
+ TypeLoc IgnoreParens() const {
+ if (isa<ParenTypeLoc>(this))
+ return IgnoreParensImpl(*this);
+ return *this;
+ }
+
/// \brief Initializes this to state that every location in this
/// type is the given location.
///
/// This method exists to provide a simple transition for code that
/// relies on location-less types.
- void initialize(SourceLocation Loc) const {
- initializeImpl(*this, Loc);
+ void initialize(ASTContext &Context, SourceLocation Loc) const {
+ initializeImpl(Context, *this, Loc);
+ }
+
+ /// \brief Initializes this by copying its information from another
+ /// TypeLoc of the same type.
+ void initializeFullCopy(TypeLoc Other) const {
+ assert(getType() == Other.getType());
+ size_t Size = getFullDataSize();
+ memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ }
+
+ /// \brief Initializes this by copying its information from another
+ /// TypeLoc of the same type. The given size must be the full data
+ /// size.
+ void initializeFullCopy(TypeLoc Other, unsigned Size) const {
+ assert(getType() == Other.getType());
+ assert(getFullDataSize() == Size);
+ memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
}
friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
@@ -135,8 +159,9 @@ public:
static bool classof(const TypeLoc *TL) { return true; }
private:
- static void initializeImpl(TypeLoc TL, SourceLocation Loc);
+ static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc);
static TypeLoc getNextTypeLocImpl(TypeLoc TL);
+ static TypeLoc IgnoreParensImpl(TypeLoc TL);
static SourceRange getLocalSourceRangeImpl(TypeLoc TL);
};
@@ -146,14 +171,14 @@ inline TypeLoc TypeSourceInfo::getTypeLoc() const {
}
/// \brief Wrapper of type source information for a type with
-/// no direct quqlaifiers.
+/// no direct qualifiers.
class UnqualTypeLoc : public TypeLoc {
public:
UnqualTypeLoc() {}
- UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
+ UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
- Type *getTypePtr() const {
- return reinterpret_cast<Type*>(Ty);
+ const Type *getTypePtr() const {
+ return reinterpret_cast<const Type*>(Ty);
}
TypeLocClass getTypeLocClass() const {
@@ -183,7 +208,7 @@ public:
/// Initializes the local data of this type source info block to
/// provide no information.
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
// do nothing
}
@@ -282,7 +307,7 @@ public:
return getNextTypeLoc(asDerived()->getInnerType());
}
- TypeClass *getTypePtr() const {
+ const TypeClass *getTypePtr() const {
return cast<TypeClass>(Base::getTypePtr());
}
@@ -355,7 +380,7 @@ public:
return true;
}
- TypeClass *getTypePtr() const {
+ const TypeClass *getTypePtr() const {
return cast<TypeClass>(Base::getTypePtr());
}
};
@@ -383,7 +408,7 @@ public:
SourceRange getLocalSourceRange() const {
return SourceRange(getNameLoc(), getNameLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
}
@@ -484,7 +509,7 @@ public:
getWrittenBuiltinSpecs().ModeAttr = written;
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setBuiltinLoc(Loc);
if (needsExtraLocalData()) {
WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs();
@@ -568,6 +593,137 @@ class SubstTemplateTypeParmTypeLoc :
SubstTemplateTypeParmType> {
};
+ /// \brief Wrapper for substituted template type parameters.
+class SubstTemplateTypeParmPackTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ SubstTemplateTypeParmPackTypeLoc,
+ SubstTemplateTypeParmPackType> {
+};
+
+struct AttributedLocInfo {
+ union {
+ Expr *ExprOperand;
+
+ /// A raw SourceLocation.
+ unsigned EnumOperandLoc;
+ };
+
+ SourceRange OperandParens;
+
+ SourceLocation AttrLoc;
+};
+
+/// \brief Type source information for an attributed type.
+class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ AttributedTypeLoc,
+ AttributedType,
+ AttributedLocInfo> {
+public:
+ AttributedType::Kind getAttrKind() const {
+ return getTypePtr()->getAttrKind();
+ }
+
+ bool hasAttrExprOperand() const {
+ return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
+ getAttrKind() <= AttributedType::LastExprOperandKind);
+ }
+
+ bool hasAttrEnumOperand() const {
+ return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
+ getAttrKind() <= AttributedType::LastEnumOperandKind);
+ }
+
+ bool hasAttrOperand() const {
+ return hasAttrExprOperand() || hasAttrEnumOperand();
+ }
+
+ /// The modified type, which is generally canonically different from
+ /// the attribute type.
+ /// int main(int, char**) __attribute__((noreturn))
+ /// ~~~ ~~~~~~~~~~~~~
+ TypeLoc getModifiedLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ /// The location of the attribute name, i.e.
+ /// __attribute__((regparm(1000)))
+ /// ^~~~~~~
+ SourceLocation getAttrNameLoc() const {
+ return getLocalData()->AttrLoc;
+ }
+ void setAttrNameLoc(SourceLocation loc) {
+ getLocalData()->AttrLoc = loc;
+ }
+
+ /// The attribute's expression operand, if it has one.
+ /// void *cur_thread __attribute__((address_space(21)))
+ /// ^~
+ Expr *getAttrExprOperand() const {
+ assert(hasAttrExprOperand());
+ return getLocalData()->ExprOperand;
+ }
+ void setAttrExprOperand(Expr *e) {
+ assert(hasAttrExprOperand());
+ getLocalData()->ExprOperand = e;
+ }
+
+ /// The location of the attribute's enumerated operand, if it has one.
+ /// void * __attribute__((objc_gc(weak)))
+ /// ^~~~
+ SourceLocation getAttrEnumOperandLoc() const {
+ assert(hasAttrEnumOperand());
+ return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
+ }
+ void setAttrEnumOperandLoc(SourceLocation loc) {
+ assert(hasAttrEnumOperand());
+ getLocalData()->EnumOperandLoc = loc.getRawEncoding();
+ }
+
+ /// The location of the parentheses around the operand, if there is
+ /// an operand.
+ /// void * __attribute__((objc_gc(weak)))
+ /// ^ ^
+ SourceRange getAttrOperandParensRange() const {
+ assert(hasAttrOperand());
+ return getLocalData()->OperandParens;
+ }
+ void setAttrOperandParensRange(SourceRange range) {
+ assert(hasAttrOperand());
+ getLocalData()->OperandParens = range;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ // Note that this does *not* include the range of the attribute
+ // enclosure, e.g.:
+ // __attribute__((foo(bar)))
+ // ^~~~~~~~~~~~~~~ ~~
+ // or
+ // [[foo(bar)]]
+ // ^~ ~~
+ // That enclosure doesn't necessarily belong to a single attribute
+ // anyway.
+ SourceRange range(getAttrNameLoc());
+ if (hasAttrOperand())
+ range.setEnd(getAttrOperandParensRange().getEnd());
+ return range;
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation loc) {
+ setAttrNameLoc(loc);
+ if (hasAttrExprOperand()) {
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrExprOperand(0);
+ } else if (hasAttrEnumOperand()) {
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrEnumOperandLoc(loc);
+ }
+ }
+
+ QualType getInnerType() const {
+ return getTypePtr()->getModifiedType();
+ }
+};
+
struct ObjCProtocolListLocInfo {
SourceLocation LAngleLoc;
@@ -638,7 +794,7 @@ public:
return SourceRange(getLAngleLoc(), getRAngleLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
@@ -682,11 +838,51 @@ public:
return SourceRange(getNameLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
}
};
+struct ParenLocInfo {
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
+};
+
+class ParenTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
+ ParenLocInfo> {
+public:
+ SourceLocation getLParenLoc() const {
+ return this->getLocalData()->LParenLoc;
+ }
+ SourceLocation getRParenLoc() const {
+ return this->getLocalData()->RParenLoc;
+ }
+ void setLParenLoc(SourceLocation Loc) {
+ this->getLocalData()->LParenLoc = Loc;
+ }
+ void setRParenLoc(SourceLocation Loc) {
+ this->getLocalData()->RParenLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ }
+
+ TypeLoc getInnerLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getInnerType();
+ }
+};
+
struct PointerLikeLocInfo {
SourceLocation StarLoc;
@@ -712,7 +908,7 @@ public:
return SourceRange(getSigilLoc(), getSigilLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setSigilLoc(Loc);
}
@@ -812,6 +1008,7 @@ public:
struct FunctionLocInfo {
SourceLocation LParenLoc, RParenLoc;
+ bool TrailingReturn;
};
/// \brief Wrapper for source info for functions.
@@ -819,11 +1016,6 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
FunctionTypeLoc,
FunctionType,
FunctionLocInfo> {
- // ParmVarDecls* are stored after Info, one for each argument.
- ParmVarDecl **getParmArray() const {
- return (ParmVarDecl**) getExtraLocalData();
- }
-
public:
SourceLocation getLParenLoc() const {
return getLocalData()->LParenLoc;
@@ -839,6 +1031,18 @@ public:
getLocalData()->RParenLoc = Loc;
}
+ bool getTrailingReturn() const {
+ return getLocalData()->TrailingReturn;
+ }
+ void setTrailingReturn(bool Trailing) {
+ getLocalData()->TrailingReturn = Trailing;
+ }
+
+ // ParmVarDecls* are stored after Info, one for each argument.
+ ParmVarDecl **getParmArray() const {
+ return (ParmVarDecl**) getExtraLocalData();
+ }
+
unsigned getNumArgs() const {
if (isa<FunctionNoProtoType>(getTypePtr()))
return 0;
@@ -855,9 +1059,10 @@ public:
return SourceRange(getLParenLoc(), getRParenLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLParenLoc(Loc);
setRParenLoc(Loc);
+ setTrailingReturn(false);
for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
setArg(i, NULL);
}
@@ -928,7 +1133,7 @@ public:
return SourceRange(getLBracketLoc(), getRBracketLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLBracketLoc(Loc);
setRBracketLoc(Loc);
setSizeExpr(NULL);
@@ -997,9 +1202,6 @@ public:
return getTypePtr()->getNumArgs();
}
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
-#ifndef NDEBUG
- AI.validateForArgument(getTypePtr()->getArg(i));
-#endif
getArgInfos()[i] = AI;
}
TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
@@ -1033,47 +1235,18 @@ public:
return SourceRange(getTemplateNameLoc(), getRAngleLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLAngleLoc(Loc);
setRAngleLoc(Loc);
setTemplateNameLoc(Loc);
- initializeArgLocs(getNumArgs(), getTypePtr()->getArgs(),
+ initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
getArgInfos(), Loc);
}
- static void initializeArgLocs(unsigned NumArgs,
+ static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
const TemplateArgument *Args,
TemplateArgumentLocInfo *ArgInfos,
- SourceLocation Loc) {
- for (unsigned i = 0, e = NumArgs; i != e; ++i) {
- TemplateArgumentLocInfo Info;
-#ifndef NDEBUG
- // If asserts are enabled, be sure to initialize the argument
- // loc with the right kind of pointer.
- switch (Args[i].getKind()) {
- case TemplateArgument::Expression:
- case TemplateArgument::Declaration:
- Info = TemplateArgumentLocInfo((Expr*) 0);
- break;
-
- case TemplateArgument::Type:
- Info = TemplateArgumentLocInfo((TypeSourceInfo*) 0);
- break;
-
- case TemplateArgument::Template:
- Info = TemplateArgumentLocInfo(SourceRange(Loc), Loc);
- break;
-
- case TemplateArgument::Integral:
- case TemplateArgument::Pack:
- case TemplateArgument::Null:
- // K_None is fine.
- break;
- }
-#endif
- ArgInfos[i] = Info;
- }
- }
+ SourceLocation Loc);
unsigned getExtraLocalDataSize() const {
return getNumArgs() * sizeof(TemplateArgumentLocInfo);
@@ -1168,7 +1341,7 @@ public:
return SourceRange(getTypeofLoc(), getRParenLoc());
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setTypeofLoc(Loc);
setLParenLoc(Loc);
setRParenLoc(Loc);
@@ -1208,6 +1381,11 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
DecltypeType> {
};
+class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ AutoTypeLoc,
+ AutoType> {
+};
+
struct ElaboratedLocInfo {
SourceLocation KeywordLoc;
SourceRange QualifierRange;
@@ -1242,7 +1420,7 @@ public:
return getQualifierRange();
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setKeywordLoc(Loc);
setQualifierRange(SourceRange(Loc));
}
@@ -1307,7 +1485,7 @@ public:
memcpy(Data, Loc.Data, size);
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setKeywordLoc(Loc);
setQualifierRange(SourceRange(Loc));
setNameLoc(Loc);
@@ -1368,9 +1546,6 @@ public:
}
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
-#ifndef NDEBUG
- AI.validateForArgument(getTypePtr()->getArg(i));
-#endif
getArgInfos()[i] = AI;
}
TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
@@ -1394,13 +1569,13 @@ public:
memcpy(Data, Loc.Data, size);
}
- void initializeLocal(SourceLocation Loc) {
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setKeywordLoc(Loc);
setQualifierRange(SourceRange(Loc));
setNameLoc(Loc);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
- TemplateSpecializationTypeLoc::initializeArgLocs(getNumArgs(),
+ TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
getTypePtr()->getArgs(),
getArgInfos(), Loc);
}
@@ -1415,6 +1590,40 @@ private:
}
};
+
+struct PackExpansionTypeLocInfo {
+ SourceLocation EllipsisLoc;
+};
+
+class PackExpansionTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc,
+ PackExpansionType, PackExpansionTypeLocInfo> {
+public:
+ SourceLocation getEllipsisLoc() const {
+ return this->getLocalData()->EllipsisLoc;
+ }
+
+ void setEllipsisLoc(SourceLocation Loc) {
+ this->getLocalData()->EllipsisLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getEllipsisLoc(), getEllipsisLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setEllipsisLoc(Loc);
+ }
+
+ TypeLoc getPatternLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getPattern();
+ }
+};
+
}
#endif
diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h
deleted file mode 100644
index 880af267f324..000000000000
--- a/include/clang/AST/TypeLocBuilder.h
+++ /dev/null
@@ -1,155 +0,0 @@
-//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This files defines TypeLocBuilder, a class for building TypeLocs
-// bottom-up.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_AST_TYPELOCBUILDER_H
-#define LLVM_CLANG_AST_TYPELOCBUILDER_H
-
-#include "clang/AST/TypeLoc.h"
-#include "llvm/ADT/SmallVector.h"
-#include "clang/AST/ASTContext.h"
-
-namespace clang {
-
-class TypeLocBuilder {
- enum { InlineCapacity = 8 * sizeof(SourceLocation) };
-
- /// The underlying location-data buffer. Data grows from the end
- /// of the buffer backwards.
- char *Buffer;
-
- /// The capacity of the current buffer.
- size_t Capacity;
-
- /// The index of the first occupied byte in the buffer.
- size_t Index;
-
-#ifndef NDEBUG
- /// The last type pushed on this builder.
- QualType LastTy;
-#endif
-
- /// The inline buffer.
- char InlineBuffer[InlineCapacity];
-
- public:
- TypeLocBuilder()
- : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
- {}
-
- ~TypeLocBuilder() {
- if (Buffer != InlineBuffer)
- delete[] Buffer;
- }
-
- /// Ensures that this buffer has at least as much capacity as described.
- void reserve(size_t Requested) {
- if (Requested > Capacity)
- // For now, match the request exactly.
- grow(Requested);
- }
-
- /// Pushes a copy of the given TypeLoc onto this builder. The builder
- /// must be empty for this to work.
- void pushFullCopy(TypeLoc L) {
-#ifndef NDEBUG
- assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder");
- LastTy = L.getNextTypeLoc().getType();
-#endif
- assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder");
-
- unsigned Size = L.getFullDataSize();
- TypeLoc Copy = pushImpl(L.getType(), Size);
- memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
- }
-
- /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
- /// previously retrieved from this builder.
- TypeSpecTypeLoc pushTypeSpec(QualType T) {
- size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
- return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
- }
-
- /// Resets this builder to the newly-initialized state.
- void clear() {
-#ifndef NDEBUG
- LastTy = QualType();
-#endif
- Index = Capacity;
- }
-
- /// Pushes space for a new TypeLoc of the given type. Invalidates
- /// any TypeLocs previously retrieved from this builder.
- template <class TyLocType> TyLocType push(QualType T) {
- size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
- return cast<TyLocType>(pushImpl(T, LocalSize));
- }
-
- /// Creates a TypeSourceInfo for the given type.
- TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
-#ifndef NDEBUG
- assert(T == LastTy && "type doesn't match last type pushed!");
-#endif
-
- size_t FullDataSize = Capacity - Index;
- TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
- memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
- return DI;
- }
-
-private:
- TypeLoc pushImpl(QualType T, size_t LocalSize) {
-#ifndef NDEBUG
- QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
- assert(TLast == LastTy &&
- "mismatch between last type and new type's inner type");
- LastTy = T;
-#endif
-
- // If we need to grow, grow by a factor of 2.
- if (LocalSize > Index) {
- size_t RequiredCapacity = Capacity + (LocalSize - Index);
- size_t NewCapacity = Capacity * 2;
- while (RequiredCapacity > NewCapacity)
- NewCapacity *= 2;
- grow(NewCapacity);
- }
-
- Index -= LocalSize;
-
- return TypeLoc(T, &Buffer[Index]);
- }
-
- /// Grow to the given capacity.
- void grow(size_t NewCapacity) {
- assert(NewCapacity > Capacity);
-
- // Allocate the new buffer and copy the old data into it.
- char *NewBuffer = new char[NewCapacity];
- unsigned NewIndex = Index + NewCapacity - Capacity;
- memcpy(&NewBuffer[NewIndex],
- &Buffer[Index],
- Capacity - Index);
-
- if (Buffer != InlineBuffer)
- delete[] Buffer;
-
- Buffer = NewBuffer;
- Capacity = NewCapacity;
- Index = NewIndex;
- }
-};
-
-}
-
-#endif
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 9cb56861a9ef..b2591cc0fbac 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -79,6 +79,7 @@ ABSTRACT_TYPE(Function, Type)
TYPE(FunctionProto, FunctionType)
TYPE(FunctionNoProto, FunctionType)
DEPENDENT_TYPE(UnresolvedUsing, Type)
+NON_CANONICAL_TYPE(Paren, Type)
NON_CANONICAL_TYPE(Typedef, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
@@ -87,12 +88,16 @@ ABSTRACT_TYPE(Tag, Type)
TYPE(Record, TagType)
TYPE(Enum, TagType)
NON_CANONICAL_TYPE(Elaborated, Type)
+NON_CANONICAL_TYPE(Attributed, Type)
DEPENDENT_TYPE(TemplateTypeParm, Type)
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
+DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type)
DEPENDENT_TYPE(InjectedClassName, Type)
DEPENDENT_TYPE(DependentName, Type)
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
+DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h
index 5c9c5285a248..c52926b1fc31 100644
--- a/include/clang/AST/TypeVisitor.h
+++ b/include/clang/AST/TypeVisitor.h
@@ -19,12 +19,13 @@
namespace clang {
#define DISPATCH(CLASS) \
- return static_cast<ImplClass*>(this)->Visit ## CLASS(static_cast<CLASS*>(T))
+ return static_cast<ImplClass*>(this)-> \
+ Visit##CLASS(static_cast<const CLASS*>(T))
template<typename ImplClass, typename RetTy=void>
class TypeVisitor {
public:
- RetTy Visit(Type *T) {
+ RetTy Visit(const Type *T) {
// Top switch stmt: dispatch to VisitFooType for each FooType.
switch (T->getTypeClass()) {
default: assert(0 && "Unknown type class!");
@@ -36,13 +37,13 @@ public:
// If the implementation chooses not to implement a certain visit method, fall
// back on superclass.
-#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(CLASS##Type *T) { \
+#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \
DISPATCH(PARENT); \
}
#include "clang/AST/TypeNodes.def"
// Base case, ignore it. :)
- RetTy VisitType(Type*) { return RetTy(); }
+ RetTy VisitType(const Type*) { return RetTy(); }
};
#undef DISPATCH
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 280b1260ac26..7cc76a8d471b 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -379,6 +379,7 @@ using analyze_format_string::OptionalAmount;
using analyze_format_string::OptionalFlag;
class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
+ OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
OptionalFlag IsLeftJustified; // '-'
OptionalFlag HasPlusPrefix; // '+'
OptionalFlag HasSpacePrefix; // ' '
@@ -388,8 +389,8 @@ class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
public:
PrintfSpecifier() :
FormatSpecifier(/* isPrintf = */ true),
- IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
- HasAlternativeForm("#"), HasLeadingZeroes("0") {}
+ HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"),
+ HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0") {}
static PrintfSpecifier Parse(const char *beg, const char *end);
@@ -397,6 +398,10 @@ public:
void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
CS = cs;
}
+ void setHasThousandsGrouping(const char *position) {
+ HasThousandsGrouping = true;
+ HasThousandsGrouping.setPosition(position);
+ }
void setIsLeftJustified(const char *position) {
IsLeftJustified = true;
IsLeftJustified.setPosition(position);
@@ -445,6 +450,9 @@ public:
/// more than one type.
ArgTypeResult getArgType(ASTContext &Ctx) const;
+ const OptionalFlag &hasThousandsGrouping() const {
+ return HasThousandsGrouping;
+ }
const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
@@ -465,6 +473,7 @@ public:
bool hasValidLeadingZeros() const;
bool hasValidSpacePrefix() const;
bool hasValidLeftJustified() const;
+ bool hasValidThousandsGroupingPrefix() const;
bool hasValidPrecision() const;
bool hasValidFieldWidth() const;
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 237fe14aed4f..fbbd2613e7c2 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -55,7 +55,8 @@ struct LiveVariables_ValueTypes {
/// ObserveStmt - A callback invoked right before invoking the
/// liveness transfer function on the given statement.
- virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD,
+ virtual void ObserveStmt(Stmt* S, const CFGBlock *currentBlock,
+ const AnalysisDataTy& AD,
const ValTy& V) {}
virtual void ObserverKill(DeclRefExpr* DR) {}
diff --git a/include/clang/Analysis/Analyses/UninitializedValuesV2.h b/include/clang/Analysis/Analyses/UninitializedValuesV2.h
new file mode 100644
index 000000000000..c1fe040793e1
--- /dev/null
+++ b/include/clang/Analysis/Analyses/UninitializedValuesV2.h
@@ -0,0 +1,40 @@
+//= UninitializedValuesV2.h - Finding uses of uninitialized values --*- 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 APIs for invoking and reported uninitialized values
+// warnings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNINIT_VALS_H
+#define LLVM_CLANG_UNINIT_VALS_H
+
+namespace clang {
+
+class AnalysisContext;
+class CFG;
+class DeclContext;
+class Expr;
+class VarDecl;
+
+class UninitVariablesHandler {
+public:
+ UninitVariablesHandler() {}
+ virtual ~UninitVariablesHandler();
+
+ virtual void handleUseOfUninitVariable(const Expr *ex,
+ const VarDecl *vd) {}
+};
+
+void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
+ AnalysisContext &ac,
+ UninitVariablesHandler &handler);
+
+}
+#endif
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 7d4d25f8b0d8..2ecbfdc6bf02 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
@@ -56,15 +57,20 @@ class AnalysisContext {
llvm::BumpPtrAllocator A;
bool UseUnoptimizedCFG;
bool AddEHEdges;
+ bool AddImplicitDtors;
+ bool AddInitializers;
public:
AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
bool useUnoptimizedCFG = false,
- bool addehedges = false)
+ bool addehedges = false,
+ bool addImplicitDtors = false,
+ bool addInitializers = false)
: D(d), TU(tu), cfg(0), completeCFG(0),
builtCFG(false), builtCompleteCFG(false),
liveness(0), relaxedLiveness(0), PM(0), PCA(0),
ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
- AddEHEdges(addehedges) {}
+ AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
+ AddInitializers(addInitializers) {}
~AnalysisContext();
@@ -80,13 +86,17 @@ public:
bool getAddEHEdges() const { return AddEHEdges; }
bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+ bool getAddImplicitDtors() const { return AddImplicitDtors; }
+ bool getAddInitializers() const { return AddInitializers; }
Stmt *getBody();
CFG *getCFG();
-
+
/// Return a version of the CFG without any edges pruned.
CFG *getUnoptimizedCFG();
+ void dumpCFG();
+
ParentMap &getParentMap();
PseudoConstantAnalysis *getPseudoConstantAnalysis();
LiveVariables *getLiveVariables();
@@ -106,15 +116,21 @@ class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts;
bool UseUnoptimizedCFG;
+ bool AddImplicitDtors;
+ bool AddInitializers;
public:
- AnalysisContextManager(bool useUnoptimizedCFG = false)
- : UseUnoptimizedCFG(useUnoptimizedCFG) {}
+ AnalysisContextManager(bool useUnoptimizedCFG = false,
+ bool addImplicitDtors = false, bool addInitializers = false)
+ : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
+ AddInitializers(addInitializers) {}
~AnalysisContextManager();
AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+ bool getAddImplicitDtors() const { return AddImplicitDtors; }
+ bool getAddInitializers() const { return AddInitializers; }
// Discard all previously created AnalysisContexts.
void clear();
@@ -196,9 +212,10 @@ class StackFrameContext : public LocationContext {
friend class LocationContextManager;
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
- const Stmt *s, const CFGBlock *blk, unsigned idx)
- : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
- Index(idx) {}
+ const Stmt *s, const CFGBlock *blk,
+ unsigned idx)
+ : LocationContext(StackFrame, ctx, parent), CallSite(s),
+ Block(blk), Index(idx) {}
public:
~StackFrameContext() {}
@@ -282,8 +299,8 @@ public:
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
const LocationContext *parent,
- const Stmt *s, const CFGBlock *blk,
- unsigned idx);
+ const Stmt *s,
+ const CFGBlock *blk, unsigned idx);
const ScopeContext *getScope(AnalysisContext *ctx,
const LocationContext *parent,
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index e98a3df472a8..295d0a2133d3 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define ANALYSISSTART
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#undef DIAG
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index b7a8e1159693..b337d74495c9 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -22,14 +22,21 @@
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
+#include <iterator>
namespace llvm {
class raw_ostream;
}
+
namespace clang {
class Decl;
class Stmt;
class Expr;
+ class FieldDecl;
+ class VarDecl;
+ class CXXCtorInitializer;
+ class CXXBaseSpecifier;
+ class CXXBindTemporaryExpr;
class CFG;
class PrinterHelper;
class LangOptions;
@@ -37,19 +44,203 @@ namespace clang {
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
- llvm::PointerIntPair<Stmt *, 2> Data;
public:
- enum Type { StartScope, EndScope };
- explicit CFGElement() {}
- CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
- CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {}
- Stmt *getStmt() const { return Data.getPointer(); }
- bool asLValue() const { return Data.getInt() == 1; }
- bool asStartScope() const { return Data.getInt() == 2; }
- bool asEndScope() const { return Data.getInt() == 3; }
- bool asDtor() const { return Data.getInt() == 4; }
+ enum Kind {
+ // main kind
+ Statement,
+ Initializer,
+ ImplicitDtor,
+ // dtor kind
+ AutomaticObjectDtor,
+ BaseDtor,
+ MemberDtor,
+ TemporaryDtor,
+ DTOR_BEGIN = AutomaticObjectDtor
+ };
+
+protected:
+ // The int bits are used to mark the main kind.
+ llvm::PointerIntPair<void *, 2> Data1;
+ // The int bits are used to mark the dtor kind.
+ llvm::PointerIntPair<void *, 2> Data2;
+
+ CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {}
+ CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2)
+ : Data1(Ptr1, Int1), Data2(Ptr2, Int2) {}
+
+public:
+ CFGElement() {}
+
+ Kind getKind() const { return static_cast<Kind>(Data1.getInt()); }
+
+ Kind getDtorKind() const {
+ assert(getKind() == ImplicitDtor);
+ return static_cast<Kind>(Data2.getInt() + DTOR_BEGIN);
+ }
+
+ bool isValid() const { return Data1.getPointer(); }
+
+ operator bool() const { return isValid(); }
+
+ template<class ElemTy> ElemTy getAs() const {
+ if (llvm::isa<ElemTy>(this))
+ return *static_cast<const ElemTy*>(this);
+ return ElemTy();
+ }
+
+ static bool classof(const CFGElement *E) { return true; }
+};
+
+class CFGStmt : public CFGElement {
+public:
+ CFGStmt() {}
+ CFGStmt(Stmt *S) : CFGElement(S, 0) {}
+
+ Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); }
+
operator Stmt*() const { return getStmt(); }
- operator bool() const { return getStmt() != 0; }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == Statement;
+ }
+};
+
+/// CFGInitializer - Represents C++ base or member initializer from
+/// constructor's initialization list.
+class CFGInitializer : public CFGElement {
+public:
+ CFGInitializer() {}
+ CFGInitializer(CXXCtorInitializer* I)
+ : CFGElement(I, Initializer) {}
+
+ CXXCtorInitializer* getInitializer() const {
+ return static_cast<CXXCtorInitializer*>(Data1.getPointer());
+ }
+ operator CXXCtorInitializer*() const { return getInitializer(); }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == Initializer;
+ }
+};
+
+/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
+/// by compiler on various occasions.
+class CFGImplicitDtor : public CFGElement {
+protected:
+ CFGImplicitDtor(unsigned K, void* P, void* S)
+ : CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {}
+
+public:
+ CFGImplicitDtor() {}
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor;
+ }
+};
+
+/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
+/// for automatic object or temporary bound to const reference at the point
+/// of leaving its local scope.
+class CFGAutomaticObjDtor: public CFGImplicitDtor {
+public:
+ CFGAutomaticObjDtor() {}
+ CFGAutomaticObjDtor(VarDecl* VD, Stmt* S)
+ : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {}
+
+ VarDecl* getVarDecl() const {
+ return static_cast<VarDecl*>(Data1.getPointer());
+ }
+
+ // Get statement end of which triggered the destructor call.
+ Stmt* getTriggerStmt() const {
+ return static_cast<Stmt*>(Data2.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor &&
+ E->getDtorKind() == AutomaticObjectDtor;
+ }
+};
+
+/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
+/// base object in destructor.
+class CFGBaseDtor : public CFGImplicitDtor {
+public:
+ CFGBaseDtor() {}
+ CFGBaseDtor(const CXXBaseSpecifier *BS)
+ : CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {}
+
+ const CXXBaseSpecifier *getBaseSpecifier() const {
+ return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor;
+ }
+};
+
+/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
+/// member object in destructor.
+class CFGMemberDtor : public CFGImplicitDtor {
+public:
+ CFGMemberDtor() {}
+ CFGMemberDtor(FieldDecl *FD)
+ : CFGImplicitDtor(MemberDtor, FD, NULL) {}
+
+ FieldDecl *getFieldDecl() const {
+ return static_cast<FieldDecl*>(Data1.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor;
+ }
+};
+
+/// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
+/// at the end of full expression for temporary object.
+class CFGTemporaryDtor : public CFGImplicitDtor {
+public:
+ CFGTemporaryDtor() {}
+ CFGTemporaryDtor(CXXBindTemporaryExpr *E)
+ : CFGImplicitDtor(TemporaryDtor, E, NULL) {}
+
+ CXXBindTemporaryExpr *getBindTemporaryExpr() const {
+ return static_cast<CXXBindTemporaryExpr *>(Data1.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor;
+ }
+};
+
+/// CFGTerminator - Represents CFGBlock terminator statement.
+///
+/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
+/// in control flow of destructors of temporaries. In this case terminator
+/// statement is the same statement that branches control flow in evaluation
+/// of matching full expression.
+class CFGTerminator {
+ llvm::PointerIntPair<Stmt *, 1> Data;
+public:
+ CFGTerminator() {}
+ CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
+ : Data(S, TemporaryDtorsBranch) {}
+
+ Stmt *getStmt() { return Data.getPointer(); }
+ const Stmt *getStmt() const { return Data.getPointer(); }
+
+ bool isTemporaryDtorsBranch() const { return Data.getInt(); }
+
+ operator Stmt *() { return getStmt(); }
+ operator const Stmt *() const { return getStmt(); }
+
+ Stmt *operator->() { return getStmt(); }
+ const Stmt *operator->() const { return getStmt(); }
+
+ Stmt &operator*() { return *getStmt(); }
+ const Stmt &operator*() const { return *getStmt(); }
+
+ operator bool() const { return getStmt(); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
@@ -77,11 +268,11 @@ public:
/// &&, || expression that uses result of && or ||, RHS
///
class CFGBlock {
- class StatementList {
+ class ElementList {
typedef BumpVector<CFGElement> ImplTy;
ImplTy Impl;
public:
- StatementList(BumpVectorContext &C) : Impl(C, 4) {}
+ ElementList(BumpVectorContext &C) : Impl(C, 4) {}
typedef std::reverse_iterator<ImplTy::iterator> iterator;
typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
@@ -89,6 +280,11 @@ class CFGBlock {
typedef ImplTy::const_iterator const_reverse_iterator;
void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
+ reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
+ BumpVectorContext& C) {
+ return Impl.insert(I, Cnt, E, C);
+ }
+
CFGElement front() const { return Impl.back(); }
CFGElement back() const { return Impl.front(); }
@@ -111,7 +307,7 @@ class CFGBlock {
};
/// Stmts - The set of statements in the basic block.
- StatementList Stmts;
+ ElementList Elements;
/// Label - An (optional) label that prefixes the executable
/// statements in the block. When this variable is non-NULL, it is
@@ -121,7 +317,7 @@ class CFGBlock {
/// Terminator - The terminator for a basic block that
/// indicates the type of control-flow that occurs between a block
/// and its successors.
- Stmt *Terminator;
+ CFGTerminator Terminator;
/// LoopTarget - Some blocks are used to represent the "loop edge" to
/// the start of a loop from within the loop body. This Stmt* will be
@@ -140,33 +336,33 @@ class CFGBlock {
public:
explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
- : Stmts(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
+ : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
BlockID(blockid), Preds(C, 1), Succs(C, 1) {}
~CFGBlock() {}
// Statement iterators
- typedef StatementList::iterator iterator;
- typedef StatementList::const_iterator const_iterator;
- typedef StatementList::reverse_iterator reverse_iterator;
- typedef StatementList::const_reverse_iterator const_reverse_iterator;
+ typedef ElementList::iterator iterator;
+ typedef ElementList::const_iterator const_iterator;
+ typedef ElementList::reverse_iterator reverse_iterator;
+ typedef ElementList::const_reverse_iterator const_reverse_iterator;
- CFGElement front() const { return Stmts.front(); }
- CFGElement back() const { return Stmts.back(); }
+ CFGElement front() const { return Elements.front(); }
+ CFGElement back() const { return Elements.back(); }
- iterator begin() { return Stmts.begin(); }
- iterator end() { return Stmts.end(); }
- const_iterator begin() const { return Stmts.begin(); }
- const_iterator end() const { return Stmts.end(); }
+ iterator begin() { return Elements.begin(); }
+ iterator end() { return Elements.end(); }
+ const_iterator begin() const { return Elements.begin(); }
+ const_iterator end() const { return Elements.end(); }
- reverse_iterator rbegin() { return Stmts.rbegin(); }
- reverse_iterator rend() { return Stmts.rend(); }
- const_reverse_iterator rbegin() const { return Stmts.rbegin(); }
- const_reverse_iterator rend() const { return Stmts.rend(); }
+ reverse_iterator rbegin() { return Elements.rbegin(); }
+ reverse_iterator rend() { return Elements.rend(); }
+ const_reverse_iterator rbegin() const { return Elements.rbegin(); }
+ const_reverse_iterator rend() const { return Elements.rend(); }
- unsigned size() const { return Stmts.size(); }
- bool empty() const { return Stmts.empty(); }
+ unsigned size() const { return Elements.size(); }
+ bool empty() const { return Elements.empty(); }
- CFGElement operator[](size_t i) const { return Stmts[i]; }
+ CFGElement operator[](size_t i) const { return Elements[i]; }
// CFG iterators
typedef AdjacentBlocks::iterator pred_iterator;
@@ -205,14 +401,67 @@ public:
unsigned pred_size() const { return Preds.size(); }
bool pred_empty() const { return Preds.empty(); }
+
+ class FilterOptions {
+ public:
+ FilterOptions() {
+ IgnoreDefaultsWithCoveredEnums = 0;
+ }
+
+ unsigned IgnoreDefaultsWithCoveredEnums : 1;
+ };
+
+ static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
+ const CFGBlock *Dst);
+
+ template <typename IMPL, bool IsPred>
+ class FilteredCFGBlockIterator {
+ private:
+ IMPL I, E;
+ const FilterOptions F;
+ const CFGBlock *From;
+ public:
+ explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
+ const CFGBlock *from,
+ const FilterOptions &f)
+ : I(i), E(e), F(f), From(from) {}
+
+ bool hasMore() const { return I != E; }
+
+ FilteredCFGBlockIterator &operator++() {
+ do { ++I; } while (hasMore() && Filter(*I));
+ return *this;
+ }
+
+ const CFGBlock *operator*() const { return *I; }
+ private:
+ bool Filter(const CFGBlock *To) {
+ return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
+ }
+ };
+
+ typedef FilteredCFGBlockIterator<const_pred_iterator, true>
+ filtered_pred_iterator;
+
+ typedef FilteredCFGBlockIterator<const_succ_iterator, false>
+ filtered_succ_iterator;
+
+ filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const {
+ return filtered_pred_iterator(pred_begin(), pred_end(), this, f);
+ }
+
+ filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const {
+ return filtered_succ_iterator(succ_begin(), succ_end(), this, f);
+ }
+
// Manipulation of block contents
void setTerminator(Stmt* Statement) { Terminator = Statement; }
void setLabel(Stmt* Statement) { Label = Statement; }
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
- Stmt* getTerminator() { return Terminator; }
- const Stmt* getTerminator() const { return Terminator; }
+ CFGTerminator getTerminator() { return Terminator; }
+ const CFGTerminator getTerminator() const { return Terminator; }
Stmt* getTerminatorCondition();
@@ -239,17 +488,39 @@ public:
Succs.push_back(Block, C);
}
- void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) {
- Stmts.push_back(CFGElement(Statement, asLValue), C);
- }
- void StartScope(Stmt* S, BumpVectorContext &C) {
- Stmts.push_back(CFGElement(S, CFGElement::StartScope), C);
+ void appendStmt(Stmt* statement, BumpVectorContext &C) {
+ Elements.push_back(CFGStmt(statement), C);
+ }
+
+ void appendInitializer(CXXCtorInitializer *initializer,
+ BumpVectorContext& C) {
+ Elements.push_back(CFGInitializer(initializer), C);
}
- void EndScope(Stmt* S, BumpVectorContext &C) {
- Stmts.push_back(CFGElement(S, CFGElement::EndScope), C);
+
+ void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
+ Elements.push_back(CFGBaseDtor(BS), C);
}
-};
+ void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) {
+ Elements.push_back(CFGMemberDtor(FD), C);
+ }
+
+ void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) {
+ Elements.push_back(CFGTemporaryDtor(E), C);
+ }
+
+ // Destructors must be inserted in reversed order. So insertion is in two
+ // steps. First we prepare space for some number of elements, then we insert
+ // the elements beginning at the last position in prepared space.
+ iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
+ BumpVectorContext& C) {
+ return iterator(Elements.insert(I.base(), Cnt, CFGElement(), C));
+ }
+ iterator insertAutomaticObjDtor(iterator I, VarDecl* VD, Stmt* S) {
+ *I = CFGAutomaticObjDtor(VD, S);
+ return ++I;
+ }
+};
/// CFG - Represents a source-level, intra-procedural CFG that represents the
/// control-flow of a Stmt. The Stmt can represent an entire function body,
@@ -264,13 +535,24 @@ public:
// CFG Construction & Manipulation.
//===--------------------------------------------------------------------===//
+ class BuildOptions {
+ public:
+ bool PruneTriviallyFalseEdges:1;
+ bool AddEHEdges:1;
+ bool AddInitializers:1;
+ bool AddImplicitDtors:1;
+
+ BuildOptions()
+ : PruneTriviallyFalseEdges(true)
+ , AddEHEdges(false)
+ , AddInitializers(false)
+ , AddImplicitDtors(false) {}
+ };
+
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
- bool pruneTriviallyFalseEdges = true,
- bool AddEHEdges = false,
- bool AddScopes = false /* NOT FULLY IMPLEMENTED.
- NOT READY FOR GENERAL USE. */);
+ BuildOptions BO = BuildOptions());
/// createBlock - Create a new block in the CFG. The CFG owns the block;
/// the caller should not directly free it.
@@ -324,8 +606,10 @@ public:
void VisitBlockStmts(CALLBACK& O) const {
for (const_iterator I=begin(), E=end(); I != E; ++I)
for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
- BI != BE; ++BI)
- O(*BI);
+ BI != BE; ++BI) {
+ if (CFGStmt S = BI->getAs<CFGStmt>())
+ O(S);
+ }
}
//===--------------------------------------------------------------------===//
@@ -340,7 +624,10 @@ public:
operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
};
- bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
+ bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
+ bool isBlkExpr(const Stmt *S) const {
+ return const_cast<CFG*>(this)->isBlkExpr(S);
+ }
BlkExprNumTy getBlkExprNum(const Stmt* S);
unsigned getNumBlkExprs();
@@ -398,18 +685,22 @@ private:
namespace llvm {
-/// Implement simplify_type for CFGElement, so that we can dyn_cast from
-/// CFGElement to a specific Stmt class.
-template <> struct simplify_type<const ::clang::CFGElement> {
- typedef ::clang::Stmt* SimpleType;
- static SimpleType getSimplifiedValue(const ::clang::CFGElement &Val) {
+/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
+/// CFGTerminator to a specific Stmt class.
+template <> struct simplify_type<const ::clang::CFGTerminator> {
+ typedef const ::clang::Stmt *SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
return Val.getStmt();
}
};
-
-template <> struct simplify_type< ::clang::CFGElement>
- : public simplify_type<const ::clang::CFGElement> {};
-
+
+template <> struct simplify_type< ::clang::CFGTerminator> {
+ typedef ::clang::Stmt *SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
+ return const_cast<SimpleType>(Val.getStmt());
+ }
+};
+
// Traits for: CFGBlock
template <> struct GraphTraits< ::clang::CFGBlock* > {
diff --git a/include/clang/Checker/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
index 4bbdab0e7fe1..7e6e3815400c 100644
--- a/include/clang/Checker/DomainSpecific/CocoaConventions.h
+++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -11,17 +11,18 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CHECKER_DS_COCOA
-#define LLVM_CLANG_CHECKER_DS_COCOA
+#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA
+#define LLVM_CLANG_ANALYSIS_DS_COCOA
#include "clang/AST/Type.h"
namespace clang {
+namespace ento {
namespace cocoa {
enum NamingConvention { NoConvention, CreateRule, InitRule };
- NamingConvention deriveNamingConvention(Selector S);
+ NamingConvention deriveNamingConvention(Selector S, bool ignorePrefix = true);
static inline bool followsFundamentalRule(Selector S) {
return deriveNamingConvention(S) == CreateRule;
@@ -34,6 +35,6 @@ namespace cocoa {
bool isCocoaObjectRef(QualType T);
-}}
+}}}
#endif
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
index 9375db06be72..d75d333db6b6 100644
--- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h
+++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -273,8 +273,13 @@ private:
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
dataflow::forward_analysis_tag) {
- for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
- ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
+ TF.setCurrentBlock(B);
+
+ for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
+ CFGElement El = *I;
+ if (CFGStmt S = El.getAs<CFGStmt>())
+ ProcessStmt(S, recordStmtValues, AnalysisDirTag());
+ }
TF.VisitTerminator(const_cast<CFGBlock*>(B));
}
@@ -282,10 +287,15 @@ private:
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
dataflow::backward_analysis_tag) {
+ TF.setCurrentBlock(B);
+
TF.VisitTerminator(const_cast<CFGBlock*>(B));
- for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
- ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
+ for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
+ CFGElement El = *I;
+ if (CFGStmt S = El.getAs<CFGStmt>())
+ ProcessStmt(S, recordStmtValues, AnalysisDirTag());
+ }
}
void ProcessStmt(const Stmt* S, bool record, dataflow::forward_analysis_tag) {
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index ba303de7a8da..54cfc3dc0db6 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -17,7 +17,7 @@
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Casting.h"
@@ -44,6 +44,7 @@ public:
PostPurgeDeadSymbolsKind,
PostStmtCustomKind,
PostLValueKind,
+ PostInitializerKind,
CallEnterKind,
CallExitKind,
MinPostStmtKind = PostStmtKind,
@@ -70,11 +71,12 @@ protected:
protected:
const void* getData1() const { return Data.first; }
const void* getData2() const { return Data.second; }
- const void *getTag() const { return Tag; }
public:
Kind getKind() const { return K; }
+ const void *getTag() const { return Tag; }
+
const LocationContext *getLocationContext() const { return L; }
// For use with DenseMap. This hash is probably slow.
@@ -118,10 +120,12 @@ public:
return B->empty() ? CFGElement() : B->front();
}
- const Stmt *getFirstStmt() const {
- return getFirstElement().getStmt();
+ /// Create a new BlockEntrance object that is the same as the original
+ /// except for using the specified tag value.
+ BlockEntrance withTag(const void *tag) {
+ return BlockEntrance(getBlock(), getLocationContext(), tag);
}
-
+
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == BlockEntranceKind;
}
@@ -136,11 +140,6 @@ public:
return reinterpret_cast<const CFGBlock*>(getData1());
}
- const Stmt* getLastStmt() const {
- const CFGBlock* B = getBlock();
- return B->empty() ? CFGElement() : B->back();
- }
-
const Stmt* getTerminator() const {
return getBlock()->getTerminator();
}
@@ -183,14 +182,15 @@ public:
class PostStmt : public StmtPoint {
protected:
- PostStmt(const Stmt* S, Kind k, const LocationContext *L, const void *tag = 0)
- : StmtPoint(S, NULL, k, L, tag) {}
-
PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
const void *tag =0)
: StmtPoint(S, data, k, L, tag) {}
public:
+ explicit PostStmt(const Stmt* S, Kind k,
+ const LocationContext *L, const void *tag = 0)
+ : StmtPoint(S, NULL, k, L, tag) {}
+
explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0)
: StmtPoint(S, NULL, PostStmtKind, L, tag) {}
@@ -313,19 +313,29 @@ public:
}
};
+class PostInitializer : public ProgramPoint {
+public:
+ PostInitializer(const CXXCtorInitializer *I,
+ const LocationContext *L)
+ : ProgramPoint(I, PostInitializerKind, L) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == PostInitializerKind;
+ }
+};
+
class CallEnter : public StmtPoint {
public:
- // L is caller's location context. AC is callee's AnalysisContext.
- CallEnter(const Stmt *S, const AnalysisContext *AC, const LocationContext *L)
- : StmtPoint(S, AC, CallEnterKind, L, 0) {}
+ CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
+ const LocationContext *callerCtx)
+ : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1());
}
- AnalysisContext *getCalleeContext() const {
- return const_cast<AnalysisContext *>(
- static_cast<const AnalysisContext *>(getData2()));
+ const StackFrameContext *getCalleeContext() const {
+ return static_cast<const StackFrameContext *>(getData2());
}
static bool classof(const ProgramPoint *Location) {
diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h
index 7cd481238f81..83532e62babe 100644
--- a/include/clang/Analysis/Support/BumpVector.h
+++ b/include/clang/Analysis/Support/BumpVector.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include <algorithm>
#include <cstring>
+#include <iterator>
#include <memory>
namespace clang {
@@ -155,7 +156,25 @@ public:
grow(C);
goto Retry;
}
-
+
+ /// insert - Insert some number of copies of element into a position. Return
+ /// iterator to position after last inserted copy.
+ iterator insert(iterator I, size_t Cnt, const_reference E,
+ BumpVectorContext &C) {
+ assert (I >= Begin && I <= End && "Iterator out of bounds.");
+ if (End + Cnt <= Capacity) {
+ Retry:
+ move_range_right(I, End, Cnt);
+ construct_range(I, I + Cnt, E);
+ End += Cnt;
+ return I + Cnt;
+ }
+ ptrdiff_t D = I - Begin;
+ grow(C, size() + Cnt);
+ I = Begin + D;
+ goto Retry;
+ }
+
void reserve(BumpVectorContext &C, unsigned N) {
if (unsigned(Capacity-Begin) < N)
grow(C, N);
@@ -181,6 +200,14 @@ private:
E->~T();
}
}
+
+ void move_range_right(T *S, T *E, size_t D) {
+ for (T *I = E + D - 1, *IL = S + D - 1; I != IL; --I) {
+ --E;
+ new (I) T(*E);
+ E->~T();
+ }
+ }
};
// Define this out-of-line to dissuade the C++ compiler from inlining it.
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
index f20a49a6fcd8..95f4ace76e8c 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -66,6 +66,8 @@ public:
DISPATCH_CASE(Record) // FIXME: Refine. VisitStructDecl?
DISPATCH_CASE(CXXRecord)
DISPATCH_CASE(Enum)
+ DISPATCH_CASE(UsingDirective)
+ DISPATCH_CASE(Using)
default:
assert(false && "Subtype of ScopedDecl not handled.");
}
@@ -85,6 +87,8 @@ public:
DEFAULT_DISPATCH(ObjCMethod)
DEFAULT_DISPATCH(ObjCProtocol)
DEFAULT_DISPATCH(ObjCCategory)
+ DEFAULT_DISPATCH(UsingDirective)
+ DEFAULT_DISPATCH(Using)
void VisitCXXRecordDecl(CXXRecordDecl *D) {
static_cast<ImplClass*>(this)->VisitRecordDecl(D);
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
index 75a4ac66012e..bb7cf0b97e53 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
@@ -26,6 +26,11 @@ public:
static_cast< ImplClass* >(this)->VisitChildren(S);
}
+ void VisitCompoundStmt(CompoundStmt *S) {
+ // Do nothing. Everything in a CompoundStmt is inlined
+ // into the CFG.
+ }
+
void VisitConditionVariableInit(Stmt *S) {
assert(S == this->getCurrentBlkStmt());
VarDecl *CondVar = 0;
diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
index 6421f185ff7f..d197e69babde 100644
--- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
@@ -80,6 +80,7 @@ public:
DISPATCH_CASE(StmtExpr)
DISPATCH_CASE(ConditionalOperator)
+ DISPATCH_CASE(BinaryConditionalOperator)
DISPATCH_CASE(ObjCForCollectionStmt)
case Stmt::BinaryOperatorClass: {
@@ -102,6 +103,7 @@ public:
DEFAULT_BLOCKSTMT_VISIT(StmtExpr)
DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
+ DEFAULT_BLOCKSTMT_VISIT(BinaryConditionalOperator)
RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
@@ -155,7 +157,7 @@ public:
}
}
- for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
+ for (Stmt::child_range I = S->children(); I; ++I)
if (*I) static_cast<ImplClass*>(this)->Visit(*I);
}
};
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
new file mode 100644
index 000000000000..018f50026541
--- /dev/null
+++ b/include/clang/Basic/ABI.h
@@ -0,0 +1,126 @@
+//===----- ABI.h - ABI related declarations ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These enums/classes describe ABI related information about constructors,
+// destructors and thunks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_BASIC_ABI_H
+#define CLANG_BASIC_ABI_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+
+/// CXXCtorType - C++ constructor types
+enum CXXCtorType {
+ Ctor_Complete, // Complete object ctor
+ Ctor_Base, // Base object ctor
+ Ctor_CompleteAllocating // Complete object allocating ctor
+};
+
+/// CXXDtorType - C++ destructor types
+enum CXXDtorType {
+ Dtor_Deleting, // Deleting dtor
+ Dtor_Complete, // Complete object dtor
+ Dtor_Base // Base object dtor
+};
+
+/// ReturnAdjustment - A return adjustment.
+struct ReturnAdjustment {
+ /// NonVirtual - The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// VBaseOffsetOffset - The offset (in bytes), relative to the address point
+ /// of the virtual base class offset.
+ int64_t VBaseOffsetOffset;
+
+ ReturnAdjustment() : NonVirtual(0), VBaseOffsetOffset(0) { }
+
+ bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
+
+ friend bool operator==(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VBaseOffsetOffset == RHS.VBaseOffsetOffset;
+ }
+
+ friend bool operator<(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VBaseOffsetOffset < RHS.VBaseOffsetOffset;
+ }
+};
+
+/// ThisAdjustment - A 'this' pointer adjustment.
+struct ThisAdjustment {
+ /// NonVirtual - The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// VCallOffsetOffset - The offset (in bytes), relative to the address point,
+ /// of the virtual call offset.
+ int64_t VCallOffsetOffset;
+
+ ThisAdjustment() : NonVirtual(0), VCallOffsetOffset(0) { }
+
+ bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
+
+ friend bool operator==(const ThisAdjustment &LHS,
+ const ThisAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VCallOffsetOffset == RHS.VCallOffsetOffset;
+ }
+
+ friend bool operator<(const ThisAdjustment &LHS,
+ const ThisAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VCallOffsetOffset < RHS.VCallOffsetOffset;
+ }
+};
+
+/// ThunkInfo - The 'this' pointer adjustment as well as an optional return
+/// adjustment for a thunk.
+struct ThunkInfo {
+ /// This - The 'this' pointer adjustment.
+ ThisAdjustment This;
+
+ /// Return - The return adjustment.
+ ReturnAdjustment Return;
+
+ ThunkInfo() { }
+
+ ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return)
+ : This(This), Return(Return) { }
+
+ friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ return LHS.This == RHS.This && LHS.Return == RHS.Return;
+ }
+
+ friend bool operator<(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ if (LHS.This < RHS.This)
+ return true;
+
+ return LHS.This == RHS.This && LHS.Return < RHS.Return;
+ }
+
+ bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
+};
+
+} // end namespace clang
+
+#endif // CLANG_BASIC_ABI_H
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 2f2267f7f79f..3e62d411d51a 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -89,171 +89,224 @@ class Attr {
code AdditionalMembers = [{}];
}
+class InheritableAttr : Attr;
+
//
// Attributes begin here
//
-def Alias : Attr {
+def Alias : InheritableAttr {
let Spellings = ["alias"];
let Args = [StringArgument<"Aliasee">];
}
-def Aligned : Attr {
+def Aligned : InheritableAttr {
let Spellings = ["align", "aligned"];
let Subjects = [NonBitField, NormalVar, Tag];
let Args = [AlignedArgument<"Alignment">];
let Namespaces = ["", "std"];
}
-def AlignMac68k : Attr {
+def AlignMac68k : InheritableAttr {
let Spellings = [];
}
-def AlwaysInline : Attr {
+def AlwaysInline : InheritableAttr {
let Spellings = ["always_inline"];
}
-def AnalyzerNoReturn : Attr {
+def AnalyzerNoReturn : InheritableAttr {
let Spellings = ["analyzer_noreturn"];
}
-def Annotate : Attr {
+def Annotate : InheritableAttr {
let Spellings = ["annotate"];
let Args = [StringArgument<"Annotation">];
}
-def AsmLabel : Attr {
+def AsmLabel : InheritableAttr {
let Spellings = [];
let Args = [StringArgument<"Label">];
}
-def BaseCheck : Attr {
- let Spellings = ["base_check"];
- let Subjects = [CXXRecord];
- let Namespaces = ["", "std"];
-}
-
-def Blocks : Attr {
+def Blocks : InheritableAttr {
let Spellings = ["blocks"];
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
}
-def CarriesDependency : Attr {
+def CarriesDependency : InheritableAttr {
let Spellings = ["carries_dependency"];
let Subjects = [ParmVar, Function];
let Namespaces = ["", "std"];
}
-def CDecl : Attr {
+def CDecl : InheritableAttr {
let Spellings = ["cdecl", "__cdecl"];
}
-def CFReturnsRetained : Attr {
+def CFReturnsRetained : InheritableAttr {
let Spellings = ["cf_returns_retained"];
+ let Subjects = [ObjCMethod, Function];
}
-def CFReturnsNotRetained : Attr {
+def CFReturnsNotRetained : InheritableAttr {
let Spellings = ["cf_returns_not_retained"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def CFConsumed : InheritableAttr {
+ let Spellings = ["cf_consumed"];
+ let Subjects = [ParmVar];
}
-def Cleanup : Attr {
+def Cleanup : InheritableAttr {
let Spellings = ["cleanup"];
let Args = [FunctionArgument<"FunctionDecl">];
}
-def Const : Attr {
+def Common : InheritableAttr {
+ let Spellings = ["common"];
+}
+
+def Const : InheritableAttr {
let Spellings = ["const"];
}
-def Constructor : Attr {
+def Constructor : InheritableAttr {
let Spellings = ["constructor"];
let Args = [IntArgument<"Priority">];
}
-def Deprecated : Attr {
+def CUDAConstant : InheritableAttr {
+ let Spellings = ["constant"];
+}
+
+def CUDADevice : Attr {
+ let Spellings = ["device"];
+}
+
+def CUDAGlobal : InheritableAttr {
+ let Spellings = ["global"];
+}
+
+def CUDAHost : Attr {
+ let Spellings = ["host"];
+}
+
+def CUDALaunchBounds : InheritableAttr {
+ let Spellings = ["launch_bounds"];
+ let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
+}
+
+def CUDAShared : InheritableAttr {
+ let Spellings = ["shared"];
+}
+
+def OpenCLKernel : Attr {
+ let Spellings = ["opencl_kernel_function"];
+}
+
+def Deprecated : InheritableAttr {
let Spellings = ["deprecated"];
+ let Args = [StringArgument<"Message">];
}
-def Destructor : Attr {
+def Destructor : InheritableAttr {
let Spellings = ["destructor"];
let Args = [IntArgument<"Priority">];
}
-def DLLExport : Attr {
+def DLLExport : InheritableAttr {
let Spellings = ["dllexport"];
}
-def DLLImport : Attr {
+def DLLImport : InheritableAttr {
let Spellings = ["dllimport"];
}
-def FastCall : Attr {
+def Explicit : InheritableAttr {
+ let Spellings = [];
+}
+
+def FastCall : InheritableAttr {
let Spellings = ["fastcall", "__fastcall"];
}
-def Final : Attr {
- let Spellings = ["final"];
- let Subjects = [CXXRecord, CXXVirtualMethod];
- let Namespaces = ["", "std"];
+def Final : InheritableAttr {
+ let Spellings = [];
}
-def Format : Attr {
+def Format : InheritableAttr {
let Spellings = ["format"];
let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">,
IntArgument<"FirstArg">];
}
-def FormatArg : Attr {
+def FormatArg : InheritableAttr {
let Spellings = ["format_arg"];
let Args = [IntArgument<"FormatIdx">];
}
-def GNUInline : Attr {
+def GNUInline : InheritableAttr {
let Spellings = ["gnu_inline"];
}
-def Hiding : Attr {
- let Spellings = ["hiding"];
- let Subjects = [Field, CXXMethod];
- let Namespaces = ["", "std"];
-}
-
-def IBAction : Attr {
+def IBAction : InheritableAttr {
let Spellings = ["ibaction"];
}
-def IBOutlet : Attr {
+def IBOutlet : InheritableAttr {
let Spellings = ["iboutlet"];
}
-def IBOutletCollection : Attr {
+def IBOutletCollection : InheritableAttr {
let Spellings = ["iboutletcollection"];
let Args = [TypeArgument<"Interface">];
}
-def Malloc : Attr {
+def Malloc : InheritableAttr {
let Spellings = ["malloc"];
}
-def MaxFieldAlignment : Attr {
+def MaxFieldAlignment : InheritableAttr {
let Spellings = [];
let Args = [UnsignedArgument<"Alignment">];
}
-def MSP430Interrupt : Attr {
+def MayAlias : InheritableAttr {
+ let Spellings = ["may_alias"];
+}
+
+def MSP430Interrupt : InheritableAttr {
let Spellings = [];
let Args = [UnsignedArgument<"Number">];
}
-def NoDebug : Attr {
+def MBlazeInterruptHandler : InheritableAttr {
+ let Spellings = [];
+}
+
+def MBlazeSaveVolatiles : InheritableAttr {
+ let Spellings = [];
+}
+
+def Naked : InheritableAttr {
+ let Spellings = ["naked"];
+}
+
+def NoCommon : InheritableAttr {
+ let Spellings = ["nocommon"];
+}
+
+def NoDebug : InheritableAttr {
let Spellings = ["nodebug"];
}
-def NoInline : Attr {
+def NoInline : InheritableAttr {
let Spellings = ["noinline"];
}
-def NonNull : Attr {
+def NonNull : InheritableAttr {
let Spellings = ["nonnull"];
let Args = [VariadicUnsignedArgument<"Args">];
let AdditionalMembers =
@@ -266,49 +319,64 @@ def NonNull : Attr {
} }];
}
-def NoReturn : Attr {
+def NoReturn : InheritableAttr {
let Spellings = ["noreturn"];
// FIXME: Does GCC allow this on the function instead?
let Subjects = [Function];
let Namespaces = ["", "std"];
}
-def NoInstrumentFunction : Attr {
+def NoInstrumentFunction : InheritableAttr {
let Spellings = ["no_instrument_function"];
let Subjects = [Function];
}
-def NoThrow : Attr {
+def NoThrow : InheritableAttr {
let Spellings = ["nothrow"];
}
-def NSReturnsRetained : Attr {
+def NSReturnsRetained : InheritableAttr {
let Spellings = ["ns_returns_retained"];
+ let Subjects = [ObjCMethod, Function];
}
-def NSReturnsNotRetained : Attr {
+def NSReturnsNotRetained : InheritableAttr {
let Spellings = ["ns_returns_not_retained"];
+ let Subjects = [ObjCMethod, Function];
}
-def ObjCException : Attr {
- let Spellings = ["objc_exception"];
+def NSReturnsAutoreleased : InheritableAttr {
+ let Spellings = ["ns_returns_autoreleased"];
+ let Subjects = [ObjCMethod, Function];
}
-def ObjCNSObject : Attr {
- let Spellings = ["NSOjbect"];
+def NSConsumesSelf : InheritableAttr {
+ let Spellings = ["ns_consumes_self"];
+ let Subjects = [ObjCMethod];
}
-def Override : Attr {
- let Spellings = ["override"];
- let Subjects = [CXXVirtualMethod];
- let Namespaces = ["", "std"];
+def NSConsumed : InheritableAttr {
+ let Spellings = ["ns_consumed"];
+ let Subjects = [ParmVar];
+}
+
+def ObjCException : InheritableAttr {
+ let Spellings = ["objc_exception"];
+}
+
+def ObjCNSObject : InheritableAttr {
+ let Spellings = ["NSObject"];
}
def Overloadable : Attr {
let Spellings = ["overloadable"];
}
-def Ownership : Attr {
+def Override : InheritableAttr {
+ let Spellings = [];
+}
+
+def Ownership : InheritableAttr {
let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
let Args = [EnumArgument<"OwnKind", "OwnershipKind",
["ownership_holds", "ownership_returns", "ownership_takes"],
@@ -316,97 +384,104 @@ def Ownership : Attr {
StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
}
-def Packed : Attr {
+def Packed : InheritableAttr {
let Spellings = ["packed"];
}
-def Pure : Attr {
+def Pure : InheritableAttr {
let Spellings = ["pure"];
}
-def Regparm : Attr {
+def Regparm : InheritableAttr {
let Spellings = ["regparm"];
let Args = [UnsignedArgument<"NumParams">];
}
-def ReqdWorkGroupSize : Attr {
+def ReqdWorkGroupSize : InheritableAttr {
let Spellings = ["reqd_work_group_size"];
let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
UnsignedArgument<"ZDim">];
}
-def InitPriority : Attr {
+def InitPriority : InheritableAttr {
let Spellings = ["init_priority"];
let Args = [UnsignedArgument<"Priority">];
}
-def Section : Attr {
+def Section : InheritableAttr {
let Spellings = ["section"];
let Args = [StringArgument<"Name">];
}
-def Sentinel : Attr {
+def Sentinel : InheritableAttr {
let Spellings = ["sentinel"];
let Args = [DefaultIntArgument<"Sentinel", 0>,
DefaultIntArgument<"NullPos", 0>];
}
-def StdCall : Attr {
+def StdCall : InheritableAttr {
let Spellings = ["stdcall", "__stdcall"];
}
-def ThisCall : Attr {
+def ThisCall : InheritableAttr {
let Spellings = ["thiscall", "__thiscall"];
}
-def Pascal : Attr {
+def Pascal : InheritableAttr {
let Spellings = ["pascal", "__pascal"];
}
-def TransparentUnion : Attr {
+def TransparentUnion : InheritableAttr {
let Spellings = ["transparent_union"];
}
-def Unavailable : Attr {
+def Unavailable : InheritableAttr {
let Spellings = ["unavailable"];
+ let Args = [StringArgument<"Message">];
}
-def Unused : Attr {
+def Unused : InheritableAttr {
let Spellings = ["unused"];
}
-def Used : Attr {
+def Used : InheritableAttr {
let Spellings = ["used"];
}
-def Visibility : Attr {
+def Uuid : InheritableAttr {
+ let Spellings = ["uuid"];
+ let Args = [StringArgument<"Guid">];
+ let Subjects = [CXXRecord];
+}
+
+def Visibility : InheritableAttr {
let Spellings = ["visibility"];
let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
}
-def VecReturn : Attr {
+def VecReturn : InheritableAttr {
let Spellings = ["vecreturn"];
let Subjects = [CXXRecord];
}
-def WarnUnusedResult : Attr {
+def WarnUnusedResult : InheritableAttr {
let Spellings = ["warn_unused_result"];
}
-def Weak : Attr {
+def Weak : InheritableAttr {
let Spellings = ["weak"];
}
-def WeakImport : Attr {
+def WeakImport : InheritableAttr {
let Spellings = ["weak_import"];
}
-def WeakRef : Attr {
+def WeakRef : InheritableAttr {
let Spellings = ["weakref"];
}
-def X86ForceAlignArgPointer : Attr {
+def X86ForceAlignArgPointer : InheritableAttr {
let Spellings = [];
}
diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h
index 822573b734a7..65c4f98c952c 100644
--- a/include/clang/Basic/AttrKinds.h
+++ b/include/clang/Basic/AttrKinds.h
@@ -21,6 +21,7 @@ namespace attr {
// Kind - This is a list of all the recognized kinds of attributes.
enum Kind {
#define ATTR(X) X,
+#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
#include "clang/Basic/AttrList.inc"
NUM_ATTRS
};
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 0da893899b0b..7d270ad7fb89 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -29,6 +29,8 @@
// d -> double
// z -> size_t
// F -> constant CFString
+// G -> id
+// H -> SEL
// a -> __builtin_va_list
// A -> "reference" to __builtin_va_list
// V -> Vector, following num elements and a base type.
@@ -38,12 +40,13 @@
// SJ -> sigjmp_buf
// . -> "...". This may only occur at the end of the function list.
//
-// Types maybe prefixed with the following modifiers:
+// Types may be prefixed with the following modifiers:
// L -> long (e.g. Li for 'long int')
// LL -> long long
// LLL -> __int128_t (e.g. LLLi)
// S -> signed
// U -> unsigned
+// I -> Required to constant fold to an integer constant expression.
//
// Types may be postfixed with the following modifiers:
// * -> pointer (optionally followed by an address space number)
@@ -75,7 +78,7 @@
// FIXME: gcc has nonnull
#if defined(BUILTIN) && !defined(LIBBUILTIN)
-# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) BUILTIN(ID, TYPE, ATTRS)
+# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
#endif
// Standard libc/libm functions:
@@ -124,12 +127,24 @@ BUILTIN(__builtin_powl, "LdLdLd", "Fnc")
BUILTIN(__builtin_acos , "dd" , "Fnc")
BUILTIN(__builtin_acosf, "ff" , "Fnc")
BUILTIN(__builtin_acosl, "LdLd", "Fnc")
+BUILTIN(__builtin_acosh , "dd" , "Fnc")
+BUILTIN(__builtin_acoshf, "ff" , "Fnc")
+BUILTIN(__builtin_acoshl, "LdLd", "Fnc")
BUILTIN(__builtin_asin , "dd" , "Fnc")
BUILTIN(__builtin_asinf, "ff" , "Fnc")
BUILTIN(__builtin_asinl, "LdLd", "Fnc")
+BUILTIN(__builtin_asinh , "dd" , "Fnc")
+BUILTIN(__builtin_asinhf, "ff" , "Fnc")
+BUILTIN(__builtin_asinhl, "LdLd", "Fnc")
BUILTIN(__builtin_atan , "dd" , "Fnc")
BUILTIN(__builtin_atanf, "ff" , "Fnc")
BUILTIN(__builtin_atanl, "LdLd", "Fnc")
+BUILTIN(__builtin_atanh , "dd", "Fnc")
+BUILTIN(__builtin_atanhf, "ff", "Fnc")
+BUILTIN(__builtin_atanhl, "LdLd", "Fnc")
+BUILTIN(__builtin_cbrt , "dd", "Fnc")
+BUILTIN(__builtin_cbrtf, "ff", "Fnc")
+BUILTIN(__builtin_cbrtl, "LdLd", "Fnc")
BUILTIN(__builtin_ceil , "dd" , "Fnc")
BUILTIN(__builtin_ceilf, "ff" , "Fnc")
BUILTIN(__builtin_ceill, "LdLd", "Fnc")
@@ -139,21 +154,99 @@ BUILTIN(__builtin_cosh , "dd" , "Fnc")
BUILTIN(__builtin_coshf, "ff" , "Fnc")
BUILTIN(__builtin_coshl, "LdLd", "Fnc")
BUILTIN(__builtin_cosl, "LdLd", "Fnc")
+BUILTIN(__builtin_erf , "dd", "Fnc")
+BUILTIN(__builtin_erff, "ff", "Fnc")
+BUILTIN(__builtin_erfl, "LdLd", "Fnc")
+BUILTIN(__builtin_erfc , "dd", "Fnc")
+BUILTIN(__builtin_erfcf, "ff", "Fnc")
+BUILTIN(__builtin_erfcl, "LdLd", "Fnc")
BUILTIN(__builtin_exp , "dd" , "Fnc")
BUILTIN(__builtin_expf, "ff" , "Fnc")
BUILTIN(__builtin_expl, "LdLd", "Fnc")
+BUILTIN(__builtin_exp2 , "dd" , "Fnc")
+BUILTIN(__builtin_exp2f, "ff" , "Fnc")
+BUILTIN(__builtin_exp2l, "LdLd", "Fnc")
+BUILTIN(__builtin_expm1 , "dd", "Fnc")
+BUILTIN(__builtin_expm1f, "ff", "Fnc")
+BUILTIN(__builtin_expm1l, "LdLd", "Fnc")
+BUILTIN(__builtin_fdim, "ddd", "Fnc")
+BUILTIN(__builtin_fdimf, "fff", "Fnc")
+BUILTIN(__builtin_fdiml, "LdLdLd", "Fnc")
BUILTIN(__builtin_floor , "dd" , "Fnc")
BUILTIN(__builtin_floorf, "ff" , "Fnc")
BUILTIN(__builtin_floorl, "LdLd", "Fnc")
+BUILTIN(__builtin_fma, "dddd", "Fnc")
+BUILTIN(__builtin_fmaf, "ffff", "Fnc")
+BUILTIN(__builtin_fmal, "LdLdLdLd", "Fnc")
+BUILTIN(__builtin_fmax, "ddd", "Fnc")
+BUILTIN(__builtin_fmaxf, "fff", "Fnc")
+BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_fmin, "ddd", "Fnc")
+BUILTIN(__builtin_fminf, "fff", "Fnc")
+BUILTIN(__builtin_fminl, "LdLdLd", "Fnc")
BUILTIN(__builtin_hypot , "ddd" , "Fnc")
BUILTIN(__builtin_hypotf, "fff" , "Fnc")
BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_ilogb , "id", "Fnc")
+BUILTIN(__builtin_ilogbf, "if", "Fnc")
+BUILTIN(__builtin_ilogbl, "iLd", "Fnc")
+BUILTIN(__builtin_lgamma , "dd", "Fnc")
+BUILTIN(__builtin_lgammaf, "ff", "Fnc")
+BUILTIN(__builtin_lgammal, "LdLd", "Fnc")
+BUILTIN(__builtin_llrint, "LLid", "Fnc")
+BUILTIN(__builtin_llrintf, "LLif", "Fnc")
+BUILTIN(__builtin_llrintl, "LLiLd", "Fnc")
+BUILTIN(__builtin_llround , "LLid", "Fnc")
+BUILTIN(__builtin_llroundf, "LLif", "Fnc")
+BUILTIN(__builtin_llroundl, "LLiLd", "Fnc")
BUILTIN(__builtin_log , "dd" , "Fnc")
BUILTIN(__builtin_log10 , "dd" , "Fnc")
BUILTIN(__builtin_log10f, "ff" , "Fnc")
BUILTIN(__builtin_log10l, "LdLd", "Fnc")
+BUILTIN(__builtin_log1p , "dd" , "Fnc")
+BUILTIN(__builtin_log1pf, "ff" , "Fnc")
+BUILTIN(__builtin_log1pl, "LdLd", "Fnc")
+BUILTIN(__builtin_log2, "dd" , "Fnc")
+BUILTIN(__builtin_log2f, "ff" , "Fnc")
+BUILTIN(__builtin_log2l, "LdLd" , "Fnc")
+BUILTIN(__builtin_logb , "dd", "Fnc")
+BUILTIN(__builtin_logbf, "ff", "Fnc")
+BUILTIN(__builtin_logbl, "LdLd", "Fnc")
BUILTIN(__builtin_logf, "ff" , "Fnc")
BUILTIN(__builtin_logl, "LdLd", "Fnc")
+BUILTIN(__builtin_lrint , "Lid", "Fnc")
+BUILTIN(__builtin_lrintf, "Lif", "Fnc")
+BUILTIN(__builtin_lrintl, "LiLd", "Fnc")
+BUILTIN(__builtin_lround , "Lid", "Fnc")
+BUILTIN(__builtin_lroundf, "Lif", "Fnc")
+BUILTIN(__builtin_lroundl, "LiLd", "Fnc")
+BUILTIN(__builtin_nearbyint , "dd", "Fnc")
+BUILTIN(__builtin_nearbyintf, "ff", "Fnc")
+BUILTIN(__builtin_nearbyintl, "LdLd", "Fnc")
+BUILTIN(__builtin_nextafter , "ddd", "Fnc")
+BUILTIN(__builtin_nextafterf, "fff", "Fnc")
+BUILTIN(__builtin_nextafterl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_nexttoward , "ddd", "Fnc")
+BUILTIN(__builtin_nexttowardf, "fff", "Fnc")
+BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_remainder , "ddd", "Fnc")
+BUILTIN(__builtin_remainderf, "fff", "Fnc")
+BUILTIN(__builtin_remainderl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_remquo , "dddi*", "Fnc")
+BUILTIN(__builtin_remquof, "fffi*", "Fnc")
+BUILTIN(__builtin_remquol, "LdLdLdi*", "Fnc")
+BUILTIN(__builtin_rint , "dd", "Fnc")
+BUILTIN(__builtin_rintf, "ff", "Fnc")
+BUILTIN(__builtin_rintl, "LdLd", "Fnc")
+BUILTIN(__builtin_round, "dd" , "Fnc")
+BUILTIN(__builtin_roundf, "ff" , "Fnc")
+BUILTIN(__builtin_roundl, "LdLd" , "Fnc")
+BUILTIN(__builtin_scalbln , "ddLi", "Fnc")
+BUILTIN(__builtin_scalblnf, "ffLi", "Fnc")
+BUILTIN(__builtin_scalblnl, "LdLdLi", "Fnc")
+BUILTIN(__builtin_scalbn , "ddi", "Fnc")
+BUILTIN(__builtin_scalbnf, "ffi", "Fnc")
+BUILTIN(__builtin_scalbnl, "LdLdi", "Fnc")
BUILTIN(__builtin_sin , "dd" , "Fnc")
BUILTIN(__builtin_sinf, "ff" , "Fnc")
BUILTIN(__builtin_sinh , "dd" , "Fnc")
@@ -169,6 +262,12 @@ BUILTIN(__builtin_tanh , "dd" , "Fnc")
BUILTIN(__builtin_tanhf, "ff" , "Fnc")
BUILTIN(__builtin_tanhl, "LdLd", "Fnc")
BUILTIN(__builtin_tanl, "LdLd", "Fnc")
+BUILTIN(__builtin_tgamma , "dd", "Fnc")
+BUILTIN(__builtin_tgammaf, "ff", "Fnc")
+BUILTIN(__builtin_tgammal, "LdLd", "Fnc")
+BUILTIN(__builtin_trunc , "dd", "Fnc")
+BUILTIN(__builtin_truncf, "ff", "Fnc")
+BUILTIN(__builtin_truncl, "LdLd", "Fnc")
// C99 complex builtins
BUILTIN(__builtin_cabs, "dXd", "Fnc")
@@ -176,15 +275,24 @@ BUILTIN(__builtin_cabsf, "fXf", "Fnc")
BUILTIN(__builtin_cabsl, "LdXLd", "Fnc")
BUILTIN(__builtin_cacos, "XdXd", "Fnc")
BUILTIN(__builtin_cacosf, "XfXf", "Fnc")
+BUILTIN(__builtin_cacosh, "XdXd", "Fnc")
+BUILTIN(__builtin_cacoshf, "XfXf", "Fnc")
+BUILTIN(__builtin_cacoshl, "XLdXLd", "Fnc")
BUILTIN(__builtin_cacosl, "XLdXLd", "Fnc")
BUILTIN(__builtin_carg, "dXd", "Fnc")
BUILTIN(__builtin_cargf, "fXf", "Fnc")
BUILTIN(__builtin_cargl, "LdXLd", "Fnc")
BUILTIN(__builtin_casin, "XdXd", "Fnc")
BUILTIN(__builtin_casinf, "XfXf", "Fnc")
+BUILTIN(__builtin_casinh, "XdXd", "Fnc")
+BUILTIN(__builtin_casinhf, "XfXf", "Fnc")
+BUILTIN(__builtin_casinhl, "XLdXLd", "Fnc")
BUILTIN(__builtin_casinl, "XLdXLd", "Fnc")
BUILTIN(__builtin_catan, "XdXd", "Fnc")
BUILTIN(__builtin_catanf, "XfXf", "Fnc")
+BUILTIN(__builtin_catanh, "XdXd", "Fnc")
+BUILTIN(__builtin_catanhf, "XfXf", "Fnc")
+BUILTIN(__builtin_catanhl, "XLdXLd", "Fnc")
BUILTIN(__builtin_catanl, "XLdXLd", "Fnc")
BUILTIN(__builtin_ccos, "XdXd", "Fnc")
BUILTIN(__builtin_ccosf, "XfXf", "Fnc")
@@ -275,7 +383,7 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc")
BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
// Random GCC builtins
-BUILTIN(__builtin_constant_p, "Us.", "nc")
+BUILTIN(__builtin_constant_p, "i.", "nc")
BUILTIN(__builtin_classify_type, "i.", "nc")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
@@ -313,14 +421,14 @@ BUILTIN(__builtin_strpbrk, "c*cC*cC*", "nF")
BUILTIN(__builtin_strrchr, "c*cC*i", "nF")
BUILTIN(__builtin_strspn, "zcC*cC*", "nF")
BUILTIN(__builtin_strstr, "c*cC*cC*", "nF")
-BUILTIN(__builtin_return_address, "v*Ui", "n")
+BUILTIN(__builtin_return_address, "v*IUi", "n")
BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
-BUILTIN(__builtin_frame_address, "v*Ui", "n")
+BUILTIN(__builtin_frame_address, "v*IUi", "n")
BUILTIN(__builtin_flt_rounds, "i", "nc")
BUILTIN(__builtin_setjmp, "iv**", "")
BUILTIN(__builtin_longjmp, "vv**i", "r")
BUILTIN(__builtin_unwind_init, "v", "")
-BUILTIN(__builtin_eh_return_data_regno, "ii", "nc")
+BUILTIN(__builtin_eh_return_data_regno, "iIi", "nc")
BUILTIN(__builtin_snprintf, "ic*zcC*.", "nFp:2:")
BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:")
BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:")
@@ -485,92 +593,135 @@ BUILTIN(__builtin_abort, "v", "Fnr")
BUILTIN(__builtin_index, "c*cC*i", "Fn")
BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
-
+// Microsoft builtins.
+BUILTIN(__assume, "vb", "n")
+BUILTIN(__noop, "v.", "n")
// C99 library functions
// C99 stdlib.h
-LIBBUILTIN(abort, "v", "fr", "stdlib.h")
-LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h")
-LIBBUILTIN(exit, "vi", "fr", "stdlib.h")
-LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h")
-LIBBUILTIN(malloc, "v*z", "f", "stdlib.h")
-LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h")
+LIBBUILTIN(abort, "v", "fr", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES)
// C99 string.h
-LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h")
-LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h")
-LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h")
-LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h")
-LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h")
-LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h")
-LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h")
-LIBBUILTIN(memchr, "v*vC*iz", "f", "string.h")
-LIBBUILTIN(strchr, "c*cC*i", "f", "string.h")
-LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h")
-LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h")
-LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h")
-LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h")
-LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h")
-LIBBUILTIN(strtok, "c*c*cC*", "f", "string.h")
-LIBBUILTIN(memset, "v*v*iz", "f", "string.h")
-LIBBUILTIN(strerror, "c*i", "f", "string.h")
-LIBBUILTIN(strlen, "zcC*", "f", "string.h")
+LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(memchr, "v*vC*iz", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strtok, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(memset, "v*v*iz", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strerror, "c*i", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strlen, "zcC*", "f", "string.h", ALL_LANGUAGES)
// C99 stdio.h
-LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h")
-LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h")
-LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h")
-LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h")
-LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h")
-LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h")
-LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h")
-LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h")
-LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h")
+LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h", ALL_LANGUAGES)
// C99
-LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h")
+LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
// Non-C library functions
// FIXME: Non-C-standard stuff shouldn't be builtins in non-GNU mode!
-LIBBUILTIN(alloca, "v*z", "f", "stdlib.h")
+LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_LANGUAGES)
// POSIX string.h
-LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h")
-LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h")
-LIBBUILTIN(strdup, "c*cC*", "f", "string.h")
-LIBBUILTIN(strndup, "c*cC*z", "f", "string.h")
+LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_LANGUAGES)
// POSIX strings.h
-LIBBUILTIN(index, "c*cC*i", "f", "strings.h")
-LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h")
-LIBBUILTIN(bzero, "vv*z", "f", "strings.h")
+LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
+LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
+LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES)
// POSIX unistd.h
-LIBBUILTIN(_exit, "vi", "fr", "unistd.h")
+LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES)
// POSIX setjmp.h
-LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h")
-LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h")
+LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_LANGUAGES)
+// id objc_msgSend(id, SEL, ...)
+LIBBUILTIN(objc_msgSend, "GGH.", "f", "objc/message.h", OBJC_LANG)
+
+// long double objc_msgSend_fpret(id self, SEL op, ...)
+LIBBUILTIN(objc_msgSend_fpret, "LdGH.", "f", "objc/message.h", OBJC_LANG)
+// id objc_msgSend_stret (id, SEL, ...)
+LIBBUILTIN(objc_msgSend_stret, "GGH.", "f", "objc/message.h", OBJC_LANG)
+// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
+LIBBUILTIN(objc_msgSendSuper, "Gv*H.", "f", "objc/message.h", OBJC_LANG)
+// void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...)
+LIBBUILTIN(objc_msgSendSuper_stret, "vv*H.", "f", "objc/message.h", OBJC_LANG)
+// id objc_getClass(const char *name)
+LIBBUILTIN(objc_getClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG)
+// id objc_getMetaClass(const char *name)
+LIBBUILTIN(objc_getMetaClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG)
+// void objc_enumerationMutation(id)
+LIBBUILTIN(objc_enumerationMutation, "vG", "f", "objc/runtime.h", OBJC_LANG)
+
+// id objc_read_weak(id *location)
+LIBBUILTIN(objc_read_weak, "GG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_weak(id value, id *location)
+LIBBUILTIN(objc_assign_weak, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_ivar(id value, id dest, ptrdiff_t offset)
+// FIXME. Darwin has ptrdiff_t typedef'ed to int.
+LIBBUILTIN(objc_assign_ivar, "GGGi", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_global(id val, id *dest)
+LIBBUILTIN(objc_assign_global, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_strongCast(id val, id *dest
+LIBBUILTIN(objc_assign_strongCast, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+
+// id objc_exception_extract(void *localExceptionData)
+LIBBUILTIN(objc_exception_extract, "Gv*", "f", "/objc/objc-exception.h", OBJC_LANG)
+// void objc_exception_try_enter(void *localExceptionData)
+LIBBUILTIN(objc_exception_try_enter, "vv*", "f", "/objc/objc-exception.h", OBJC_LANG)
+// void objc_exception_try_exit(void *localExceptionData)
+LIBBUILTIN(objc_exception_try_exit, "vv*", "f", "/objc/objc-exception.h", OBJC_LANG)
+// int objc_exception_match(Class exceptionClass, id exception)
+LIBBUILTIN(objc_exception_match, "iGG", "f", "/objc/objc-exception.h", OBJC_LANG)
+// void objc_exception_throw(id exception)
+LIBBUILTIN(objc_exception_throw, "vG", "f", "/objc/objc-exception.h", OBJC_LANG)
+
+// int objc_sync_enter(id obj)
+LIBBUILTIN(objc_sync_enter, "iG", "f", "/objc/objc-sync.h", OBJC_LANG)
+// int objc_sync_exit(id obj)
+LIBBUILTIN(objc_sync_exit, "iG", "f", "/objc/objc-sync.h", OBJC_LANG)
-// FIXME: This type isn't very correct, it should be
-// id objc_msgSend(id, SEL)
-// but we need new type letters for that.
-LIBBUILTIN(objc_msgSend, "v*.", "f", "objc/message.h")
BUILTIN(__builtin_objc_memmove_collectable, "v*v*vC*z", "nF")
// Builtin math library functions
-LIBBUILTIN(pow, "ddd", "fe", "math.h")
-LIBBUILTIN(powl, "LdLdLd", "fe", "math.h")
-LIBBUILTIN(powf, "fff", "fe", "math.h")
+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(sqrt, "dd", "fe", "math.h")
-LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h")
-LIBBUILTIN(sqrtf, "ff", "fe", "math.h")
+LIBBUILTIN(sqrt, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtf, "ff", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(sin, "dd", "fe", "math.h")
-LIBBUILTIN(sinl, "LdLd", "fe", "math.h")
-LIBBUILTIN(sinf, "ff", "fe", "math.h")
+LIBBUILTIN(sin, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinf, "ff", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cos, "dd", "fe", "math.h")
-LIBBUILTIN(cosl, "LdLd", "fe", "math.h")
-LIBBUILTIN(cosf, "ff", "fe", "math.h")
+LIBBUILTIN(cos, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosf, "ff", "fe", "math.h", ALL_LANGUAGES)
// Blocks runtime Builtin math library functions
-LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h")
-LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h")
+LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
+LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
#undef BUILTIN
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 94d5e6955a24..4df4c8f95374 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -30,7 +30,15 @@ namespace clang {
class IdentifierTable;
class ASTContext;
class QualType;
-
+ class LangOptions;
+
+ enum LanguageID {
+ C_LANG = 0x1, // builtin for c only.
+ CXX_LANG = 0x2, // builtin for cplusplus only.
+ OBJC_LANG = 0x4, // builtin for objective-c and objective-c++
+ ALL_LANGUAGES = (C_LANG|CXX_LANG|OBJC_LANG) //builtin is for all languages.
+ };
+
namespace Builtin {
enum ID {
NotBuiltin = 0, // This is not a builtin function.
@@ -41,6 +49,7 @@ enum ID {
struct Info {
const char *Name, *Type, *Attributes, *HeaderName;
+ LanguageID builtin_lang;
bool Suppressed;
bool operator==(const Info &RHS) const {
@@ -62,7 +71,7 @@ public:
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
- void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false);
+ void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
/// \brief Popular the vector with the names of all of the builtins.
void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
@@ -108,6 +117,10 @@ public:
return strchr(GetRecord(ID).Attributes, 'f') != 0;
}
+ /// \brief Completely forget that the given ID was ever considered a builtin,
+ /// e.g., because the user provided a conflicting signature.
+ void ForgetBuiltin(unsigned ID, IdentifierTable &Table);
+
/// \brief If this is a library function that comes from a specific
/// header, retrieve that header name.
const char *getHeaderName(unsigned ID) const {
@@ -124,12 +137,6 @@ public:
/// argument and whether this function as a va_list argument.
bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
- /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
- /// as an operand or return type.
- bool hasVAListUse(unsigned ID) const {
- return strpbrk(GetRecord(ID).Type, "Aa") != 0;
- }
-
/// isConstWithoutErrno - Return true if this function has no side
/// effects and doesn't read memory, except for possibly errno. Such
/// functions can be const when the MathErrno lang option is
diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def
index e0518dcdb681..8a751e4ce846 100644
--- a/include/clang/Basic/BuiltinsPPC.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -50,25 +50,25 @@ BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fi", "")
BUILTIN(__builtin_altivec_dss, "vUi", "")
BUILTIN(__builtin_altivec_dssall, "v", "")
-BUILTIN(__builtin_altivec_dst, "vv*iUi", "")
-BUILTIN(__builtin_altivec_dstt, "vv*iUi", "")
-BUILTIN(__builtin_altivec_dstst, "vv*iUi", "")
-BUILTIN(__builtin_altivec_dststt, "vv*iUi", "")
+BUILTIN(__builtin_altivec_dst, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dstt, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dstst, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dststt, "vvC*iUi", "")
BUILTIN(__builtin_altivec_vexptefp, "V4fV4f", "")
BUILTIN(__builtin_altivec_vrfim, "V4fV4f", "")
-BUILTIN(__builtin_altivec_lvx, "V4iiv*", "")
-BUILTIN(__builtin_altivec_lvxl, "V4iiv*", "")
-BUILTIN(__builtin_altivec_lvebx, "V16civ*", "")
-BUILTIN(__builtin_altivec_lvehx, "V8siv*", "")
-BUILTIN(__builtin_altivec_lvewx, "V4iiv*", "")
+BUILTIN(__builtin_altivec_lvx, "V4iivC*", "")
+BUILTIN(__builtin_altivec_lvxl, "V4iivC*", "")
+BUILTIN(__builtin_altivec_lvebx, "V16civC*", "")
+BUILTIN(__builtin_altivec_lvehx, "V8sivC*", "")
+BUILTIN(__builtin_altivec_lvewx, "V4iivC*", "")
BUILTIN(__builtin_altivec_vlogefp, "V4fV4f", "")
-BUILTIN(__builtin_altivec_lvsl, "V16cUcv*", "")
-BUILTIN(__builtin_altivec_lvsr, "V16cUcv*", "")
+BUILTIN(__builtin_altivec_lvsl, "V16cUcvC*", "")
+BUILTIN(__builtin_altivec_lvsr, "V16cUcvC*", "")
BUILTIN(__builtin_altivec_vmaddfp, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_altivec_vmhaddshs, "V8sV8sV8sV8s", "")
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index 5ad64b9b49d1..da106daf26ec 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -25,11 +25,16 @@
// FIXME: Are these nothrow/const?
// MMX
+//
+// FIXME: All MMX instructions will be generated via builtins. Any MMX vector
+// types (<1 x i64>, <2 x i32>, etc.) that aren't used by these builtins will be
+// expanded by the back-end.
BUILTIN(__builtin_ia32_emms, "v", "")
BUILTIN(__builtin_ia32_femms, "v", "")
BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
@@ -37,6 +42,7 @@ BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
@@ -76,6 +82,7 @@ BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "")
BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
@@ -91,7 +98,7 @@ BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
-BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") // FIXME: Correct type?
+BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "")
BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
@@ -249,8 +256,8 @@ BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLii", "")
-BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLiIi", "")
+BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLiIi", "")
BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "")
@@ -267,7 +274,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
-BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") // FIXME: Correct type?
+BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "") // FIXME: Correct type?
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index e2f93e02c525..2ec7427cf758 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -15,6 +15,7 @@ def Named : Decl<1>;
def Namespace : DDecl<Named>, DeclContext;
def UsingDirective : DDecl<Named>;
def NamespaceAlias : DDecl<Named>;
+ def Label : DDecl<Named>;
def Type : DDecl<Named, 1>;
def Typedef : DDecl<Type>;
def UnresolvedUsingTypename : DDecl<Type>;
@@ -29,6 +30,7 @@ def Named : Decl<1>;
def Value : DDecl<Named, 1>;
def EnumConstant : DDecl<Value>;
def UnresolvedUsingValue : DDecl<Value>;
+ def IndirectField : DDecl<Value>;
def Declarator : DDecl<Value, 1>;
def Function : DDecl<Declarator>, DeclContext;
def CXXMethod : DDecl<Function>;
@@ -41,7 +43,7 @@ def Named : Decl<1>;
def Var : DDecl<Declarator>;
def ImplicitParam : DDecl<Var>;
def ParmVar : DDecl<Var>;
- def NonTypeTemplateParm : DDecl<Var>;
+ def NonTypeTemplateParm : DDecl<Declarator>;
def Template : DDecl<Named, 1>;
def RedeclarableTemplate : DDecl<Template, 1>;
def FunctionTemplate : DDecl<RedeclarableTemplate>;
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 37d26947c335..19e7c91f5324 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -14,76 +14,24 @@
#ifndef LLVM_CLANG_DIAGNOSTIC_H
#define LLVM_CLANG_DIAGNOSTIC_H
+#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/type_traits.h"
-#include <string>
-#include <vector>
-#include <cassert>
-namespace llvm {
- template <typename T> class SmallVectorImpl;
-}
+#include <vector>
+#include <list>
namespace clang {
- class DeclContext;
- class DiagnosticBuilder;
class DiagnosticClient;
- class FileManager;
+ class DiagnosticBuilder;
class IdentifierInfo;
+ class DeclContext;
class LangOptions;
- class PartialDiagnostic;
class Preprocessor;
-
- // Import the diagnostic enums themselves.
- namespace diag {
- // Start position for diagnostics.
- enum {
- DIAG_START_DRIVER = 300,
- DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
- DIAG_START_LEX = DIAG_START_FRONTEND + 100,
- DIAG_START_PARSE = DIAG_START_LEX + 300,
- DIAG_START_AST = DIAG_START_PARSE + 300,
- DIAG_START_SEMA = DIAG_START_AST + 100,
- DIAG_START_ANALYSIS = DIAG_START_SEMA + 1500,
- DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
- };
-
- class CustomDiagInfo;
-
- /// diag::kind - All of the diagnostics that can be emitted by the frontend.
- typedef unsigned kind;
-
- // Get typedefs for common diagnostics.
- enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
-#include "clang/Basic/DiagnosticCommonKinds.inc"
- NUM_BUILTIN_COMMON_DIAGNOSTICS
-#undef DIAG
- };
-
- /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
- /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
- /// (emit as an error). It allows clients to map errors to
- /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
- /// one).
- enum Mapping {
- // NOTE: 0 means "uncomputed".
- MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
- MAP_WARNING = 2, //< Map this diagnostic to a warning.
- MAP_ERROR = 3, //< Map this diagnostic to an error.
- MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
-
- /// Map this diagnostic to "warning", but make it immune to -Werror. This
- /// happens when you specify -Wno-error=foo.
- MAP_WARNING_NO_WERROR = 5,
- /// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
- /// This happens for -Wno-fatal-errors=foo.
- MAP_ERROR_NO_WFATAL = 6
- };
- }
+ class DiagnosticErrorTrap;
/// \brief Annotates a diagnostic with some code that should be
/// inserted, removed, or replaced to fix the problem.
@@ -153,12 +101,17 @@ public:
/// Diagnostic - This concrete class is used by the front-end to report
/// problems and issues. It massages the diagnostics (e.g. handling things like
/// "report warnings as errors" and passes them off to the DiagnosticClient for
-/// reporting to the user.
+/// reporting to the user. Diagnostic is tied to one translation unit and
+/// one SourceManager.
class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
public:
/// Level - The level of the diagnostic, after it has been through mapping.
enum Level {
- Ignored, Note, Warning, Error, Fatal
+ Ignored = DiagnosticIDs::Ignored,
+ Note = DiagnosticIDs::Note,
+ Warning = DiagnosticIDs::Warning,
+ Error = DiagnosticIDs::Error,
+ Fatal = DiagnosticIDs::Fatal
};
/// ExtensionHandling - How do we handle otherwise-unmapped extension? This
@@ -203,33 +156,94 @@ private:
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
// 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
- llvm::OwningPtr<DiagnosticClient> Client;
-
- /// DiagMappings - Mapping information for diagnostics. Mapping info is
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags;
+ DiagnosticClient *Client;
+ bool OwnsDiagClient;
+ SourceManager *SourceMgr;
+
+ /// \brief Mapping information for diagnostics. Mapping info is
/// packed into four bits per diagnostic. The low three bits are the mapping
/// (an instance of diag::Mapping), or zero if unset. The high bit is set
/// when the mapping was established as a user mapping. If the high bit is
/// clear, then the low bits are set to the default value, and should be
/// mapped with -pedantic, -Werror, etc.
- class DiagMappings {
- unsigned char Values[diag::DIAG_UPPER_LIMIT/2];
+ ///
+ /// A new DiagState is created and kept around when diagnostic pragmas modify
+ /// the state so that we know what is the diagnostic state at any given
+ /// source location.
+ class DiagState {
+ llvm::DenseMap<unsigned, unsigned> DiagMap;
public:
- DiagMappings() {
- memset(Values, 0, diag::DIAG_UPPER_LIMIT/2);
- }
+ typedef llvm::DenseMap<unsigned, unsigned>::const_iterator iterator;
- void setMapping(diag::kind Diag, unsigned Map) {
- size_t Shift = (Diag & 1)*4;
- Values[Diag/2] = (Values[Diag/2] & ~(15 << Shift)) | (Map << Shift);
- }
+ void setMapping(diag::kind Diag, unsigned Map) { DiagMap[Diag] = Map; }
diag::Mapping getMapping(diag::kind Diag) const {
- return (diag::Mapping)((Values[Diag/2] >> (Diag & 1)*4) & 15);
+ iterator I = DiagMap.find(Diag);
+ if (I != DiagMap.end())
+ return (diag::Mapping)I->second;
+ return diag::Mapping();
+ }
+
+ iterator begin() const { return DiagMap.begin(); }
+ iterator end() const { return DiagMap.end(); }
+ };
+
+ /// \brief Keeps and automatically disposes all DiagStates that we create.
+ std::list<DiagState> DiagStates;
+
+ /// \brief Represents a point in source where the diagnostic state was
+ /// modified because of a pragma. 'Loc' can be null if the point represents
+ /// the diagnostic state modifications done through the command-line.
+ struct DiagStatePoint {
+ DiagState *State;
+ FullSourceLoc Loc;
+ DiagStatePoint(DiagState *State, FullSourceLoc Loc)
+ : State(State), Loc(Loc) { }
+
+ bool operator<(const DiagStatePoint &RHS) const {
+ // If Loc is invalid it means it came from <command-line>, in which case
+ // we regard it as coming before any valid source location.
+ if (RHS.Loc.isInvalid())
+ return false;
+ if (Loc.isInvalid())
+ return true;
+ return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
}
};
- mutable std::vector<DiagMappings> DiagMappingsStack;
+ /// \brief A vector of all DiagStatePoints representing changes in diagnostic
+ /// state due to diagnostic pragmas. The vector is always sorted according to
+ /// the SourceLocation of the DiagStatePoint.
+ typedef std::vector<DiagStatePoint> DiagStatePointsTy;
+ mutable DiagStatePointsTy DiagStatePoints;
+
+ /// \brief Keeps the DiagState that was active during each diagnostic 'push'
+ /// so we can get back at it when we 'pop'.
+ std::vector<DiagState *> DiagStateOnPushStack;
+
+ DiagState *GetCurDiagState() const {
+ assert(!DiagStatePoints.empty());
+ return DiagStatePoints.back().State;
+ }
+
+ void PushDiagStatePoint(DiagState *State, SourceLocation L) {
+ FullSourceLoc Loc(L, *SourceMgr);
+ // Make sure that DiagStatePoints is always sorted according to Loc.
+ assert((Loc.isValid() || DiagStatePoints.empty()) &&
+ "Adding invalid loc point after another point");
+ assert((Loc.isInvalid() || DiagStatePoints.empty() ||
+ DiagStatePoints.back().Loc.isInvalid() ||
+ DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
+ "Previous point loc comes after or is the same as new one");
+ DiagStatePoints.push_back(DiagStatePoint(State,
+ FullSourceLoc(Loc, *SourceMgr)));
+ }
+
+ /// \brief Finds the DiagStatePoint that contains the diagnostic state of
+ /// the given source location.
+ DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
/// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
/// fatal error is emitted, and is sticky.
@@ -239,14 +253,11 @@ private:
/// LastDiagLevel - This is the level of the last diagnostic emitted. This is
/// used to emit continuation diagnostics with the same level as the
/// diagnostic that they follow.
- Diagnostic::Level LastDiagLevel;
+ DiagnosticIDs::Level LastDiagLevel;
unsigned NumWarnings; // Number of warnings reported
unsigned NumErrors; // Number of errors reported
unsigned NumErrorsSuppressed; // Number of errors suppressed
-
- /// CustomDiagInfo - Information for uniquing and looking up custom diags.
- diag::CustomDiagInfo *CustomDiagInfo;
/// ArgToStringFn - A function pointer that converts an opaque diagnostic
/// argument to a strings. This takes the modifiers and argument that was
@@ -279,34 +290,52 @@ private:
std::string DelayedDiagArg2;
public:
- explicit Diagnostic(DiagnosticClient *client = 0);
+ explicit Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
+ DiagnosticClient *client = 0,
+ bool ShouldOwnClient = true);
~Diagnostic();
- //===--------------------------------------------------------------------===//
- // Diagnostic characterization methods, used by a client to customize how
- //
+ const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
+ return Diags;
+ }
+
+ DiagnosticClient *getClient() { return Client; }
+ const DiagnosticClient *getClient() const { return Client; }
- DiagnosticClient *getClient() { return Client.get(); }
- const DiagnosticClient *getClient() const { return Client.get(); }
-
/// \brief Return the current diagnostic client along with ownership of that
/// client.
- DiagnosticClient *takeClient() { return Client.take(); }
+ DiagnosticClient *takeClient() {
+ OwnsDiagClient = false;
+ return Client;
+ }
+
+ bool hasSourceManager() const { return SourceMgr != 0; }
+ SourceManager &getSourceManager() const {
+ assert(SourceMgr && "SourceManager not set!");
+ return *SourceMgr;
+ }
+ void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic characterization methods, used by a client to customize how
+ // diagnostics are emitted.
+ //
/// pushMappings - Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack.
- void pushMappings();
+ void pushMappings(SourceLocation Loc);
/// popMappings - Pops the current DiagMappings off the top of the stack
/// causing the new top of the stack to be the active mappings. Returns
/// true if the pop happens, false if there is only one DiagMapping on the
/// stack.
- bool popMappings();
+ bool popMappings(SourceLocation Loc);
/// \brief Set the diagnostic client associated with this diagnostic object.
///
- /// The diagnostic object takes ownership of \c client.
- void setClient(DiagnosticClient* client) { Client.reset(client); }
+ /// \param ShouldOwnClient true if the diagnostic object should take
+ /// ownership of \c client.
+ void setClient(DiagnosticClient *client, bool ShouldOwnClient = true);
/// setErrorLimit - Specify a limit for the number of errors we should
/// emit before giving up. Zero disables the limit.
@@ -362,7 +391,7 @@ public:
/// \brief Pretend that the last diagnostic issued was ignored. This can
/// be used by clients who suppress diagnostics themselves.
void setLastDiagnosticIgnored() {
- LastDiagLevel = Ignored;
+ LastDiagLevel = DiagnosticIDs::Ignored;
}
/// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
@@ -379,28 +408,29 @@ public:
void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
- /// setDiagnosticMapping - This allows the client to specify that certain
+ /// \brief This allows the client to specify that certain
/// warnings are ignored. Notes can never be mapped, errors can only be
/// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
- void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
- assert(Diag < diag::DIAG_UPPER_LIMIT &&
- "Can only map builtin diagnostics");
- assert((isBuiltinWarningOrExtension(Diag) ||
- (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) &&
- "Cannot map errors into warnings!");
- setDiagnosticMappingInternal(Diag, Map, true);
- }
+ ///
+ /// \param Loc The source location that this change of diagnostic state should
+ /// take affect. It can be null if we are setting the latest state.
+ void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
+ SourceLocation Loc);
/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
/// "unknown-pragmas" to have the specified mapping. This returns true and
/// ignores the request if "Group" was unknown, false otherwise.
- bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map);
+ ///
+ /// 'Loc' is the source location that this change of diagnostic state should
+ /// take affect. It can be null if we are setting the state from command-line.
+ bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map,
+ SourceLocation Loc = SourceLocation()) {
+ return Diags->setDiagnosticGroupMapping(Group, Map, Loc, *this);
+ }
bool hasErrorOccurred() const { return ErrorOccurred; }
bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
- unsigned getNumErrors() const { return NumErrors; }
- unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; }
unsigned getNumWarnings() const { return NumWarnings; }
void setNumWarnings(unsigned NumWarnings) {
@@ -410,8 +440,9 @@ public:
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
- unsigned getCustomDiagID(Level L, llvm::StringRef Message);
-
+ unsigned getCustomDiagID(Level L, llvm::StringRef Message) {
+ return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
+ }
/// ConvertArgToString - This method converts a diagnostic argument (as an
/// intptr_t) into the string that represents it.
@@ -437,92 +468,22 @@ public:
// Diagnostic classification and reporting interfaces.
//
- /// getDescription - Given a diagnostic ID, return a description of the
- /// issue.
- const char *getDescription(unsigned DiagID) const;
-
- /// isNoteWarningOrExtension - Return true if the unmapped diagnostic
- /// level of the specified diagnostic ID is a Warning or Extension.
- /// This only works on builtin diagnostics, not custom ones, and is not legal to
- /// call on NOTEs.
- static bool isBuiltinWarningOrExtension(unsigned DiagID);
-
- /// \brief Determine whether the given built-in diagnostic ID is a
- /// Note.
- static bool isBuiltinNote(unsigned DiagID);
-
- /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
- /// ID is for an extension of some sort.
- ///
- static bool isBuiltinExtensionDiag(unsigned DiagID) {
- bool ignored;
- return isBuiltinExtensionDiag(DiagID, ignored);
- }
-
- /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
- /// ID is for an extension of some sort. This also returns EnabledByDefault,
- /// which is set to indicate whether the diagnostic is ignored by default (in
- /// which case -pedantic enables it) or treated as a warning/error by default.
- ///
- static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
-
-
- /// getWarningOptionForDiag - Return the lowest-level warning option that
- /// enables the specified diagnostic. If there is no -Wfoo flag that controls
- /// the diagnostic, this returns null.
- static const char *getWarningOptionForDiag(unsigned DiagID);
-
- /// getWarningOptionForDiag - Return the category number that a specified
- /// DiagID belongs to, or 0 if no category.
- static unsigned getCategoryNumberForDiag(unsigned DiagID);
-
- /// getCategoryNameFromID - Given a category ID, return the name of the
- /// category.
- static const char *getCategoryNameFromID(unsigned CategoryID);
-
- /// \brief Enumeration describing how the the emission of a diagnostic should
- /// be treated when it occurs during C++ template argument deduction.
- enum SFINAEResponse {
- /// \brief The diagnostic should not be reported, but it should cause
- /// template argument deduction to fail.
- ///
- /// The vast majority of errors that occur during template argument
- /// deduction fall into this category.
- SFINAE_SubstitutionFailure,
-
- /// \brief The diagnostic should be suppressed entirely.
- ///
- /// Warnings generally fall into this category.
- SFINAE_Suppress,
-
- /// \brief The diagnostic should be reported.
- ///
- /// The diagnostic should be reported. Various fatal errors (e.g.,
- /// template instantiation depth exceeded) fall into this category.
- SFINAE_Report
- };
-
- /// \brief Determines whether the given built-in diagnostic ID is
- /// for an error that is suppressed if it occurs during C++ template
- /// argument deduction.
- ///
- /// When an error is suppressed due to SFINAE, the template argument
- /// deduction fails but no diagnostic is emitted. Certain classes of
- /// errors, such as those errors that involve C++ access control,
- /// are not SFINAE errors.
- static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
-
- /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
+ /// \brief Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
- Level getDiagnosticLevel(unsigned DiagID) const;
+ ///
+ /// \param Loc The source location we are interested in finding out the
+ /// diagnostic state. Can be null in order to query the latest state.
+ Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
+ return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
+ }
/// Report - Issue the message to the client. @c DiagID is a member of the
/// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder
/// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
/// @c Pos represents the source location associated with the diagnostic,
/// which can be an invalid location if no position information is available.
- inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
+ inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
inline DiagnosticBuilder Report(unsigned DiagID);
/// \brief Determine whethere there is already a diagnostic in flight.
@@ -563,32 +524,34 @@ private:
/// getDiagnosticMappingInfo - Return the mapping info currently set for the
/// specified builtin diagnostic. This returns the high bit encoding, or zero
/// if the field is completely uninitialized.
- diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const {
- return DiagMappingsStack.back().getMapping(Diag);
+ diag::Mapping getDiagnosticMappingInfo(diag::kind Diag,
+ DiagState *State) const {
+ return State->getMapping(Diag);
}
void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
- bool isUser) const {
+ DiagState *State,
+ bool isUser, bool isPragma) const {
if (isUser) Map |= 8; // Set the high bit for user mappings.
- DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map);
+ if (isPragma) Map |= 0x10; // Set the bit for diagnostic pragma mappings.
+ State->setMapping((diag::kind)DiagId, Map);
}
- /// getDiagnosticLevel - This is an internal implementation helper used when
- /// DiagClass is already known.
- Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const;
-
// This is private state used by DiagnosticBuilder. We put it here instead of
// in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
// object. This implementation choice means that we can only have one
// diagnostic "in flight" at a time, but this seems to be a reasonable
// tradeoff to keep these objects small. Assertions verify that only one
// diagnostic is in flight at a time.
+ friend class DiagnosticIDs;
friend class DiagnosticBuilder;
friend class DiagnosticInfo;
-
+ friend class PartialDiagnostic;
+ friend class DiagnosticErrorTrap;
+
/// CurDiagLoc - This is the location of the current diagnostic that is in
/// flight.
- FullSourceLoc CurDiagLoc;
+ SourceLocation CurDiagLoc;
/// CurDiagID - This is the ID of the current diagnostic that is in flight.
/// This is set to ~0U when there is no diagnostic in flight.
@@ -640,7 +603,33 @@ private:
///
/// \returns true if the diagnostic was emitted, false if it was
/// suppressed.
- bool ProcessDiag();
+ bool ProcessDiag() {
+ return Diags->ProcessDiag(*this);
+ }
+
+ friend class ASTReader;
+ friend class ASTWriter;
+};
+
+/// \brief RAII class that determines when any errors have occurred
+/// between the time the instance was created and the time it was
+/// queried.
+class DiagnosticErrorTrap {
+ Diagnostic &Diag;
+ unsigned PrevErrors;
+
+public:
+ explicit DiagnosticErrorTrap(Diagnostic &Diag)
+ : Diag(Diag), PrevErrors(Diag.NumErrors) {}
+
+ /// \brief Determine whether any errors have occurred since this
+ /// object instance was created.
+ bool hasErrorOccurred() const {
+ return Diag.NumErrors > PrevErrors;
+ }
+
+ // Set to initial state of "no errors occurred".
+ void reset() { PrevErrors = Diag.NumErrors; }
};
//===----------------------------------------------------------------------===//
@@ -667,6 +656,11 @@ class DiagnosticBuilder {
explicit DiagnosticBuilder(Diagnostic *diagObj)
: DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
+ friend class PartialDiagnostic;
+
+protected:
+ void FlushCounts();
+
public:
/// Copy constructor. When copied, this "takes" the diagnostic info from the
/// input and neuters it.
@@ -703,6 +697,17 @@ public:
/// isActive - Determine whether this diagnostic is still active.
bool isActive() const { return DiagObj != 0; }
+ /// \brief Retrieve the active diagnostic ID.
+ ///
+ /// \pre \c isActive()
+ unsigned getDiagID() const {
+ assert(isActive() && "Diagnostic is inactive");
+ return DiagObj->CurDiagID;
+ }
+
+ /// \brief Clear out the current diagnostic.
+ void Clear() { DiagObj = 0; }
+
/// Operator bool: conversion of DiagnosticBuilder to bool always returns
/// true. This allows is to be used in boolean error contexts like:
/// return Diag(...);
@@ -816,14 +821,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
/// Report - Issue the message to the client. DiagID is a member of the
/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
-inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){
+inline DiagnosticBuilder Diagnostic::Report(SourceLocation Loc,
+ unsigned DiagID){
assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
CurDiagLoc = Loc;
CurDiagID = DiagID;
return DiagnosticBuilder(this);
}
inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
- return Report(FullSourceLoc(), DiagID);
+ return Report(SourceLocation(), DiagID);
}
//===----------------------------------------------------------------------===//
@@ -840,7 +846,9 @@ public:
const Diagnostic *getDiags() const { return DiagObj; }
unsigned getID() const { return DiagObj->CurDiagID; }
- const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; }
+ const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
+ bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
+ SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
@@ -930,10 +938,11 @@ public:
};
/**
- * \brief Represents a diagnostic in a form that can be serialized and
- * deserialized.
+ * \brief Represents a diagnostic in a form that can be retained until its
+ * corresponding source manager is destroyed.
*/
class StoredDiagnostic {
+ unsigned ID;
Diagnostic::Level Level;
FullSourceLoc Loc;
std::string Message;
@@ -943,12 +952,14 @@ class StoredDiagnostic {
public:
StoredDiagnostic();
StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info);
- StoredDiagnostic(Diagnostic::Level Level, llvm::StringRef Message);
+ StoredDiagnostic(Diagnostic::Level Level, unsigned ID,
+ llvm::StringRef Message);
~StoredDiagnostic();
/// \brief Evaluates true when this object stores a diagnostic.
operator bool() const { return Message.size() > 0; }
+ unsigned getID() const { return ID; }
Diagnostic::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; }
@@ -964,25 +975,21 @@ public:
fixit_iterator fixit_begin() const { return FixIts.begin(); }
fixit_iterator fixit_end() const { return FixIts.end(); }
unsigned fixit_size() const { return FixIts.size(); }
-
- /// Serialize - Serialize the given diagnostic (with its diagnostic
- /// level) to the given stream. Serialization is a lossy operation,
- /// since the specific diagnostic ID and any macro-instantiation
- /// information is lost.
- void Serialize(llvm::raw_ostream &OS) const;
-
- /// Deserialize - Deserialize the first diagnostic within the memory
- /// [Memory, MemoryEnd), producing a new diagnostic builder describing the
- /// deserialized diagnostic. If the memory does not contain a
- /// diagnostic, returns a diagnostic builder with no diagnostic ID.
- static StoredDiagnostic Deserialize(FileManager &FM, SourceManager &SM,
- const char *&Memory, const char *MemoryEnd);
};
/// DiagnosticClient - This is an abstract interface implemented by clients of
/// the front-end, which formats and prints fully processed diagnostics.
class DiagnosticClient {
+protected:
+ unsigned NumWarnings; // Number of warnings reported
+ unsigned NumErrors; // Number of errors reported
+
public:
+ DiagnosticClient() : NumWarnings(0), NumErrors(0) { }
+
+ unsigned getNumErrors() const { return NumErrors; }
+ unsigned getNumWarnings() const { return NumWarnings; }
+
virtual ~DiagnosticClient();
/// BeginSourceFile - Callback to inform the diagnostic client that processing
@@ -1012,8 +1019,11 @@ public:
/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
/// capturing it to a log as needed.
+ ///
+ /// Default implementation just keeps track of the total number of warnings
+ /// and errors.
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
- const DiagnosticInfo &Info) = 0;
+ const DiagnosticInfo &Info);
};
} // end namespace clang
diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
index fabf9ebb4498..be510ed844e1 100644
--- a/include/clang/Basic/Diagnostic.td
+++ b/include/clang/Basic/Diagnostic.td
@@ -56,6 +56,7 @@ class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
string Text = text;
DiagClass Class = DC;
bit SFINAE = 1;
+ bit AccessControl = 0;
DiagMapping DefaultMapping = defaultmapping;
DiagGroup Group;
string CategoryName = "";
@@ -74,6 +75,7 @@ class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; }
class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; }
class NoSFINAE { bit SFINAE = 0; }
+class AccessControl { bit AccessControl = 1; }
// Definitions for Diagnostics.
include "DiagnosticASTKinds.td"
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index d755d99e6be5..7d45bc58463c 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -56,6 +56,8 @@ def note_odr_number_of_bases : Note<
"class has %0 base %plural{1:class|:classes}0">;
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
+
+// Importing Objective-C ASTs
def err_odr_ivar_type_inconsistent : Error<
"instance variable %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
@@ -80,5 +82,32 @@ def note_odr_objc_method_here : Note<
def err_odr_objc_property_type_inconsistent : Error<
"property %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
+def err_odr_objc_property_impl_kind_inconsistent : Error<
+ "property %0 is implemented with %select{@synthesize|@dynamic}1 in one "
+ "translation but %select{@dynamic|@synthesize}1 in another translation unit">;
+def note_odr_objc_property_impl_kind : Note<
+ "property %0 is implemented with %select{@synthesize|@dynamic}1 here">;
+def err_odr_objc_synthesize_ivar_inconsistent : Error<
+ "property %0 is synthesized to different ivars in different translation "
+ "units (%1 vs. %2)">;
+def note_odr_objc_synthesize_ivar_here : Note<
+ "property is synthesized to ivar %0 here">;
+
+// Importing C++ ASTs
+def err_odr_different_num_template_parameters : Error<
+ "template parameter lists have a different number of parameters (%0 vs %1)">;
+def note_odr_template_parameter_list : Note<
+ "template parameter list also declared here">;
+def err_odr_different_template_parameter_kind : Error<
+ "template parameter has different kinds in different translation units">;
+def note_odr_template_parameter_here : Note<
+ "template parameter declared here">;
+def err_odr_parameter_pack_non_pack : Error<
+ "parameter kind mismatch; parameter is %select{not a|a}0 parameter pack">;
+def note_odr_parameter_pack_non_pack : Note<
+ "%select{parameter|parameter pack}0 declared here">;
+def err_odr_non_type_parameter_type_inconsistent : Error<
+ "non-type template parameter declared with incompatible types in different "
+ "translation units (%0 vs. %1)">;
def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">;
}
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 98ea9d4bd6d9..85c64c5cef65 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -44,9 +44,12 @@ def err_expected_colon_after_setter_name : Error<
def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
InGroup<MissingDeclarations>;
def err_param_redefinition : Error<"redefinition of parameter %0">;
+def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">;
def err_invalid_storage_class_in_func_decl : Error<
"invalid storage class specifier in function declarator">;
def err_expected_namespace_name : Error<"expected namespace name">;
+def ext_variadic_templates : ExtWarn<
+ "variadic templates are a C++0x extension">, InGroup<CXX0x>;
// Sema && Lex
def ext_longlong : Extension<
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 34cd6004edee..ef1c9e7d8b9a 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -11,11 +11,15 @@ 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_option_argument : Error<
+ "unsupported argument '%1' to option '%0'">;
def err_drv_unknown_stdin_type : Error<
"-E or -x required when input is from standard input">;
def err_drv_unknown_language : Error<"language not recognized: '%0'">;
def err_drv_invalid_arch_name : Error<
"invalid arch name '%0'">;
+def err_drv_invalid_stdlib_name : Error<
+ "invalid library name in argument '%0'">;
def err_drv_invalid_opt_with_multiple_archs : Error<
"option '%0' cannot be used with multiple -arch options">;
def err_drv_invalid_output_with_multiple_archs : Error<
@@ -49,6 +53,8 @@ def err_drv_no_ast_support : Error<
"'%0': unable to use AST files with this tool">;
def err_drv_clang_unsupported : Error<
"the clang compiler does not support '%0'">;
+def err_drv_clang_unsupported_per_platform : Error<
+ "the clang compiler does not support '%0' on this platform">;
def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error<
"the clang compiler does not support '%0' for C++ on Darwin/i386">;
def err_drv_command_failed : Error<
@@ -71,6 +77,10 @@ def err_drv_cc_print_options_failure : Error<
def err_drv_preamble_format : Error<
"incorrect format for -preamble-bytes=N,END">;
+def warn_c_kext : Warning<
+ "ignoring -fapple-kext which is valid for c++ and objective-c++ only">;
+def warn_drv_unsupported_option_argument : Warning<
+ "ignoring unsupported argument '%1' to option '%0'">;
def warn_drv_input_file_unused : Warning<
"%0: '%1' input unused when '%2' is present">;
def warn_drv_preprocessed_input_file_unused : Warning<
@@ -91,8 +101,6 @@ def warn_drv_assuming_mfloat_abi_is : Warning<
"unknown platform, assuming -mfloat-abi=%0">;
def warn_ignoring_ftabstop_value : Warning<
"ignoring invalid -ftabstop value '%0', using default value %1">;
-def warn_drv_missing_resource_library : Warning<
- "missing resource library '%0', link may fail">;
def warn_drv_conflicting_deployment_targets : Warning<
"conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">;
def warn_drv_treating_input_as_cxx : Warning<
@@ -100,5 +108,7 @@ def warn_drv_treating_input_as_cxx : Warning<
InGroup<Deprecated>;
def warn_drv_objc_gc_unsupported : Warning<
"Objective-C garbage collection is not supported on this platform, ignoring '%0'">;
+def warn_drv_pch_not_first_include : Warning<
+ "precompiled header '%0' was ignored because '%1' is not first '-include'">;
}
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 7c74bf458e58..5f9f4a7f3927 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -18,7 +18,7 @@ def err_fe_invalid_ast_action : Error<"invalid action for AST input">,
DefaultFatal;
// Error generated by the backend.
def err_fe_inline_asm : Error<"%0">, CatInlineAsm;
-def note_fe_inline_asm_here : Note<"instantated into assembly here">;
+def note_fe_inline_asm_here : Note<"instantiated into assembly here">;
@@ -69,12 +69,16 @@ def err_fe_pch_file_modified : Error<
DefaultFatal;
def err_fe_unable_to_open_output : Error<
"unable to open output file '%0': '%1'">;
+def err_fe_unable_to_rename_temp : Error<
+ "unable to rename temporary '%0' to output file '%1': '%2'">;
def err_fe_unable_to_open_logfile : Error<
"unable to open logfile file '%0': '%1'">;
def err_fe_pth_file_has_no_source_header : Error<
"PTH file '%0' does not designate an original source header file for -include-pth">;
def warn_fe_macro_contains_embedded_newline : Warning<
"macro '%0' contains embedded newline, text after the newline is ignored.">;
+def warn_fe_cc_print_header_failure : Warning<
+ "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">;
def err_verify_missing_start : Error<
"cannot find start ('{{') of expected %0">;
@@ -83,7 +87,8 @@ def err_verify_missing_end : Error<
def err_verify_invalid_content : Error<
"invalid expected %0: %1">;
def err_verify_inconsistent_diags : Error<
- "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: %2">;
+ "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: "
+ "%2">;
def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
def note_fixit_in_macro : Note<
@@ -127,6 +132,12 @@ def warn_pch_nonfragile_abi2 : Error<
"PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 "
"Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 "
"Objective-C ABI is selected">;
+def warn_pch_apple_kext : Error<
+ "PCH file was compiled %select{with|without}0 support for Apple's kernel "
+ "extensions ABI but it is currently %select{disabled|enabled}1">;
+def warn_pch_objc_auto_properties : Error<
+ "PCH file was compiled %select{with|without}0 support for auto-synthesized "
+ "@properties but it is currently %select{disabled|enabled}1">;
def warn_pch_no_constant_cfstrings : Error<
"Objctive-C NSstring generation support was %select{disabled|enabled}0 "
"in PCH file but currently %select{disabled|enabled}1">;
@@ -142,6 +153,9 @@ def warn_pch_gnu_keywords : Error<
def warn_pch_microsoft_extensions : Error<
"Microsoft extensions were %select{disabled|enabled}0 in PCH file but are "
"currently %select{disabled|enabled}1">;
+def warn_pch_ms_bitfields : Error<
+ "Microsoft-compatible structure layout was %select{disabled|enabled}0 in "
+ "PCH file but is currently %select{disabled|enabled}1">;
def warn_pch_heinous_extensions : Error<
"heinous extensions were %select{disabled|enabled}0 in PCH file but are "
"currently %select{disabled|enabled}1">;
@@ -154,6 +168,9 @@ def warn_pch_altivec : Error<
def warn_pch_opencl : Error<
"OpenCL language extensions were %select{disabled|enabled}0 in PCH file "
"but are currently %select{disabled|enabled}1">;
+def warn_pch_cuda : Error<
+ "CUDA language extensions were %select{disabled|enabled}0 in PCH file "
+ "but are currently %select{disabled|enabled}1">;
def warn_pch_elide_constructors : Error<
"Elidable copy constructors were %select{disabled|enabled}0 in PCH file "
"but are currently %select{disabled|enabled}1">;
@@ -163,6 +180,9 @@ def warn_pch_exceptions : Error<
def warn_pch_sjlj_exceptions : Error<
"sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
+def warn_pch_objc_exceptions : Error<
+ "Objective-C exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
def warn_pch_objc_runtime : Error<
"PCH file was compiled with the %select{NeXT|GNU}0 runtime but the "
"%select{NeXT|GNU}1 runtime is selected">;
@@ -241,6 +261,9 @@ def warn_pch_char_signed : Error<
def warn_pch_short_wchar : Error<
"-fshort-wchar was %select{disabled|enabled}0 in the PCH file but "
"is currently %select{disabled|enabled}1">;
+def warn_pch_short_enums : Error<
+ "-fshort-enums was %select{disabled|enabled}0 in the PCH file but "
+ "is currently %select{disabled|enabled}1">;
def err_not_a_pch_file : Error<
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
@@ -250,4 +273,7 @@ def warn_unknown_warning_option : Warning<
def warn_unknown_warning_specifier : Warning<
"unknown %0 warning specifier: '%1'">,
InGroup<DiagGroup<"unknown-warning-option"> >;
+
+def warn_unkwown_analyzer_checker : Warning<
+ "no analyzer checkers are associated with '%0'">;
}
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index d4b7f1f55743..d4377c9a0b07 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -35,9 +35,12 @@ def : DiagGroup<"declaration-after-statement">;
def GNUDesignator : DiagGroup<"gnu-designator">;
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
+def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings">;
def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >,
DiagCategory<"Deprecations">;
+def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
+
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">;
@@ -54,6 +57,7 @@ def : DiagGroup<"effc++">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
def GlobalConstructors : DiagGroup<"global-constructors">;
def : DiagGroup<"idiomatic-parentheses">;
+def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
def : DiagGroup<"init-self">;
@@ -74,17 +78,19 @@ def : DiagGroup<"newline-eof">;
def LongLong : DiagGroup<"long-long">;
def MismatchedTags : DiagGroup<"mismatched-tags">;
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def NullDereference : DiagGroup<"null-dereference">;
def InitializerOverrides : DiagGroup<"initializer-overrides">;
def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">;
-def : DiagGroup<"non-virtual-dtor">;
+def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
def : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
def : DiagGroup<"overflow">;
def OverlengthStrings : DiagGroup<"overlength-strings">;
-def : DiagGroup<"overloaded-virtual">;
-def : DiagGroup<"packed">;
+def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
+def Packed : DiagGroup<"packed">;
+def Padded : DiagGroup<"padded">;
def PointerArith : DiagGroup<"pointer-arith">;
def PoundWarning : DiagGroup<"#warnings">,
DiagCategory<"#warning Directive">;
@@ -92,6 +98,7 @@ def : DiagGroup<"pointer-to-int-cast">;
def : DiagGroup<"redundant-decls">;
def ReturnType : DiagGroup<"return-type">;
def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy">;
+def SelfAssignment : DiagGroup<"self-assign">;
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
def : DiagGroup<"sequence-point">;
def Shadow : DiagGroup<"shadow">;
@@ -101,6 +108,7 @@ def SignCompare : DiagGroup<"sign-compare">;
def : DiagGroup<"stack-protector">;
def : DiagGroup<"switch-default">;
def : DiagGroup<"synth">;
+def TautologicalCompare : DiagGroup<"tautological-compare">;
// Preprocessor warnings.
def : DiagGroup<"builtin-macro-redefined">;
@@ -140,9 +148,14 @@ def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">;
def UnusedVariable : DiagGroup<"unused-variable">;
+def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
+def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
+def CustomAtomic : DiagGroup<"custom-atomic-properties">;
+def AtomicProperties : DiagGroup<"atomic-properties",
+ [ImplicitAtomic, CustomAtomic]>;
def Selector : DiagGroup<"selector">;
def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">;
@@ -154,17 +167,27 @@ def VLA : DiagGroup<"vla">;
def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
def : DiagGroup<"write-strings">;
def CharSubscript : DiagGroup<"char-subscripts">;
+def LargeByValueCopy : DiagGroup<"large-by-value-copy">;
// Aggregation warning settings.
// -Widiomatic-parentheses contains warnings about 'idiomatic'
// missing parentheses; it is off by default.
-def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]>;
+def Parentheses : DiagGroup<"parentheses",
+ [LogicalOpParentheses,
+ DiagGroup<"idiomatic-parentheses">]>;
-// -Wconversion has its own warnings, but we split this one out for
-// legacy reasons.
+// -Wconversion has its own warnings, but we split a few out for
+// legacy reasons:
+// - some people want just 64-to-32 warnings
+// - conversion warnings with constant sources are on by default
+// - conversion warnings for literals are on by default
+// - bool-to-pointer conversion warnings are on by default
def Conversion : DiagGroup<"conversion",
- [DiagGroup<"shorten-64-to-32">, BoolConversions]>,
+ [DiagGroup<"shorten-64-to-32">,
+ DiagGroup<"constant-conversion">,
+ DiagGroup<"literal-conversion">,
+ BoolConversions]>,
DiagCategory<"Value Conversion Issue">;
def Unused : DiagGroup<"unused",
@@ -202,13 +225,15 @@ def Most : DiagGroup<"most", [
MultiChar,
Reorder,
ReturnType,
+ SelfAssignment,
Switch,
Trigraphs,
Uninitialized,
UnknownPragmas,
Unused,
VectorConversions,
- VolatileRegisterVar
+ VolatileRegisterVar,
+ OverloadedVirtual
]>;
// -Wall is -Wmost -Wparentheses
@@ -224,5 +249,12 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
def NonGCC : DiagGroup<"non-gcc",
[SignCompare, Conversion, LiteralRange]>;
+// A warning group for warnings about using C++0x features as extensions in
+// earlier C++ versions.
+def CXX0x : DiagGroup<"c++0x-extensions">;
+
// A warning group for warnings about GCC extensions.
def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>;
+
+// A warning group for warnings about Microsoft extensions.
+def Microsoft : DiagGroup<"microsoft">;
diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
new file mode 100644
index 000000000000..b46380569851
--- /dev/null
+++ b/include/clang/Basic/DiagnosticIDs.h
@@ -0,0 +1,212 @@
+//===--- DiagnosticIDs.h - Diagnostic IDs Handling --------------*- 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 IDs-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICIDS_H
+#define LLVM_CLANG_DIAGNOSTICIDS_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ class Diagnostic;
+ class SourceLocation;
+
+ // Import the diagnostic enums themselves.
+ namespace diag {
+ // Start position for diagnostics.
+ enum {
+ DIAG_START_DRIVER = 300,
+ DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
+ DIAG_START_LEX = DIAG_START_FRONTEND + 120,
+ DIAG_START_PARSE = DIAG_START_LEX + 300,
+ DIAG_START_AST = DIAG_START_PARSE + 300,
+ DIAG_START_SEMA = DIAG_START_AST + 100,
+ DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
+ DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
+ };
+
+ class CustomDiagInfo;
+
+ /// diag::kind - All of the diagnostics that can be emitted by the frontend.
+ typedef unsigned kind;
+
+ // Get typedefs for common diagnostics.
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+ NUM_BUILTIN_COMMON_DIAGNOSTICS
+#undef DIAG
+ };
+
+ /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
+ /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
+ /// (emit as an error). It allows clients to map errors to
+ /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
+ /// one).
+ enum Mapping {
+ // NOTE: 0 means "uncomputed".
+ MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
+ MAP_WARNING = 2, //< Map this diagnostic to a warning.
+ MAP_ERROR = 3, //< Map this diagnostic to an error.
+ MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
+
+ /// Map this diagnostic to "warning", but make it immune to -Werror. This
+ /// happens when you specify -Wno-error=foo.
+ MAP_WARNING_NO_WERROR = 5,
+ /// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
+ /// This happens for -Wno-fatal-errors=foo.
+ MAP_ERROR_NO_WFATAL = 6
+ };
+ }
+
+/// \brief Used for handling and querying diagnostic IDs. Can be used and shared
+/// by multiple Diagnostics for multiple translation units.
+class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
+public:
+ /// Level - The level of the diagnostic, after it has been through mapping.
+ enum Level {
+ Ignored, Note, Warning, Error, Fatal
+ };
+
+private:
+ /// CustomDiagInfo - Information for uniquing and looking up custom diags.
+ diag::CustomDiagInfo *CustomDiagInfo;
+
+public:
+ DiagnosticIDs();
+ ~DiagnosticIDs();
+
+ /// getCustomDiagID - Return an ID for a diagnostic with the specified message
+ /// and level. If this is the first request for this diagnosic, it is
+ /// registered and created, otherwise the existing ID is returned.
+ unsigned getCustomDiagID(Level L, llvm::StringRef Message);
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic classification and reporting interfaces.
+ //
+
+ /// getDescription - Given a diagnostic ID, return a description of the
+ /// issue.
+ const char *getDescription(unsigned DiagID) const;
+
+ /// isNoteWarningOrExtension - Return true if the unmapped diagnostic
+ /// level of the specified diagnostic ID is a Warning or Extension.
+ /// This only works on builtin diagnostics, not custom ones, and is not legal to
+ /// call on NOTEs.
+ static bool isBuiltinWarningOrExtension(unsigned DiagID);
+
+ /// \brief Determine whether the given built-in diagnostic ID is a
+ /// Note.
+ static bool isBuiltinNote(unsigned DiagID);
+
+ /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+ /// ID is for an extension of some sort.
+ ///
+ static bool isBuiltinExtensionDiag(unsigned DiagID) {
+ bool ignored;
+ return isBuiltinExtensionDiag(DiagID, ignored);
+ }
+
+ /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+ /// ID is for an extension of some sort. This also returns EnabledByDefault,
+ /// which is set to indicate whether the diagnostic is ignored by default (in
+ /// which case -pedantic enables it) or treated as a warning/error by default.
+ ///
+ static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
+
+
+ /// getWarningOptionForDiag - Return the lowest-level warning option that
+ /// enables the specified diagnostic. If there is no -Wfoo flag that controls
+ /// the diagnostic, this returns null.
+ static const char *getWarningOptionForDiag(unsigned DiagID);
+
+ /// getWarningOptionForDiag - Return the category number that a specified
+ /// DiagID belongs to, or 0 if no category.
+ static unsigned getCategoryNumberForDiag(unsigned DiagID);
+
+ /// getCategoryNameFromID - Given a category ID, return the name of the
+ /// category.
+ static const char *getCategoryNameFromID(unsigned CategoryID);
+
+ /// \brief Enumeration describing how the the emission of a diagnostic should
+ /// be treated when it occurs during C++ template argument deduction.
+ enum SFINAEResponse {
+ /// \brief The diagnostic should not be reported, but it should cause
+ /// template argument deduction to fail.
+ ///
+ /// The vast majority of errors that occur during template argument
+ /// deduction fall into this category.
+ SFINAE_SubstitutionFailure,
+
+ /// \brief The diagnostic should be suppressed entirely.
+ ///
+ /// Warnings generally fall into this category.
+ SFINAE_Suppress,
+
+ /// \brief The diagnostic should be reported.
+ ///
+ /// The diagnostic should be reported. Various fatal errors (e.g.,
+ /// template instantiation depth exceeded) fall into this category.
+ SFINAE_Report,
+
+ /// \brief The diagnostic is an access-control diagnostic, which will be
+ /// substitution failures in some contexts and reported in others.
+ SFINAE_AccessControl
+ };
+
+ /// \brief Determines whether the given built-in diagnostic ID is
+ /// for an error that is suppressed if it occurs during C++ template
+ /// argument deduction.
+ ///
+ /// When an error is suppressed due to SFINAE, the template argument
+ /// deduction fails but no diagnostic is emitted. Certain classes of
+ /// errors, such as those errors that involve C++ access control,
+ /// are not SFINAE errors.
+ static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
+
+private:
+ /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
+ /// "unknown-pragmas" to have the specified mapping. This returns true and
+ /// ignores the request if "Group" was unknown, false otherwise.
+ bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map,
+ SourceLocation Loc, Diagnostic &Diag) const;
+
+ /// \brief Based on the way the client configured the Diagnostic
+ /// object, classify the specified diagnostic ID into a Level, consumable by
+ /// the DiagnosticClient.
+ ///
+ /// \param Loc The source location we are interested in finding out the
+ /// diagnostic state. Can be null in order to query the latest state.
+ DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
+ const Diagnostic &Diag) const;
+
+ /// getDiagnosticLevel - This is an internal implementation helper used when
+ /// DiagClass is already known.
+ DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
+ unsigned DiagClass,
+ SourceLocation Loc,
+ const Diagnostic &Diag) const;
+
+ /// ProcessDiag - This is the method used to report a diagnostic that is
+ /// finally fully formed.
+ ///
+ /// \returns true if the diagnostic was emitted, false if it was
+ /// suppressed.
+ bool ProcessDiag(Diagnostic &Diag) const;
+
+ friend class Diagnostic;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index dcb05c8fcd45..6d1d9b6ad869 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -45,8 +45,8 @@ def charize_microsoft_ext : Extension<"@# is a microsoft extension">;
def ext_token_used : Extension<"extension used">;
-def err_unterminated_string : Error<"missing terminating '\"' character">;
-def err_unterminated_char : Error<"missing terminating ' character">;
+def warn_unterminated_string : ExtWarn<"missing terminating '\"' character">;
+def warn_unterminated_char : ExtWarn<"missing terminating ' character">;
def err_empty_character : Error<"empty character constant">;
def err_unterminated_block_comment : Error<"unterminated /* comment">;
def err_invalid_character_to_charify : Error<
@@ -98,6 +98,10 @@ def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">;
def ext_string_too_long : Extension<"string literal of length %0 exceeds "
"maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to "
"support">, InGroup<OverlengthStrings>;
+def warn_ucn_escape_too_large : ExtWarn<
+ "character unicode escape sequence too long for its type">;
+def warn_ucn_not_valid_in_c89 : ExtWarn<
+ "unicode escape sequences are only valid in C99 or C++">;
//===----------------------------------------------------------------------===//
// PTH Diagnostics
@@ -240,11 +244,11 @@ def warn_pragma_ignored : Warning<"unknown pragma ignored">,
InGroup<UnknownPragmas>, DefaultIgnore;
def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
InGroup<UnknownPragmas>;
-def ext_stdc_pragma_syntax :
+def ext_on_off_switch_syntax :
ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">,
InGroup<UnknownPragmas>;
-def ext_stdc_pragma_syntax_eom :
- ExtWarn<"expected end of macro in STDC pragma">,
+def ext_pragma_syntax_eom :
+ ExtWarn<"expected end of macro in pragma">,
InGroup<UnknownPragmas>;
def warn_stdc_fenv_access_not_supported :
Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 646fd0d1bfb6..9d7ec9d45447 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -55,11 +55,15 @@ def ext_c99_compound_literal : Extension<
def ext_enumerator_list_comma : Extension<
"commas at the end of enumerator lists are a %select{C99|C++0x}0-specific "
"feature">;
+def err_enumerator_list_missing_comma : Error<
+ "missing ',' between enumerators">;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNU>;
def ext_gnu_address_of_label : Extension<
"use of GNU address-of-label extension">, InGroup<GNU>;
+def ext_gnu_local_label : Extension<
+ "use of GNU locally declared label extension">, InGroup<GNU>;
def ext_gnu_statement_expr : Extension<
"use of GNU statement expression extension">, InGroup<GNU>;
def ext_gnu_conditional_expr : Extension<
@@ -93,6 +97,7 @@ def err_expected_lsquare : Error<"expected '['">;
def err_expected_rsquare : Error<"expected ']'">;
def err_expected_rbrace : Error<"expected '}'">;
def err_expected_greater : Error<"expected '>'">;
+def err_expected_ggg : Error<"expected '>>>'">;
def err_expected_semi_declaration : Error<
"expected ';' at end of declaration">;
def err_expected_semi_decl_list : Error<
@@ -110,6 +115,8 @@ def err_expected_fn_body : Error<
def err_expected_method_body : Error<"expected method body">;
def err_invalid_token_after_toplevel_declarator : Error<
"expected ';' after top level declarator">;
+def err_invalid_equalequal_after_declarator : Error<
+ "invalid '==' at end of declaration; did you mean '='?">;
def err_expected_statement : Error<"expected statement">;
def err_expected_lparen_after : Error<"expected '(' after '%0'">;
def err_expected_lparen_after_id : Error<"expected '(' after %0">;
@@ -122,6 +129,8 @@ def err_expected_while : Error<"expected 'while' in do/while loop">;
def err_expected_semi_after : Error<"expected ';' after %0">;
def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">;
def err_expected_semi_after_expr : Error<"expected ';' after expression">;
+def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">;
+
def err_expected_semi_after_method_proto : Error<
"expected ';' after method prototype">;
def err_expected_semi_after_namespace_name : Error<
@@ -139,6 +148,8 @@ def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
def err_expected_colon_after : Error<"expected ':' after %0">;
def err_label_end_of_compound_statement : Error<
"label at end of compound statement: expected statement">;
+def err_address_of_label_outside_fn : Error<
+ "use of address-of-label extension outside of a function body">;
def err_expected_string_literal : Error<"expected string literal">;
def err_expected_asm_operand : Error<
"expected string literal or '[' for asm operand">, CatInlineAsm;
@@ -152,10 +163,12 @@ def err_invalid_reference_qualifier_application : Error<
"'%0' qualifier may not be applied to a reference">;
def err_illegal_decl_reference_to_reference : Error<
"%0 declared as a reference to a reference">;
-def err_rvalue_reference : Error<
- "rvalue references are only allowed in C++0x">;
-def ext_inline_namespace : Extension<
- "inline namespaces are a C++0x feature">;
+def ext_rvalue_reference : ExtWarn<
+ "rvalue references are a C++0x extension">, InGroup<CXX0x>;
+def ext_ref_qualifier : ExtWarn<
+ "reference qualifiers on functions are a C++0x extension">, InGroup<CXX0x>;
+def ext_inline_namespace : ExtWarn<
+ "inline namespaces are a C++0x feature">, InGroup<CXX0x>;
def err_argument_required_after_attribute : Error<
"argument required after attribute">;
def err_missing_param : Error<"expected parameter declarator">;
@@ -194,10 +207,16 @@ def err_unknown_typename : Error<
"unknown type name %0">;
def err_use_of_tag_name_without_tag : Error<
"must use '%1' tag to refer to type %0%select{| in this scope}2">;
+def err_templated_using_directive : Error<
+ "cannot template a using directive">;
+def err_templated_using_declaration : Error<
+ "cannot template a using declaration">;
def err_expected_ident_in_using : Error<
"expected an identifier in using directive">;
def err_unexected_colon_in_nested_name_spec : Error<
"unexpected ':' in nested name specifier">;
+def err_bool_redeclaration : Error<
+ "redeclaration of C++ built-in type 'bool'">;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
@@ -214,13 +233,17 @@ def err_illegal_super_cast : Error<
def err_objc_illegal_visibility_spec : Error<
"illegal visibility specification">;
def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">;
-def err_objc_expected_equal : Error<
- "setter/getter expects '=' followed by name">;
+def err_objc_expected_equal_for_getter : Error<
+ "expected '=' for Objective-C getter">;
+def err_objc_expected_equal_for_setter : Error<
+ "expected '=' for Objective-C setter">;
+def err_objc_expected_selector_for_getter_setter : Error<
+ "expected selector for Objective-C %select{setter|getter}0">;
def err_objc_property_requires_field_name : Error<
"property requires fields to be named">;
def err_objc_property_bitfield : Error<"property name cannot be a bitfield">;
def err_objc_expected_property_attr : Error<"unknown property attribute %0">;
-def err_objc_propertoes_require_objc2 : Error<
+def err_objc_properties_require_objc2 : Error<
"properties are an Objective-C 2 feature">;
def err_objc_unexpected_attr : Error<
"prefix attribute must be followed by an interface or protocol">;
@@ -283,8 +306,6 @@ def err_default_arg_unparsed : Error<
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
// C++ operator overloading
-def err_operator_missing_type_specifier : Error<
- "missing type specifier after 'operator'">;
def err_operator_string_not_empty : Error<
"string literal after 'operator' must be '\"\"'">;
@@ -334,6 +355,10 @@ def err_enum_template : Error<"enumeration cannot be a template">;
def err_missing_dependent_template_keyword : Error<
"use 'template' keyword to treat '%0' as a dependent template name">;
+def warn_static_inline_explicit_inst_ignored : Warning<
+ "ignoring '%select{static|inline}0' keyword on explicit template "
+ "instantiation">;
+
// Constructor template diagnostics.
def err_out_of_line_constructor_template_id : Error<
"out-of-line constructor for %0 cannot have template arguments">;
@@ -356,18 +381,42 @@ def err_expected_type_name_after_typename : Error<
def err_explicit_spec_non_template : Error<
"explicit %select{specialization|instantiation}0 of non-template "
"%select{class|struct|union}1 %2">;
-
-def err_variadic_templates : Error<
- "variadic templates are only allowed in C++0x">;
def err_default_template_template_parameter_not_template : Error<
"default template argument for a template template parameter must be a class "
"template">;
+def err_ctor_init_missing_comma : Error<
+ "missing ',' between base or member initializers">;
+
// C++ declarations
def err_friend_decl_defines_class : Error<
"cannot define a type in a friend declaration">;
-
+
+def warn_deleted_function_accepted_as_extension: ExtWarn<
+ "deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
+
+// C++0x override control
+def ext_override_control_keyword : Extension<
+ "'%0' keyword accepted as a C++0x extension">, InGroup<CXX0x>;
+def ext_override_inline: Extension<
+ "'%0' keyword only allowed in declarations, allowed as an extension">;
+
+def err_duplicate_virt_specifier : Error<
+ "class member already marked '%0'">;
+def err_duplicate_class_virt_specifier : Error<
+ "class already marked '%0'">;
+
+def err_scoped_enum_missing_identifier : Error<
+ "scoped enumeration requires a name">;
+
+def err_expected_parameter_pack : Error<
+ "expected the name of a parameter pack">;
+def err_paren_sizeof_parameter_pack : Error<
+ "missing parentheses around the size of parameter pack %0">;
+def err_sizeof_parameter_pack : Error<
+ "expected parenthesized parameter pack name in 'sizeof...' expression">;
+
// Language specific pragmas
// - Generic warnings
def warn_pragma_expected_lparen : Warning<
@@ -398,5 +447,17 @@ def warn_pragma_unused_expected_var : Warning<
def warn_pragma_unused_expected_punc : Warning<
"expected ')' or ',' in '#pragma unused'">;
+// OpenCL Section 6.8.g
+def err_not_opencl_storage_class_specifier : Error<
+ "OpenCL does not support the '%0' storage class specifier">;
+
+// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
+def warn_pragma_expected_colon : Warning<
+ "missing ':' after %0 - ignoring">;
+def warn_pragma_expected_enable_disable : Warning<
+ "expected 'enable' or 'disable' - ignoring">;
+def warn_pragma_unknown_extension : Warning<
+ "unknown OpenCL extension %0 - ignoring">;
+
} // end of Parse Issue category.
} // end of Parser diagnostics
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index a25b2a341fc5..2e7f274b8ed5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -46,14 +46,18 @@ def err_vla_decl_has_static_storage : Error<
"variable length array declaration can not have 'static' storage duration">;
def err_vla_decl_has_extern_linkage : Error<
"variable length array declaration can not have 'extern' linkage">;
-
+
// C99 variably modified types
def err_variably_modified_template_arg : Error<
"variably modified type %0 cannot be used as a template argument">;
def err_variably_modified_nontype_template_param : Error<
"non-type template parameter of variably modified type %0">;
+def err_variably_modified_new_type : Error<
+ "'new' cannot allocate object of variably modified type %0">;
// C99 Designated Initializers
+def ext_designated_init : Extension<
+ "designated initializers are a C99 feature, accepted in C++ as an extension">;
def err_array_designator_negative : Error<
"array designator value '%0' is negative">;
def err_array_designator_empty_range : Error<
@@ -93,6 +97,8 @@ def ext_anon_param_requires_type_specifier : Extension<
"type specifier required for unnamed parameter, defaults to int">;
def err_bad_variable_name : Error<
"'%0' cannot be the name of a variable or data member">;
+def err_bad_parameter_name : Error<
+ "'%0' cannot be the name of a parameter">;
def err_parameter_name_omitted : Error<"parameter name omitted">;
def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
@@ -106,7 +112,16 @@ def warn_unused_function : Warning<"unused function %0">,
InGroup<UnusedFunction>, DefaultIgnore;
def warn_unused_member_function : Warning<"unused member function %0">,
InGroup<UnusedMemberFunction>, DefaultIgnore;
-
+def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">,
+ InGroup<UsedButMarkedUnused>, DefaultIgnore;
+
+def warn_parameter_size: Warning<
+ "%0 is a large (%1 bytes) pass-by-value argument; "
+ "pass it by reference instead ?">, InGroup<LargeByValueCopy>;
+def warn_return_value_size: Warning<
+ "return value of %0 is a large (%1 bytes) pass-by-value object; "
+ "pass it by reference instead ?">, InGroup<LargeByValueCopy>;
+
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
@@ -147,6 +162,17 @@ def err_using_decl_nested_name_specifier_is_current_class : Error<
"using declaration refers to its own class">;
def err_using_decl_nested_name_specifier_is_not_base_class : Error<
"using declaration refers into '%0', which is not a base class of %1">;
+def err_using_decl_constructor_not_in_direct_base : Error<
+ "%0 is not a direct base of %1, can not inherit constructors">;
+def err_using_decl_constructor_conflict : Error<
+ "can not inherit constructor, already inherited constructor with "
+ "the same signature">;
+def note_using_decl_constructor_conflict_current_ctor : Note<
+ "conflicting constructor">;
+def note_using_decl_constructor_conflict_previous_ctor : Note<
+ "previous constructor">;
+def note_using_decl_constructor_conflict_previous_using : Note<
+ "previously inherited here">;
def err_using_decl_can_not_refer_to_class_member : Error<
"using declaration can not refer to class member">;
def err_using_decl_can_not_refer_to_namespace : Error<
@@ -210,10 +236,12 @@ def note_please_include_header : Note<
"please include the header <%0> or explicitly provide a "
"declaration for '%1'">;
def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
-def err_implicit_decl_requires_stdio : Error<
- "implicit declaration of '%0' requires inclusion of the header <stdio.h>">;
-def err_implicit_decl_requires_setjmp : Error<
- "implicit declaration of '%0' requires inclusion of the header <setjmp.h>">;
+def warn_implicit_decl_requires_stdio : Warning<
+ "declaration of built-in function '%0' requires inclusion of the header "
+ "<stdio.h>">;
+def warn_implicit_decl_requires_setjmp : Warning<
+ "declaration of built-in function '%0' requires inclusion of the header "
+ "<setjmp.h>">;
def warn_redecl_library_builtin : Warning<
"incompatible redeclaration of library function %0">;
def err_builtin_definition : Error<"definition of builtin function %0">;
@@ -227,6 +255,7 @@ def warn_unusual_main_decl : Warning<"'main' should not be declared "
"%select{static|inline|static or inline}0">;
def err_unusual_main_decl : Error<"'main' is not allowed to be declared "
"%select{static|inline|static or inline}0">;
+def err_main_template_decl : Error<"'main' cannot be a template">;
def err_main_returns_nonint : Error<"'main' must return 'int'">;
def err_main_surplus_args : Error<"too many parameters (%0) for 'main': "
"must be 0, 2, or 3">;
@@ -261,8 +290,8 @@ def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
def warn_pragma_unused_undeclared_var : Warning<
"undeclared variable %0 used as an argument for '#pragma unused'">;
-def warn_pragma_unused_expected_localvar : Warning<
- "only local variables can be arguments to '#pragma unused'">;
+def warn_pragma_unused_expected_var_arg : Warning<
+ "only variables can be arguments to '#pragma unused'">;
def err_unsupported_pragma_weak : Error<
"using '#pragma weak' to refer to an undeclared identifier is not yet supported">;
@@ -314,16 +343,23 @@ def err_conflicting_ivar_name : Error<
"conflicting instance variable names: %0 vs %1">;
def err_inconsistant_ivar_count : Error<
"inconsistent number of instance variables specified">;
-def warn_incomplete_impl : Warning<"incomplete implementation">;
+def warn_incomplete_impl : Warning<"incomplete implementation">,
+ InGroup<DiagGroup<"incomplete-implementation">>;
def note_undef_method_impl : Note<"method definition for %0 not found">;
def note_required_for_protocol_at :
Note<"required for direct or indirect protocol %0">;
def warn_conflicting_ret_types : Warning<
"conflicting return type in implementation of %0: %1 vs %2">;
+def warn_non_covariant_ret_types : Warning<
+ "conflicting return type in implementation of %0: %1 vs %2">,
+ InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
def warn_conflicting_param_types : Warning<
"conflicting parameter types in implementation of %0: %1 vs %2">;
+def warn_non_contravariant_param_types : Warning<
+ "conflicting parameter types in implementation of %0: %1 vs %2">,
+ InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
def warn_conflicting_variadic :Warning<
"conflicting variadic declaration of method and its implementation">;
@@ -337,6 +373,7 @@ def warn_strict_multiple_method_decl : Warning<
def warn_accessor_property_type_mismatch : Warning<
"type of property %0 does not match type of accessor %1">;
def note_declared_at : Note<"declared here">;
+def note_method_declared_at : Note<"method declared 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_missing_atend : Warning<"'@end' is missing in implementation context">;
@@ -361,9 +398,17 @@ def warn_objc_property_copy_missing_on_block : Warning<
def warn_atomic_property_rule : Warning<
"writable atomic property %0 cannot pair a synthesized setter/getter "
"with a user defined setter/getter">;
+def warn_default_atomic_custom_getter_setter : Warning<
+ "atomic by default property %0 has a user defined %select{getter|setter}1 "
+ "(property should be marked 'atomic' if this is intended)">,
+ InGroup<CustomAtomic>, DefaultIgnore;
def err_use_continuation_class : Error<
- "illegal declaration of property in continuation class %0"
- ": attribute must be readwrite, while its primary must be readonly">;
+ "illegal redeclaration of property in continuation class %0"
+ " (attribute must be 'readwrite', while its primary must be 'readonly')">;
+def err_use_continuation_class_redeclaration_readwrite : Error<
+ "illegal redeclaration of 'readwrite' property in continuation class %0"
+ " (perhaps you intended this to be a 'readwrite' redeclaration of a "
+ "'readonly' public property?)">;
def err_continuation_class : Error<"continuation class has no primary class">;
def err_property_type : Error<"property cannot have array or function type %0">;
def error_missing_property_context : Error<
@@ -400,7 +445,7 @@ def error_ivar_in_superclass_use : Error<
def error_weak_property : Error<
"existing ivar %1 for __weak property %0 must be __weak">;
def error_strong_property : Error<
- "existing ivar %1 for a __strong property %0 must be garbage collectable">;
+ "property %0 must be declared __weak to match existing ivar %1 with __weak attribute">;
def error_dynamic_property_ivar_decl : Error<
"dynamic property can not have ivar specification">;
def error_duplicate_ivar_use : Error<
@@ -411,6 +456,11 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
+def warn_implicit_atomic_property : Warning<
+ "property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore;
+def warn_auto_implicit_atomic_property : Warning<
+ "property is assumed atomic when auto-synthesizing the property">,
+ InGroup<ImplicitAtomic>, DefaultIgnore;
def warn_unimplemented_selector: Warning<
"unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
@@ -442,11 +492,15 @@ def err_introducing_special_friend : Error<
"destructor|conversion operator}0 as a friend">;
def err_tagless_friend_type_template : Error<
"friend type templates must use an elaborated type">;
+def err_no_matching_local_friend : Error<
+ "no matching function found in local scope">;
+def err_partial_specialization_friend : Error<
+ "partial specialization cannot be declared as a friend">;
def err_abstract_type_in_decl : Error<
"%select{return|parameter|variable|field}0 type %1 is an abstract class">;
def err_allocation_of_abstract_type : Error<
- "allocation of an object of abstract type %0">;
+ "allocating an object of abstract class type %0">;
def err_throw_abstract_type : Error<
"cannot throw an object of abstract type %0">;
def err_array_of_abstract_type : Error<"array of abstract class type %0">;
@@ -463,7 +517,7 @@ def err_type_defined_in_param_type : Error<
"%0 can not be defined in a parameter type">;
def note_pure_virtual_function : Note<
- "pure virtual function %0">;
+ "unimplemented pure virtual method %0 in %1">;
def err_deleted_non_function : Error<
"only functions can have deleted definitions">;
@@ -503,65 +557,70 @@ def warn_missing_exception_specification : Warning<
def err_class_redeclared_with_different_access : Error<
"%0 redeclared with '%1' access">;
def err_access : Error<
- "%1 is a %select{private|protected}0 member of %3">, NoSFINAE;
+ "%1 is a %select{private|protected}0 member of %3">, AccessControl;
def err_access_ctor : Error<
- "calling a %select{private|protected}0 constructor of class %2">, NoSFINAE;
+ "calling a %select{private|protected}0 constructor of class %2">,
+ AccessControl;
def ext_rvalue_to_reference_access_ctor : ExtWarn<
"C++98 requires an accessible copy constructor for class %2 when binding "
"a reference to a temporary; was %select{private|protected}0">,
- NoSFINAE, InGroup<BindToTemporaryCopy>;
+ AccessControl, InGroup<BindToTemporaryCopy>;
def err_access_base : Error<
"%select{base class|inherited virtual base class}0 %1 has %select{private|"
"protected}3 %select{constructor|copy constructor|copy assignment operator|"
- "destructor}2">, NoSFINAE;
+ "destructor}2">, AccessControl;
def err_access_field: Error<
"field of type %0 has %select{private|protected}2 %select{constructor|copy "
- "constructor|copy assignment operator|destructor}1">, NoSFINAE;
+ "constructor|copy assignment operator|destructor}1">, AccessControl;
def err_access_ctor_field :
Error<"field of type %1 has %select{private|protected}2 constructor">,
- NoSFINAE;
+ AccessControl;
+def err_access_dtor : Error<
+ "calling a %select{private|protected}1 destructor of class %0">,
+ AccessControl;
def err_access_dtor_base :
Error<"base class %0 has %select{private|protected}1 destructor">,
- NoSFINAE;
+ AccessControl;
def err_access_dtor_vbase :
Error<"inherited virtual base class %0 has "
"%select{private|protected}1 destructor">,
- NoSFINAE;
+ AccessControl;
def err_access_dtor_temp :
Error<"temporary of type %0 has %select{private|protected}1 destructor">,
- NoSFINAE;
+ AccessControl;
def err_access_dtor_exception :
Error<"exception object of type %0 has %select{private|protected}1 "
- "destructor">, NoSFINAE;
+ "destructor">, AccessControl;
def err_access_dtor_field :
Error<"field of type %1 has %select{private|protected}2 destructor">,
- NoSFINAE;
+ AccessControl;
def err_access_dtor_var :
Error<"variable of type %1 has %select{private|protected}2 destructor">,
- NoSFINAE;
+ AccessControl;
def err_access_assign_field :
Error<"field of type %1 has %select{private|protected}2 copy assignment"
" operator">,
- NoSFINAE;
+ AccessControl;
def err_access_assign_base :
Error<"base class %0 has %select{private|protected}1 copy assignment"
" operator">,
- NoSFINAE;
+ AccessControl;
def err_access_copy_field :
Error<"field of type %1 has %select{private|protected}2 copy constructor">,
- NoSFINAE;
+ AccessControl;
def err_access_copy_base :
Error<"base class %0 has %select{private|protected}1 copy constructor">,
- NoSFINAE;
+ AccessControl;
def err_access_dtor_ivar :
Error<"instance variable of type %0 has %select{private|protected}1 "
"destructor">,
- NoSFINAE;
+ AccessControl;
def note_previous_access_declaration : Note<
"previously declared '%1' here">;
def err_access_outside_class : Error<
- "access to %select{private|protected}0 member outside any class context">;
+ "access to %select{private|protected}0 member outside any class context">,
+ AccessControl;
def note_access_natural : Note<
"%select{|implicitly }1declared %select{private|protected}0 here">;
def note_access_constrained_by_path : Note<
@@ -604,6 +663,10 @@ def err_virtual_non_function : Error<
"'virtual' can only appear on non-static member functions">;
def err_virtual_out_of_class : Error<
"'virtual' can only be specified inside the class definition">;
+def err_virtual_member_function_template : Error<
+ "'virtual' can not be specified on member function templates">;
+def err_static_overrides_virtual : Error<
+ "'static' member function %0 overrides a virtual function in a base class">;
def err_explicit_non_function : Error<
"'explicit' can only appear on non-static member functions">;
def err_explicit_out_of_class : Error<
@@ -619,7 +682,7 @@ def err_not_integral_type_bitfield : Error<
def err_not_integral_type_anon_bitfield : Error<
"anonymous bit-field has non-integral type %0">;
def err_member_initialization : Error<
- "%0 can only be initialized if it is a static const integral data member">;
+ "fields can only be initialized in constructors">;
def err_member_function_initialization : Error<
"initializer on function does not look like a pure-specifier">;
def err_non_virtual_pure : Error<
@@ -652,6 +715,10 @@ def note_nontrivial_has_nontrivial : Note<
def note_nontrivial_user_defined : Note<
"because type %0 has a user-declared %select{constructor|copy constructor|"
"copy assignment operator|destructor}1">;
+def err_static_data_member_not_allowed_in_union_or_anon_struct : Error<
+ "static data member %0 not allowed in %select{anonymous struct|union}1">;
+def err_union_member_of_reference_type : Error<
+ "union member %0 has reference type %1">;
def err_different_return_type_for_overriding_virtual_function : Error<
"virtual function %0 has a different return type (%1) than the "
@@ -661,7 +728,7 @@ def note_overridden_virtual_function : Note<
def err_covariant_return_inaccessible_base : Error<
"invalid covariant return for virtual function: %1 is a "
- "%select{private|protected}2 base class of %0">, NoSFINAE;
+ "%select{private|protected}2 base class of %0">, AccessControl;
def err_covariant_return_ambiguous_derived_to_base_conv : Error<
"return type of virtual function %3 is not covariant with the return type of "
"the function it overrides (ambiguous conversion from derived class "
@@ -684,6 +751,9 @@ def err_covariant_return_type_class_type_more_qualified : Error<
def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">;
def err_invalid_qualified_constructor : Error<
"'%0' qualifier is not allowed on a constructor">;
+def err_ref_qualifier_constructor : Error<
+ "ref-qualifier '%select{&&|&}0' is not allowed on a constructor">;
+
def err_constructor_return_type : Error<
"constructor cannot have a return type">;
def err_constructor_redeclared : Error<"constructor cannot be redeclared">;
@@ -694,6 +764,8 @@ def warn_no_constructor_for_refconst : Warning<
"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<
+ "explicit constructor calls are a Microsoft extension">, InGroup<Microsoft>;
// C++ destructors
def err_destructor_not_member : Error<
@@ -701,6 +773,8 @@ def err_destructor_not_member : Error<
def err_destructor_cannot_be : Error<"destructor cannot be declared '%0'">;
def err_invalid_qualified_destructor : Error<
"'%0' qualifier is not allowed on a destructor">;
+def err_ref_qualifier_destructor : Error<
+ "ref-qualifier '%select{&&|&}0' is not allowed on a destructor">;
def err_destructor_return_type : Error<"destructor cannot have a return type">;
def err_destructor_redeclared : Error<"destructor cannot be redeclared">;
def err_destructor_with_params : Error<"destructor cannot have any parameters">;
@@ -721,7 +795,8 @@ def err_init_conversion_failed : Error<
"base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of "
"type %3">;
-def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
+def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind "
+ "to lvalue of type %1">;
def err_invalid_initialization : Error<
"invalid initialization of reference of type %0 from expression of type %1">;
def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue "
@@ -745,6 +820,10 @@ def err_reference_bind_init_list : Error<
def err_init_list_bad_dest_type : Error<
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
"list">;
+def err_member_function_call_bad_cvr : Error<"member function %0 not viable: "
+ "'this' argument has type %1, but function is not marked "
+ "%select{const|restrict|const or restrict|volatile|const or volatile|"
+ "volatile or restrict|const, volatile, or restrict}2">;
def err_reference_init_drops_quals : Error<
"initialization of reference to type %0 with a %select{value|temporary}1 of type %2 drops "
@@ -768,7 +847,16 @@ def err_init_reference_member_uninitialized : Error<
def note_uninit_reference_member : Note<
"uninitialized reference member is here">;
def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
- InGroup<DiagGroup<"uninitialized">>;
+ InGroup<Uninitialized>;
+def warn_uninit_var : Warning<"variable %0 is possibly uninitialized when used here">,
+ InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore;
+def note_uninit_var_def : Note<
+ "variable %0 is declared here">;
+def warn_uninit_var_captured_by_block : Warning<
+ "variable %0 is possibly uninitialized when captured by block">,
+ InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore;
+def note_var_fixit_add_initialization : Note<
+ "add initialization to silence this warning">;
def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
def err_temp_copy_no_viable : Error<
@@ -798,20 +886,46 @@ def err_temp_copy_incomplete : Error<
// C++0x decltype
def err_cannot_determine_declared_type_of_overloaded_function : Error<
- "cannot determine the %select{type|declared type}0 of an overloaded "
- "function">;
+ "cannot determine the type of an overloaded function">;
// C++0x auto
def err_auto_variable_cannot_appear_in_own_initializer : Error<
"variable %0 declared with 'auto' type cannot appear in its own initializer">;
def err_illegal_decl_array_of_auto : Error<
- "'%0' declared as array of 'auto'">;
+ "'%0' declared as array of %1">;
+def err_new_array_of_auto : Error<
+ "cannot allocate array of 'auto'">;
def err_auto_not_allowed : Error<
- "'auto' not allowed in %select{function prototype|struct member|union member"
- "|class member|exception declaration|template parameter|block literal}0">;
+ "'auto' not allowed %select{in function prototype|in struct member"
+ "|in union member|in class member|in exception declaration"
+ "|in template parameter|in block literal|in template argument|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<
+ "new expression for type %0 requires a constructor argument">;
+def err_auto_var_init_multiple_expressions : Error<
+ "initializer for variable %0 with type %1 contains multiple expressions">;
+def err_auto_new_ctor_multiple_expressions : Error<
+ "new expression for type %0 contains multiple constructor arguments">;
+def err_auto_missing_trailing_return : Error<
+ "'auto' return without trailing return type">;
+def err_trailing_return_without_auto : Error<
+ "function with trailing return type must specify return type 'auto', not %0">;
+def err_auto_var_deduction_failure : Error<
+ "variable %0 with type %1 has incompatible initializer of type %2">;
+def err_auto_new_deduction_failure : Error<
+ "new expression for type %0 has incompatible constructor argument of type %1">;
+def err_auto_different_deductions : Error<
+ "'auto' deduced as %0 in declaration of %1 and deduced as %2 in declaration of %3">;
+
+// C++0x override control
+def override_keyword_only_allowed_on_virtual_member_functions : Error<
+ "only virtual member functions can be marked '%0'">;
+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'">;
+
// C++0x attributes
def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">;
@@ -820,6 +934,32 @@ def err_final_function_overridden : Error<
"declaration of %0 overrides a 'final' function">;
def err_final_base : Error<
"derivation from 'final' %0">;
+
+def err_function_overriding_without_override : Error<
+ "%0 overrides function%s1 without being marked 'override'">;
+
+// C++0x scoped enumerations
+def err_enum_invalid_underlying : Error<
+ "non-integral type %0 is an invalid underlying type">;
+def err_enumerator_too_large : Error<
+ "enumerator value is not representable in the underlying type %0">;
+def ext_enumerator_too_large : ExtWarn<
+ "enumerator value is not representable in the underlying type %0">,
+ InGroup<Microsoft>;
+def err_enumerator_wrapped : Error<
+ "enumerator value %0 is not representable in the underlying type %1">;
+def err_enum_redeclare_type_mismatch : Error<
+ "enumeration redeclared with different underlying type %0 (was %1)">;
+def err_enum_redeclare_fixed_mismatch : Error<
+ "enumeration previously declared with %select{non|}0fixed underlying type">;
+def err_enum_redeclare_scoped_mismatch : Error<
+ "enumeration previously declared as %select{un|}0scoped">;
+
+// C++0x delegating constructors
+def err_delegation_0x_only : Error<
+ "delegating constructors are permitted only in C++0x">;
+def err_delegation_unimplemented : Error<
+ "delegating constructors are not fully implemented">;
// Objective-C++
def err_objc_decls_may_only_appear_in_global_scope : Error<
@@ -842,13 +982,15 @@ def err_iboutletcollection_object_type : Error<
def err_attribute_missing_parameter_name : Error<
"attribute requires unquoted parameter">;
def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
+def err_attribute_bad_neon_vector_size : Error<
+ "Neon vector size must be 64 or 128 bits">;
def err_attribute_argument_not_int : Error<
"'%0' attribute requires integer constant">;
def err_attribute_argument_outof_range : Error<
"init_priority attribute requires integer constant between "
"101 and 65535 inclusive">;
def err_init_priority_object_attr : Error<
- "can only use ‘init_priority’ attribute on file-scope definitions "
+ "can only use 'init_priority' attribute on file-scope definitions "
"of objects of class type">;
def err_attribute_argument_n_not_int : Error<
"'%0' attribute requires parameter %1 to be an integer constant">;
@@ -858,8 +1000,12 @@ def err_attribute_argument_out_of_bounds : Error<
"'%0' attribute parameter %1 is out of bounds">;
def err_attribute_requires_objc_interface : Error<
"attribute may only be applied to an Objective-C interface">;
+def err_attribute_uuid_malformed_guid : Error<
+ "uuid attribute contains a malformed GUID">;
def warn_nonnull_pointers_only : Warning<
"nonnull attribute only applies to pointer arguments">;
+def err_attribute_invalid_implicit_this_argument : Error<
+ "'%0' attribute is invalid for the implicit this argument">;
def err_ownership_type : Error<
"%0 attribute only applies to %1 arguments">;
def err_format_strftime_third_parameter : Error<
@@ -868,6 +1014,9 @@ def err_format_attribute_requires_variadic : Error<
"format attribute requires variadic function">;
def err_format_attribute_not : Error<"format argument not %0">;
def err_format_attribute_result_not : Error<"function does not return %0">;
+def err_format_attribute_implicit_this_format_string : Error<
+ "format attribute cannot specify the implicit this argument as the format "
+ "string">;
def err_attribute_invalid_size : Error<
"vector size not an integral multiple of component size">;
def err_attribute_zero_size : Error<"zero vector size">;
@@ -889,9 +1038,6 @@ def err_attribute_address_space_too_high : Error<
"address space is larger than the maximum supported (%0)">;
def err_attribute_address_multiple_qualifiers : Error<
"multiple address spaces specified for type">;
-def err_implicit_pointer_address_space_cast : Error<
- "illegal implicit conversion between two pointers with different address "
- "spaces">;
def err_as_qualified_auto_decl : Error<
"automatic variable qualified with an address space">;
def err_arg_with_address_space : Error<
@@ -921,32 +1067,39 @@ def warn_attribute_weak_on_local : Warning<
def warn_weak_identifier_undeclared : Warning<
"weak identifier %0 never declared">;
def err_attribute_weak_static : Error<
- "weak declaration of '%0' must be public">;
+ "weak declaration cannot have internal linkage">;
def warn_attribute_weak_import_invalid_on_definition : Warning<
"'weak_import' attribute cannot be specified on a definition">;
def err_attribute_weakref_not_static : Error<
- "weakref declaration of '%0' must be static">;
+ "weakref declaration must have internal linkage">;
def err_attribute_weakref_not_global_context : Error<
"weakref declaration of '%0' must be in a global context">;
def err_attribute_weakref_without_alias : Error<
"weakref declaration of '%0' must also have an alias attribute">;
+def err_alias_not_supported_on_darwin : Error <
+ "only weak aliases are supported on darwin">;
def warn_attribute_wrong_decl_type : Warning<
- "%0 attribute only applies to %select{function|union|"
- "variable and function|function or method|parameter|"
- "parameter or Objective-C method |function, method or block|"
- "virtual method or class|function, method, or parameter|class|virtual method"
- "|member}1 types">;
+ "%0 attribute only applies to %select{functions|unions|"
+ "variables and functions|functions and methods|parameters|"
+ "parameters and methods|functions, methods and blocks|"
+ "classes and virtual methods|functions, methods, and parameters|"
+ "classes|virtual methods|class members|variables|methods|"
+ "variables, functions and labels}1">;
def err_attribute_wrong_decl_type : Error<
- "%0 attribute only applies to %select{function|union|"
- "variable and function|function or method|parameter|"
- "parameter or Objective-C method |function, method or block|"
- "virtual method or class|function, method, or parameter|class|virtual method"
- "|member}1 types">;
+ "%0 attribute only applies to %select{functions|unions|"
+ "variables and functions|functions and methods|parameters|"
+ "parameters and methods|functions, methods and blocks|"
+ "classes and virtual methods|functions, methods, and parameters|"
+ "classes|virtual methods|class members|variables|methods}1">;
def warn_function_attribute_wrong_type : Warning<
"%0 only applies to function types; type here is %1">;
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">;
+def err_attribute_vecreturn_only_vector_member : Error<
+ "the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">;
+def err_attribute_vecreturn_only_pod_record : Error<
+ "the vecreturn attribute can only be used on a POD (plain old data) class or structure (i.e. no virtual functions)">;
def err_cconv_change : Error<
"function declared '%0' here was previously declared "
"%select{'%2'|without calling convention}1">;
@@ -955,9 +1108,8 @@ def err_cconv_knr : Error<
def err_cconv_varargs : Error<
"variadic function cannot use %0 calling convention">;
def err_regparm_mismatch : Error<"function declared with with regparm(%0) "
- "attribute was previously declared %plural{0:without the regparm|1:"
- "with the regparm(1)|2:with the regparm(2)|3:with the regparm(3)|:with the"
- "regparm}1 attribute">;
+ "attribute was previously declared "
+ "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
def warn_impcast_vector_scalar : Warning<
"implicit conversion turns vector to scalar: %0 to %1">,
@@ -983,6 +1135,16 @@ def warn_impcast_integer_precision : Warning<
def warn_impcast_integer_64_32 : Warning<
"implicit conversion loses integer precision: %0 to %1">,
InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
+def warn_impcast_integer_precision_constant : Warning<
+ "implicit conversion from %2 to %3 changes value from %0 to %1">,
+ InGroup<DiagGroup<"constant-conversion">>;
+def warn_impcast_bitfield_precision_constant : Warning<
+ "implicit truncation from %2 to bitfield changes value from %0 to %1">,
+ InGroup<DiagGroup<"constant-conversion">>;
+def warn_impcast_literal_float_to_integer : Warning<
+ "implicit conversion turns literal floating-point number into integer: "
+ "%0 to %1">,
+ InGroup<DiagGroup<"literal-conversion">>, DefaultIgnore;
def warn_cast_align : Warning<
"cast from %0 to %1 increases required alignment from %2 to %3">,
@@ -1023,7 +1185,6 @@ def warn_attribute_malloc_pointer_only : Warning<
def warn_transparent_union_nonpointer : Warning<
"'transparent_union' attribute support incomplete; only supported for "
"pointer unions">;
-
def warn_attribute_sentinel_named_arguments : Warning<
"'sentinel' attribute requires named arguments">;
def warn_attribute_sentinel_not_variadic : Warning<
@@ -1048,9 +1209,9 @@ def err_attribute_regparm_invalid_number : Error<
// Clang-Specific Attributes
-def err_attribute_iboutlet : Error<
+def warn_attribute_iboutlet : Warning<
"%0 attribute can only be applied to instance variables or properties">;
-def err_attribute_ibaction: Error<
+def warn_attribute_ibaction: Warning<
"ibaction attribute can only be applied to Objective-C instance methods">;
def err_attribute_overloadable_not_function : Error<
"'overloadable' attribute can only be applied to a function">;
@@ -1062,8 +1223,11 @@ def note_attribute_overloadable_prev_overload : Note<
def err_attribute_overloadable_no_prototype : Error<
"'overloadable' function %0 must have a prototype">;
def warn_ns_attribute_wrong_return_type : Warning<
- "%0 attribute only applies to functions or methods that "
- "return a pointer or Objective-C object">;
+ "%0 attribute only applies to %select{functions|methods}1 that "
+ "return %select{an Objective-C object|a pointer}2">;
+def warn_ns_attribute_wrong_parameter_type : Warning<
+ "%0 attribute only applies to %select{Objective-C object|pointer}1 "
+ "parameters">;
// Function Parameter Semantic Analysis.
def err_param_with_void_type : Error<"argument may not have 'void' type">;
@@ -1148,12 +1312,14 @@ def note_ovl_candidate : Note<"candidate "
"function |function |constructor |"
"is the implicit default constructor|"
"is the implicit copy constructor|"
- "is the implicit copy assignment operator}0%1">;
+ "is the implicit copy assignment operator|"
+ "is an inherited constructor}0%1">;
def warn_init_pointer_from_false : Warning<
"initialization of pointer of type %0 from literal 'false'">,
InGroup<BoolConversions>;
+def note_ovl_candidate_inherited_constructor : Note<"inherited from here">;
def note_ovl_candidate_bad_deduction : Note<
"candidate template ignored: failed template argument deduction">;
def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
@@ -1181,14 +1347,15 @@ def note_ovl_candidate_arity : Note<"candidate "
"%select{function|function|constructor|function|function|constructor|"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0 %select{|template }1"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0 %select{|template }1"
"not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 "
"%plural{1:was|:were}4 provided">;
def note_ovl_candidate_deleted : Note<
- "candidate %select{function|function|constructor|"
- "function |function |constructor |||}0%1 "
- "has been explicitly %select{made unavailable|deleted}2">;
+ "candidate %select{function|function|constructor|"
+ "function |function |constructor ||||constructor (inherited)}0%1 "
+ "has been explicitly %select{made unavailable|deleted}2">;
// Giving the index of the bad argument really clutters this message, and
// it's relatively unimportant because 1) it's generally obvious which
@@ -1200,21 +1367,24 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
"function |function |constructor |"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1 "
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1 "
"not viable: cannot convert argument of incomplete type %2 to %3">;
def note_ovl_candidate_bad_overload : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1"
" not viable: no overload of %3 matching %2 for %ordinal4 argument">;
def note_ovl_candidate_bad_conv : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1"
" not viable: no known conversion from %2 to %3 for "
"%select{%ordinal5 argument|object argument}4">;
def note_ovl_candidate_bad_addrspace : Note<"candidate "
@@ -1222,12 +1392,13 @@ def note_ovl_candidate_bad_addrspace : Note<"candidate "
"function |function |constructor |"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1 not viable: "
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1 not viable: "
"%select{%ordinal6|'this'}5 argument (%2) is in "
"address space %3, but parameter must be in address space %4">;
def note_ovl_candidate_bad_cvr_this : Note<"candidate "
"%select{|function|||function||||"
- "function (the implicit copy assignment operator)}0 not viable: "
+ "function (the implicit copy assignment operator)|}0 not viable: "
"'this' argument has type %2, but method is not marked "
"%select{const|restrict|const or restrict|volatile|const or volatile|"
"volatile or restrict|const, volatile, or restrict}3">;
@@ -1236,7 +1407,8 @@ def note_ovl_candidate_bad_cvr : Note<"candidate "
"function |function |constructor |"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1 not viable: "
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1 not viable: "
"%ordinal4 argument (%2) would lose "
"%select{const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}3 qualifier"
@@ -1246,7 +1418,8 @@ def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
"function |function |constructor |"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1"
" not viable: cannot %select{convert from|convert from|bind}2 "
"%select{base class pointer|superclass|base class object of type}2 %3 to "
"%select{derived class pointer|subclass|derived class reference}2 %4 for "
@@ -1260,13 +1433,26 @@ def note_ovl_builtin_unary_candidate : Note<
"built-in candidate %0">;
def err_ovl_no_viable_function_in_init : Error<
"no matching constructor for initialization of %0">;
+def err_ovl_no_conversion_in_cast : Error<
+ "cannot convert %1 to %2 without a conversion operator">;
+def err_ovl_no_viable_conversion_in_cast : Error<
+ "no matching conversion for %select{|static_cast|reinterpret_cast|"
+ "dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">;
+def err_ovl_ambiguous_conversion_in_cast : Error<
+ "ambiguous conversion for %select{|static_cast|reinterpret_cast|"
+ "dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">;
+def err_ovl_deleted_conversion_in_cast : Error<
+ "%select{|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from %1 to %2 uses deleted function">;
def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">;
def err_ref_init_ambiguous : Error<
"reference initialization of type %0 with initializer of type %1 is ambiguous">;
def err_ovl_deleted_init : Error<
"call to %select{unavailable|deleted}0 constructor of %1">;
-def err_ovl_ambiguous_oper : Error<
- "use of overloaded operator '%0' is ambiguous">;
+def err_ovl_ambiguous_oper_unary : Error<
+ "use of overloaded operator '%0' is ambiguous (operand type %1)">;
+def err_ovl_ambiguous_oper_binary : Error<
+ "use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">;
def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
def err_ovl_deleted_oper : Error<
"overload resolution selected %select{unavailable|deleted}0 operator '%1'">;
@@ -1274,6 +1460,9 @@ def err_ovl_no_viable_subscript :
Error<"no viable overloaded operator[] for type %0">;
def err_ovl_no_oper :
Error<"type %0 does not provide a %select{subscript|call}1 operator">;
+def err_ovl_unresolvable :
+ Error<"cannot resolve overloaded function from context">;
+
def err_ovl_no_viable_object_call : Error<
"no matching function for call to object of type %0">;
@@ -1337,14 +1526,16 @@ def note_template_param_prev_default_arg : Note<
"previous default template argument defined here">;
def err_template_param_default_arg_missing : Error<
"template parameter missing a default argument">;
-def err_template_parameter_default_in_function_template : Error<
- "a template parameter of a function template cannot have a default argument "
- "in C++98">;
+def ext_template_parameter_default_in_function_template : ExtWarn<
+ "default template arguments for a function template are a C++0x extension">,
+ InGroup<CXX0x>;
def err_template_parameter_default_template_member : Error<
"cannot add a default template argument to the definition of a member of a "
"class template">;
def err_template_parameter_default_friend_template : Error<
"default template argument not permitted on a friend template">;
+def err_template_template_parm_no_parms : Error<
+ "template template parameter must have its own template parameters">;
def err_template_variable : Error<"variable %0 declared as a template">;
def err_template_variable_noparams : Error<
@@ -1401,10 +1592,10 @@ def err_template_arg_not_convertible : Error<
"of type %1">;
def warn_template_arg_negative : Warning<
"non-type template argument with value '%0' converted to '%1' for unsigned "
- "template parameter of type %2">;
+ "template parameter of type %2">, InGroup<Conversion>, DefaultIgnore;
def warn_template_arg_too_large : Warning<
"non-type template argument value '%0' truncated to '%1' for "
- "template parameter of type %2">;
+ "template parameter of type %2">, InGroup<Conversion>, DefaultIgnore;
def err_template_arg_no_ref_bind : Error<
"non-type template parameter of reference type %0 cannot bind to template "
"argument of type %1">;
@@ -1440,10 +1631,15 @@ def err_template_arg_not_object_or_func : Error<
"non-type template argument does not refer to an object or function">;
def err_template_arg_not_pointer_to_member_form : Error<
"non-type template argument is not a pointer to member constant">;
-def err_template_arg_extra_parens : Error<
- "non-type template argument cannot be surrounded by parentheses">;
+def ext_template_arg_extra_parens : ExtWarn<
+ "address non-type template argument cannot be surrounded by parentheses">;
def err_pointer_to_member_type : Error<
"invalid use of pointer to member type after %select{.*|->*}0">;
+def err_pointer_to_member_call_drops_quals : Error<
+ "call to pointer to member function of type %0 drops '%1' qualifier%s2">;
+def err_pointer_to_member_oper_value_classify: Error<
+ "pointer-to-member function type %0 can only be called on an "
+ "%select{rvalue|lvalue}1">;
// C++ template specialization
def err_template_spec_unknown_kind : Error<
@@ -1462,10 +1658,20 @@ def err_template_spec_decl_out_of_scope_global : Error<
"%select{class template|class template partial|function template|member "
"function|static data member|member class}0 specialization of %1 must "
"originally be declared in the global scope">;
+def ext_template_spec_decl_out_of_scope_global : ExtWarn<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 must "
+ "originally be declared in the global scope; accepted as a C++0x extension">,
+ InGroup<CXX0x>;
def err_template_spec_decl_out_of_scope : Error<
"%select{class template|class template partial|function template|member "
"function|static data member|member class}0 specialization of %1 must "
"originally be declared in namespace %2">;
+def ext_template_spec_decl_out_of_scope : ExtWarn<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 must "
+ "originally be declared in namespace %2; accepted as a C++0x extension">,
+ InGroup<CXX0x>;
def err_template_spec_redecl_out_of_scope : Error<
"%select{class template|class template partial|function template|member "
"function|static data member|member class}0 specialization of %1 not in a "
@@ -1549,6 +1755,8 @@ def err_function_template_spec_ambiguous : Error<
"arguments to identify a particular function template">;
def note_function_template_spec_matched : Note<
"function template matches specialization %0">;
+def err_function_template_partial_spec : Error<
+ "function template partial specialization is not allowed">;
// C++ Template Instantiation
def err_template_recursion_depth_exceeded : Error<
@@ -1597,6 +1805,8 @@ def note_instantiation_contexts_suppressed : Note<
def err_field_instantiates_to_function : Error<
"data member instantiated with function type %0">;
+def err_variable_instantiates_to_function : Error<
+ "%select{variable|static data member}0 instantiated with function type %1">;
def err_nested_name_spec_non_tag : Error<
"type %0 cannot be used prior to '::' because it has no members">;
@@ -1607,7 +1817,8 @@ def note_previous_explicit_instantiation : Note<
"previous explicit instantiation is here">;
def ext_explicit_instantiation_after_specialization : Extension<
"explicit instantiation of %0 that occurs after an explicit "
- "specialization will be ignored (C++0x extension)">;
+ "specialization will be ignored (C++0x extension)">,
+ InGroup<CXX0x>;
def note_previous_template_specialization : Note<
"previous template specialization is here">;
def err_explicit_instantiation_enum : Error<
@@ -1678,7 +1889,12 @@ def note_typename_refers_here : Note<
def err_typename_missing : Error<
"missing 'typename' prior to dependent type name '%0%1'">;
def ext_typename_outside_of_template : ExtWarn<
- "'typename' occurs outside of a template">;
+ "'typename' occurs outside of a template">, InGroup<CXX0x>;
+def err_typename_refers_to_using_value_decl : Error<
+ "typename specifier refers to a dependent using declaration for a value "
+ "%0 in %1">;
+def note_using_value_decl_missing_typename : Note<
+ "add 'typename' to treat this using declaration as a type">;
def err_template_kw_refers_to_non_template : Error<
"%0 following the 'template' keyword does not refer to a template">;
@@ -1691,7 +1907,7 @@ def note_referenced_class_template : Error<
def err_template_kw_missing : Error<
"missing 'template' keyword prior to dependent template name '%0%1'">;
def ext_template_outside_of_template : ExtWarn<
- "'template' keyword outside of a template">;
+ "'template' keyword outside of a template">, InGroup<CXX0x>;
// C++0x Variadic Templates
def err_template_param_pack_default_arg : Error<
@@ -1700,17 +1916,62 @@ def err_template_param_pack_must_be_last_template_parameter : Error<
"template parameter pack must be the last template parameter">;
def err_template_parameter_pack_non_pack : Error<
- "template %select{type|non-type|template}0 parameter%select{| pack}1 "
- "conflicts with previous template %select{type|non-type|template}0 "
- "parameter%select{ pack|}1">;
+ "%select{template type|non-type template|template template}0 parameter"
+ "%select{| pack}1 conflicts with previous %select{template type|"
+ "non-type template|template template}0 parameter%select{ pack|}1">;
def note_template_parameter_pack_non_pack : Note<
- "template %select{type|non-type|template}0 parameter%select{| pack}1 "
- "does not match template %select{type|non-type|template}0 "
- "parameter%select{ pack|}1 in template argument">;
+ "%select{template type|non-type template|template template}0 parameter"
+ "%select{| pack}1 does not match %select{template type|non-type template"
+ "|template template}0 parameter%select{ pack|}1 in template argument">;
def note_template_parameter_pack_here : Note<
- "previous template %select{type|non-type|template}0 "
+ "previous %select{template type|non-type template|template template}0 "
"parameter%select{| pack}1 declared here">;
+def err_unexpanded_parameter_pack_0 : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains an unexpanded parameter pack">;
+def err_unexpanded_parameter_pack_1 : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains unexpanded parameter pack %1">;
+def err_unexpanded_parameter_pack_2 : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains unexpanded parameter packs %1 and %2">;
+def err_unexpanded_parameter_pack_3_or_more : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains unexpanded parameter packs %1, %2, ...">;
+
+def err_pack_expansion_without_parameter_packs : Error<
+ "pack expansion does not contain any unexpanded parameter packs">;
+def err_pack_expansion_length_conflict : Error<
+ "pack expansion contains parameter packs %0 and %1 that have different "
+ "lengths (%2 vs. %3)">;
+def err_pack_expansion_length_conflict_multilevel : Error<
+ "pack expansion contains parameter pack %0 that has a different "
+ "length (%1 vs. %2) from outer parameter packs">;
+def err_pack_expansion_member_init : Error<
+ "pack expansion for initialization of member %0">;
+
+def err_function_parameter_pack_without_parameter_packs : Error<
+ "type %0 of function parameter pack does not contain any unexpanded "
+ "parameter packs">;
+def err_ellipsis_in_declarator_not_parameter : Error<
+ "only function and template parameters can be parameter packs">;
+
+def err_sizeof_pack_no_pack_name : Error<
+ "%0 does not refer to the name of a parameter pack">;
+
def err_unexpected_typedef : Error<
"unexpected type name %0: expected expression">;
def err_unexpected_namespace : Error<
@@ -1721,9 +1982,20 @@ def note_dependent_var_use : Note<"must qualify identifier to find this "
def err_undeclared_use : Error<"use of undeclared %0">;
def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DeprecatedDeclarations>;
+def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
+ InGroup<DeprecatedDeclarations>;
+def warn_deprecated_fwdclass_message : Warning<
+ "%0 maybe deprecated because receiver type is unknown">,
+ InGroup<DeprecatedDeclarations>;
+def warn_deprecated_def : Warning<
+ "Implementing deprecated %select{method|class|category}0">,
+ InGroup<DeprecatedImplementations>, DefaultIgnore;
def err_unavailable : Error<"%0 is unavailable">;
+def err_unavailable_message : Error<"%0 is unavailable: %1">;
+def warn_unavailable_fwdclass_message : Warning<
+ "%0 maybe unavailable because receiver type is unknown">;
def note_unavailable_here : Note<
- "function has been explicitly marked %select{unavailable|deleted}0 here">;
+ "function has been explicitly marked %select{unavailable|deleted|deprecated}0 here">;
def warn_not_enough_argument : Warning<
"not enough variable arguments in %0 declaration to fit a sentinel">;
def warn_missing_sentinel : Warning <
@@ -1737,6 +2009,14 @@ def err_redefinition : Error<"redefinition of %0">;
def err_definition_of_implicitly_declared_member : Error<
"definition of implicitly declared %select{constructor|copy constructor|"
"copy assignment operator|destructor}1">;
+def err_redefinition_extern_inline : Error<
+ "redefinition of a 'extern inline' function %0 is not supported in "
+ "%select{C99 mode|C++}1">;
+
+// This should eventually be an error.
+def warn_undefined_internal : Warning<
+ "%select{function|variable}0 %q1 has internal linkage but is not defined">;
+def note_used_here : Note<"used here">;
def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">,
@@ -1748,6 +2028,10 @@ def err_static_non_static : Error<
"static declaration of %0 follows non-static declaration">;
def err_non_static_static : Error<
"non-static declaration of %0 follows static declaration">;
+def err_extern_non_extern : Error<
+ "extern declaration of %0 follows non-extern declaration">;
+def err_non_extern_extern : Error<
+ "non-extern declaration of %0 follows extern declaration">;
def err_non_thread_thread : Error<
"non-thread-local declaration of %0 follows thread-local declaration">;
def err_thread_non_thread : Error<
@@ -1780,6 +2064,8 @@ def ext_forward_ref_enum : Extension<
"ISO C forbids forward references to 'enum' types">;
def err_forward_ref_enum : Error<
"ISO C++ forbids forward references to 'enum' types">;
+def ext_ms_forward_ref_enum : Extension<
+ "forward references to 'enum' types are a Microsoft extension">, InGroup<Microsoft>;
def ext_forward_ref_enum_def : Extension<
"redeclaration of already-defined enum %0 is a GNU extension">, InGroup<GNU>;
@@ -1809,6 +2095,19 @@ def err_vm_func_decl : Error<
def err_array_too_large : Error<
"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<Padded>, 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<Padded>, DefaultIgnore;
+def warn_padded_struct_size : Warning<
+ "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 "
+ "to alignment boundary">, InGroup<Padded>, DefaultIgnore;
+def warn_unnecessary_packed : Warning<
+ "packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
+
def err_typecheck_negative_array_size : Error<"array size is negative">;
def warn_typecheck_function_qualifiers : Warning<
"qualifier on function type %0 has unspecified behavior">;
@@ -1881,17 +2180,18 @@ def warn_missing_braces : Warning<
"suggest braces around initialization of subobject">,
InGroup<DiagGroup<"missing-braces">>, DefaultIgnore;
-def err_redefinition_of_label : Error<"redefinition of label '%0'">;
-def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
+def err_redefinition_of_label : Error<"redefinition of label %0">;
+def err_undeclared_label_use : Error<"use of undeclared label %0">;
+def warn_unused_label : Warning<"unused label %0">,
+ InGroup<UnusedLabel>, DefaultIgnore;
def err_goto_into_protected_scope : Error<"goto into protected scope">;
def err_switch_into_protected_scope : Error<
"switch case is in protected scope">;
def err_indirect_goto_without_addrlabel : Error<
"indirect goto in function with no address-of-label expressions">;
-def warn_indirect_goto_in_protected_scope : Warning<
- "indirect goto might cross protected scopes">,
- InGroup<DiagGroup<"label-address-scope">>;
+def err_indirect_goto_in_protected_scope : Error<
+ "indirect goto might cross protected scopes">;
def note_indirect_goto_target : Note<"possible target of indirect goto">;
def note_protected_by_variable_init : Note<
"jump bypasses variable initialization">;
@@ -1953,6 +2253,13 @@ def ext_flexible_array_in_array : Extension<
"%0 may not be used as an array element due to flexible array member">;
def err_flexible_array_init_nonempty : Error<
"non-empty initialization of flexible array member inside subobject">;
+def ext_flexible_array_empty_aggregate : Extension<
+ "flexible array member %0 in otherwise empty %select{struct|class}1 "
+ "is a Microsoft extension">, InGroup<Microsoft>;
+def ext_flexible_array_union : Extension<
+ "flexible array member %0 in a union is a Microsoft extension">,
+ InGroup<Microsoft>;
+
def err_flexible_array_init_needs_braces : Error<
"flexible array requires brace-enclosed initializer">;
def err_illegal_decl_array_of_functions : Error<
@@ -1963,6 +2270,8 @@ def err_illegal_message_expr_incomplete_type : Error<
"objective-c message has incomplete result type %0">;
def err_illegal_decl_array_of_references : Error<
"'%0' declared as array of references of type %1">;
+def err_decl_negative_array_size : Error<
+ "'%0' declared as an array with a negative size">;
def err_array_star_outside_prototype : Error<
"star modifier used outside of function prototype">;
def err_illegal_decl_pointer_to_reference : Error<
@@ -2031,7 +2340,16 @@ def note_precedence_bitwise_silence : Note<
def warn_logical_instead_of_bitwise : Warning<
"use of logical %0 with constant operand; switch to bitwise %1 or "
"remove constant">, InGroup<DiagGroup<"constant-logical-operand">>;
-
+
+def warn_logical_and_in_logical_or : Warning<
+ "'&&' within '||'">, InGroup<LogicalOpParentheses>;
+def note_logical_and_in_logical_or_silence : Note<
+ "place parentheses around the '&&' expression to silence this warning">;
+
+def warn_self_assignment : Warning<
+ "explicitly assigning a variable of type %0 to itself">,
+ InGroup<SelfAssignment>, DefaultIgnore;
+
def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in "
"non-fragile ABI">;
@@ -2069,6 +2387,11 @@ def err_typecheck_member_reference_type : Error<
def err_typecheck_member_reference_unknown : Error<
"cannot refer to member %0 in %1 with '%select{.|->}2'">;
def err_member_reference_needs_call : Error<
+ "base of member reference is an overloaded function; perhaps you meant "
+ "to call %select{it|the 0-argument overload}0?">;
+def note_member_ref_possible_intended_overload : Note<
+ "possibly valid overload here">;
+def err_member_reference_needs_call_zero_arg : Error<
"base of member reference has function type %0; perhaps you meant to call "
"this function with '()'?">;
def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
@@ -2078,12 +2401,17 @@ def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
def err_no_member : Error<"no member named %0 in %1">;
def err_member_redeclared : Error<"class member cannot be redeclared">;
+def err_member_name_of_class : Error<"member %0 has the same name as its class">;
def err_member_def_undefined_record : Error<
"out-of-line definition of %0 from class %1 without definition">;
def err_member_def_does_not_match : Error<
"out-of-line definition of %0 does not match any declaration in %1">;
+def err_member_def_does_not_match_ret_type : Error<
+ "out-of-line definition of %q0 differ from the declaration in the return type">;
def err_nonstatic_member_out_of_line : Error<
"non-static data member defined out-of-line">;
+def err_nonstatic_flexible_variable : Error<
+ "non-static initialization of a variable with flexible array member">;
def err_qualified_typedef_declarator : Error<
"typedef declarator cannot be qualified">;
def err_qualified_param_declarator : Error<
@@ -2091,6 +2419,10 @@ def err_qualified_param_declarator : Error<
def ext_out_of_line_declaration : ExtWarn<
"out-of-line declaration of a member must be a definition">,
InGroup<OutOfLineDeclaration>, DefaultError;
+def warn_member_extra_qualification : Warning<
+ "extra qualification on member %0">;
+def err_member_qualification : Error<
+ "non-friend class member %0 cannot have a qualified name">;
def note_member_def_close_match : Note<"member declaration nearly matches">;
def err_typecheck_ivar_variable_size : Error<
"instance variables must have a constant size">;
@@ -2121,7 +2453,7 @@ def err_array_init_not_init_list : Error<
"array initializer must be an initializer "
"list%select{| or string literal}0">;
def warn_deprecated_string_literal_conversion : Warning<
- "conversion from string literal to %0 is deprecated">, InGroup<Deprecated>;
+ "conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>;
def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
def err_typecheck_sclass_fscope : Error<
"illegal storage class on file-scoped variable">;
@@ -2151,7 +2483,7 @@ def err_typecheck_unary_expr : Error<
def err_typecheck_indirection_requires_pointer : Error<
"indirection requires pointer operand (%0 invalid)">;
def warn_indirection_through_null : Warning<
- "indirection of non-volatile null pointer will be deleted, not trap">;
+ "indirection of non-volatile null pointer will be deleted, not trap">, InGroup<NullDereference>;
def note_indirection_through_null : Note<
"consider using __builtin_trap() or qualifying pointer with 'volatile'">;
@@ -2200,11 +2532,14 @@ def warn_mixed_sign_conditional : Warning<
"operands of ? are integers of different signs: %0 and %1">,
InGroup<SignCompare>, DefaultIgnore;
def warn_lunsigned_always_true_comparison : Warning<
- "comparison of unsigned expression %0 is always %1">,
- InGroup<SignCompare>, DefaultIgnore;
+ "comparison of unsigned%select{| enum}2 expression %0 is always %1">,
+ InGroup<TautologicalCompare>;
def warn_runsigned_always_true_comparison : Warning<
- "comparison of %0 unsigned expression is always %1">,
- InGroup<SignCompare>, DefaultIgnore;
+ "comparison of %0 unsigned%select{| enum}2 expression is always %1">,
+ InGroup<TautologicalCompare>;
+def warn_comparison_of_mixed_enum_types : Warning<
+ "comparison of two values with different enumeration types (%0 and %1)">,
+ InGroup<DiagGroup<"enum-compare">>;
def err_invalid_this_use : Error<
"invalid use of 'this' outside of a nonstatic member function">;
@@ -2212,11 +2547,26 @@ def err_invalid_member_use_in_static_method : Error<
"invalid use of member %0 in static member function">;
def err_invalid_qualified_function_type : Error<
"type qualifier is not allowed on this function">;
+def err_invalid_ref_qualifier_function_type : Error<
+ "ref-qualifier '%select{&&|&}0' is only allowed on non-static member functions,"
+ " member function pointers, and typedefs of function types">;
+def ext_qualified_function_type_template_arg : ExtWarn<
+ "template argument of '%0' qualified function type is a GNU extension">,
+ InGroup<GNU>;
+
def err_invalid_qualified_function_pointer : Error<
"type qualifier is not allowed on this function %select{pointer|reference}0">;
def err_invalid_qualified_typedef_function_type_use : Error<
"a qualified function type cannot be used to declare a "
"%select{static member|nonmember}0 function">;
+def err_invalid_ref_qualifier_typedef_function_type_use : Error<
+ "%select{static member|nonmember}0 function cannot have a ref-qualifier "
+ "'%select{&&|&}1'">;
+
+def err_ref_qualifier_overload : Error<
+ "cannot overload a member function %select{without a ref-qualifier|with "
+ "ref-qualifier '&'|with ref-qualifier '&&'}0 with a member function %select{"
+ "without a ref-qualifier|with ref-qualifier '&'|with ref-qualifier '&&'}1">;
def err_invalid_non_static_member_use : Error<
"invalid use of nonstatic data member %0">;
@@ -2244,6 +2594,15 @@ def err_ref_array_type : Error<
"cannot refer to declaration with an array type inside block">;
def err_property_not_found : Error<
"property %0 not found on object of type %1">;
+def err_getter_not_found : Error<
+ "expected getter method not found on object of type %0">;
+def err_property_not_found_forward_class : Error<
+ "property %0 cannot be found in forward class object %1">;
+def err_property_not_as_forward_class : Error<
+ "property %0 refers to an incomplete Objective-C class %1 "
+ "(with no @interface available)">;
+def note_forward_class : Note<
+ "forward class is declared here">;
def err_duplicate_property : Error<
"property has a previous declaration">;
def ext_gnu_void_ptr : Extension<
@@ -2265,6 +2624,8 @@ def error_no_subobject_property_setting : Error<
def ext_freestanding_complex : Extension<
"complex numbers are an extension in a freestanding C99 implementation">;
+// FIXME: Remove when we support imaginary.
+def err_imaginary_not_supported : Error<"imaginary types are not supported">;
// Obj-c expressions
def warn_root_inst_method_not_found : Warning<
@@ -2275,14 +2636,16 @@ def warn_inst_method_not_found : Warning<
"method %objcinstance0 not found (return type defaults to 'id')">;
def error_no_super_class_message : Error<
"no @interface declaration found in class messaging of %0">;
-def error_no_super_class : Error<
- "no super class declared in @interface for %0">;
+def error_root_class_cannot_use_super : Error<
+ "%0 cannot use 'super' because it is a root class">;
def err_invalid_receiver_to_message : Error<
"invalid receiver to message expression">;
def err_invalid_receiver_to_message_super : Error<
"'super' is only valid in a method body">;
def err_invalid_receiver_class_message : Error<
"receiver type %0 is not an Objective-C class">;
+def err_missing_open_square_message_send : Error<
+ "missing '[' at start of message send expression">;
def warn_bad_receiver_type : Warning<
"receiver type %0 is not 'id' or interface pointer, consider "
"casting it to 'id'">;
@@ -2332,6 +2695,16 @@ def note_parameter_here : Note<
// C++ casts
// These messages adhere to the TryCast pattern: %0 is an int specifying the
// cast type, %1 is the source type, %2 is the destination type.
+def err_bad_reinterpret_cast_overload : Error<
+ "reinterpret_cast cannot resolve overloaded function %0 to type %1">;
+
+def err_bad_static_cast_overload : Error<
+ "address of overloaded function %0 cannot be static_cast to type %1">;
+
+def err_bad_cstyle_cast_overload : Error<
+ "address of overloaded function %0 cannot be cast to type %1">;
+
+
def err_bad_cxx_cast_generic : Error<
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
"functional-style cast}0 from %1 to %2 is not allowed">;
@@ -2389,6 +2762,10 @@ def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
// Other C++ expressions
def err_need_header_before_typeid : Error<
"you need to include <typeinfo> before using the 'typeid' operator">;
+def err_need_header_before_ms_uuidof : Error<
+ "you need to include <guiddef.h> before using the '__uuidof' operator">;
+def err_uuidof_without_guid : Error<
+ "cannot call operator __uuidof on a type with no GUID">;
def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">;
def err_static_illegal_in_new : Error<
"the 'static' modifier for the array size is not legal in new expressions">;
@@ -2420,7 +2797,8 @@ def err_array_size_ambiguous_conversion : Error<
"enumeration type">;
def ext_array_size_conversion : Extension<
"implicit conversion from array size expression of type %0 to "
- "%select{integral|enumeration}1 type %2 is a C++0x extension">;
+ "%select{integral|enumeration}1 type %2 is a C++0x extension">,
+ InGroup<CXX0x>;
def err_default_init_const : Error<
"default initialization of an object of const type %0"
@@ -2434,6 +2812,8 @@ def warn_delete_incomplete : Warning<
"deleting pointer to incomplete type %0 may cause undefined behaviour">;
def err_delete_incomplete_class_type : Warning<
"deleting incomplete class type %0; no conversions to pointer type">;
+def warn_delete_array_type : Warning<
+ "'delete' applied to a pointer-to-array type %0 treated as delete[]">;
def err_no_suitable_delete_member_function_found : Error<
"no suitable member %0 in %1">;
def err_ambiguous_suitable_delete_member_function_found : Error<
@@ -2462,6 +2842,18 @@ def err_bad_memptr_lhs : Error<
def warn_exception_caught_by_earlier_handler : Warning<
"exception of type %0 will be caught by earlier handler">;
def note_previous_exception_handler : Note<"for type %0">;
+def err_exceptions_disabled : Error<
+ "cannot use '%0' with exceptions disabled">;
+def err_objc_exceptions_disabled : Error<
+ "cannot use '%0' with Objective-C exceptions disabled">;
+def warn_non_virtual_dtor : Warning<
+ "%0 has virtual functions but non-virtual destructor">,
+ InGroup<NonVirtualDtor>, DefaultIgnore;
+def warn_overloaded_virtual : Warning<
+ "%q0 hides overloaded virtual %select{function|functions}1">,
+ InGroup<OverloadedVirtual>, DefaultIgnore;
+def note_hidden_overloaded_virtual_declared_here : Note<
+ "hidden overloaded virtual function %q0 declared here">;
def err_conditional_void_nonvoid : Error<
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
@@ -2527,6 +2919,8 @@ def err_not_tag_in_scope : Error<
def err_cannot_form_pointer_to_member_of_reference_type : Error<
"cannot form a pointer-to-member to member %0 of reference type %1">;
+def err_invalid_use_of_bound_member_func : Error<
+ "a bound member function may only be called">;
def err_incomplete_object_call : Error<
"incomplete type in call to object of type %0">;
def err_incomplete_pointer_to_member_return : Error<
@@ -2541,9 +2935,21 @@ def warn_condition_is_idiomatic_assignment : Warning<"using the result "
InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore;
def note_condition_assign_to_comparison : Note<
"use '==' to turn this assignment into an equality comparison">;
+def note_condition_or_assign_to_comparison : Note<
+ "use '!=' to turn this compound assignment into an inequality comparison">;
def note_condition_assign_silence : Note<
"place parentheses around the assignment to silence this warning">;
+def warn_equality_with_extra_parens : Warning<"equality comparison with "
+ "extraneous parentheses">, InGroup<Parentheses>;
+def note_equality_comparison_to_assign : Note<
+ "use '=' to turn this equality comparison into an assignment">;
+def note_equality_comparison_silence : Note<
+ "remove extraneous parentheses around the comparison to silence this warning">;
+
+def warn_synthesized_ivar_access : Warning<
+ "direct access of synthesized ivar by using property access %0">,
+ InGroup<NonfragileAbi2>, DefaultIgnore;
def warn_ivar_variable_conflict : Warning<
"when default property synthesis is on, "
"%0 lookup will access property ivar instead of global variable">,
@@ -2629,7 +3035,15 @@ def err_typecheck_convert_incompatible_block_pointer : Error<
" %0 "
"%select{from|to parameter of type|from a function with result type|to type|"
"with an expression of type|to parameter of type|to type}2 %1">;
-
+def err_typecheck_incompatible_address_space : Error<
+ "%select{assigning %1 to %0"
+ "|passing %0 to parameter of type %1"
+ "|returning %0 from a function with result type %1"
+ "|converting %0 to type %1"
+ "|initializing %0 with an expression of type %1"
+ "|sending %0 to parameter of type %1"
+ "|casting %0 to type %1}2"
+ " changes address space of pointer">;
def err_typecheck_convert_ambiguous : Error<
"ambiguity in initializing value of type %0 with initializer of type %1">;
def err_cannot_initialize_decl_noname : Error<
@@ -2688,9 +3102,14 @@ def err_atomic_builtin_pointer_size : Error<
"first argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte "
"type (%0 invalid)">;
-
def err_deleted_function_use : Error<"attempt to use a deleted function">;
+def err_kern_type_not_void_return : Error<
+ "kernel function type %0 must have void return type">;
+def err_config_scalar_return : Error<
+ "CUDA special function 'cudaConfigureCall' must have scalar return type">;
+
+
def err_cannot_pass_objc_interface_to_vararg : Error<
"cannot pass object with interface type %0 by-value through variadic "
"%select{function|block|method}1">;
@@ -2709,6 +3128,8 @@ def err_typecheck_cond_expect_scalar : Error<
"used type %0 where arithmetic or pointer type is required">;
def ext_typecheck_cond_one_void : Extension<
"C99 forbids conditional expressions with only one void side">;
+def err_typecheck_cond_expect_scalar_or_vector : Error<
+ "used type %0 where arithmetic, pointer, or vector type is required">;
def err_typecheck_cast_to_incomplete : Error<
"cast to incomplete type %0">;
def ext_typecheck_cast_nonscalar : Extension<
@@ -2754,6 +3175,8 @@ def err_incomplete_type_used_in_type_trait_expr : Error<
"incomplete type %0 used in type trait expression">;
def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
+def err_typecheck_cond_incompatible_operands_null : Error<
+ "non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
} // End of general sema category.
// inline asm.
@@ -2771,6 +3194,8 @@ let CategoryName = "Inline Assembly Issue" in {
def err_asm_tying_incompatible_types : Error<
"unsupported inline asm: input with type %0 matching output with type %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_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">;
@@ -2824,10 +3249,15 @@ def err_base_init_direct_and_virtual : Error<
def err_not_direct_base_or_virtual : Error<
"type %0 is not a direct or virtual base of %1">;
-def err_in_class_initializer_non_integral_type : Error<
- "in-class initializer has non-integral, non-enumeration type %0">;
+def err_in_class_initializer_non_const : Error<
+ "non-const static data member must be initialized out of line">;
+def err_in_class_initializer_bad_type : Error<
+ "static data member of type %0 must be initialized out of line">;
+def ext_in_class_initializer_float_type : ExtWarn<
+ "in-class initializer for static data member of type %0 "
+ "is a C++0x extension">, InGroup<CXX0x>;
def err_in_class_initializer_non_constant : Error<
- "in-class initializer is not an integral constant expression">;
+ "in-class initializer is not a constant expression">;
// C++ anonymous unions and GNU anonymous structs/unions
def ext_anonymous_union : Extension<
@@ -2847,6 +3277,9 @@ def err_anonymous_struct_member_redecl : Error<
"member of anonymous struct redeclares %0">;
def err_anonymous_record_with_type : Error<
"types cannot be declared in an anonymous %select{struct|union}0">;
+def ext_anonymous_record_with_type : Extension<
+ "types declared in an anonymous %select{struct|union}0 are a Microsoft "
+ "extension">, InGroup<Microsoft>;
def err_anonymous_record_with_function : Error<
"functions cannot be declared in an anonymous %select{struct|union}0">;
def err_anonymous_record_with_static : Error<
@@ -2856,6 +3289,8 @@ def err_anonymous_record_bad_member : Error<
def err_anonymous_record_nonpublic_member : Error<
"anonymous %select{struct|union}0 cannot contain a "
"%select{private|protected}1 data member">;
+def ext_ms_anonymous_struct : ExtWarn<
+ "anonymous structs are a Microsoft extension">, InGroup<Microsoft>;
// C++ local classes
def err_reference_to_local_var_in_enclosing_function : Error<
@@ -2885,7 +3320,7 @@ def err_memptr_conv_via_virtual : Error<
// C++ access control
def err_conv_to_inaccessible_base : Error<
- "conversion from %0 to inaccessible base class %1">, NoSFINAE;
+ "conversion from %0 to inaccessible base class %1">, AccessControl;
def note_inheritance_specifier_here : Note<
"'%0' inheritance specifier here">;
def note_inheritance_implicitly_private_here : Note<
@@ -2986,7 +3421,16 @@ def warn_not_compound_assign : Warning<
// C++0x explicit conversion operators
def warn_explicit_conversion_functions : Warning<
- "explicit conversion functions are a C++0x extension">;
+ "explicit conversion functions are a C++0x extension">, InGroup<CXX0x>;
+
+def warn_array_index_precedes_bounds : Warning<
+ "array index of '%0' indexes before the beginning of the array">,
+ InGroup<DiagGroup<"array-bounds">>;
+def warn_array_index_exceeds_bounds : Warning<
+ "array index of '%0' indexes past the end of an array (that contains %1 elements)">,
+ InGroup<DiagGroup<"array-bounds">>;
+def note_array_index_out_of_bounds : Note<
+ "array %0 declared here">;
def warn_printf_write_back : Warning<
"use of '%%n' in format string discouraged (potentially insecure)">,
@@ -3054,10 +3498,16 @@ def warn_ret_stack_addr : Warning<
"address of stack memory associated with local variable %0 returned">;
def warn_ret_stack_ref : Warning<
"reference to stack memory associated with local variable %0 returned">;
+def warn_ret_local_temp_addr : Warning<
+ "returning address of local temporary object">;
+def warn_ret_local_temp_ref : Warning<
+ "returning reference to local temporary object">;
def warn_ret_addr_label : Warning<
"returning address of label, which is local">;
def err_ret_local_block : Error<
"returning block that lives on the local stack">;
+def note_ref_var_local_bind : Note<
+ "binding reference variable %0 here">;
// For non-floating point, expressions of the form x == x or x != x
@@ -3065,7 +3515,7 @@ def err_ret_local_block : Error<
// Array comparisons have similar warnings
def warn_comparison_always : Warning<
"%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">,
- InGroup<DiagGroup<"tautological-compare">>;
+ InGroup<TautologicalCompare>;
def warn_stringcompare : Warning<
"result of comparison against %select{a string literal|@encode}0 is "
@@ -3079,8 +3529,8 @@ def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
def err_expected_block_lbrace : Error<"expected '{' in block literal">;
def err_return_in_block_expression : Error<
"return not allowed in block expression literal">;
-def err_block_returns_array : Error<
- "block declared as returning an array">;
+def err_block_returning_array_function : Error<
+ "block cannot return %select{array|function}0 type %1">;
// CFString checking
@@ -3088,6 +3538,9 @@ def err_cfstring_literal_not_string_constant : Error<
"CFString literal is not a string constant">;
def warn_cfstring_literal_contains_nul_character : Warning<
"CFString literal contains NUL character">;
+def warn_cfstring_truncated : Warning<
+ "input conversion stopped due to an input byte that does not "
+ "belong to the input codeset UTF-8">;
// Statements.
def err_continue_not_in_loop : Error<
@@ -3106,8 +3559,18 @@ def err_duplicate_case : Error<"duplicate case value '%0'">;
def warn_case_empty_range : Warning<"empty case range specified">;
def warn_missing_case_for_condition :
Warning<"no case matching constant switch condition '%0'">;
-def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">,
+def warn_missing_case1 : Warning<"enumeration value %0 not handled in switch">,
+ InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_case2 : Warning<
+ "enumeration values %0 and %1 not handled in switch">,
+ InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_case3 : Warning<
+ "enumeration values %0, %1, and %2 not handled in switch">,
InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_cases : Warning<
+ "%0 enumeration values not handled in switch: %1, %2, %3...">,
+ InGroup<DiagGroup<"switch-enum"> >;
+
def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
InGroup<DiagGroup<"switch-enum"> >;
def err_typecheck_statement_requires_scalar : Error<
@@ -3225,6 +3688,8 @@ def ext_c99_array_usage : Extension<
"use of C99-specific array features, accepted as an extension">;
def err_c99_array_usage_cxx : Error<
"C99-specific array features are not permitted in C++">;
+def err_double_requires_fp64 : Error<
+ "use of type 'double' requires cl_khr_fp64 extension to be enabled">;
def note_getter_unavailable : Note<
"or because setter is declared here, but no getter method %0 is found">;
@@ -3235,9 +3700,9 @@ def warn_ivar_use_hidden : Warning<
def error_ivar_use_in_class_method : Error<
"instance variable %0 accessed in class method">;
def error_private_ivar_access : Error<"instance variable %0 is private">,
- NoSFINAE;
+ AccessControl;
def error_protected_ivar_access : Error<"instance variable %0 is protected">,
- NoSFINAE;
+ AccessControl;
def warn_maynot_respond : Warning<"%0 may not respond to %1">;
def warn_attribute_method_def : Warning<
"method attribute can only be specified on method declarations">;
@@ -3284,6 +3749,9 @@ def err_using_directive_suggest : Error<
def err_using_directive_member_suggest : Error<
"no namespace named %0 in %1; did you mean %2?">;
def note_namespace_defined_here : Note<"namespace %0 defined here">;
+def err_sizeof_pack_no_pack_name_suggest : Error<
+ "%0 does not refer to the name of a parameter pack; did you mean %1?">;
+def note_parameter_pack_here : Note<"parameter pack %0 declared here">;
} // end of sema category
} // end of sema component.
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index e71f51a0e700..563157fa8fbe 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_FILEMANAGER_H
#define LLVM_CLANG_FILEMANAGER_H
+#include "clang/Basic/FileSystemOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -22,12 +23,20 @@
#include "llvm/Config/config.h" // for mode_t
// FIXME: Enhance libsystem to support inode and other fields in stat.
#include <sys/types.h>
-#include <sys/stat.h>
+
+struct stat;
+
+namespace llvm {
+class MemoryBuffer;
+namespace sys { class Path; }
+}
namespace clang {
class FileManager;
-
-/// DirectoryEntry - Cached information about one directory on the disk.
+class FileSystemStatCache;
+
+/// DirectoryEntry - Cached information about one directory (either on
+/// the disk or in the virtual file system).
///
class DirectoryEntry {
const char *Name; // Name of the directory.
@@ -37,7 +46,9 @@ public:
const char *getName() const { return Name; }
};
-/// FileEntry - Cached information about one file on the disk.
+/// FileEntry - Cached information about one file (either on the disk
+/// or in the virtual file system). If the 'FD' member is valid, then
+/// this FileEntry has an open file descriptor for the file.
///
class FileEntry {
const char *Name; // Name of the file.
@@ -48,12 +59,29 @@ class FileEntry {
dev_t Device; // ID for the device containing the file.
ino_t Inode; // Inode number for the file.
mode_t FileMode; // The file mode as returned by 'stat'.
+
+ /// FD - The file descriptor for the file entry if it is opened and owned
+ /// by the FileEntry. If not, this is set to -1.
+ mutable int FD;
friend class FileManager;
+
public:
FileEntry(dev_t device, ino_t inode, mode_t m)
- : Name(0), Device(device), Inode(inode), FileMode(m) {}
+ : Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {}
// Add a default constructor for use with llvm::StringMap
- FileEntry() : Name(0), Device(0), Inode(0), FileMode(0) {}
+ FileEntry() : Name(0), Device(0), Inode(0), FileMode(0), FD(-1) {}
+
+ FileEntry(const FileEntry &FE) {
+ memcpy(this, &FE, sizeof(FE));
+ assert(FD == -1 && "Cannot copy a file-owning FileEntry");
+ }
+
+ void operator=(const FileEntry &FE) {
+ memcpy(this, &FE, sizeof(FE));
+ assert(FD == -1 && "Cannot assign a file-owning FileEntry");
+ }
+
+ ~FileEntry();
const char *getName() const { return Name; }
off_t getSize() const { return Size; }
@@ -67,111 +95,68 @@ public:
///
const DirectoryEntry *getDir() const { return Dir; }
- bool operator<(const FileEntry& RHS) const {
+ bool operator<(const FileEntry &RHS) const {
return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode);
}
};
-/// \brief Abstract interface for introducing a FileManager cache for 'stat'
-/// system calls, which is used by precompiled and pretokenized headers to
-/// improve performance.
-class StatSysCallCache {
-protected:
- llvm::OwningPtr<StatSysCallCache> NextStatCache;
-
-public:
- virtual ~StatSysCallCache() {}
- virtual int stat(const char *path, struct stat *buf) {
- if (getNextStatCache())
- return getNextStatCache()->stat(path, buf);
-
- return ::stat(path, buf);
- }
-
- /// \brief Sets the next stat call cache in the chain of stat caches.
- /// Takes ownership of the given stat cache.
- void setNextStatCache(StatSysCallCache *Cache) {
- NextStatCache.reset(Cache);
- }
-
- /// \brief Retrieve the next stat call cache in the chain.
- StatSysCallCache *getNextStatCache() { return NextStatCache.get(); }
-
- /// \brief Retrieve the next stat call cache in the chain, transferring
- /// ownership of this cache (and, transitively, all of the remaining caches)
- /// to the caller.
- StatSysCallCache *takeNextStatCache() { return NextStatCache.take(); }
-};
-
-/// \brief A stat "cache" that can be used by FileManager to keep
-/// track of the results of stat() calls that occur throughout the
-/// execution of the front end.
-class MemorizeStatCalls : public StatSysCallCache {
-public:
- /// \brief The result of a stat() call.
- ///
- /// The first member is the result of calling stat(). If stat()
- /// found something, the second member is a copy of the stat
- /// structure.
- typedef std::pair<int, struct stat> StatResult;
-
- /// \brief The set of stat() calls that have been
- llvm::StringMap<StatResult, llvm::BumpPtrAllocator> StatCalls;
-
- typedef llvm::StringMap<StatResult, llvm::BumpPtrAllocator>::const_iterator
- iterator;
-
- iterator begin() const { return StatCalls.begin(); }
- iterator end() const { return StatCalls.end(); }
-
- virtual int stat(const char *path, struct stat *buf);
-};
-
/// FileManager - Implements support for file system lookup, file system
/// caching, and directory search management. This also handles more advanced
/// properties, such as uniquing files based on "inode", so that a file with two
/// names (e.g. symlinked) will be treated as a single file.
///
class FileManager {
+ FileSystemOptions FileSystemOpts;
class UniqueDirContainer;
class UniqueFileContainer;
- /// UniqueDirs/UniqueFiles - Cache for existing directories/files.
+ /// UniqueRealDirs/UniqueRealFiles - Cache for existing real directories/files.
///
- UniqueDirContainer &UniqueDirs;
- UniqueFileContainer &UniqueFiles;
+ UniqueDirContainer &UniqueRealDirs;
+ UniqueFileContainer &UniqueRealFiles;
- /// DirEntries/FileEntries - This is a cache of directory/file entries we have
- /// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above.
+ /// \brief The virtual directories that we have allocated. For each
+ /// virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
+ /// directories (foo/ and foo/bar/) here.
+ llvm::SmallVector<DirectoryEntry*, 4> VirtualDirectoryEntries;
+ /// \brief The virtual files that we have allocated.
+ llvm::SmallVector<FileEntry*, 4> VirtualFileEntries;
+
+ /// SeenDirEntries/SeenFileEntries - This is a cache that maps paths
+ /// to directory/file entries (either real or virtual) we have
+ /// looked up. The actual Entries for real directories/files are
+ /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
+ /// for virtual directories/files are owned by
+ /// VirtualDirectoryEntries/VirtualFileEntries above.
///
- llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> DirEntries;
- llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> FileEntries;
+ llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
+ llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
/// NextFileUID - Each FileEntry we create is assigned a unique ID #.
///
unsigned NextFileUID;
- /// \brief The virtual files that we have allocated.
- llvm::SmallVector<FileEntry *, 4> VirtualFileEntries;
-
// Statistics.
unsigned NumDirLookups, NumFileLookups;
unsigned NumDirCacheMisses, NumFileCacheMisses;
// Caching.
- llvm::OwningPtr<StatSysCallCache> StatCache;
+ llvm::OwningPtr<FileSystemStatCache> StatCache;
- int stat_cached(const char* path, struct stat* buf) {
- return StatCache.get() ? StatCache->stat(path, buf) : stat(path, buf);
- }
+ bool getStatValue(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor);
+
+ /// Add all ancestors of the given path (pointing to either a file
+ /// or a directory) as virtual directories.
+ void addAncestorsAsVirtualDirs(llvm::StringRef Path);
public:
- FileManager();
+ FileManager(const FileSystemOptions &FileSystemOpts);
~FileManager();
- /// \brief Installs the provided StatSysCallCache object within
- /// the FileManager.
+ /// \brief Installs the provided FileSystemStatCache object within
+ /// the FileManager.
///
/// Ownership of this object is transferred to the FileManager.
///
@@ -181,33 +166,46 @@ public:
/// \param AtBeginning whether this new stat cache must be installed at the
/// beginning of the chain of stat caches. Otherwise, it will be added to
/// the end of the chain.
- void addStatCache(StatSysCallCache *statCache, bool AtBeginning = false);
+ void addStatCache(FileSystemStatCache *statCache, bool AtBeginning = false);
- /// \brief Removes the provided StatSysCallCache object from the file manager.
- void removeStatCache(StatSysCallCache *statCache);
-
- /// getDirectory - Lookup, cache, and verify the specified directory. This
- /// returns null if the directory doesn't exist.
+ /// \brief Removes the specified FileSystemStatCache object from the manager.
+ void removeStatCache(FileSystemStatCache *statCache);
+
+ /// getDirectory - Lookup, cache, and verify the specified directory
+ /// (real or virtual). This returns NULL if the directory doesn't exist.
///
- const DirectoryEntry *getDirectory(llvm::StringRef Filename) {
- return getDirectory(Filename.begin(), Filename.end());
- }
- const DirectoryEntry *getDirectory(const char *FileStart,const char *FileEnd);
+ const DirectoryEntry *getDirectory(llvm::StringRef DirName);
- /// getFile - Lookup, cache, and verify the specified file. This returns null
- /// if the file doesn't exist.
+ /// getFile - Lookup, cache, and verify the specified file (real or
+ /// virtual). This returns NULL if the file doesn't exist.
///
- const FileEntry *getFile(llvm::StringRef Filename) {
- return getFile(Filename.begin(), Filename.end());
- }
- const FileEntry *getFile(const char *FilenameStart,
- const char *FilenameEnd);
+ const FileEntry *getFile(llvm::StringRef Filename);
/// \brief Retrieve a file entry for a "virtual" file that acts as
/// if there were a file with the given name on disk. The file
/// itself is not accessed.
const FileEntry *getVirtualFile(llvm::StringRef Filename, off_t Size,
time_t ModificationTime);
+
+ /// \brief Open the specified file as a MemoryBuffer, returning a new
+ /// MemoryBuffer if successful, otherwise returning null.
+ llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry,
+ std::string *ErrorStr = 0);
+ llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename,
+ std::string *ErrorStr = 0);
+
+ /// \brief If path is not absolute and FileSystemOptions set the working
+ /// directory, the path is modified to be relative to the given
+ /// working directory.
+ static void FixupRelativePath(llvm::sys::Path &path,
+ const FileSystemOptions &FSOpts);
+
+
+ /// \brief Produce an array mapping from the unique IDs assigned to each
+ /// file to the corresponding FileEntry pointer.
+ void GetUniqueIDMapping(
+ llvm::SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
+
void PrintStats() const;
};
diff --git a/include/clang/Basic/FileSystemOptions.h b/include/clang/Basic/FileSystemOptions.h
new file mode 100644
index 000000000000..81e928da2a70
--- /dev/null
+++ b/include/clang/Basic/FileSystemOptions.h
@@ -0,0 +1,31 @@
+//===--- FileSystemOptions.h - File System 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 FileSystemOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H
+#define LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H
+
+#include <string>
+
+namespace clang {
+
+/// \brief Keeps track of options that affect how file operations are performed.
+class FileSystemOptions {
+public:
+ /// \brief If set, paths are resolved as if the working directory was
+ /// set to the value of WorkingDir.
+ std::string WorkingDir;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
new file mode 100644
index 000000000000..77828b3ecb8a
--- /dev/null
+++ b/include/clang/Basic/FileSystemStatCache.h
@@ -0,0 +1,101 @@
+//===--- FileSystemStatCache.h - Caching for 'stat' calls -------*- 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 FileSystemStatCache interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FILESYSTEMSTATCACHE_H
+#define LLVM_CLANG_FILESYSTEMSTATCACHE_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringMap.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+namespace clang {
+
+/// \brief Abstract interface for introducing a FileManager cache for 'stat'
+/// system calls, which is used by precompiled and pretokenized headers to
+/// improve performance.
+class FileSystemStatCache {
+protected:
+ llvm::OwningPtr<FileSystemStatCache> NextStatCache;
+
+public:
+ virtual ~FileSystemStatCache() {}
+
+ enum LookupResult {
+ CacheExists, //< We know the file exists and its cached stat data.
+ CacheMissing //< We know that the file doesn't exist.
+ };
+
+ /// FileSystemStatCache::get - Get the 'stat' information for the specified
+ /// path, using the cache to accellerate it if possible. This returns true if
+ /// the path does not exist or false if it exists.
+ ///
+ /// If FileDescriptor is non-null, then this lookup should only return success
+ /// for files (not directories). If it is null this lookup should only return
+ /// success for directories (not files). On a successful file lookup, the
+ /// implementation can optionally fill in FileDescriptor with a valid
+ /// descriptor and the client guarantees that it will close it.
+ static bool get(const char *Path, struct stat &StatBuf, int *FileDescriptor,
+ FileSystemStatCache *Cache);
+
+
+ /// \brief Sets the next stat call cache in the chain of stat caches.
+ /// Takes ownership of the given stat cache.
+ void setNextStatCache(FileSystemStatCache *Cache) {
+ NextStatCache.reset(Cache);
+ }
+
+ /// \brief Retrieve the next stat call cache in the chain.
+ FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); }
+
+ /// \brief Retrieve the next stat call cache in the chain, transferring
+ /// ownership of this cache (and, transitively, all of the remaining caches)
+ /// to the caller.
+ FileSystemStatCache *takeNextStatCache() { return NextStatCache.take(); }
+
+protected:
+ virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) = 0;
+
+ LookupResult statChained(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) {
+ if (FileSystemStatCache *Next = getNextStatCache())
+ return Next->getStat(Path, StatBuf, FileDescriptor);
+
+ // If we hit the end of the list of stat caches to try, just compute and
+ // return it without a cache.
+ return get(Path, StatBuf, FileDescriptor, 0) ? CacheMissing : CacheExists;
+ }
+};
+
+/// \brief A stat "cache" that can be used by FileManager to keep
+/// track of the results of stat() calls that occur throughout the
+/// execution of the front end.
+class MemorizeStatCalls : public FileSystemStatCache {
+public:
+ /// \brief The set of stat() calls that have been seen.
+ llvm::StringMap<struct stat, llvm::BumpPtrAllocator> StatCalls;
+
+ typedef llvm::StringMap<struct stat, llvm::BumpPtrAllocator>::const_iterator
+ iterator;
+
+ iterator begin() const { return StatCalls.begin(); }
+ iterator end() const { return StatCalls.end(); }
+
+ virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 24fe086a79e9..d576643550bd 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -22,8 +22,9 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
-#include <string>
#include <cassert>
+#include <cctype>
+#include <string>
namespace llvm {
template <typename T> struct DenseMapInfo;
@@ -53,7 +54,7 @@ class IdentifierInfo {
// Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
// First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
// are for builtins.
- unsigned ObjCOrBuiltinID :10;
+ unsigned ObjCOrBuiltinID :11;
bool HasMacro : 1; // True if there is a #define for this.
bool IsExtension : 1; // True if identifier is a lang extension.
bool IsPoisoned : 1; // True if identifier is poisoned.
@@ -63,7 +64,7 @@ class IdentifierInfo {
// file and wasn't modified since.
bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
// called.
- // 7 bits left in 32-bit word.
+ // 6 bits left in 32-bit word.
void *FETokenInfo; // Managed by the language front-end.
llvm::StringMapEntry<IdentifierInfo*> *Entry;
@@ -71,7 +72,7 @@ class IdentifierInfo {
void operator=(const IdentifierInfo&); // NONASSIGNABLE.
friend class IdentifierTable;
-
+
public:
IdentifierInfo();
@@ -254,6 +255,35 @@ private:
}
};
+/// \brief An iterator that walks over all of the known identifiers
+/// in the lookup table.
+///
+/// Since this iterator uses an abstract interface via virtual
+/// functions, it uses an object-oriented interface rather than the
+/// more standard C++ STL iterator interface. In this OO-style
+/// iteration, the single function \c Next() provides dereference,
+/// advance, and end-of-sequence checking in a single
+/// operation. Subclasses of this iterator type will provide the
+/// actual functionality.
+class IdentifierIterator {
+private:
+ IdentifierIterator(const IdentifierIterator&); // Do not implement
+ IdentifierIterator &operator=(const IdentifierIterator&); // Do not implement
+
+protected:
+ IdentifierIterator() { }
+
+public:
+ virtual ~IdentifierIterator();
+
+ /// \brief Retrieve the next string in the identifier table and
+ /// advances the iterator for the following string.
+ ///
+ /// \returns The next string in the identifier table. If there is
+ /// no such string, returns an empty \c llvm::StringRef.
+ virtual llvm::StringRef Next() = 0;
+};
+
/// IdentifierInfoLookup - An abstract class used by IdentifierTable that
/// provides an interface for performing lookups from strings
/// (const char *) to IdentiferInfo objects.
@@ -266,6 +296,18 @@ public:
/// of a reference. If the pointer is NULL then the IdentifierInfo cannot
/// be found.
virtual IdentifierInfo* get(llvm::StringRef Name) = 0;
+
+ /// \brief Retrieve an iterator into the set of all identifiers
+ /// known to this identifier lookup source.
+ ///
+ /// This routine provides access to all of the identifiers known to
+ /// the identifier lookup, allowing access to the contents of the
+ /// identifiers without introducing the overhead of constructing
+ /// IdentifierInfo objects for each.
+ ///
+ /// \returns A new iterator into the set of known identifiers. The
+ /// caller is responsible for deleting this iterator.
+ virtual IdentifierIterator *getIdentifiers() const;
};
/// \brief An abstract class used to resolve numerical identifier
@@ -304,6 +346,11 @@ public:
ExternalLookup = IILookup;
}
+ /// \brief Retrieve the external identifier lookup object, if any.
+ IdentifierInfoLookup *getExternalIdentifierLookup() const {
+ return ExternalLookup;
+ }
+
llvm::BumpPtrAllocator& getAllocator() {
return HashTable.getAllocator();
}
@@ -463,8 +510,33 @@ public:
return getIdentifierInfoFlag() == ZeroArg;
}
unsigned getNumArgs() const;
+
+
+ /// \brief Retrieve the identifier at a given position in the selector.
+ ///
+ /// Note that the identifier pointer returned may be NULL. Clients that only
+ /// care about the text of the identifier string, and not the specific,
+ /// uniqued identifier pointer, should use \c getNameForSlot(), which returns
+ /// an empty string when the identifier pointer would be NULL.
+ ///
+ /// \param argIndex The index for which we want to retrieve the identifier.
+ /// This index shall be less than \c getNumArgs() unless this is a keyword
+ /// selector, in which case 0 is the only permissible value.
+ ///
+ /// \returns the uniqued identifier for this slot, or NULL if this slot has
+ /// no corresponding identifier.
IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
-
+
+ /// \brief Retrieve the name at a given position in the selector.
+ ///
+ /// \param argIndex The index for which we want to retrieve the name.
+ /// This index shall be less than \c getNumArgs() unless this is a keyword
+ /// selector, in which case 0 is the only permissible value.
+ ///
+ /// \returns the name for this slot, which may be the empty string if no
+ /// name was supplied.
+ llvm::StringRef getNameForSlot(unsigned argIndex) const;
+
/// getAsString - Derive the full selector name (e.g. "foo:bar:") and return
/// it as an std::string.
std::string getAsString() const;
@@ -570,6 +642,17 @@ struct DenseMapInfo<clang::Selector> {
template <>
struct isPodLike<clang::Selector> { static const bool value = true; };
+template<>
+class PointerLikeTypeTraits<clang::Selector> {
+public:
+ static inline const void *getAsVoidPointer(clang::Selector P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::Selector getFromVoidPointer(const void *P) {
+ return clang::Selector(reinterpret_cast<uintptr_t>(P));
+ }
+ enum { NumLowBitsAvailable = 0 };
+};
// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which
// are not guaranteed to be 8-byte aligned.
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index 5bd0d04a4eea..f4db55ae0626 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_LANGOPTIONS_H
#include <string>
+#include "clang/Basic/Visibility.h"
namespace clang {
@@ -43,6 +44,8 @@ public:
unsigned ObjC2 : 1; // Objective-C 2 support enabled.
unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled
unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled
+ unsigned ObjCDefaultSynthProperties : 1; // Objective-C auto-synthesized properties.
+ unsigned AppleKext : 1; // Allow apple kext features.
unsigned PascalStrings : 1; // Allow Pascal strings
unsigned WritableStrings : 1; // Allow writable strings
@@ -51,8 +54,10 @@ public:
unsigned AltiVec : 1; // Support AltiVec-style vector initializers.
unsigned Exceptions : 1; // Support exception handling.
unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling.
+ unsigned ObjCExceptions : 1; // Support Objective-C exceptions.
unsigned RTTI : 1; // Support RTTI information.
+ unsigned MSBitfields : 1; // MS-compatible structure layout
unsigned NeXTRuntime : 1; // Use NeXT runtime.
unsigned Freestanding : 1; // Freestanding implementation
unsigned NoBuiltin : 1; // Do not use builtin functions (-fno-builtin)
@@ -89,8 +94,12 @@ public:
unsigned CharIsSigned : 1; // Whether char is a signed or unsigned type
unsigned ShortWChar : 1; // Force wchar_t to be unsigned short int.
+ unsigned ShortEnums : 1; // The enum type will be equivalent to the
+ // smallest integer type with enough room.
+
unsigned OpenCL : 1; // OpenCL C99 language extensions.
-
+ unsigned CUDA : 1; // CUDA C++ language extensions.
+
unsigned AssumeSaneOperatorNew : 1; // Whether to add __attribute__((malloc))
// to the declaration of C++'s new
// operators
@@ -101,10 +110,16 @@ public:
unsigned DumpVTableLayouts : 1; /// Dump the layouts of emitted vtables.
unsigned NoConstantCFStrings : 1; // Do not do CF strings
unsigned InlineVisibilityHidden : 1; // Whether inline C++ methods have
- // hidden visibility by default.
+ // hidden visibility by default.
unsigned SpellChecking : 1; // Whether to perform spell-checking for error
// recovery.
+ unsigned SinglePrecisionConstants : 1; // Whether to treat double-precision
+ // floating point constants as
+ // single precision constants.
+ unsigned FastRelaxedMath : 1; // OpenCL fast relaxed math (on its own,
+ // defines __FAST_RELAXED_MATH__).
+ unsigned DefaultFPContract : 1; // Default setting for FP_CONTRACT
// FIXME: This is just a temporary option, for testing purposes.
unsigned NoBitFieldTypeAlign : 1;
@@ -118,47 +133,56 @@ private:
public:
unsigned InstantiationDepth; // Maximum template instantiation depth.
+ unsigned NumLargeByValueCopy; // Warn if parameter/return value is larger
+ // in bytes than this setting. 0 is no check.
+
+ // Version of Microsoft Visual C/C++ we are pretending to be. This is
+ // temporary until we support all MS extensions used in Windows SDK and stdlib
+ // headers. Sets _MSC_VER.
+ unsigned MSCVersion;
std::string ObjCConstantStringClass;
enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
- enum VisibilityMode {
- Default,
- Protected,
- Hidden
- };
-
+
enum SignedOverflowBehaviorTy {
SOB_Undefined, // Default C standard behavior.
SOB_Defined, // -fwrapv
SOB_Trapping // -ftrapv
};
+ /// The name of the handler function to be called when -ftrapv is specified.
+ /// If none is specified, abort (GCC-compatible behaviour).
+ std::string OverflowHandler;
LangOptions() {
Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0;
GNUMode = GNUKeywords = ImplicitInt = Digraphs = 0;
HexFloats = 0;
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
+ AppleKext = 0;
+ ObjCDefaultSynthProperties = 0;
NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
+ ObjCExceptions = 1;
+ MSBitfields = 0;
NeXTRuntime = 1;
RTTI = 1;
LaxVectorConversions = 1;
HeinousExtensions = 0;
- AltiVec = OpenCL = StackProtector = 0;
+ AltiVec = OpenCL = CUDA = StackProtector = 0;
+
+ SymbolVisibility = (unsigned) DefaultVisibility;
- SymbolVisibility = (unsigned) Default;
-
ThreadsafeStatics = 1;
POSIXThreads = 0;
Blocks = 0;
EmitAllDecls = 0;
MathErrno = 1;
SignedOverflowBehavior = SOB_Undefined;
-
+
AssumeSaneOperatorNew = 1;
AccessControl = 1;
ElideConstructors = 1;
@@ -168,6 +192,9 @@ public:
InstantiationDepth = 1024;
+ NumLargeByValueCopy = 0;
+ MSCVersion = 0;
+
Optimize = 0;
OptimizeSize = 0;
@@ -179,10 +206,14 @@ public:
CharIsSigned = 1;
ShortWChar = 0;
+ ShortEnums = 0;
CatchUndefined = 0;
DumpRecordLayouts = 0;
DumpVTableLayouts = 0;
SpellChecking = 1;
+ SinglePrecisionConstants = 0;
+ FastRelaxedMath = 0;
+ DefaultFPContract = 0;
NoBitFieldTypeAlign = 0;
}
@@ -196,17 +227,44 @@ public:
StackProtector = static_cast<unsigned>(m);
}
- VisibilityMode getVisibilityMode() const {
- return (VisibilityMode) SymbolVisibility;
+ Visibility getVisibilityMode() const {
+ return (Visibility) SymbolVisibility;
}
- void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; }
-
+ void setVisibilityMode(Visibility v) { SymbolVisibility = (unsigned) v; }
+
SignedOverflowBehaviorTy getSignedOverflowBehavior() const {
return (SignedOverflowBehaviorTy)SignedOverflowBehavior;
}
void setSignedOverflowBehavior(SignedOverflowBehaviorTy V) {
SignedOverflowBehavior = (unsigned)V;
}
+
+ bool areExceptionsEnabled() const {
+ return Exceptions;
+ }
+};
+
+/// Floating point control options
+class FPOptions {
+public:
+ unsigned fp_contract : 1;
+
+ FPOptions() : fp_contract(0) {}
+
+ FPOptions(const LangOptions &LangOpts) :
+ fp_contract(LangOpts.DefaultFPContract) {}
+};
+
+/// OpenCL volatile options
+class OpenCLOptions {
+public:
+#define OPENCLEXT(nm) unsigned nm : 1;
+#include "clang/Basic/OpenCLExtensions.def"
+
+ OpenCLOptions() {
+#define OPENCLEXT(nm) nm = 0;
+#include "clang/Basic/OpenCLExtensions.def"
+ }
};
} // end namespace clang
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
index 8909e47146a7..267ecbcd6df4 100644
--- a/include/clang/Basic/OnDiskHashTable.h
+++ b/include/clang/Basic/OnDiskHashTable.h
@@ -15,10 +15,10 @@
#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
#include "llvm/Support/Allocator.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Host.h"
+#include "llvm/Support/Host.h"
#include <cassert>
#include <cstdlib>
@@ -320,7 +320,7 @@ public:
InfoPtr->ReadKey((const unsigned char* const) Items, L.first);
// If the key doesn't match just skip reading the value.
- if (!Info::EqualKey(X, iKey)) {
+ if (!InfoPtr->EqualKey(X, iKey)) {
Items += item_len;
continue;
}
@@ -334,6 +334,70 @@ public:
iterator end() const { return iterator(); }
+ /// \brief Iterates over all of the keys in the table.
+ class key_iterator {
+ const unsigned char* Ptr;
+ unsigned NumItemsInBucketLeft;
+ unsigned NumEntriesLeft;
+ Info *InfoObj;
+ public:
+ typedef external_key_type value_type;
+
+ key_iterator(const unsigned char* const Ptr, unsigned NumEntries,
+ Info *InfoObj)
+ : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
+ InfoObj(InfoObj) { }
+ key_iterator()
+ : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
+
+ friend bool operator==(const key_iterator &X, const key_iterator &Y) {
+ return X.NumEntriesLeft == Y.NumEntriesLeft;
+ }
+ friend bool operator!=(const key_iterator& X, const key_iterator &Y) {
+ return X.NumEntriesLeft != Y.NumEntriesLeft;
+ }
+
+ key_iterator& operator++() { // Preincrement
+ if (!NumItemsInBucketLeft) {
+ // 'Items' starts with a 16-bit unsigned integer representing the
+ // number of items in this bucket.
+ NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
+ }
+ Ptr += 4; // Skip the hash.
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
+ Ptr += L.first + L.second;
+ assert(NumItemsInBucketLeft);
+ --NumItemsInBucketLeft;
+ assert(NumEntriesLeft);
+ --NumEntriesLeft;
+ return *this;
+ }
+ key_iterator operator++(int) { // Postincrement
+ key_iterator tmp = *this; ++*this; return tmp;
+ }
+
+ value_type operator*() const {
+ const unsigned char* LocalPtr = Ptr;
+ if (!NumItemsInBucketLeft)
+ LocalPtr += 2; // number of items in bucket
+ LocalPtr += 4; // Skip the hash.
+
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L
+ = Info::ReadKeyDataLength(LocalPtr);
+
+ // Read the key.
+ const internal_key_type& Key = InfoObj->ReadKey(LocalPtr, L.first);
+ return InfoObj->GetExternalKey(Key);
+ }
+ };
+
+ key_iterator key_begin() {
+ return key_iterator(Base + 4, getNumEntries(), &InfoObj);
+ }
+ key_iterator key_end() { return key_iterator(); }
+
/// \brief Iterates over all the entries in the table, returning
/// a key/data pair.
class item_iterator {
diff --git a/include/clang/Basic/OpenCLExtensions.def b/include/clang/Basic/OpenCLExtensions.def
new file mode 100644
index 000000000000..95cc1a9a513f
--- /dev/null
+++ b/include/clang/Basic/OpenCLExtensions.def
@@ -0,0 +1,28 @@
+//===--- OpenCLExtensions.def - OpenCL extension list -----------*- 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 list of supported OpenCL extensions.
+//
+//===----------------------------------------------------------------------===//
+
+OPENCLEXT(cl_khr_fp64)
+OPENCLEXT(cl_khr_int64_base_atomics)
+OPENCLEXT(cl_khr_int64_extended_atomics)
+OPENCLEXT(cl_khr_fp16)
+OPENCLEXT(cl_khr_gl_sharing)
+OPENCLEXT(cl_khr_gl_event)
+OPENCLEXT(cl_khr_d3d10_sharing)
+OPENCLEXT(cl_khr_global_int32_base_atomics)
+OPENCLEXT(cl_khr_global_int32_extended_atomics)
+OPENCLEXT(cl_khr_local_int32_base_atomics)
+OPENCLEXT(cl_khr_local_int32_extended_atomics)
+OPENCLEXT(cl_khr_byte_addressable_store)
+OPENCLEXT(cl_khr_3d_image_writes)
+
+#undef OPENCLEXT
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index cd0da97e2ba3..d00195b32674 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -18,7 +18,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace clang {
@@ -57,6 +57,10 @@ public:
/// what sort of argument kind it is.
intptr_t DiagArgumentsVal[MaxArguments];
+ /// \brief The values for the various substitution positions that have
+ /// string arguments.
+ std::string DiagArgumentsStr[MaxArguments];
+
/// DiagRanges - The list of ranges added to this diagnostic. It currently
/// only support 10 ranges, could easily be extended if needed.
CharSourceRange DiagRanges[10];
@@ -186,6 +190,26 @@ public:
*this->DiagStorage = *Other.DiagStorage;
}
+ PartialDiagnostic(const DiagnosticInfo &Other, StorageAllocator &Allocator)
+ : DiagID(Other.getID()), DiagStorage(0), Allocator(&Allocator)
+ {
+ // Copy arguments.
+ for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
+ if (Other.getArgKind(I) == Diagnostic::ak_std_string)
+ AddString(Other.getArgStdStr(I));
+ else
+ AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I));
+ }
+
+ // Copy source ranges.
+ for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I)
+ AddSourceRange(Other.getRange(I));
+
+ // Copy fix-its.
+ for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I)
+ AddFixItHint(Other.getFixItHint(I));
+ }
+
PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
DiagID = Other.DiagID;
if (Other.DiagStorage) {
@@ -216,13 +240,28 @@ public:
DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
}
+ void AddString(llvm::StringRef V) const {
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs]
+ = Diagnostic::ak_std_string;
+ DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = V;
+ }
+
void Emit(const DiagnosticBuilder &DB) const {
if (!DiagStorage)
return;
// Add all arguments.
for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
- DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
+ if ((Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]
+ == Diagnostic::ak_std_string)
+ DB.AddString(DiagStorage->DiagArgumentsStr[i]);
+ else
+ DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
(Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
}
@@ -230,7 +269,7 @@ public:
for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i)
DB.AddSourceRange(DiagStorage->DiagRanges[i]);
- // Add all code modification hints
+ // Add all fix-its.
for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i)
DB.AddFixItHint(DiagStorage->FixItHints[i]);
}
@@ -263,6 +302,13 @@ public:
}
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ llvm::StringRef S) {
+
+ PD.AddString(S);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const SourceRange &R) {
PD.AddSourceRange(CharSourceRange::getTokenRange(R));
return PD;
@@ -288,6 +334,9 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
+/// \brief A partial diagnostic along with the source location where this
+/// diagnostic occurs.
+typedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt;
} // end namespace clang
#endif
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 35f27fbebd72..605c4bbafc74 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_SOURCELOCATION_H
#define LLVM_CLANG_SOURCELOCATION_H
+#include "llvm/Support/PointerLikeTypeTraits.h"
#include <utility>
#include <cassert>
@@ -121,7 +122,6 @@ public:
/// directly.
unsigned getRawEncoding() const { return ID; }
-
/// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
/// a real SourceLocation.
static SourceLocation getFromRawEncoding(unsigned Encoding) {
@@ -130,6 +130,22 @@ public:
return X;
}
+ /// getPtrEncoding - When a SourceLocation itself cannot be used, this returns
+ /// an (opaque) pointer encoding for it. This should only be passed
+ /// to SourceLocation::getFromPtrEncoding, it should not be inspected
+ /// directly.
+ void* getPtrEncoding() const {
+ // Double cast to avoid a warning "cast to pointer from integer of different
+ // size".
+ return (void*)(uintptr_t)getRawEncoding();
+ }
+
+ /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object
+ /// into a real SourceLocation.
+ static SourceLocation getFromPtrEncoding(void *Encoding) {
+ return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
+ }
+
void print(llvm::raw_ostream &OS, const SourceManager &SM) const;
void dump(const SourceManager &SM) const;
};
@@ -265,6 +281,20 @@ public:
bool isInSystemHeader() const;
+ /// \brief Determines the order of 2 source locations in the translation unit.
+ ///
+ /// \returns true if this source location comes before 'Loc', false otherwise.
+ bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
+
+ /// \brief Determines the order of 2 source locations in the translation unit.
+ ///
+ /// \returns true if this source location comes before 'Loc', false otherwise.
+ bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
+ assert(Loc.isValid());
+ assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!");
+ return isBeforeInTranslationUnitThan((SourceLocation)Loc);
+ }
+
/// Prints information about this FullSourceLoc to stderr. Useful for
/// debugging.
void dump() const { SourceLocation::dump(*SrcMgr); }
@@ -350,6 +380,19 @@ namespace llvm {
template <>
struct isPodLike<clang::FileID> { static const bool value = true; };
+ // Teach SmallPtrSet how to handle SourceLocation.
+ template<>
+ class PointerLikeTypeTraits<clang::SourceLocation> {
+ public:
+ static inline void *getAsVoidPointer(clang::SourceLocation L) {
+ return L.getPtrEncoding();
+ }
+ static inline clang::SourceLocation getFromVoidPointer(void *P) {
+ return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P);
+ }
+ enum { NumLowBitsAvailable = 0 };
+ };
+
} // end namespace llvm
#endif
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 7a66117f2076..c0fbd089e760 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -16,7 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/DenseMap.h"
@@ -369,7 +369,9 @@ public:
class SourceManager {
/// \brief Diagnostic object.
Diagnostic &Diag;
-
+
+ FileManager &FileMgr;
+
mutable llvm::BumpPtrAllocator ContentCacheAlloc;
/// FileInfos - Memoized information about all of the files tracked by this
@@ -427,15 +429,15 @@ class SourceManager {
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
- SourceManager(Diagnostic &Diag)
- : Diag(Diag), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
- NumBinaryProbes(0) {
- clearIDTables();
- }
+ SourceManager(Diagnostic &Diag, FileManager &FileMgr);
~SourceManager();
void clearIDTables();
+ Diagnostic &getDiagnostics() const { return Diag; }
+
+ FileManager &getFileManager() const { return FileMgr; }
+
//===--------------------------------------------------------------------===//
// MainFileID creation and querying methods.
//===--------------------------------------------------------------------===//
@@ -450,6 +452,13 @@ public:
return MainFileID;
}
+ /// \brief Set the file ID for the precompiled preamble, which is also the
+ /// main file.
+ void SetPreambleFileID(FileID Preamble) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
+ MainFileID = Preamble;
+ }
+
//===--------------------------------------------------------------------===//
// Methods to create new FileID's and instantiations.
//===--------------------------------------------------------------------===//
@@ -464,7 +473,7 @@ public:
unsigned PreallocatedID = 0,
unsigned Offset = 0) {
const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
- if (IR == 0) return FileID(); // Error opening file?
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
return createFileID(IR, IncludePos, FileCharacter, PreallocatedID, Offset);
}
@@ -514,9 +523,7 @@ public:
///
/// \param DoNotFree If true, then the buffer will not be freed when the
/// source manager is destroyed.
- ///
- /// \returns true if an error occurred, false otherwise.
- bool overrideFileContents(const FileEntry *SourceFile,
+ void overrideFileContents(const FileEntry *SourceFile,
const llvm::MemoryBuffer *Buffer,
bool DoNotFree = false);
@@ -715,6 +722,11 @@ public:
///
/// Note that a presumed location is always given as the instantiation point
/// of an instantiation location, not at the spelling location.
+ ///
+ /// \returns The presumed location of the specified SourceLocation. If the
+ /// presumed location cannot be calculate (e.g., because \p Loc is invalid
+ /// or the file containing \p Loc has changed on disk), returns an invalid
+ /// presumed location.
PresumedLoc getPresumedLoc(SourceLocation Loc) const;
/// isFromSameFile - Returns true if both SourceLocations correspond to
@@ -771,7 +783,7 @@ public:
/// If the source file is included multiple times, the source location will
/// be based upon the first inclusion.
SourceLocation getLocation(const FileEntry *SourceFile,
- unsigned Line, unsigned Col) const;
+ unsigned Line, unsigned Col);
/// \brief Determines the order of 2 source locations in the translation unit.
///
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index e757a2f4a185..e6b6218100ad 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -95,6 +95,23 @@ namespace clang {
VK_XValue
};
+ /// A further classification of the kind of object referenced by an
+ /// l-value or x-value.
+ enum ExprObjectKind {
+ /// An ordinary object is located at an address in memory.
+ OK_Ordinary,
+
+ /// A bitfield object is a bitfield on a C or C++ record.
+ OK_BitField,
+
+ /// A vector component is an element or range of elements on a vector.
+ OK_VectorComponent,
+
+ /// An Objective C property is a logical field of an Objective-C
+ /// object which is read and written via Objective C method calls.
+ OK_ObjCProperty
+ };
+
// \brief Describes the kind of template specialization that a
// particular template specialization declaration represents.
enum TemplateSpecializationKind {
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 4aa055e695e9..be0d8ff091e8 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -23,7 +23,7 @@ def ContinueStmt : Stmt;
def BreakStmt : Stmt;
def ReturnStmt : Stmt;
def DeclStmt : Stmt;
-def SwitchCase : Stmt;
+def SwitchCase : Stmt<1>;
def CaseStmt : DStmt<SwitchCase>;
def DefaultStmt : DStmt<SwitchCase>;
@@ -61,7 +61,9 @@ def MemberExpr : DStmt<Expr>;
def CastExpr : DStmt<Expr, 1>;
def BinaryOperator : DStmt<Expr>;
def CompoundAssignOperator : DStmt<BinaryOperator>;
-def ConditionalOperator : DStmt<Expr>;
+def AbstractConditionalOperator : DStmt<Expr, 1>;
+def ConditionalOperator : DStmt<AbstractConditionalOperator>;
+def BinaryConditionalOperator : DStmt<AbstractConditionalOperator>;
def ImplicitCastExpr : DStmt<CastExpr>;
def ExplicitCastExpr : DStmt<CastExpr, 1>;
def CStyleCastExpr : DStmt<ExplicitCastExpr>;
@@ -76,7 +78,6 @@ def VAArgExpr : DStmt<Expr>;
// GNU Extensions.
def AddrLabelExpr : DStmt<Expr>;
def StmtExpr : DStmt<Expr>;
-def TypesCompatibleExpr : DStmt<Expr>;
def ChooseExpr : DStmt<Expr>;
def GNUNullExpr : DStmt<Expr>;
@@ -100,16 +101,21 @@ def CXXNewExpr : DStmt<Expr>;
def CXXDeleteExpr : DStmt<Expr>;
def CXXPseudoDestructorExpr : DStmt<Expr>;
def UnaryTypeTraitExpr : DStmt<Expr>;
+def BinaryTypeTraitExpr : DStmt<Expr>;
def DependentScopeDeclRefExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>;
-def CXXExprWithTemporaries : DStmt<Expr>;
+def ExprWithCleanups : DStmt<Expr>;
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
def CXXUnresolvedConstructExpr : DStmt<Expr>;
def CXXDependentScopeMemberExpr : DStmt<Expr>;
def OverloadExpr : DStmt<Expr, 1>;
def UnresolvedLookupExpr : DStmt<OverloadExpr>;
def UnresolvedMemberExpr : DStmt<OverloadExpr>;
+def CXXNoexceptExpr : DStmt<Expr>;
+def PackExpansionExpr : DStmt<Expr>;
+def SizeOfPackExpr : DStmt<Expr>;
+def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
// Obj-C Expressions.
def ObjCStringLiteral : DStmt<Expr>;
@@ -119,11 +125,17 @@ def ObjCSelectorExpr : DStmt<Expr>;
def ObjCProtocolExpr : DStmt<Expr>;
def ObjCIvarRefExpr : DStmt<Expr>;
def ObjCPropertyRefExpr : DStmt<Expr>;
-def ObjCImplicitSetterGetterRefExpr : DStmt<Expr>;
-def ObjCSuperExpr : DStmt<Expr>;
def ObjCIsaExpr : DStmt<Expr>;
+// CUDA Expressions.
+def CUDAKernelCallExpr : DStmt<CallExpr>;
+
// Clang Extensions.
def ShuffleVectorExpr : DStmt<Expr>;
def BlockExpr : DStmt<Expr>;
def BlockDeclRefExpr : DStmt<Expr>;
+def OpaqueValueExpr : DStmt<Expr>;
+
+// Microsoft Extensions.
+def CXXUuidofExpr : DStmt<Expr>;
+
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 40df9ba11da4..b9087f2c47e8 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -18,7 +18,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <vector>
#include <string>
@@ -64,6 +64,7 @@ protected:
bool TLSSupported;
bool NoAsmVariants; // True if {|} are normal characters.
unsigned char PointerWidth, PointerAlign;
+ unsigned char BoolWidth, BoolAlign;
unsigned char IntWidth, IntAlign;
unsigned char FloatWidth, FloatAlign;
unsigned char DoubleWidth, DoubleAlign;
@@ -73,6 +74,7 @@ protected:
unsigned char LongLongWidth, LongLongAlign;
const char *DescriptionString;
const char *UserLabelPrefix;
+ const char *MCountName;
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
unsigned char RegParmMax, SSERegParmMax;
TargetCXXABI CXXABI;
@@ -139,7 +141,7 @@ public:
IntType getSigAtomicType() const { return SigAtomicType; }
- /// getTypeWidth - Return the width (in bits) of the specified integer type
+ /// getTypeWidth - Return the width (in bits) of the specified integer type
/// enum. For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
@@ -149,7 +151,7 @@ public:
/// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
- bool isTypeSigned(IntType T) const;
+ static bool isTypeSigned(IntType T);
/// getPointerWidth - Return the width of pointers on this target, for the
/// specified address space.
@@ -162,8 +164,8 @@ public:
/// getBoolWidth/Align - Return the size of '_Bool' and C++ 'bool' for this
/// target, in bits.
- unsigned getBoolWidth(bool isWide = false) const { return 8; } // FIXME
- unsigned getBoolAlign(bool isWide = false) const { return 8; } // FIXME
+ unsigned getBoolWidth() const { return BoolWidth; }
+ unsigned getBoolAlign() const { return BoolAlign; }
unsigned getCharWidth() const { return 8; } // FIXME
unsigned getCharAlign() const { return 8; } // FIXME
@@ -240,6 +242,11 @@ public:
return UserLabelPrefix;
}
+ /// MCountName - This returns name of the mcount instrumentation function.
+ const char *getMCountName() const {
+ return MCountName;
+ }
+
bool useBitFieldTypeAlignment() const {
return UseBitFieldTypeAlignment;
}
@@ -306,7 +313,7 @@ public:
std::string Name; // Operand name: [foo] with no []'s.
public:
ConstraintInfo(llvm::StringRef ConstraintStr, llvm::StringRef Name)
- : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
+ : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
Name(Name.str()) {}
const std::string &getConstraintStr() const { return ConstraintStr; }
@@ -356,6 +363,9 @@ public:
unsigned NumOutputs, unsigned &Index) const;
virtual std::string convertConstraint(const char Constraint) const {
+ // 'p' defaults to 'r', but can be overridden by targets.
+ if (Constraint == 'p')
+ return std::string("r");
return std::string(1, Constraint);
}
@@ -391,7 +401,7 @@ public:
return "__OBJC,__cstring_object,regular,no_dead_strip";
}
- /// getNSStringNonFragileABISection - Return the section to use for
+ /// getNSStringNonFragileABISection - Return the section to use for
/// NSString literals, or 0 if no special section is used (NonFragile ABI).
virtual const char *getNSStringNonFragileABISection() const {
return "__DATA, __objc_stringobj, regular, no_dead_strip";
@@ -499,7 +509,7 @@ public:
bool isTLSSupported() const {
return TLSSupported;
}
-
+
/// hasNoAsmVariants - Return true if {|} are normal characters in the
/// asm string. If this returns false (the default), then {abc|xyz} is syntax
/// that says that when compiling for asm variant #0, "abc" should be
@@ -508,19 +518,18 @@ public:
bool hasNoAsmVariants() const {
return NoAsmVariants;
}
-
+
/// getEHDataRegisterNumber - Return the register number that
/// __builtin_eh_return_regno would return with the specified argument.
virtual int getEHDataRegisterNumber(unsigned RegNo) const {
- return -1;
+ return -1;
}
-
- /// getStaticInitSectionSpecifier - Return the section to use for C++ static
+
+ /// getStaticInitSectionSpecifier - Return the section to use for C++ static
/// initialization functions.
virtual const char *getStaticInitSectionSpecifier() const {
return 0;
}
-
protected:
virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
return PointerWidth;
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index dc360adf8f19..b84b04da3de2 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -103,6 +103,7 @@ TOK(comment) // Comment (only in -E -C[C] mode)
// C99 6.4.2: Identifiers.
TOK(identifier) // abcde123
+TOK(raw_identifier) // Used only in raw lexing mode.
// C99 6.4.4.1: Integer Constants
// C99 6.4.4.2: Floating Constants
@@ -175,6 +176,10 @@ PUNCTUATOR(coloncolon, "::")
// Objective C support.
PUNCTUATOR(at, "@")
+// CUDA support.
+PUNCTUATOR(lesslessless, "<<<")
+PUNCTUATOR(greatergreatergreater, ">>>")
+
// C99 6.4.1: Keywords. These turn into kw_* tokens.
// Flags allowed:
// KEYALL - This is a keyword in all variants of C and C++, or it
@@ -183,9 +188,12 @@ PUNCTUATOR(at, "@")
// KEYC99 - This is a keyword introduced to C in C99
// KEYCXX - This is a C++ keyword, or a C++-specific keyword in the
// implementation namespace
+// KEYNOCXX - This is a keyword in every non-C++ dialect.
// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x
// KEYGNU - This is a keyword if GNU extensions are enabled
// KEYMS - This is a keyword if Microsoft extensions are enabled
+// KEYOPENCL - This is a keyword in OpenCL
+// KEYALTIVEC - This is a keyword in AltiVec
// KEYBORLAND - This is a keyword if Borland extensions are enabled
//
KEYWORD(auto , KEYALL)
@@ -222,7 +230,7 @@ KEYWORD(unsigned , KEYALL)
KEYWORD(void , KEYALL)
KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
-KEYWORD(_Bool , KEYNOMS)
+KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
KEYWORD(_Imaginary , KEYALL)
KEYWORD(__func__ , KEYALL)
@@ -278,6 +286,7 @@ KEYWORD(char16_t , KEYCXX0X)
KEYWORD(char32_t , KEYCXX0X)
KEYWORD(constexpr , KEYCXX0X)
KEYWORD(decltype , KEYCXX0X)
+KEYWORD(noexcept , KEYCXX0X)
KEYWORD(nullptr , KEYCXX0X)
KEYWORD(static_assert , KEYCXX0X)
KEYWORD(thread_local , KEYCXX0X)
@@ -316,6 +325,7 @@ KEYWORD(__has_virtual_destructor , KEYCXX)
KEYWORD(__is_abstract , KEYCXX)
KEYWORD(__is_base_of , KEYCXX)
KEYWORD(__is_class , KEYCXX)
+KEYWORD(__is_convertible_to , KEYCXX)
KEYWORD(__is_empty , KEYCXX)
KEYWORD(__is_enum , KEYCXX)
KEYWORD(__is_pod , KEYCXX)
@@ -323,7 +333,6 @@ KEYWORD(__is_polymorphic , KEYCXX)
KEYWORD(__is_union , KEYCXX)
// Tentative name - there's no implementation of std::is_literal_type yet.
KEYWORD(__is_literal , KEYCXX)
-// FIXME: Add MS's traits, too.
// Apple Extension.
KEYWORD(__private_extern__ , KEYALL)
@@ -336,7 +345,11 @@ KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYALL)
-// Borland Extension.
+// OpenCL-specific keywords (see OpenCL 1.1 [6.1.9])
+KEYWORD(__kernel , KEYOPENCL)
+ALIAS("kernel", __kernel , KEYOPENCL)
+
+// Borland Extensions.
KEYWORD(__pascal , KEYALL)
// Altivec Extension.
@@ -356,6 +369,7 @@ ALIAS("__complex__" , _Complex , KEYALL)
ALIAS("__imag__" , __imag , KEYALL)
ALIAS("__inline" , inline , KEYALL)
ALIAS("__inline__" , inline , KEYALL)
+ALIAS("__nullptr" , nullptr , KEYCXX)
ALIAS("__real__" , __real , KEYALL)
ALIAS("__restrict" , restrict , KEYALL)
ALIAS("__restrict__" , restrict , KEYALL)
@@ -369,15 +383,23 @@ ALIAS("__volatile__" , volatile , KEYALL)
// Microsoft extensions which should be disabled in strict conformance mode
KEYWORD(__ptr64 , KEYMS)
KEYWORD(__w64 , KEYMS)
+KEYWORD(__uuidof , KEYMS | KEYBORLAND)
ALIAS("_asm" , asm , KEYMS)
-ALIAS("_cdecl" , __cdecl , KEYMS)
-ALIAS("_fastcall" , __fastcall , KEYMS)
-ALIAS("_stdcall" , __stdcall , KEYMS)
+ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND)
+ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND)
+ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND)
ALIAS("_thiscall" , __thiscall , KEYMS)
+ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
+ALIAS("_inline" , inline , KEYMS)
// Borland Extensions which should be disabled in strict conformance mode.
ALIAS("_pascal" , __pascal , KEYBORLAND)
+// Clang Extensions.
+ALIAS("__char16_t" , char16_t , KEYCXX)
+ALIAS("__char32_t" , char32_t , KEYCXX)
+
+
//===----------------------------------------------------------------------===//
// Objective-C @-preceeded keywords.
//===----------------------------------------------------------------------===//
@@ -421,6 +443,12 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly
ANNOTATION(template_id) // annotation for a C++ template-id that names a
// function template specialization (not a type),
// e.g., "std::swap<int>"
+
+// Annotation for #pragma unused(...)
+// For each argument inside the parentheses the pragma handler will produce
+// one 'pragma_unused' annotation token followed by the argument token.
+ANNOTATION(pragma_unused)
+
#undef ANNOTATION
#undef OBJC2_AT_KEYWORD
#undef OBJC1_AT_KEYWORD
diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
index 85dc0671de62..515390a8ce93 100644
--- a/include/clang/Basic/TokenKinds.h
+++ b/include/clang/Basic/TokenKinds.h
@@ -43,6 +43,12 @@ enum ObjCKeywordKind {
NUM_OBJC_KEYWORDS
};
+/// OnOffSwitch - This defines the possible values of an on-off-switch
+/// (C99 6.10.6p2).
+enum OnOffSwitch {
+ OOS_ON, OOS_OFF, OOS_DEFAULT
+};
+
/// \brief Determines the name of a token as used within the front end.
///
/// The name of a token will be an internal name (such as "l_square")
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index 36b830069f86..00c6e9ed5000 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -36,6 +36,12 @@ namespace clang {
UTT_IsLiteral
};
+ /// BinaryTypeTrait - Names for the binary type traits.
+ enum BinaryTypeTrait {
+ BTT_IsBaseOf,
+ BTT_TypeCompatible,
+ BTT_IsConvertibleTo
+ };
}
#endif
diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
index 9948677662cd..ede68ed50d52 100644
--- a/include/clang/Basic/Version.h
+++ b/include/clang/Basic/Version.h
@@ -44,7 +44,7 @@ namespace clang {
/// \brief Retrieves the repository path (e.g., Subversion path) that
/// identifies the particular Clang branch, tag, or trunk from which this
/// Clang was built.
- llvm::StringRef getClangRepositoryPath();
+ std::string getClangRepositoryPath();
/// \brief Retrieves the repository revision number (or identifer) from which
/// this Clang was built.
diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h
new file mode 100644
index 000000000000..90e288a224ec
--- /dev/null
+++ b/include/clang/Basic/Visibility.h
@@ -0,0 +1,48 @@
+//===--- Visibility.h - Visibility enumeration and utilities ----*- 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 Visibility enumeration and various utility
+// functions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
+#define LLVM_CLANG_BASIC_VISIBILITY_H
+
+namespace clang {
+
+/// \link Describes the different kinds of visibility that a
+/// declaration may have. Visibility determines how a declaration
+/// interacts with the dynamic linker. It may also affect whether the
+/// symbol can be found by runtime symbol lookup APIs.
+///
+/// Visibility is not described in any language standard and
+/// (nonetheless) sometimes has odd behavior. Not all platforms
+/// support all visibility kinds.
+enum Visibility {
+ /// Objects with "hidden" visibility are not seen by the dynamic
+ /// linker.
+ HiddenVisibility,
+
+ /// Objects with "protected" visibility are seen by the dynamic
+ /// linker but always dynamically resolve to an object within this
+ /// shared object.
+ ProtectedVisibility,
+
+ /// Objects with "default" visibility are seen by the dynamic linker
+ /// and act like normal objects.
+ DefaultVisibility
+};
+
+inline Visibility minVisibility(Visibility L, Visibility R) {
+ return L < R ? L : R;
+}
+
+}
+
+#endif // LLVM_CLANG_BASIC_VISIBILITY_H
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index fa6ebb756ca3..880a0da6bc68 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -16,13 +16,34 @@ class Op;
def OP_NONE : Op;
def OP_ADD : Op;
+def OP_ADDL : Op;
+def OP_ADDW : Op;
def OP_SUB : Op;
+def OP_SUBL : Op;
+def OP_SUBW : Op;
def OP_MUL : Op;
+def OP_MULL : Op;
def OP_MLA : Op;
+def OP_MLAL : Op;
def OP_MLS : Op;
+def OP_MLSL : Op;
def OP_MUL_N : Op;
+def OP_MULL_N: Op;
def OP_MLA_N : Op;
def OP_MLS_N : Op;
+def OP_MLAL_N : Op;
+def OP_MLSL_N : Op;
+def OP_MUL_LN: Op;
+def OP_MULL_LN : Op;
+def OP_MLA_LN: Op;
+def OP_MLS_LN: Op;
+def OP_MLAL_LN : Op;
+def OP_MLSL_LN : Op;
+def OP_QDMULL_LN : Op;
+def OP_QDMLAL_LN : Op;
+def OP_QDMLSL_LN : Op;
+def OP_QDMULH_LN : Op;
+def OP_QRDMULH_LN : Op;
def OP_EQ : Op;
def OP_GE : Op;
def OP_LE : Op;
@@ -40,22 +61,31 @@ def OP_HI : Op;
def OP_LO : Op;
def OP_CONC : Op;
def OP_DUP : Op;
+def OP_DUP_LN: Op;
def OP_SEL : Op;
def OP_REV64 : Op;
def OP_REV32 : Op;
def OP_REV16 : Op;
+def OP_REINT : Op;
+def OP_ABDL : Op;
+def OP_ABA : Op;
+def OP_ABAL : Op;
-class Inst <string p, string t, Op o> {
+class Inst <string n, string p, string t, Op o> {
+ string Name = n;
string Prototype = p;
string Types = t;
Op Operand = o;
bit isShift = 0;
}
-// Used to generate Builtins.def
-class SInst<string p, string t> : Inst<p, t, OP_NONE> {}
-class IInst<string p, string t> : Inst<p, t, OP_NONE> {}
-class WInst<string p, string t> : Inst<p, t, OP_NONE> {}
+// Used to generate Builtins.def:
+// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8", "p8")
+// IInst: Instruction with generic integer suffix (e.g., "i8")
+// WInst: Instruction with only bit size suffix (e.g., "8")
+class SInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+class IInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
// prototype: return (arg, arg, ...)
// v: void
@@ -93,251 +123,273 @@ class WInst<string p, string t> : Inst<p, t, OP_NONE> {}
////////////////////////////////////////////////////////////////////////////////
// E.3.1 Addition
-def VADD : Inst<"ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_ADD>;
-def VADDL : SInst<"wdd", "csiUcUsUi">;
-def VADDW : SInst<"wwd", "csiUcUsUi">;
-def VHADD : SInst<"ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
-def VRHADD : SInst<"ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
-def VQADD : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VADDHN : IInst<"dww", "csiUcUsUi">;
-def VRADDHN : IInst<"dww", "csiUcUsUi">;
+def VADD : Inst<"vadd", "ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_ADD>;
+def VADDL : Inst<"vaddl", "wdd", "csiUcUsUi", OP_ADDL>;
+def VADDW : Inst<"vaddw", "wwd", "csiUcUsUi", OP_ADDW>;
+def VHADD : SInst<"vhadd", "ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VRHADD : SInst<"vrhadd", "ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VQADD : SInst<"vqadd", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VADDHN : IInst<"vaddhn", "hkk", "silUsUiUl">;
+def VRADDHN : IInst<"vraddhn", "hkk", "silUsUiUl">;
////////////////////////////////////////////////////////////////////////////////
// E.3.2 Multiplication
-def VMUL : Inst<"ddd", "csifUcUsUiPcQcQsQiQfQUcQUsQUiQPc", OP_MUL>;
-def VMLA : Inst<"dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLA>;
-def VMLAL : SInst<"wwdd", "csiUcUsUi">;
-def VMLS : Inst<"dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLS>;
-def VMLSL : SInst<"wwdd", "csiUcUsUi">;
-def VQDMULH : SInst<"ddd", "siQsQi">;
-def VQRDMULH : SInst<"ddd", "siQsQi">;
-def VQDMLAL : SInst<"wwdd", "si">;
-def VQDMLSL : SInst<"wwdd", "si">;
-def VMULL : SInst<"wdd", "csiUcUsUiPc">;
-def VQDMULL : SInst<"wdd", "si">;
+def VMUL : Inst<"vmul", "ddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MUL>;
+def VMULP : SInst<"vmul", "ddd", "PcQPc">;
+def VMLA : Inst<"vmla", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLA>;
+def VMLAL : Inst<"vmlal", "wwdd", "csiUcUsUi", OP_MLAL>;
+def VMLS : Inst<"vmls", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLS>;
+def VMLSL : Inst<"vmlsl", "wwdd", "csiUcUsUi", OP_MLSL>;
+def VQDMULH : SInst<"vqdmulh", "ddd", "siQsQi">;
+def VQRDMULH : SInst<"vqrdmulh", "ddd", "siQsQi">;
+def VQDMLAL : SInst<"vqdmlal", "wwdd", "si">;
+def VQDMLSL : SInst<"vqdmlsl", "wwdd", "si">;
+def VMULL : Inst<"vmull", "wdd", "csiUcUsUi", OP_MULL>;
+def VMULLP : SInst<"vmull", "wdd", "Pc">;
+def VQDMULL : SInst<"vqdmull", "wdd", "si">;
////////////////////////////////////////////////////////////////////////////////
// E.3.3 Subtraction
-def VSUB : Inst<"ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_SUB>;
-def VSUBL : SInst<"wdd", "csiUcUsUi">;
-def VSUBW : SInst<"wwd", "csiUcUsUi">;
-def VQSUB : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VHSUB : SInst<"ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
-def VSUBHN : IInst<"dww", "csiUcUsUi">;
-def VRSUBHN : IInst<"dww", "csiUcUsUi">;
+def VSUB : Inst<"vsub", "ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_SUB>;
+def VSUBL : Inst<"vsubl", "wdd", "csiUcUsUi", OP_SUBL>;
+def VSUBW : Inst<"vsubw", "wwd", "csiUcUsUi", OP_SUBW>;
+def VQSUB : SInst<"vqsub", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VHSUB : SInst<"vhsub", "ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VSUBHN : IInst<"vsubhn", "hkk", "silUsUiUl">;
+def VRSUBHN : IInst<"vrsubhn", "hkk", "silUsUiUl">;
////////////////////////////////////////////////////////////////////////////////
// E.3.4 Comparison
-def VCEQ : Inst<"udd", "csifUcUsUiPcQcQsQiQfQUcQUsQUiQPc", OP_EQ>;
-def VCGE : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GE>;
-def VCLE : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LE>;
-def VCGT : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GT>;
-def VCLT : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LT>;
-def VCAGE : IInst<"udd", "fQf">;
-def VCALE : IInst<"udd", "fQf">;
-def VCAGT : IInst<"udd", "fQf">;
-def VCALT : IInst<"udd", "fQf">;
-def VTST : WInst<"udd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc">;
+def VCEQ : Inst<"vceq", "udd", "csifUcUsUiPcQcQsQiQfQUcQUsQUiQPc", OP_EQ>;
+def VCGE : Inst<"vcge", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GE>;
+def VCLE : Inst<"vcle", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LE>;
+def VCGT : Inst<"vcgt", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GT>;
+def VCLT : Inst<"vclt", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LT>;
+def VCAGE : IInst<"vcage", "udd", "fQf">;
+def VCALE : IInst<"vcale", "udd", "fQf">;
+def VCAGT : IInst<"vcagt", "udd", "fQf">;
+def VCALT : IInst<"vcalt", "udd", "fQf">;
+def VTST : WInst<"vtst", "udd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc">;
////////////////////////////////////////////////////////////////////////////////
// E.3.5 Absolute Difference
-def VABD : SInst<"ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
-def VABDL : SInst<"wdd", "csiUcUsUi">;
-def VABA : SInst<"dddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
-def VABAL : SInst<"wwdd", "csiUcUsUi">;
+def VABD : SInst<"vabd", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
+def VABDL : Inst<"vabdl", "wdd", "csiUcUsUi", OP_ABDL>;
+def VABA : Inst<"vaba", "dddd", "csiUcUsUiQcQsQiQUcQUsQUi", OP_ABA>;
+def VABAL : Inst<"vabal", "wwdd", "csiUcUsUi", OP_ABAL>;
////////////////////////////////////////////////////////////////////////////////
// E.3.6 Max/Min
-def VMAX : SInst<"ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
-def VMIN : SInst<"ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
+def VMAX : SInst<"vmax", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
+def VMIN : SInst<"vmin", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
////////////////////////////////////////////////////////////////////////////////
// E.3.7 Pairdise Addition
-def VPADD : IInst<"ddd", "csiUcUsUif">;
-def VPADDL : SInst<"nd", "csiUcUsUiQcQsQiQUcQUsQUi">;
-def VPADAL : SInst<"nnd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VPADD : IInst<"vpadd", "ddd", "csiUcUsUif">;
+def VPADDL : SInst<"vpaddl", "nd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VPADAL : SInst<"vpadal", "nnd", "csiUcUsUiQcQsQiQUcQUsQUi">;
////////////////////////////////////////////////////////////////////////////////
// E.3.8-9 Folding Max/Min
-def VPMAX : SInst<"ddd", "csiUcUsUif">;
-def VPMIN : SInst<"ddd", "csiUcUsUif">;
+def VPMAX : SInst<"vpmax", "ddd", "csiUcUsUif">;
+def VPMIN : SInst<"vpmin", "ddd", "csiUcUsUif">;
////////////////////////////////////////////////////////////////////////////////
// E.3.10 Reciprocal/Sqrt
-def VRECPS : IInst<"ddd", "fQf">;
-def VRSQRTS : IInst<"ddd", "fQf">;
+def VRECPS : IInst<"vrecps", "ddd", "fQf">;
+def VRSQRTS : IInst<"vrsqrts", "ddd", "fQf">;
////////////////////////////////////////////////////////////////////////////////
// E.3.11 Shifts by signed variable
-def VSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VQSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VRSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VQRSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VSHL : SInst<"vshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQSHL : SInst<"vqshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VRSHL : SInst<"vrshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQRSHL : SInst<"vqrshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
////////////////////////////////////////////////////////////////////////////////
// E.3.12 Shifts by constant
let isShift = 1 in {
-def VSHR_N : SInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VSHL_N : IInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VRSHR_N : SInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VSRA_N : SInst<"dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VRSRA_N : SInst<"dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VQSHL_N : SInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
-def VQSHLU_N : SInst<"udi", "csilQcQsQiQl">;
-def VSHRN_N : IInst<"hki", "silUsUiUl">;
-def VQSHRUN_N : SInst<"eki", "sil">;
-def VQRSHRUN_N : SInst<"eki", "sil">;
-def VQSHRN_N : SInst<"hki", "silUsUiUl">;
-def VRSHRN_N : IInst<"hki", "silUsUiUl">;
-def VQRSHRN_N : SInst<"hki", "silUsUiUl">;
-def VSHLL_N : SInst<"wdi", "csiUcUsUi">;
+def VSHR_N : SInst<"vshr_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VSHL_N : IInst<"vshl_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VRSHR_N : SInst<"vrshr_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VSRA_N : SInst<"vsra_n", "dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VRSRA_N : SInst<"vrsra_n", "dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQSHL_N : SInst<"vqshl_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQSHLU_N : SInst<"vqshlu_n", "udi", "csilQcQsQiQl">;
+def VSHRN_N : IInst<"vshrn_n", "hki", "silUsUiUl">;
+def VQSHRUN_N : SInst<"vqshrun_n", "eki", "sil">;
+def VQRSHRUN_N : SInst<"vqrshrun_n", "eki", "sil">;
+def VQSHRN_N : SInst<"vqshrn_n", "hki", "silUsUiUl">;
+def VRSHRN_N : IInst<"vrshrn_n", "hki", "silUsUiUl">;
+def VQRSHRN_N : SInst<"vqrshrn_n", "hki", "silUsUiUl">;
+def VSHLL_N : SInst<"vshll_n", "wdi", "csiUcUsUi">;
////////////////////////////////////////////////////////////////////////////////
// E.3.13 Shifts with insert
-def VSRI_N : WInst<"dddi", "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">;
-def VSLI_N : WInst<"dddi", "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">;
+def VSRI_N : WInst<"vsri_n", "dddi",
+ "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">;
+def VSLI_N : WInst<"vsli_n", "dddi",
+ "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">;
}
////////////////////////////////////////////////////////////////////////////////
// E.3.14 Loads and stores of a single vector
-def VLD1 : WInst<"dc", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD1_LANE : WInst<"dcdi", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD1_DUP : WInst<"dc", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST1 : WInst<"vpd", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST1_LANE : WInst<"vpdi", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD1 : WInst<"vld1", "dc",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD1_LANE : WInst<"vld1_lane", "dcdi",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD1_DUP : WInst<"vld1_dup", "dc",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST1 : WInst<"vst1", "vpd",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST1_LANE : WInst<"vst1_lane", "vpdi",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
////////////////////////////////////////////////////////////////////////////////
// E.3.15 Loads and stores of an N-element structure
-def VLD2 : WInst<"2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD3 : WInst<"3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD4 : WInst<"4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VLD2_DUP : WInst<"2c", "UcUsUiUlcsilhfPcPs">;
-def VLD3_DUP : WInst<"3c", "UcUsUiUlcsilhfPcPs">;
-def VLD4_DUP : WInst<"4c", "UcUsUiUlcsilhfPcPs">;
-def VLD2_LANE : WInst<"2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VLD3_LANE : WInst<"3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VLD4_LANE : WInst<"4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VST2 : WInst<"vp2", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST3 : WInst<"vp3", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST4 : WInst<"vp4", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
-def VST2_LANE : WInst<"vp2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VST3_LANE : WInst<"vp3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
-def VST4_LANE : WInst<"vp4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VLD2 : WInst<"vld2", "2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD3 : WInst<"vld3", "3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD4 : WInst<"vld4", "4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD2_DUP : WInst<"vld2_dup", "2c", "UcUsUiUlcsilhfPcPs">;
+def VLD3_DUP : WInst<"vld3_dup", "3c", "UcUsUiUlcsilhfPcPs">;
+def VLD4_DUP : WInst<"vld4_dup", "4c", "UcUsUiUlcsilhfPcPs">;
+def VLD2_LANE : WInst<"vld2_lane", "2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VLD3_LANE : WInst<"vld3_lane", "3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VLD4_LANE : WInst<"vld4_lane", "4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VST2 : WInst<"vst2", "vp2", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST3 : WInst<"vst3", "vp3", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST4 : WInst<"vst4", "vp4", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST2_LANE : WInst<"vst2_lane", "vp2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VST3_LANE : WInst<"vst3_lane", "vp3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VST4_LANE : WInst<"vst4_lane", "vp4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
////////////////////////////////////////////////////////////////////////////////
// E.3.16 Extract lanes from a vector
-def VGET_LANE : IInst<"sdi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
+def VGET_LANE : IInst<"vget_lane", "sdi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
////////////////////////////////////////////////////////////////////////////////
// E.3.17 Set lanes within a vector
-def VSET_LANE : IInst<"dsdi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
+def VSET_LANE : IInst<"vset_lane", "dsdi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
////////////////////////////////////////////////////////////////////////////////
// E.3.18 Initialize a vector from bit pattern
-def VCREATE: Inst<"dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
+def VCREATE: Inst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
////////////////////////////////////////////////////////////////////////////////
// E.3.19 Set all lanes to same value
-def VDUP_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
-def VMOV_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
-def VDUP_LANE : WInst<"dgi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
+def VDUP_N : Inst<"vdup_n", "ds",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+def VMOV_N : Inst<"vmov_n", "ds",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+def VDUP_LANE : Inst<"vdup_lane", "dgi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl",OP_DUP_LN>;
////////////////////////////////////////////////////////////////////////////////
// E.3.20 Combining vectors
-def VCOMBINE : Inst<"kdd", "csilhfUcUsUiUlPcPs", OP_CONC>;
+def VCOMBINE : Inst<"vcombine", "kdd", "csilhfUcUsUiUlPcPs", OP_CONC>;
////////////////////////////////////////////////////////////////////////////////
// E.3.21 Splitting vectors
-def VGET_HIGH : Inst<"dk", "csilhfUcUsUiUlPcPs", OP_HI>;
-def VGET_LOW : Inst<"dk", "csilhfUcUsUiUlPcPs", OP_LO>;
+def VGET_HIGH : Inst<"vget_high", "dk", "csilhfUcUsUiUlPcPs", OP_HI>;
+def VGET_LOW : Inst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>;
////////////////////////////////////////////////////////////////////////////////
// E.3.22 Converting vectors
-def VCVT_S32 : SInst<"xd", "fQf">;
-def VCVT_U32 : SInst<"ud", "fQf">;
-def VCVT_F16 : SInst<"hk", "f">;
-def VCVT_N_S32 : SInst<"xdi", "fQf">;
-def VCVT_N_U32 : SInst<"udi", "fQf">;
-def VCVT_F32 : SInst<"fd", "iUiQiQUi">;
-def VCVT_F32_F16 : SInst<"kh", "f">;
-def VCVT_N_F32 : SInst<"fdi", "iUiQiQUi">;
-def VMOVN : IInst<"hk", "silUsUiUl">;
-def VMOVL : SInst<"wd", "csiUcUsUi">;
-def VQMOVN : SInst<"hk", "silUsUiUl">;
-def VQMOVUN : SInst<"ek", "sil">;
+def VCVT_S32 : SInst<"vcvt_s32", "xd", "fQf">;
+def VCVT_U32 : SInst<"vcvt_u32", "ud", "fQf">;
+def VCVT_F16 : SInst<"vcvt_f16", "hk", "f">;
+def VCVT_N_S32 : SInst<"vcvt_n_s32", "xdi", "fQf">;
+def VCVT_N_U32 : SInst<"vcvt_n_u32", "udi", "fQf">;
+def VCVT_F32 : SInst<"vcvt_f32", "fd", "iUiQiQUi">;
+def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "fd", "h">;
+def VCVT_N_F32 : SInst<"vcvt_n_f32", "fdi", "iUiQiQUi">;
+def VMOVN : IInst<"vmovn", "hk", "silUsUiUl">;
+def VMOVL : SInst<"vmovl", "wd", "csiUcUsUi">;
+def VQMOVN : SInst<"vqmovn", "hk", "silUsUiUl">;
+def VQMOVUN : SInst<"vqmovun", "ek", "sil">;
////////////////////////////////////////////////////////////////////////////////
// E.3.23-24 Table lookup, Extended table lookup
-def VTBL1 : WInst<"ddt", "UccPc">;
-def VTBL2 : WInst<"d2t", "UccPc">;
-def VTBL3 : WInst<"d3t", "UccPc">;
-def VTBL4 : WInst<"d4t", "UccPc">;
-def VTBX1 : WInst<"dddt", "UccPc">;
-def VTBX2 : WInst<"dd2t", "UccPc">;
-def VTBX3 : WInst<"dd3t", "UccPc">;
-def VTBX4 : WInst<"dd4t", "UccPc">;
+def VTBL1 : WInst<"vtbl1", "ddt", "UccPc">;
+def VTBL2 : WInst<"vtbl2", "d2t", "UccPc">;
+def VTBL3 : WInst<"vtbl3", "d3t", "UccPc">;
+def VTBL4 : WInst<"vtbl4", "d4t", "UccPc">;
+def VTBX1 : WInst<"vtbx1", "dddt", "UccPc">;
+def VTBX2 : WInst<"vtbx2", "dd2t", "UccPc">;
+def VTBX3 : WInst<"vtbx3", "dd3t", "UccPc">;
+def VTBX4 : WInst<"vtbx4", "dd4t", "UccPc">;
////////////////////////////////////////////////////////////////////////////////
// E.3.25 Operations with a scalar value
-def VMLA_LANE : IInst<"ddddi", "siUsUifQsQiQUsQUiQf">;
-def VMLAL_LANE : SInst<"wwddi", "siUsUi">;
-def VQDMLAL_LANE : SInst<"wwddi", "si">;
-def VMLS_LANE : IInst<"ddddi", "siUsUifQsQiQUsQUiQf">;
-def VMLSL_LANE : SInst<"wwddi", "siUsUi">;
-def VQDMLSL_LANE : SInst<"wwddi", "si">;
-def VMUL_N : Inst<"dds", "sifUsUiQsQiQfQUsQUi", OP_MUL_N>;
-def VMULL_N : SInst<"wda", "siUsUi">;
-def VMULL_LANE : SInst<"wddi", "siUsUi">;
-def VQDMULL_N : SInst<"wda", "si">;
-def VQDMULL_LANE : SInst<"wddi", "si">;
-def VQDMULH_N : SInst<"dda", "siQsQi">;
-def VQDMULH_LANE : SInst<"dddi", "siQsQi">;
-def VQRDMULH_N : SInst<"dda", "siQsQi">;
-def VQRDMULH_LANE : SInst<"dddi", "siQsQi">;
-def VMLA_N : Inst<"ddda", "siUsUifQsQiQUsQUiQf", OP_MLA_N>;
-def VMLAL_N : SInst<"wwda", "siUsUi">;
-def VQDMLAL_N : SInst<"wwda", "si">;
-def VMLS_N : Inst<"ddds", "siUsUifQsQiQUsQUiQf", OP_MLS_N>;
-def VMLSL_N : SInst<"wwda", "siUsUi">;
-def VQDMLSL_N : SInst<"wwda", "si">;
+def VMLA_LANE : Inst<"vmla_lane", "dddgi", "siUsUifQsQiQUsQUiQf", OP_MLA_LN>;
+def VMLAL_LANE : Inst<"vmlal_lane", "wwddi", "siUsUi", OP_MLAL_LN>;
+def VQDMLAL_LANE : Inst<"vqdmlal_lane", "wwddi", "si", OP_QDMLAL_LN>;
+def VMLS_LANE : Inst<"vmls_lane", "dddgi", "siUsUifQsQiQUsQUiQf", OP_MLS_LN>;
+def VMLSL_LANE : Inst<"vmlsl_lane", "wwddi", "siUsUi", OP_MLSL_LN>;
+def VQDMLSL_LANE : Inst<"vqdmlsl_lane", "wwddi", "si", OP_QDMLSL_LN>;
+def VMUL_N : Inst<"vmul_n", "dds", "sifUsUiQsQiQfQUsQUi", OP_MUL_N>;
+def VMUL_LANE : Inst<"vmul_lane", "ddgi", "sifUsUiQsQiQfQUsQUi", OP_MUL_LN>;
+def VMULL_N : Inst<"vmull_n", "wda", "siUsUi", OP_MULL_N>;
+def VMULL_LANE : Inst<"vmull_lane", "wddi", "siUsUi", OP_MULL_LN>;
+def VQDMULL_N : SInst<"vqdmull_n", "wda", "si">;
+def VQDMULL_LANE : Inst<"vqdmull_lane", "wddi", "si", OP_QDMULL_LN>;
+def VQDMULH_N : SInst<"vqdmulh_n", "dda", "siQsQi">;
+def VQDMULH_LANE : Inst<"vqdmulh_lane", "ddgi", "siQsQi", OP_QDMULH_LN>;
+def VQRDMULH_N : SInst<"vqrdmulh_n", "dda", "siQsQi">;
+def VQRDMULH_LANE : Inst<"vqrdmulh_lane", "ddgi", "siQsQi", OP_QRDMULH_LN>;
+def VMLA_N : Inst<"vmla_n", "ddda", "siUsUifQsQiQUsQUiQf", OP_MLA_N>;
+def VMLAL_N : Inst<"vmlal_n", "wwda", "siUsUi", OP_MLAL_N>;
+def VQDMLAL_N : SInst<"vqdmlal_n", "wwda", "si">;
+def VMLS_N : Inst<"vmls_n", "ddds", "siUsUifQsQiQUsQUiQf", OP_MLS_N>;
+def VMLSL_N : Inst<"vmlsl_n", "wwda", "siUsUi", OP_MLSL_N>;
+def VQDMLSL_N : SInst<"vqdmlsl_n", "wwda", "si">;
////////////////////////////////////////////////////////////////////////////////
// E.3.26 Vector Extract
-def VEXT : WInst<"dddi", "cUcPcsUsPsiUilUlQcQUcQPcQsQUsQPsQiQUiQlQUl">;
+def VEXT : WInst<"vext", "dddi",
+ "cUcPcsUsPsiUilUlfQcQUcQPcQsQUsQPsQiQUiQlQUlQf">;
////////////////////////////////////////////////////////////////////////////////
// E.3.27 Reverse vector elements (sdap endianness)
-def VREV64 : Inst<"dd", "csiUcUsUiPcPsfQcQsQiQUcQUsQUiQPcQPsQf", OP_REV64>;
-def VREV32 : Inst<"dd", "csUcUsPcQcQsQUcQUsQPc", OP_REV32>;
-def VREV16 : Inst<"dd", "cUcPcQcQUcQPc", OP_REV16>;
+def VREV64 : Inst<"vrev64", "dd", "csiUcUsUiPcPsfQcQsQiQUcQUsQUiQPcQPsQf",
+ OP_REV64>;
+def VREV32 : Inst<"vrev32", "dd", "csUcUsPcPsQcQsQUcQUsQPcQPs", OP_REV32>;
+def VREV16 : Inst<"vrev16", "dd", "cUcPcQcQUcQPc", OP_REV16>;
////////////////////////////////////////////////////////////////////////////////
// E.3.28 Other single operand arithmetic
-def VABS : SInst<"dd", "csifQcQsQiQf">;
-def VQABS : SInst<"dd", "csiQcQsQi">;
-def VNEG : Inst<"dd", "csifQcQsQiQf", OP_NEG>;
-def VQNEG : SInst<"dd", "csiQcQsQi">;
-def VCLS : SInst<"dd", "csiQcQsQi">;
-def VCLZ : IInst<"dd", "csiUcUsUiQcQsQiQUcQUsQUi">;
-def VCNT : WInst<"dd", "UccPcQUcQcQPc">;
-def VRECPE : SInst<"dd", "fUiQfQUi">;
-def VRSQRTE : SInst<"dd", "fUiQfQUi">;
+def VABS : SInst<"vabs", "dd", "csifQcQsQiQf">;
+def VQABS : SInst<"vqabs", "dd", "csiQcQsQi">;
+def VNEG : Inst<"vneg", "dd", "csifQcQsQiQf", OP_NEG>;
+def VQNEG : SInst<"vqneg", "dd", "csiQcQsQi">;
+def VCLS : SInst<"vcls", "dd", "csiQcQsQi">;
+def VCLZ : IInst<"vclz", "dd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VCNT : WInst<"vcnt", "dd", "UccPcQUcQcQPc">;
+def VRECPE : SInst<"vrecpe", "dd", "fUiQfQUi">;
+def VRSQRTE : SInst<"vrsqrte", "dd", "fUiQfQUi">;
////////////////////////////////////////////////////////////////////////////////
// E.3.29 Logical operations
-def VMVN : Inst<"dd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc", OP_NOT>;
-def VAND : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_AND>;
-def VORR : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_OR>;
-def VEOR : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_XOR>;
-def VBIC : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ANDN>;
-def VORN : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ORN>;
-def VBSL : Inst<"dudd", "csilUcUsUiUlfPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPs", OP_SEL>;
+def VMVN : Inst<"vmvn", "dd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc", OP_NOT>;
+def VAND : Inst<"vand", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_AND>;
+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>;
////////////////////////////////////////////////////////////////////////////////
// E.3.30 Transposition operations
-def VTRN: WInst<"2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
-def VZIP: WInst<"2dd", "csUcUsfPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
-def VUZP: WInst<"2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
+def VTRN : WInst<"vtrn", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
+def VZIP : WInst<"vzip", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
+def VUZP : WInst<"vuzp", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
////////////////////////////////////////////////////////////////////////////////
// E.3.31 Vector reinterpret cast operations
+def VREINTERPRET
+ : Inst<"vreinterpret", "dd",
+ "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT>;
+
diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt
index e82cf429eecc..375ae5bdabc8 100644
--- a/include/clang/CMakeLists.txt
+++ b/include/clang/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(AST)
add_subdirectory(Basic)
add_subdirectory(Driver)
+add_subdirectory(Lex)
add_subdirectory(Serialization)
diff --git a/include/clang/Checker/AnalysisConsumer.h b/include/clang/Checker/AnalysisConsumer.h
deleted file mode 100644
index c236766f0ac9..000000000000
--- a/include/clang/Checker/AnalysisConsumer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- 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 functions necessary for a front-end to run various
-// analyses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_CHECKER_ANALYSISCONSUMER_H
-#define LLVM_CLANG_CHECKER_ANALYSISCONSUMER_H
-
-#include <string>
-
-namespace clang {
-
-class AnalyzerOptions;
-class ASTConsumer;
-class Preprocessor;
-
-/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
-/// analysis passes. (The set of analyses run is controlled by command-line
-/// options.)
-ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp,
- const std::string &output,
- const AnalyzerOptions& Opts);
-
-}
-
-#endif
diff --git a/include/clang/Checker/Checkers/LocalCheckers.h b/include/clang/Checker/Checkers/LocalCheckers.h
deleted file mode 100644
index 4a9e381a7c15..000000000000
--- a/include/clang/Checker/Checkers/LocalCheckers.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- 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 interface to call a set of intra-procedural (local)
-// checkers that use flow/path-sensitive analyses to find bugs.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H
-#define LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H
-
-namespace clang {
-
-class CFG;
-class Decl;
-class Diagnostic;
-class ASTContext;
-class PathDiagnosticClient;
-class GRTransferFuncs;
-class BugType;
-class LangOptions;
-class ParentMap;
-class LiveVariables;
-class BugReporter;
-class ObjCImplementationDecl;
-class LangOptions;
-class GRExprEngine;
-class TranslationUnitDecl;
-
-void CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &map,
- BugReporter& BR);
-
-GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
- const LangOptions& lopts);
-
-void CheckObjCDealloc(const ObjCImplementationDecl* D, const LangOptions& L,
- BugReporter& BR);
-
-void CheckObjCInstMethSignature(const ObjCImplementationDecl *ID,
- BugReporter& BR);
-
-void CheckObjCUnusedIvar(const ObjCImplementationDecl *D, BugReporter& BR);
-
-void RegisterAppleChecks(GRExprEngine& Eng, const Decl &D);
-void RegisterExperimentalChecks(GRExprEngine &Eng);
-void RegisterExperimentalInternalChecks(GRExprEngine &Eng);
-
-void CheckLLVMConventions(TranslationUnitDecl &TU, BugReporter &BR);
-void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR);
-void CheckSizeofPointer(const Decl *D, BugReporter &BR);
-
-void RegisterCallInliner(GRExprEngine &Eng);
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Checker/ManagerRegistry.h b/include/clang/Checker/ManagerRegistry.h
deleted file mode 100644
index ebfd28e10930..000000000000
--- a/include/clang/Checker/ManagerRegistry.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===-- ManagerRegistry.h - Pluggable analyzer module registry --*- 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 ManagerRegistry and Register* classes.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H
-#define LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H
-
-#include "clang/Checker/PathSensitive/GRState.h"
-
-namespace clang {
-
-/// ManagerRegistry - This class records manager creators registered at
-/// runtime. The information is communicated to AnalysisManager through static
-/// members. Better design is expected.
-
-class ManagerRegistry {
-public:
- static StoreManagerCreator StoreMgrCreator;
- static ConstraintManagerCreator ConstraintMgrCreator;
-};
-
-/// RegisterConstraintManager - This class is used to setup the constraint
-/// manager of the static analyzer. The constructor takes a creator function
-/// pointer for creating the constraint manager.
-///
-/// It is used like this:
-///
-/// class MyConstraintManager {};
-/// ConstraintManager* CreateMyConstraintManager(GRStateManager& statemgr) {
-/// return new MyConstraintManager(statemgr);
-/// }
-/// RegisterConstraintManager X(CreateMyConstraintManager);
-
-class RegisterConstraintManager {
-public:
- RegisterConstraintManager(ConstraintManagerCreator CMC) {
- assert(ManagerRegistry::ConstraintMgrCreator == 0
- && "ConstraintMgrCreator already set!");
- ManagerRegistry::ConstraintMgrCreator = CMC;
- }
-};
-
-}
-#endif
diff --git a/include/clang/Checker/PathSensitive/GRAuditor.h b/include/clang/Checker/PathSensitive/GRAuditor.h
deleted file mode 100644
index 015c82e80bb5..000000000000
--- a/include/clang/Checker/PathSensitive/GRAuditor.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//==- GRAuditor.h - Observers of the creation of ExplodedNodes------*- 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 GRAuditor and its primary subclasses, an interface
-// to audit the creation of ExplodedNodes. This interface can be used
-// to implement simple checkers that do not mutate analysis state but
-// instead operate by perfoming simple logical checks at key monitoring
-// locations (e.g., function calls).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_GRAUDITOR
-#define LLVM_CLANG_ANALYSIS_GRAUDITOR
-
-namespace clang {
-
-class ExplodedNode;
-class GRStateManager;
-
-class GRAuditor {
-public:
- virtual ~GRAuditor() {}
- virtual bool Audit(ExplodedNode* N, GRStateManager& M) = 0;
-};
-
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h
deleted file mode 100644
index 6d85e5fe6a90..000000000000
--- a/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// GRCheckAPI.h - Simple API checks based on GRAuditor ------------*- 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 interface for building simple, path-sensitive checks
-// that are stateless and only emit warnings at errors that occur at
-// CallExpr or ObjCMessageExpr.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_GRAPICHECKS
-#define LLVM_CLANG_ANALYSIS_GRAPICHECKS
-
-#include "clang/Checker/PathSensitive/GRAuditor.h"
-
-namespace clang {
-
-class GRSimpleAPICheck : public GRAuditor {
-public:
- GRSimpleAPICheck() {}
- virtual ~GRSimpleAPICheck() {}
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h
deleted file mode 100644
index 1904835fbc34..000000000000
--- a/include/clang/Checker/PathSensitive/GRSubEngine.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//== GRSubEngine.h - Interface of the subengine of GRCoreEngine ----*- 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 interface of a subengine of the GRCoreEngine.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
-#define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
-
-#include "clang/Checker/PathSensitive/SVals.h"
-
-namespace clang {
-
-class AnalysisManager;
-class CFGBlock;
-class CFGElement;
-class ExplodedNode;
-class GRState;
-class GRStateManager;
-class GRBlockCounter;
-class GRStmtNodeBuilder;
-class GRBranchNodeBuilder;
-class GRIndirectGotoNodeBuilder;
-class GRSwitchNodeBuilder;
-class GREndPathNodeBuilder;
-class GRCallEnterNodeBuilder;
-class GRCallExitNodeBuilder;
-class LocationContext;
-class MemRegion;
-class Stmt;
-
-class GRSubEngine {
-public:
- virtual ~GRSubEngine() {}
-
- virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0;
-
- virtual AnalysisManager &getAnalysisManager() = 0;
-
- virtual GRStateManager &getStateManager() = 0;
-
- /// Called by GRCoreEngine. Used to generate new successor
- /// nodes by processing the 'effects' of a block-level statement.
- virtual void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder) = 0;
-
- /// Called by GRCoreEngine when start processing
- /// a CFGBlock. This method returns true if the analysis should continue
- /// exploring the given path, and false otherwise.
- virtual bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
- GRBlockCounter BC) = 0;
-
- /// Called by GRCoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a branch condition.
- virtual void ProcessBranch(const Stmt* Condition, const Stmt* Term,
- GRBranchNodeBuilder& builder) = 0;
-
- /// Called by GRCoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a computed goto jump.
- virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) = 0;
-
- /// Called by GRCoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a switch statement.
- virtual void ProcessSwitch(GRSwitchNodeBuilder& builder) = 0;
-
- /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
- /// nodes when the control reaches the end of a function.
- virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0;
-
- // Generate the entry node of the callee.
- virtual void ProcessCallEnter(GRCallEnterNodeBuilder &builder) = 0;
-
- // Generate the first post callsite node.
- virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0;
-
- /// Called by ConstraintManager. Used to call checker-specific
- /// logic for handling assumptions on symbolic values.
- virtual const GRState* ProcessAssume(const GRState *state,
- SVal cond, bool assumption) = 0;
-
- /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
- /// region change should trigger a ProcessRegionChanges update.
- virtual bool WantsRegionChangeUpdate(const GRState* state) = 0;
-
- /// ProcessRegionChanges - Called by GRStateManager whenever a change is made
- /// to the store. Used to update checkers that track region values.
- virtual const GRState* ProcessRegionChanges(const GRState* state,
- const MemRegion* const *Begin,
- const MemRegion* const *End) = 0;
-
- inline const GRState* ProcessRegionChange(const GRState* state,
- const MemRegion* MR) {
- return ProcessRegionChanges(state, &MR, &MR+1);
- }
-
- /// Called by GRCoreEngine when the analysis worklist is either empty or the
- // maximum number of analysis steps have been reached.
- virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0;
-};
-}
-
-#endif
diff --git a/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h
deleted file mode 100644
index 320b7f7b8abd..000000000000
--- a/include/clang/Checker/PathSensitive/GRTransferFuncs.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//== GRTransferFuncs.h - Path-Sens. Transfer Functions 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 GRTransferFuncs, which provides a base-class that
-// defines an interface for transfer functions used by GRExprEngine.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_GRTF
-#define LLVM_CLANG_ANALYSIS_GRTF
-
-#include "clang/Checker/PathSensitive/GRState.h"
-#include "clang/Checker/PathSensitive/SVals.h"
-#include <vector>
-
-namespace clang {
-class ExplodedNode;
-class ExplodedNodeSet;
-class GREndPathNodeBuilder;
-class GRExprEngine;
-class GRStmtNodeBuilder;
-class GRStmtNodeBuilderRef;
-class ObjCMessageExpr;
-
-class GRTransferFuncs {
-public:
- GRTransferFuncs() {}
- virtual ~GRTransferFuncs() {}
-
- virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
- virtual void RegisterChecks(GRExprEngine& Eng) {}
-
-
- // Calls.
-
- virtual void EvalCall(ExplodedNodeSet& Dst,
- GRExprEngine& Engine,
- GRStmtNodeBuilder& Builder,
- const CallExpr* CE, SVal L,
- ExplodedNode* Pred) {}
-
- virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
- GRExprEngine& Engine,
- GRStmtNodeBuilder& Builder,
- const ObjCMessageExpr* ME,
- ExplodedNode* Pred,
- const GRState *state) {}
-
- // Stores.
-
- virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {}
-
- // End-of-path and dead symbol notification.
-
- virtual void EvalEndPath(GRExprEngine& Engine,
- GREndPathNodeBuilder& Builder) {}
-
-
- virtual void EvalDeadSymbols(ExplodedNodeSet& Dst,
- GRExprEngine& Engine,
- GRStmtNodeBuilder& Builder,
- ExplodedNode* Pred,
- const GRState* state,
- SymbolReaper& SymReaper) {}
-
- // Return statements.
- virtual void EvalReturn(ExplodedNodeSet& Dst,
- GRExprEngine& Engine,
- GRStmtNodeBuilder& Builder,
- const ReturnStmt* S,
- ExplodedNode* Pred) {}
-
- // Assumptions.
- virtual const GRState* EvalAssume(const GRState *state,
- SVal Cond, bool Assumption) {
- return state;
- }
-};
-} // end clang namespace
-
-#endif
diff --git a/include/clang/Checker/PathSensitive/GRWorkList.h b/include/clang/Checker/PathSensitive/GRWorkList.h
deleted file mode 100644
index 315b614043d4..000000000000
--- a/include/clang/Checker/PathSensitive/GRWorkList.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//==- GRWorkList.h - Worklist class used by GRCoreEngine -----------*- 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 GRWorkList, a pure virtual class that represents an opaque
-// worklist used by GRCoreEngine to explore the reachability state space.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_GRWORKLIST
-#define LLVM_CLANG_ANALYSIS_GRWORKLIST
-
-#include "clang/Checker/PathSensitive/GRBlockCounter.h"
-#include <cstddef>
-
-namespace clang {
-
-class CFGBlock;
-class ExplodedNode;
-class ExplodedNodeImpl;
-
-class GRWorkListUnit {
- ExplodedNode* Node;
- GRBlockCounter Counter;
- const CFGBlock* Block;
- unsigned BlockIdx; // This is the index of the next statement.
-
-public:
- GRWorkListUnit(ExplodedNode* N, GRBlockCounter C,
- const CFGBlock* B, unsigned idx)
- : Node(N),
- Counter(C),
- Block(B),
- BlockIdx(idx) {}
-
- explicit GRWorkListUnit(ExplodedNode* N, GRBlockCounter C)
- : Node(N),
- Counter(C),
- Block(NULL),
- BlockIdx(0) {}
-
- ExplodedNode* getNode() const { return Node; }
- GRBlockCounter getBlockCounter() const { return Counter; }
- const CFGBlock* getBlock() const { return Block; }
- unsigned getIndex() const { return BlockIdx; }
-};
-
-class GRWorkList {
- GRBlockCounter CurrentCounter;
-public:
- virtual ~GRWorkList();
- virtual bool hasWork() const = 0;
-
- virtual void Enqueue(const GRWorkListUnit& U) = 0;
-
- void Enqueue(ExplodedNode* N, const CFGBlock* B, unsigned idx) {
- Enqueue(GRWorkListUnit(N, CurrentCounter, B, idx));
- }
-
- void Enqueue(ExplodedNode* N) {
- Enqueue(GRWorkListUnit(N, CurrentCounter));
- }
-
- virtual GRWorkListUnit Dequeue() = 0;
-
- void setBlockCounter(GRBlockCounter C) { CurrentCounter = C; }
- GRBlockCounter getBlockCounter() const { return CurrentCounter; }
-
- static GRWorkList *MakeDFS();
- static GRWorkList *MakeBFS();
- static GRWorkList *MakeBFSBlockDFSContents();
-};
-} // end clang namespace
-#endif
diff --git a/include/clang/Checker/PathSensitive/SValuator.h b/include/clang/Checker/PathSensitive/SValuator.h
deleted file mode 100644
index 9192ca7b8614..000000000000
--- a/include/clang/Checker/PathSensitive/SValuator.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// SValuator.h - Construction of SVals from evaluating expressions -*- 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 SValuator, a class that defines the interface for
-// "symbolical evaluators" which construct an SVal from an expression.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_SVALUATOR
-#define LLVM_CLANG_ANALYSIS_SVALUATOR
-
-#include "clang/AST/Expr.h"
-#include "clang/Checker/PathSensitive/SVals.h"
-
-namespace clang {
-
-class GRState;
-class ValueManager;
-
-class SValuator {
- friend class ValueManager;
-protected:
- ValueManager &ValMgr;
-
-public:
- // FIXME: Make these protected again one RegionStoreManager correctly
- // handles loads from differening bound value types.
- virtual SVal EvalCastNL(NonLoc val, QualType castTy) = 0;
- virtual SVal EvalCastL(Loc val, QualType castTy) = 0;
-
-public:
- SValuator(ValueManager &valMgr) : ValMgr(valMgr) {}
- virtual ~SValuator() {}
-
- SVal EvalCast(SVal V, QualType castTy, QualType originalType);
-
- virtual SVal EvalMinus(NonLoc val) = 0;
-
- virtual SVal EvalComplement(NonLoc val) = 0;
-
- virtual SVal EvalBinOpNN(const GRState *state, BinaryOperator::Opcode Op,
- NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
-
- virtual SVal EvalBinOpLL(const GRState *state, BinaryOperator::Opcode Op,
- Loc lhs, Loc rhs, QualType resultTy) = 0;
-
- virtual SVal EvalBinOpLN(const GRState *state, BinaryOperator::Opcode Op,
- Loc lhs, NonLoc rhs, QualType resultTy) = 0;
-
- /// getKnownValue - Evaluates a given SVal. If the SVal has only one possible
- /// (integer) value, that value is returned. Otherwise, returns NULL.
- virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V) = 0;
-
- SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
- SVal L, SVal R, QualType T);
-
- DefinedOrUnknownSVal EvalEQ(const GRState *ST, DefinedOrUnknownSVal L,
- DefinedOrUnknownSVal R);
-};
-
-SValuator* CreateSimpleSValuator(ValueManager &valMgr);
-
-} // end clang namespace
-#endif
diff --git a/include/clang/CodeGen/CodeGenAction.h b/include/clang/CodeGen/CodeGenAction.h
index cecfcda461bb..052c6603f5a7 100644
--- a/include/clang/CodeGen/CodeGenAction.h
+++ b/include/clang/CodeGen/CodeGenAction.h
@@ -14,18 +14,25 @@
#include "llvm/ADT/OwningPtr.h"
namespace llvm {
+ class LLVMContext;
class Module;
}
namespace clang {
+class BackendConsumer;
class CodeGenAction : public ASTFrontendAction {
private:
unsigned Act;
llvm::OwningPtr<llvm::Module> TheModule;
+ llvm::LLVMContext *VMContext;
+ bool OwnsVMContext;
protected:
- CodeGenAction(unsigned _Act);
+ /// Create a new code generation action. If the optional \arg _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);
virtual bool hasIRSupport() const;
@@ -42,36 +49,41 @@ public:
/// takeModule - Take the generated LLVM module, for use after the action has
/// been run. The result may be null on failure.
llvm::Module *takeModule();
+
+ /// Take the LLVM context used by this action.
+ llvm::LLVMContext *takeLLVMContext();
+
+ BackendConsumer *BEConsumer;
};
class EmitAssemblyAction : public CodeGenAction {
public:
- EmitAssemblyAction();
+ EmitAssemblyAction(llvm::LLVMContext *_VMContext = 0);
};
class EmitBCAction : public CodeGenAction {
public:
- EmitBCAction();
+ EmitBCAction(llvm::LLVMContext *_VMContext = 0);
};
class EmitLLVMAction : public CodeGenAction {
public:
- EmitLLVMAction();
+ EmitLLVMAction(llvm::LLVMContext *_VMContext = 0);
};
class EmitLLVMOnlyAction : public CodeGenAction {
public:
- EmitLLVMOnlyAction();
+ EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = 0);
};
class EmitCodeGenOnlyAction : public CodeGenAction {
public:
- EmitCodeGenOnlyAction();
+ EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = 0);
};
class EmitObjAction : public CodeGenAction {
public:
- EmitObjAction();
+ EmitObjAction(llvm::LLVMContext *_VMContext = 0);
};
}
diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake
new file mode 100644
index 000000000000..5f13d2faa311
--- /dev/null
+++ b/include/clang/Config/config.h.cmake
@@ -0,0 +1,17 @@
+/* Relative directory for resource files */
+#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}"
+
+/* 32 bit multilib directory. */
+#define CXX_INCLUDE_32BIT_DIR "${CXX_INCLUDE_32BIT_DIR}"
+
+/* 64 bit multilib directory. */
+#define CXX_INCLUDE_64BIT_DIR "${CXX_INCLUDE_64BIT_DIR}"
+
+/* Arch the libstdc++ headers. */
+#define CXX_INCLUDE_ARCH "${CXX_INCLUDE_ARCH}"
+
+/* Directory with the libstdc++ headers. */
+#define CXX_INCLUDE_ROOT "${CXX_INCLUDE_ROOT}"
+
+/* Directories clang will search for headers */
+#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h
index 257b653f57e6..0fcf821c752c 100644
--- a/include/clang/Driver/ArgList.h
+++ b/include/clang/Driver/ArgList.h
@@ -288,7 +288,7 @@ namespace driver {
unsigned NumInputArgStrings;
public:
- InputArgList(const char **ArgBegin, const char **ArgEnd);
+ InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
~InputArgList();
virtual const char *getArgString(unsigned Index) const {
diff --git a/include/clang/Driver/CC1AsOptions.td b/include/clang/Driver/CC1AsOptions.td
index 5c08dc630551..50472ffdf9cd 100644
--- a/include/clang/Driver/CC1AsOptions.td
+++ b/include/clang/Driver/CC1AsOptions.td
@@ -46,6 +46,7 @@ def _help : Flag<"--help">, Alias<help>;
def version : Flag<"-version">,
HelpText<"Print the assembler version">;
def _version : Flag<"--version">, Alias<version>;
+def v : Flag<"-v">, Alias<version>;
// Generic forwarding to LLVM options. This should only be used for debugging
// and experimental features.
@@ -69,3 +70,6 @@ def show_inst : Flag<"-show-inst">,
def relax_all : Flag<"-relax-all">,
HelpText<"Relax all fixups (for performance testing)">;
+
+def no_exec_stack : Flag<"--noexecstack">,
+ HelpText<"Mark the file as not needing an executable stack">; \ No newline at end of file
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index fd40aa0c5f4b..a2c69f99540e 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -36,34 +36,20 @@ def triple_EQ : Joined<"-triple=">, Alias<triple>;
// Analyzer Options
//===----------------------------------------------------------------------===//
-def analysis_CFGDump : Flag<"-cfg-dump">,
- HelpText<"Display Control-Flow Graphs">;
-def analysis_CFGView : Flag<"-cfg-view">,
- HelpText<"View Control-Flow Graphs using GraphViz">;
def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">,
HelpText<"Generate unoptimized CFGs for all analyses">;
-def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">,
- HelpText<"Print results of live variable analysis">;
-def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">,
- HelpText<"Check code for LLVM codebase conventions (domain-specific)">;
-def analysis_SecuritySyntacticChecks : Flag<"-analyzer-check-security-syntactic">,
- HelpText<"Perform quick security checks that require no data flow">;
-def analysis_WarnDeadStores : Flag<"-analyzer-check-dead-stores">,
- HelpText<"Warn about stores to dead variables">;
+def analysis_CFGAddImplicitDtors : Flag<"-cfg-add-implicit-dtors">,
+ HelpText<"Add C++ implicit destructors to CFGs for all analyses">;
+def analysis_CFGAddInitializers : Flag<"-cfg-add-initializers">,
+ HelpText<"Add C++ initializers to CFGs for all analyses">;
def analysis_WarnUninitVals : Flag<"-warn-uninit-values">,
HelpText<"Warn about uses of uninitialized variables">;
-def analysis_WarnObjCMethSigs : Flag<"-analyzer-check-objc-methodsigs">,
- HelpText<"Warn about Objective-C method signatures with type incompatibilities">;
-def analysis_WarnObjCDealloc : Flag<"-analyzer-check-objc-missing-dealloc">,
- HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">;
-def analysis_WarnObjCUnusedIvars : Flag<"-analyzer-check-objc-unused-ivars">,
- HelpText<"Warn about private ivars that are never used">;
def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">,
HelpText<"Run the [Core] Foundation reference count checker">;
-def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
- HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
-def analysis_WarnIdempotentOps : Flag<"-analyzer-check-idempotent-operations">,
- HelpText<"Warn about idempotent operations">;
+def analysis_AnalyzerStats : Flag<"-analyzer-stats">,
+ HelpText<"Emit warnings with analyzer statistics">;
+def analysis_WarnBufferOverflows : Flag<"-analyzer-check-buffer-overflows">,
+ HelpText<"Warn about buffer overflows">;
def analyzer_store : Separate<"-analyzer-store">,
HelpText<"Source Code Analysis - Abstract Memory Store Models">;
@@ -82,7 +68,7 @@ def analyzer_output_EQ : Joined<"-analyzer-output=">,
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">,
- HelpText<"Analyze the definitions of blocks in addition to functions">;
+ HelpText<"Analyze the definitions of blocks in addition to functions">;
def analyzer_display_progress : Flag<"-analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
@@ -97,6 +83,8 @@ def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">,
HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
def analyzer_no_purge_dead : Flag<"-analyzer-no-purge-dead">,
HelpText<"Don't remove dead symbols, bindings, and constraints before processing a statement">;
+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">,
HelpText<"Only show error-related paths in the analysis graph">;
def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">,
@@ -106,10 +94,20 @@ def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">,
def analyzer_inline_call : Flag<"-analyzer-inline-call">,
HelpText<"Experimental transfer function inlining callees when its definition is available.">;
def analyzer_max_nodes : Separate<"-analyzer-max-nodes">,
- HelpText<"The maximum number of nodes the analyzer can generate">;
+ HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">;
def analyzer_max_loop : Separate<"-analyzer-max-loop">,
HelpText<"The maximum number of times the analyzer will go through a loop">;
+def analyzer_checker : Separate<"-analyzer-checker">,
+ HelpText<"Choose analyzer checkers to enable">;
+def analyzer_checker_EQ : Joined<"-analyzer-checker=">,
+ Alias<analyzer_checker>;
+
+def analyzer_disable_checker : Separate<"-analyzer-disable-checker">,
+ HelpText<"Choose analyzer checkers to disable">;
+def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">,
+ Alias<analyzer_disable_checker>;
+
//===----------------------------------------------------------------------===//
// CodeGen Options
//===----------------------------------------------------------------------===//
@@ -125,6 +123,8 @@ def dwarf_debug_flags : Separate<"-dwarf-debug-flags">,
def g : Flag<"-g">, HelpText<"Generate source level debug information">;
def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
HelpText<"Generate runtime checks for undefined behavior.">;
+def flimit_debug_info : Flag<"-flimit-debug-info">,
+ HelpText<"Limit debug information produced to reduce size of debug binary">;
def fno_common : Flag<"-fno-common">,
HelpText<"Compile common globals like normal definitions">;
def no_implicit_float : Flag<"-no-implicit-float">,
@@ -143,6 +143,8 @@ def fdata_sections : Flag<"-fdata-sections">,
HelpText<"Place each data in its own section (ELF Only)">;
def funroll_loops : Flag<"-funroll-loops">,
HelpText<"Turn on loop unroller">;
+def relaxed_aliasing : Flag<"-relaxed-aliasing">,
+ HelpText<"Turn off Type Based Alias Analysis">;
def masm_verbose : Flag<"-masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<"-mcode-model">,
@@ -161,6 +163,8 @@ def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">,
HelpText<"Omit frame pointer setup for leaf functions.">;
def msoft_float : Flag<"-msoft-float">,
HelpText<"Use software floating point">;
+def mregparm : Separate<"-mregparm">,
+ HelpText<"Limit the number of registers available for integer arguments">;
def mrelax_all : Flag<"-mrelax-all">,
HelpText<"Relax all machine instructions">;
def mrelocation_model : Separate<"-mrelocation-model">,
@@ -169,8 +173,11 @@ def munwind_tables : Flag<"-munwind-tables">,
HelpText<"Generate unwinding tables for all functions">;
def mconstructor_aliases : Flag<"-mconstructor-aliases">,
HelpText<"Emit complete constructors and destructors as aliases when possible">;
+def mms_bitfields : Flag<"-mms-bitfields">,
+ HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">;
def O : Joined<"-O">, HelpText<"Optimization level">;
def Os : Flag<"-Os">, HelpText<"Optimize for size">;
+def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
@@ -180,6 +187,10 @@ def dependency_file : Separate<"-dependency-file">,
HelpText<"Filename (or -) to write dependency output to">;
def sys_header_deps : Flag<"-sys-header-deps">,
HelpText<"Include system headers in dependency output">;
+def header_include_file : Separate<"-header-include-file">,
+ HelpText<"Filename (or -) to write header include output to">;
+def H : Flag<"-H">,
+ HelpText<"Show header includes and nesting depth">;
def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">;
def MT : Separate<"-MT">, HelpText<"Specify target for dependency">;
def MP : Flag<"-MP">,
@@ -203,7 +214,6 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">,
HelpText<"Do not include source line and caret with diagnostics">;
def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">,
HelpText<"Do not include fixit information in diagnostics">;
-def fdiagnostics_binary : Flag<"-fdiagnostics-binary">;
def w : Flag<"-w">, HelpText<"Suppress all warnings">;
def pedantic : Flag<"-pedantic">;
def pedantic_errors : Flag<"-pedantic-errors">;
@@ -221,7 +231,7 @@ def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
HelpText<"Print diagnostic name with mappable diagnostics">;
def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,
HelpText<"Print diagnostic category">;
-
+
def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">,
HelpText<"Set the tab stop distance.">;
def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">,
@@ -260,8 +270,6 @@ def remap_file : Separate<"-remap-file">,
HelpText<"Replace the contents of the <from> file with the contents of the <to> file">;
def code_completion_at_EQ : Joined<"-code-completion-at=">,
Alias<code_completion_at>;
-def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">,
- HelpText<"Don't use the \"debug\" code-completion print">;
def code_completion_macros : Flag<"-code-completion-macros">,
HelpText<"Include macros in code-completion results">;
def code_completion_patterns : Flag<"-code-completion-patterns">,
@@ -274,17 +282,16 @@ def help : Flag<"-help">,
HelpText<"Print this help text">;
def _help : Flag<"--help">, Alias<help>;
def x : Separate<"-x">, HelpText<"Input language type">;
-def cxx_inheritance_view : Separate<"-cxx-inheritance-view">,
- MetaVarName<"<class name>">,
- HelpText<"View C++ inheritance for a specified class">;
def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">;
def load : Separate<"-load">, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
def plugin : Separate<"-plugin">, MetaVarName<"<name>">,
- HelpText<"Use the named plugin action (use \"help\" to list available options)">;
-def plugin_arg : JoinedAndSeparate<"-plugin-arg-">,
+ HelpText<"Use the named plugin action instead of the default action (use \"help\" to list available options)">;
+def plugin_arg : JoinedAndSeparate<"-plugin-arg-">,
MetaVarName<"<name> <arg>">,
HelpText<"Pass <arg> to plugin <name>">;
+def add_plugin : Separate<"-add-plugin">, MetaVarName<"<name>">,
+ HelpText<"Use the named plugin action in addition to the default action">;
def resource_dir : Separate<"-resource-dir">,
HelpText<"The directory which holds the compiler resource files">;
def version : Flag<"-version">,
@@ -323,6 +330,8 @@ def ast_print_xml : Flag<"-ast-print-xml">,
HelpText<"Build ASTs and then print them in XML format">;
def ast_dump : Flag<"-ast-dump">,
HelpText<"Build ASTs and then debug dump them">;
+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">,
HelpText<"Build ASTs and view them with GraphViz">;
def boostcon : Flag<"-boostcon">,
@@ -359,6 +368,11 @@ def create_module : Flag<"-create-module">,
def import_module : Separate<"-import-module">,
HelpText<"Import a module definition file">;
+def working_directory : JoinedOrSeparate<"-working-directory">,
+ HelpText<"Resolve file paths relative to the specified directory">;
+def working_directory_EQ : Joined<"-working-directory=">,
+ Alias<working_directory>;
+
def relocatable_pch : Flag<"-relocatable-pch">,
HelpText<"Whether to build a relocatable precompiled header">;
def chained_pch : Flag<"-chained-pch">,
@@ -401,11 +415,13 @@ def femit_all_decls : Flag<"-femit-all-decls">,
HelpText<"Emit all declarations, even if unused">;
def fblocks : Flag<"-fblocks">,
HelpText<"enable the 'blocks' language feature">;
-def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
+def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
def fexceptions : Flag<"-fexceptions">,
HelpText<"Enable support for exception handling">;
def fsjlj_exceptions : Flag<"-fsjlj-exceptions">,
HelpText<"Use SjLj style exceptions">;
+def fno_objc_exceptions : Flag<"-fno-objc-exceptions">,
+ HelpText<"Disable Objective-C exceptions">;
def ffreestanding : Flag<"-ffreestanding">,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fgnu_runtime : Flag<"-fgnu-runtime">,
@@ -418,6 +434,8 @@ def fmath_errno : Flag<"-fmath-errno">,
HelpText<"Require math functions to indicate errors by setting errno">;
def fms_extensions : Flag<"-fms-extensions">,
HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
+def fmsc_version : Joined<"-fmsc-version=">,
+ HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">;
def fborland_extensions : Flag<"-fborland-extensions">,
HelpText<"Accept non-standard constructs supported by the Borland compiler">;
def main_file_name : Separate<"-main-file-name">,
@@ -431,7 +449,7 @@ def fno_operator_names : Flag<"-fno-operator-names">,
def fno_signed_char : Flag<"-fno-signed-char">,
HelpText<"Char is unsigned">;
def fno_spell_checking : Flag<"-fno-spell-checking">,
- HelpText<"Disable spell-checking">;
+ HelpText<"Disable spell-checking">;
def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">,
HelpText<"Don't use __cxa_atexit for calling destructors">;
def fconstant_string_class : Separate<"-fconstant-string-class">,
@@ -443,16 +461,21 @@ def fobjc_gc : Flag<"-fobjc-gc">,
HelpText<"Enable Objective-C garbage collection">;
def fobjc_gc_only : Flag<"-fobjc-gc-only">,
HelpText<"Use GC exclusively for Objective-C related memory management">;
+def fapple_kext : Flag<"-fapple-kext">,
+ HelpText<"Use Apple's kernel extensions ABI">;
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">,
+ HelpText<"enable the default synthesis of Objective-C properties">;
def print_ivar_layout : Flag<"-print-ivar-layout">,
HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">,
HelpText<"enable objective-c's nonfragile abi">;
-def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">,
- HelpText<"enable objective-c's enhanced nonfragile abi">;
def ftrapv : Flag<"-ftrapv">,
HelpText<"Trap on integer overflow">;
+def ftrapv_handler : Separate<"-ftrapv-handler">,
+ MetaVarName<"<function name>">,
+ HelpText<"Specify the function to be called on overflow.">;
def fwrapv : Flag<"-fwrapv">,
HelpText<"Treat signed integer overflow as two's complement">;
def pic_level : Separate<"-pic-level">,
@@ -465,8 +488,14 @@ def fno_rtti : Flag<"-fno-rtti">,
HelpText<"Disable generation of rtti information">;
def fno_validate_pch : Flag<"-fno-validate-pch">,
HelpText<"Disable validation of precompiled headers">;
+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">,
+ HelpText<"Emit error if a specific declaration is deserialized from PCH, for testing">;
def fshort_wchar : Flag<"-fshort-wchar">,
HelpText<"Force wchar_t to be a short unsigned int">;
+def fshort_enums : Flag<"-fshort-enums">,
+ HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
def static_define : Flag<"-static-define">,
HelpText<"Should __STATIC__ be defined">;
def stack_protector : Separate<"-stack-protector">,
@@ -477,6 +506,11 @@ def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">,
HelpText<"Give inline C++ member functions default visibility by default">;
def ftemplate_depth : Separate<"-ftemplate-depth">,
HelpText<"Maximum depth of recursive template instantiation">;
+def Wlarge_by_value_copy : Separate<"-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=">,
+ Alias<Wlarge_by_value_copy>;
def trigraphs : Flag<"-trigraphs">,
HelpText<"Process trigraph sequences">;
def fwritable_strings : Flag<"-fwritable-strings">,
@@ -516,6 +550,8 @@ def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">,
HelpText<"Set directory to include search path with prefix">;
def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">,
HelpText<"Set the system root directory (usually /)">;
+def cxx_system_include : Separate<"-cxx-system-include">,
+ HelpText<"Add a system #include directory for the C++ standard library">;
def v : Flag<"-v">, HelpText<"Enable verbose output">;
//===----------------------------------------------------------------------===//
@@ -543,7 +579,7 @@ def undef : Flag<"-undef">, MetaVarName<"<macro>">,
HelpText<"undef all system defines">;
def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">,
HelpText<"include a detailed record of preprocessing actions">;
-
+
//===----------------------------------------------------------------------===//
// Preprocessed Output Options
//===----------------------------------------------------------------------===//
@@ -558,5 +594,22 @@ def dM : Flag<"-dM">,
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dD : Flag<"-dD">,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
-def H : Flag<"-H">,
- HelpText<"Show header includes and nesting depth">;
+
+//===----------------------------------------------------------------------===//
+// OpenCL Options
+//===----------------------------------------------------------------------===//
+
+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">,
+ HelpText<"OpenCL only. Treat double precision floating-point constant as single precision constant.">;
+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">,
+ 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">,
+ 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">,
+ HelpText<"OpenCL only. Enable less precise MAD instructions to be generated.">;
+def cl_std_EQ : Joined<"-cl-std=">,
+ HelpText<"OpenCL language standard to compile for">;
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 28eff4f1d71d..03fa0ef972d0 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -17,7 +17,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/System/Path.h" // FIXME: Kill when CompilationInfo
+#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo
// lands.
#include <list>
#include <set>
@@ -74,7 +74,8 @@ public:
/// functionality.
/// FIXME: This type of customization should be removed in favor of the
/// universal driver when it is ready.
- std::string PrefixDir;
+ typedef llvm::SmallVector<std::string, 4> prefix_list;
+ prefix_list PrefixDirs;
/// Default host triple.
std::string DefaultHostTriple;
@@ -92,12 +93,12 @@ public:
/// Information about the host which can be overriden by the user.
std::string HostBits, HostMachine, HostSystem, HostRelease;
- /// Name to use when calling the generic gcc.
- std::string CCCGenericGCCName;
-
/// The file to log CC_PRINT_OPTIONS output to, if enabled.
const char *CCPrintOptionsFilename;
+ /// The file to log CC_PRINT_HEADERS output to, if enabled.
+ const char *CCPrintHeadersFilename;
+
/// Whether the driver should follow g++ like behavior.
unsigned CCCIsCXX : 1;
@@ -111,7 +112,14 @@ public:
/// CCPrintOptionsFilename or to stderr.
unsigned CCPrintOptions : 1;
+ /// Set CC_PRINT_HEADERS mode, which causes the frontend to log header include
+ /// information to CCPrintHeadersFilename or to stderr.
+ unsigned CCPrintHeaders : 1;
+
private:
+ /// Name to use when calling the generic gcc.
+ std::string CCCGenericGCCName;
+
/// Whether to check that input files exist when constructing compilation
/// jobs.
unsigned CheckInputsExist : 1;
@@ -157,6 +165,10 @@ public:
/// @name Accessors
/// @{
+ /// Name to use when calling the generic gcc.
+ const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }
+
+
const OptTable &getOpts() const { return *Opts; }
const Diagnostic &getDiags() const { return Diags; }
diff --git a/include/clang/Driver/DriverDiagnostic.h b/include/clang/Driver/DriverDiagnostic.h
index c20d807b5811..0733c51027d9 100644
--- a/include/clang/Driver/DriverDiagnostic.h
+++ b/include/clang/Driver/DriverDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define DRIVERSTART
#include "clang/Basic/DiagnosticDriverKinds.inc"
#undef DIAG
diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h
index 04e72992d684..7285a48b1cca 100644
--- a/include/clang/Driver/HostInfo.h
+++ b/include/clang/Driver/HostInfo.h
@@ -71,6 +71,8 @@ const HostInfo *createOpenBSDHostInfo(const Driver &D,
const llvm::Triple& Triple);
const HostInfo *createFreeBSDHostInfo(const Driver &D,
const llvm::Triple& Triple);
+const HostInfo *createNetBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
const HostInfo *createMinixHostInfo(const Driver &D,
const llvm::Triple& Triple);
const HostInfo *createDragonFlyHostInfo(const Driver &D,
diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h
index 08b483c90017..3befe1defba9 100644
--- a/include/clang/Driver/OptTable.h
+++ b/include/clang/Driver/OptTable.h
@@ -170,8 +170,8 @@ namespace options {
/// \param MissingArgCount - On error, the number of missing options.
/// \return - An InputArgList; on error this will contain all the options
/// which could be parsed.
- InputArgList *ParseArgs(const char **ArgBegin,
- const char **ArgEnd,
+ InputArgList *ParseArgs(const char* const *ArgBegin,
+ const char* const *ArgEnd,
unsigned &MissingArgIndex,
unsigned &MissingArgCount) const;
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index c51d12a48769..7e3ddc616e1c 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -38,6 +38,7 @@ def u_Group : OptionGroup<"<u group>">;
def pedantic_Group : OptionGroup<"<pedantic group>">,
Group<CompileOnly_Group>;
+def reserved_lib_Group : OptionGroup<"<reserved libs group>">;
// Temporary groups for clang options which we know we don't support,
// but don't want to verbosely warn the user about.
@@ -195,6 +196,7 @@ def allowable__client : Separate<"-allowable_client">;
def ansi : Flag<"-ansi">, Group<a_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<a_Group>;
def bind__at__load : Flag<"-bind_at_load">;
def bundle__loader : Separate<"-bundle_loader">;
@@ -213,7 +215,7 @@ def dD : Flag<"-dD">, Group<d_Group>;
def dM : Flag<"-dM">, Group<d_Group>;
def dead__strip : Flag<"-dead_strip">;
def dependency_file : Separate<"-dependency-file">;
-def dumpmachine : Flag<"-dumpmachine">, Flags<[Unsupported]>;
+def dumpmachine : Flag<"-dumpmachine">;
def dumpspecs : Flag<"-dumpspecs">, Flags<[Unsupported]>;
def dumpversion : Flag<"-dumpversion">;
def dylib__file : Separate<"-dylib_file">;
@@ -233,9 +235,13 @@ def fPIC : Flag<"-fPIC">, Group<f_Group>;
def fPIE : Flag<"-fPIE">, Group<f_Group>;
def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>;
def faccess_control : Flag<"-faccess-control">, Group<f_Group>;
+def fallow_unsupported : Flag<"-fallow-unsupported">, Group<f_Group>;
def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>;
def fasm : Flag<"-fasm">, Group<f_Group>;
-def fasm_blocks : Flag<"-fasm-blocks">, Group<clang_ignored_f_Group>;
+
+def fasm_blocks : Flag<"-fasm-blocks">, Group<f_Group>;
+def fno_asm_blocks : Flag<"-fno-asm-blocks">, Group<f_Group>;
+
def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group<f_Group>;
def fastcp : Flag<"-fastcp">, Group<f_Group>;
def fastf : Flag<"-fastf">, Group<f_Group>;
@@ -259,13 +265,13 @@ def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group<f_Grou
def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>;
def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>;
def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>;
-def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>;
def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>;
def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_Group>;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>;
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>;
+def felide_constructors : Flag<"-felide-constructors">, Group<f_Group>;
def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>;
def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>;
def fencoding_EQ : Joined<"-fencoding=">, Group<f_Group>;
@@ -274,6 +280,10 @@ def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>;
def fhosted : Flag<"-fhosted">, Group<f_Group>;
def ffast_math : Flag<"-ffast-math">, Group<clang_ignored_f_Group>;
def ffinite_math_only : Flag<"-ffinite-math-only">, Group<clang_ignored_f_Group>;
+
+def ffor_scope : Flag<"-ffor-scope">, Group<f_Group>;
+def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>;
+
def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>;
def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>;
def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>;
@@ -286,14 +296,17 @@ def finstrument_functions : Flag<"-finstrument-functions">, Group<f_Group>;
def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group<clang_ignored_f_Group>;
def flat__namespace : Flag<"-flat_namespace">;
def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>;
+def flimit_debug_info : Flag<"-flimit-debug-info">, Group<f_Group>,
+ HelpText<"Limit debug information produced to reduce size of debug binary">;
def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>;
def flto : Flag<"-flto">, Group<f_Group>;
-def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">,
+def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">,
Group<f_Group>;
def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>;
def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>;
def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>;
def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>;
+def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>;
def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>;
def fmudflap : Flag<"-fmudflap">, Group<f_Group>;
def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>;
@@ -314,6 +327,7 @@ def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>;
def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>;
def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>;
def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>;
+def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>;
def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>;
def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>;
def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<clang_ignored_f_Group>;
@@ -325,15 +339,19 @@ def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Gr
def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>;
def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>;
def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>;
+def fno_objc_default_synthesize_properties
+ : Flag<"-fno-objc-default-synthesize-properties">, Group<f_Group>;
+def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group<f_Group>;
def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group<f_Group>;
def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group<f_Group>;
def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>;
def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>;
+def fno_short_enums : Flag<"-fno-short-enums">, Group<f_Group>;
def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>;
def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>;
def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>;
def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>;
-def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<clang_ignored_f_Group>;
+def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<f_Group>;
def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>;
def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>;
def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>;
@@ -341,15 +359,23 @@ def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>;
def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>;
def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>;
def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>;
-def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>;
def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>;
def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>;
+def fobjc_default_synthesize_properties :
+ Flag<"-fobjc-default-synthesize-properties">, Group<f_Group>;
+def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group<f_Group>;
+
def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>;
def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>;
def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>;
def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>;
+
+// Objective-C ABI options.
+def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>;
+def fobjc_nonfragile_abi_version_EQ : Joined<"-fobjc-nonfragile-abi-version=">, Group<f_Group>;
def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group<f_Group>;
-def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, Group<f_Group>;
+def fno_objc_nonfragile_abi : Flag<"-fno-objc-nonfragile-abi">, Group<f_Group>;
+
def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, Group<f_Group>;
def fobjc : Flag<"-fobjc">, Group<f_Group>;
def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group<f_Group>;
@@ -368,7 +394,7 @@ def framework : Separate<"-framework">, Flags<[LinkerInput]>;
def frandom_seed_EQ : Joined<"-frandom-seed=">, Group<clang_ignored_f_Group>;
def frtti : Flag<"-frtti">, Group<f_Group>;
def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>;
-def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>;
+def fshort_enums : Flag<"-fshort-enums">, Group<f_Group>;
def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>;
def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>;
def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>;
@@ -378,17 +404,20 @@ def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>;
def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>;
def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>;
def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>;
-def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<clang_ignored_f_Group>;
+def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<f_Group>;
def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>;
def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>;
def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>;
def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>;
-def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
+def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
Group<f_Group>;
+def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">;
+def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">;
def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>;
def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
def ftime_report : Flag<"-ftime-report">, Group<f_Group>;
def ftrapv : Flag<"-ftrapv">, Group<f_Group>;
+def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>;
def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>;
def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>;
def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>;
@@ -417,6 +446,7 @@ def iframework : JoinedOrSeparate<"-iframework">, Group<clang_i_Group>;
def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>;
def image__base : Separate<"-image_base">;
def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">;
+def include_pch : Separate<"-include-pch">, Group<clang_i_Group>;
def init : Separate<"-init">;
def install__name : Separate<"-install_name">;
def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>;
@@ -450,6 +480,7 @@ def mkernel : Flag<"-mkernel">, Group<m_Group>;
def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>;
def mllvm : Separate<"-mllvm">;
def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>;
+def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>;
def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>;
def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>;
def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>;
@@ -478,6 +509,7 @@ def mno_omit_leaf_frame_pointer : Flag<"-mno-omit-leaf-frame-pointer">, Group<f_
def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>;
def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>;
def mred_zone : Flag<"-mred-zone">, Group<m_Group>;
+def mregparm_EQ : Joined<"-mregparm=">, Group<m_Group>;
def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>;
def msoft_float : Flag<"-msoft-float">, Group<m_Group>;
def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>;
@@ -544,10 +576,12 @@ def private__bundle : Flag<"-private_bundle">;
def pthreads : Flag<"-pthreads">;
def pthread : Flag<"-pthread">;
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]>,
HelpText<"Rewrite Objective-C source to C++">;
+def rdynamic : Flag<"-rdynamic">;
def rpath : Separate<"-rpath">, Flags<[LinkerInput]>;
def r : Flag<"-r">;
def save_temps : Flag<"-save-temps">, Flags<[DriverOption]>,
@@ -575,6 +609,7 @@ def static_libgcc : Flag<"-static-libgcc">;
def static : Flag<"-static">, Flags<[NoArgumentUnused]>;
def std_default_EQ : Joined<"-std-default=">;
def std_EQ : Joined<"-std=">;
+def stdlib_EQ : Joined<"-stdlib=">;
def sub__library : JoinedOrSeparate<"-sub_library">;
def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">;
def s : Flag<"-s">;
@@ -591,6 +626,7 @@ def undefined : JoinedOrSeparate<"-undefined">, Group<u_Group>;
def undef : Flag<"-undef">, Group<u_Group>;
def unexported__symbols__list : Separate<"-unexported_symbols_list">;
def u : JoinedOrSeparate<"-u">, Group<u_Group>;
+def use_gold_plugin : Flag<"-use-gold-plugin">;
def v : Flag<"-v">,
HelpText<"Show commands to run and use verbose output">;
def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>;
@@ -605,6 +641,11 @@ def x : JoinedOrSeparate<"-x">, Flags<[DriverOption]>,
MetaVarName<"<language>">;
def y : Joined<"-y">;
+def working_directory : Separate<"-working-directory">,
+ HelpText<"Resolve file paths relative to the specified directory">;
+def working_directory_EQ : Joined<"-working-directory=">,
+ Alias<working_directory>;
+
// Double dash options, which are usually an alias for one of the previous
// options.
@@ -719,6 +760,8 @@ def _specs : Separate<"--specs">, Alias<specs_EQ>;
def _static : Flag<"--static">, Alias<static>;
def _std_EQ : Joined<"--std=">, Alias<std_EQ>;
def _std : Separate<"--std">, Alias<std_EQ>;
+def _stdlib_EQ : Joined<"--stdlib=">, Alias<std_EQ>;
+def _stdlib : Separate<"--stdlib">, Alias<std_EQ>;
def _sysroot_EQ : Joined<"--sysroot=">;
def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>;
def _target_help : Flag<"--target-help">;
@@ -739,4 +782,15 @@ def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias<MMD>;
def _ : Joined<"--">, Flags<[Unsupported]>;
// Special internal option to handle -Xlinker --no-demangle.
-def Z_Xlinker__no_demangle : Flag<"-Z-Xlinker-no-demangle">, Flags<[Unsupported]>;
+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">,
+ Flags<[Unsupported, NoArgumentUnused]>;
+
+// Reserved library options.
+def Z_reserved_lib_stdcxx : Flag<"-Z-reserved-lib-stdc++">,
+ Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
+def Z_reserved_lib_cckext : Flag<"-Z-reserved-lib-cckext">,
+ Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 55be4eee3d19..f0012bd851eb 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -10,10 +10,11 @@
#ifndef CLANG_DRIVER_TOOLCHAIN_H_
#define CLANG_DRIVER_TOOLCHAIN_H_
+#include "clang/Driver/Util.h"
#include "clang/Driver/Types.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/System/Path.h"
+#include "llvm/Support/Path.h"
#include <string>
namespace clang {
@@ -32,6 +33,11 @@ class ToolChain {
public:
typedef llvm::SmallVector<std::string, 4> path_list;
+ enum CXXStdlibType {
+ CST_Libcxx,
+ CST_Libstdcxx
+ };
+
private:
const HostInfo &Host;
const llvm::Triple Triple;
@@ -92,6 +98,10 @@ public:
// Platform defaults information
+ /// HasNativeLTOLinker - Check whether the linker and related tools have
+ /// native LLVM support.
+ virtual bool HasNativeLLVMSupport() const;
+
/// LookupTypeForExtension - Return the default language type to use for the
/// given extension.
virtual types::ID LookupTypeForExtension(const char *Ext) const;
@@ -103,6 +113,14 @@ public:
/// by default.
virtual bool IsIntegratedAssemblerDefault() const { return false; }
+ /// IsStrictAliasingDefault - Does this tool chain use -fstrict-aliasing by
+ /// default.
+ virtual bool IsStrictAliasingDefault() const { return true; }
+
+ /// IsObjCDefaultSynthPropertiesDefault - Does this tool chain enable
+ /// -fobjc-default-synthesize-properties by default.
+ virtual bool IsObjCDefaultSynthPropertiesDefault() const { return false; }
+
/// IsObjCNonFragileABIDefault - Does this tool chain set
/// -fobjc-nonfragile-abi by default.
virtual bool IsObjCNonFragileABIDefault() const { return false; }
@@ -153,6 +171,25 @@ public:
/// sets the deployment target) determines the version in the triple passed to
/// Clang.
virtual std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
+ // GetCXXStdlibType - Determine the C++ standard library type to use with the
+ // given compilation arguments.
+ virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
+
+ /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set
+ /// the include paths to use for the given C++ standard library type.
+ virtual void AddClangCXXStdlibIncludeArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use
+ /// for the given C++ standard library type.
+ virtual void AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// AddCCKextLibArgs - Add the system specific linker arguments to use
+ /// for kernel extensions (Darwin-specific).
+ virtual void AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
};
} // end namespace driver
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index 06a8690ce833..f09a1dcaf26f 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -42,6 +42,7 @@
TYPE("cpp-output", PP_C, INVALID, "i", "u")
TYPE("c", C, PP_C, 0, "u")
TYPE("cl", CL, PP_C, 0, "u")
+TYPE("cuda", CUDA, PP_CXX, 0, "u")
TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
TYPE("objective-c", ObjC, PP_ObjC, 0, "u")
TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u")
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index cca243d6cd71..c45bd4070600 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -18,8 +18,6 @@
namespace llvm {
class raw_ostream;
- class Module;
- class LLVMContext;
namespace sys { class Path; }
}
namespace clang {
@@ -48,6 +46,10 @@ ASTConsumer *CreateASTPrinterXML(llvm::raw_ostream *OS);
// intended for debugging.
ASTConsumer *CreateASTDumper();
+// AST XML-dumper: dumps out the AST to stderr in a very detailed XML
+// format; this is intended for particularly intense debugging.
+ASTConsumer *CreateASTDumperXML(llvm::raw_ostream &OS);
+
// Graphical AST viewer: for each function definition, creates a graph of
// the AST and displays it with the graph viewer "dotty". Also outputs
// function declarations to stderr.
@@ -57,10 +59,6 @@ ASTConsumer *CreateASTViewer();
// to stderr; this is intended for debugging.
ASTConsumer *CreateDeclContextPrinter();
-// Inheritance viewer: for C++ code, creates a graph of the inheritance
-// tree for the given class and displays it with "dotty".
-ASTConsumer *CreateInheritanceViewer(const std::string& clsname);
-
} // end clang namespace
#endif
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index e3fd4b37edac..e93563311b85 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -21,13 +21,13 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "clang-c/Index.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/System/Path.h"
-#include "llvm/Support/Timer.h"
+#include "llvm/Support/Path.h"
#include <map>
#include <string>
#include <vector>
@@ -54,6 +54,14 @@ class TargetInfo;
using namespace idx;
+/// \brief Allocator for a cached set of global code completions.
+class GlobalCodeCompletionAllocator
+ : public CodeCompletionAllocator,
+ public llvm::RefCountedBase<GlobalCodeCompletionAllocator>
+{
+
+};
+
/// \brief Utility class for loading a ASTContext from an AST file.
///
class ASTUnit {
@@ -69,7 +77,9 @@ private:
llvm::OwningPtr<TargetInfo> Target;
llvm::OwningPtr<Preprocessor> PP;
llvm::OwningPtr<ASTContext> Ctx;
-
+
+ FileSystemOptions FileSystemOpts;
+
/// \brief The AST consumer that received information about the translation
/// unit as it was parsed or loaded.
llvm::OwningPtr<ASTConsumer> Consumer;
@@ -82,6 +92,13 @@ private:
/// LoadFromCommandLine available.
llvm::OwningPtr<CompilerInvocation> 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<std::string> 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.
@@ -89,13 +106,16 @@ private:
/// \brief Whether to capture any diagnostics produced.
bool CaptureDiagnostics;
-
+
/// \brief Track whether the main file was loaded from an AST or not.
bool MainFileIsAST;
/// \brief Whether this AST represents a complete translation unit.
bool CompleteTranslationUnit;
+ /// \brief Whether we should time each operation.
+ bool WantTiming;
+
/// Track the top-level decls which appeared in an ASTUnit which was loaded
/// from a source file.
//
@@ -105,6 +125,14 @@ private:
// more scalable search mechanisms.
std::vector<Decl*> TopLevelDecls;
+ /// \brief The list of preprocessed entities which appeared when the ASTUnit
+ /// was loaded.
+ ///
+ /// FIXME: This is just an optimization hack to avoid deserializing large
+ /// parts of a PCH file while performing a walk or search. In the long term,
+ /// we should provide more scalable search mechanisms.
+ std::vector<PreprocessedEntity *> PreprocessedEntities;
+
/// The name of the original source file used to generate this ASTUnit.
std::string OriginalSourceFile;
@@ -115,6 +143,13 @@ private:
/// translation unit.
llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
+ /// \brief The number of stored diagnostics that come from the driver
+ /// itself.
+ ///
+ /// Diagnostics that come from the driver are retained from one parse to
+ /// the next.
+ unsigned NumStoredDiagnosticsFromDriver;
+
/// \brief Temporary files that should be removed when the ASTUnit is
/// destroyed.
llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles;
@@ -199,22 +234,21 @@ private:
/// a precompiled preamble.
unsigned NumStoredDiagnosticsInPreamble;
- /// \brief The group of timers associated with this translation unit.
- llvm::OwningPtr<llvm::TimerGroup> TimerGroup;
-
/// \brief A list of the serialization ID numbers for each of the top-level
/// declarations parsed within the precompiled preamble.
std::vector<serialization::DeclID> TopLevelDeclsInPreamble;
- ///
- /// \defgroup CodeCompleteCaching Code-completion caching
- ///
- /// \{
- ///
-
+ /// \brief A list of the offsets into the precompiled preamble which
+ /// correspond to preprocessed entities.
+ std::vector<uint64_t> PreprocessedEntitiesInPreamble;
+
/// \brief Whether we should be caching code-completion results.
bool ShouldCacheCodeCompletionResults;
+ static void ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags,
+ const char **ArgBegin, const char **ArgEnd,
+ ASTUnit &AST, bool CaptureDiagnostics);
+
public:
/// \brief A cached code-completion result, which may be introduced in one of
/// many different contexts.
@@ -261,7 +295,17 @@ public:
return CachedCompletionTypes;
}
+ /// \brief Retrieve the allocator used to cache global code completions.
+ llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+ getCachedCompletionAllocator() {
+ return CachedCompletionAllocator;
+ }
+
private:
+ /// \brief Allocator used to store cached code completions.
+ llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+ CachedCompletionAllocator;
+
/// \brief The set of cached code-completion results.
std::vector<CachedCodeCompletionResult> CachedCompletionResults;
@@ -269,20 +313,24 @@ private:
/// type, which is used for type equality comparisons.
llvm::StringMap<unsigned> CachedCompletionTypes;
- /// \brief The number of top-level declarations present the last time we
- /// cached code-completion results.
+ /// \brief A string hash of the top-level declaration and macro definition
+ /// names processed the last time that we reparsed the file.
///
- /// The value is used to help detect when we should repopulate the global
- /// completion cache.
- unsigned NumTopLevelDeclsAtLastCompletionCache;
+ /// This hash value is used to determine when we need to refresh the
+ /// global code-completion cache.
+ unsigned CompletionCacheTopLevelHashValue;
- /// \brief The number of reparses left until we'll consider updating the
- /// code-completion cache.
+ /// \brief A string hash of the top-level declaration and macro definition
+ /// names processed the last time that we reparsed the precompiled preamble.
///
- /// This is meant to avoid thrashing during reparsing, by not allowing the
- /// code-completion cache to be updated on every reparse.
- unsigned CacheCodeCompletionCoolDown;
+ /// This hash value is used to determine when we need to refresh the
+ /// global code-completion cache after a rebuild of the precompiled preamble.
+ unsigned PreambleTopLevelHashValue;
+ /// \brief The current hash value for the top-level declaration and macro
+ /// definition names
+ unsigned CurrentTopLevelHashValue;
+
/// \brief Bit used by CIndex to mark when a translation unit may be in an
/// inconsistent state, and is not safe to free.
unsigned UnsafeToFree : 1;
@@ -294,14 +342,6 @@ private:
/// \brief Clear out and deallocate
void ClearCachedCompletionResults();
- ///
- /// \}
- ///
-
- /// \brief The timers we've created from the various parses, reparses, etc.
- /// involved in this translation unit.
- std::vector<llvm::Timer *> Timers;
-
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
@@ -319,7 +359,8 @@ private:
bool AllowRebuild = true,
unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble();
-
+ void RealizePreprocessedEntitiesFromPreamble();
+
public:
class ConcurrencyCheck {
volatile ASTUnit &Self;
@@ -367,6 +408,8 @@ public:
const FileManager &getFileManager() const { return *FileMgr; }
FileManager &getFileManager() { return *FileMgr; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+
const std::string &getOriginalSourceFileName();
const std::string &getASTFileName();
@@ -386,6 +429,9 @@ public:
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
ASTLocation getLastASTLocation() const { return LastLoc; }
+
+ llvm::StringRef getMainFileName() const;
+
typedef std::vector<Decl *>::iterator top_level_iterator;
top_level_iterator top_level_begin() {
@@ -423,6 +469,22 @@ public:
TopLevelDeclsInPreamble.push_back(D);
}
+ /// \brief Retrieve a reference to the current top-level name hash value.
+ ///
+ /// Note: This is used internally by the top-level tracking action
+ unsigned &getCurrentTopLevelHashValue() { return CurrentTopLevelHashValue; }
+
+ typedef std::vector<PreprocessedEntity *>::iterator pp_entity_iterator;
+
+ pp_entity_iterator pp_entity_begin();
+ pp_entity_iterator pp_entity_end();
+
+ /// \brief Add a new preprocessed entity that's stored at the given offset
+ /// in the precompiled preamble.
+ void addPreprocessedEntityFromPreamble(uint64_t Offset) {
+ PreprocessedEntitiesInPreamble.push_back(Offset);
+ }
+
/// \brief Retrieve the mapping from File IDs to the preprocessed entities
/// within that file.
PreprocessedEntitiesByFileMap &getPreprocessedEntitiesByFile() {
@@ -457,7 +519,10 @@ public:
unsigned cached_completion_size() const {
return CachedCompletionResults.size();
}
-
+
+ llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename,
+ std::string *ErrorStr = 0);
+
/// \brief Whether this AST represents a complete translation unit.
///
/// If false, this AST is only a partial translation unit, e.g., one
@@ -478,11 +543,25 @@ public:
/// \returns - The initialized ASTUnit or null if the AST failed to load.
static ASTUnit *LoadFromASTFile(const std::string &Filename,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ const FileSystemOptions &FileSystemOpts,
bool OnlyLocalDecls = false,
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0,
bool CaptureDiagnostics = false);
+private:
+ /// \brief Helper function for \c LoadFromCompilerInvocation() and
+ /// \c LoadFromCommandLine(), which loads an AST from a compiler invocation.
+ ///
+ /// \param PrecompilePreamble Whether to precompile the preamble of this
+ /// translation unit, to improve the performance of reparsing.
+ ///
+ /// \returns \c true if a catastrophic failure occurred (which means that the
+ /// \c ASTUnit itself is invalid), or \c false otherwise.
+ bool LoadFromCompilerInvocation(bool PrecompilePreamble);
+
+public:
+
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
/// CompilerInvocation object.
///
@@ -521,12 +600,14 @@ public:
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
llvm::StringRef ResourceFilesPath,
bool OnlyLocalDecls = false,
+ bool CaptureDiagnostics = false,
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0,
- bool CaptureDiagnostics = false,
bool PrecompilePreamble = false,
bool CompleteTranslationUnit = true,
- bool CacheCodeCompletionResults = false);
+ bool CacheCodeCompletionResults = false,
+ bool CXXPrecompilePreamble = false,
+ bool CXXChainedPCH = false);
/// \brief Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit.
diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def
index aaa3920cee4f..75b52a824c63 100644
--- a/include/clang/Frontend/Analyses.def
+++ b/include/clang/Frontend/Analyses.def
@@ -15,45 +15,12 @@
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
#endif
-ANALYSIS(CFGDump, "cfg-dump",
- "Display Control-Flow Graphs", Code)
-
-ANALYSIS(CFGView, "cfg-view",
- "View Control-Flow Graphs using GraphViz", Code)
-
-ANALYSIS(DisplayLiveVariables, "dump-live-variables",
- "Print results of live variable analysis", Code)
-
-ANALYSIS(SecuritySyntacticChecks, "analyzer-check-security-syntactic",
- "Perform quick security checks that require no data flow", Code)
-
-ANALYSIS(LLVMConventionChecker, "analyzer-check-llvm-conventions",
- "Check code for LLVM codebase conventions (domain-specific)",
- TranslationUnit)
-
-ANALYSIS(WarnDeadStores, "analyzer-check-dead-stores",
- "Warn about stores to dead variables", Code)
-
ANALYSIS(WarnUninitVals, "warn-uninit-values",
"Warn about uses of uninitialized variables", Code)
-
-ANALYSIS(WarnObjCMethSigs, "analyzer-check-objc-methodsigs",
- "Warn about Objective-C method signatures with type incompatibilities",
- ObjCImplementation)
-
-ANALYSIS(WarnObjCDealloc, "analyzer-check-objc-missing-dealloc",
-"Warn about Objective-C classes that lack a correct implementation of -dealloc",
- ObjCImplementation)
-ANALYSIS(WarnObjCUnusedIvars, "analyzer-check-objc-unused-ivars",
- "Warn about private ivars that are never used", ObjCImplementation)
-
ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem",
"Run the [Core] Foundation reference count checker", Code)
-ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer",
- "Warn about unintended use of sizeof() on pointer expressions", Code)
-
#ifndef ANALYSIS_STORE
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)
#endif
@@ -73,9 +40,10 @@ ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of conc
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)
#endif
-ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", CreateHTMLDiagnosticClient, false)
-ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", CreatePlistDiagnosticClient, true)
-ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", CreatePlistHTMLDiagnosticClient, true)
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticClient, false)
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticClient, true)
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticClient, true)
+ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticClient, true)
#undef ANALYSIS
#undef ANALYSIS_STORE
diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h
index 9ed15ba2f996..580692865819 100644
--- a/include/clang/Frontend/AnalyzerOptions.h
+++ b/include/clang/Frontend/AnalyzerOptions.h
@@ -56,6 +56,8 @@ NUM_ANALYSIS_DIAG_CLIENTS
class AnalyzerOptions {
public:
std::vector<Analyses> AnalysisList;
+ /// \brief Pair of checker name and enable/disable.
+ std::vector<std::pair<std::string, bool> > CheckersControlList;
AnalysisStores AnalysisStoreOpt;
AnalysisConstraints AnalysisConstraintsOpt;
AnalysisDiagClients AnalysisDiagOpt;
@@ -65,17 +67,20 @@ public:
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
+ unsigned AnalyzerStats : 1;
unsigned EagerlyAssume : 1;
- unsigned IdempotentOps : 1;
+ unsigned BufferOverflows : 1;
unsigned PurgeDead : 1;
unsigned TrimGraph : 1;
unsigned VisualizeEGDot : 1;
unsigned VisualizeEGUbi : 1;
unsigned EnableExperimentalChecks : 1;
unsigned EnableExperimentalInternalChecks : 1;
- unsigned EnableIdempotentOperationChecker : 1;
unsigned InlineCall : 1;
unsigned UnoptimizedCFG : 1;
+ unsigned CFGAddImplicitDtors : 1;
+ unsigned CFGAddInitializers : 1;
+ unsigned EagerlyTrimEGraph : 1;
public:
AnalyzerOptions() {
@@ -85,14 +90,20 @@ public:
AnalyzeAll = 0;
AnalyzerDisplayProgress = 0;
AnalyzeNestedBlocks = 0;
+ AnalyzerStats = 0;
EagerlyAssume = 0;
+ BufferOverflows = 0;
PurgeDead = 1;
TrimGraph = 0;
VisualizeEGDot = 0;
VisualizeEGUbi = 0;
EnableExperimentalChecks = 0;
EnableExperimentalInternalChecks = 0;
+ InlineCall = 0;
UnoptimizedCFG = 0;
+ CFGAddImplicitDtors = 0;
+ CFGAddInitializers = 0;
+ EagerlyTrimEGraph = 0;
}
};
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index b3f57094b4af..ee85b655c23f 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -40,24 +40,32 @@ public:
/// aliases to base ctors when possible.
unsigned DataSections : 1; /// Set when -fdata-sections is enabled
unsigned DebugInfo : 1; /// Should generate debug info (-g).
+ unsigned LimitDebugInfo : 1; /// Limit generated debug info to reduce size.
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 EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl*
- /// various IR entities came from. Only useful
- /// when running CodeGen as a subroutine.
+ unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what
+ /// Decl* various IR entities came from. Only
+ /// useful when running CodeGen as a
+ /// subroutine.
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
+ /// 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 NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
+ unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf.
+ 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
@@ -65,12 +73,14 @@ public:
unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
unsigned OptimizeSize : 1; /// If -Os is specified.
unsigned RelaxAll : 1; /// Relax all machine code instructions.
+ unsigned RelaxedAliasing : 1; /// Set when -fno-strict-aliasing is enabled.
unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled.
unsigned SoftFloat : 1; /// -soft-float.
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.
unsigned VerifyModule : 1; /// Control whether the module should be run
/// through the LLVM Verifier.
@@ -102,6 +112,10 @@ public:
/// The name of the relocation model to use.
std::string RelocationModel;
+ /// The user specified number of registers to be used for integral arguments,
+ /// or 0 if unspecified.
+ unsigned NumRegisterParameters;
+
public:
CodeGenOptions() {
AsmVerbose = 0;
@@ -109,6 +123,7 @@ public:
CXXCtorDtorAliases = 0;
DataSections = 0;
DebugInfo = 0;
+ LimitDebugInfo = 0;
DisableFPElim = 0;
DisableLLVMOpts = 0;
DisableRedZone = 0;
@@ -117,20 +132,27 @@ public:
HiddenWeakTemplateVTables = 0;
HiddenWeakVTables = 0;
InstrumentFunctions = 0;
+ InstrumentForProfiling = 0;
+ LessPreciseFPMAD = 0;
MergeAllConstants = 1;
NoCommon = 0;
NoImplicitFloat = 0;
+ NoInfsFPMath = 0;
+ NoNaNsFPMath = 0;
NoZeroInitializedInBSS = 0;
+ NumRegisterParameters = 0;
ObjCDispatchMethod = Legacy;
OmitLeafFramePointer = 0;
OptimizationLevel = 0;
OptimizeSize = 0;
RelaxAll = 0;
+ RelaxedAliasing = 0;
SimplifyLibCalls = 1;
SoftFloat = 0;
TimePasses = 0;
UnitAtATime = 1;
UnrollLoops = 0;
+ UnsafeFPMath = 0;
UnwindTables = 0;
VerifyModule = 1;
diff --git a/include/clang/Frontend/CommandLineSourceLoc.h b/include/clang/Frontend/CommandLineSourceLoc.h
index bea468b01791..8911cfadd530 100644
--- a/include/clang/Frontend/CommandLineSourceLoc.h
+++ b/include/clang/Frontend/CommandLineSourceLoc.h
@@ -37,9 +37,15 @@ public:
// If both tail splits were valid integers, return success.
if (!ColSplit.second.getAsInteger(10, PSL.Column) &&
- !LineSplit.second.getAsInteger(10, PSL.Line))
+ !LineSplit.second.getAsInteger(10, PSL.Line)) {
PSL.FileName = LineSplit.first;
+ // On the command-line, stdin may be specified via "-". Inside the
+ // compiler, stdin is called "<stdin>".
+ if (PSL.FileName == "-")
+ PSL.FileName = "<stdin>";
+ }
+
return PSL;
}
};
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 1b3c336fc0eb..7ea79e5599ff 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -19,7 +19,6 @@
#include <string>
namespace llvm {
-class LLVMContext;
class raw_ostream;
class raw_fd_ostream;
class Timer;
@@ -59,9 +58,6 @@ class TargetInfo;
/// come in two forms; a short form that reuses the CompilerInstance objects,
/// and a long form that takes explicit instances of any required objects.
class CompilerInstance {
- /// The LLVM context used for this instance.
- llvm::OwningPtr<llvm::LLVMContext> LLVMContext;
-
/// The options used in this compiler instance.
llvm::OwningPtr<CompilerInvocation> Invocation;
@@ -95,8 +91,23 @@ class CompilerInstance {
/// The frontend timer
llvm::OwningPtr<llvm::Timer> FrontendTimer;
+ /// \brief Holds information about the output file.
+ ///
+ /// If TempFilename is not empty we must rename it to Filename at the end.
+ /// TempFilename may be empty and Filename non empty if creating the temporary
+ /// failed.
+ struct OutputFile {
+ std::string Filename;
+ std::string TempFilename;
+ llvm::raw_ostream *OS;
+
+ OutputFile(const std::string &filename, const std::string &tempFilename,
+ llvm::raw_ostream *os)
+ : Filename(filename), TempFilename(tempFilename), OS(os) { }
+ };
+
/// The list of active output files.
- std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
+ std::list<OutputFile> OutputFiles;
void operator=(const CompilerInstance &); // DO NOT IMPLEMENT
CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT
@@ -140,23 +151,6 @@ public:
bool ExecuteAction(FrontendAction &Act);
/// }
- /// @name LLVM Context
- /// {
-
- bool hasLLVMContext() const { return LLVMContext != 0; }
-
- llvm::LLVMContext &getLLVMContext() const {
- assert(LLVMContext && "Compiler instance has no LLVM context!");
- return *LLVMContext;
- }
-
- llvm::LLVMContext *takeLLVMContext() { return LLVMContext.take(); }
-
- /// setLLVMContext - Replace the current LLVM context and take ownership of
- /// \arg Value.
- void setLLVMContext(llvm::LLVMContext *Value);
-
- /// }
/// @name Compiler Invocation and Options
/// {
@@ -205,6 +199,10 @@ public:
return Invocation->getDiagnosticOpts();
}
+ const FileSystemOptions &getFileSystemOpts() const {
+ return Invocation->getFileSystemOpts();
+ }
+
FrontendOptions &getFrontendOpts() {
return Invocation->getFrontendOpts();
}
@@ -435,16 +433,10 @@ public:
/// @name Output Files
/// {
- /// getOutputFileList - Get the list of (path, output stream) pairs of output
- /// files; the path may be empty but the stream will always be non-null.
- const std::list< std::pair<std::string,
- llvm::raw_ostream*> > &getOutputFileList() const;
-
/// addOutputFile - Add an output file onto the list of tracked output files.
///
- /// \param Path - The path to the output file, or empty.
- /// \param OS - The output stream, which should be non-null.
- void addOutputFile(llvm::StringRef Path, llvm::raw_ostream *OS);
+ /// \param OutFile - The output file info.
+ void addOutputFile(const OutputFile &OutFile);
/// clearOutputFiles - Clear the output file list, destroying the contained
/// output streams.
@@ -459,8 +451,14 @@ public:
/// Create the diagnostics engine using the invocation's diagnostic options
/// and replace any existing one with it.
///
- /// Note that this routine also replaces the diagnostic client.
- void createDiagnostics(int Argc, char **Argv);
+ /// Note that this routine also replaces the diagnostic client,
+ /// allocating one if one is not provided.
+ ///
+ /// \param Client If non-NULL, a diagnostic client that will be
+ /// attached to (and, then, owned by) the Diagnostic inside this AST
+ /// unit.
+ void createDiagnostics(int Argc, const char* const *Argv,
+ DiagnosticClient *Client = 0);
/// Create a Diagnostic object with a the TextDiagnosticPrinter.
///
@@ -468,23 +466,30 @@ public:
/// when the diagnostic options indicate that the compiler should output
/// logging information.
///
- /// Note that this creates an unowned DiagnosticClient, if using directly the
- /// caller is responsible for releasing the returned Diagnostic's client
- /// eventually.
+ /// If no diagnostic client is provided, this creates a
+ /// DiagnosticClient that is owned by the returned diagnostic
+ /// object, if using directly the caller is responsible for
+ /// releasing the returned Diagnostic'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.
///
+ /// \param Client If non-NULL, a diagnostic client that will be
+ /// attached to (and, then, owned by) the returned Diagnostic
+ /// object.
+ ///
/// \return The new object on success, or null on failure.
static llvm::IntrusiveRefCntPtr<Diagnostic>
- createDiagnostics(const DiagnosticOptions &Opts, int Argc, char **Argv);
+ createDiagnostics(const DiagnosticOptions &Opts, int Argc,
+ const char* const *Argv,
+ DiagnosticClient *Client = 0);
/// Create the file manager and replace any existing one with it.
void createFileManager();
/// Create the source manager and replace any existing one with it.
- void createSourceManager();
+ void createSourceManager(FileManager &FileMgr);
/// Create the preprocessor, using the invocation, file, and source managers,
/// and replace any existing one with it.
@@ -511,6 +516,7 @@ public:
/// context.
void createPCHExternalASTSource(llvm::StringRef Path,
bool DisablePCHValidation,
+ bool DisableStatCache,
void *DeserializationListener);
/// Create an external AST source to read a PCH file.
@@ -519,8 +525,9 @@ public:
static ExternalASTSource *
createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
bool DisablePCHValidation,
+ bool DisableStatCache,
Preprocessor &PP, ASTContext &Context,
- void *DeserializationListener);
+ void *DeserializationListener, bool Preamble);
/// Create a code completion consumer using the invocation; note that this
/// will cause the source manager to truncate the input source file at the
@@ -533,7 +540,7 @@ public:
static CodeCompleteConsumer *
createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
unsigned Line, unsigned Column,
- bool UseDebugPrinter, bool ShowMacros,
+ bool ShowMacros,
bool ShowCodePatterns, bool ShowGlobals,
llvm::raw_ostream &OS);
@@ -557,7 +564,8 @@ public:
///
/// \return - Null on error.
llvm::raw_fd_ostream *
- createOutputFile(llvm::StringRef OutputPath, bool Binary = true,
+ createOutputFile(llvm::StringRef OutputPath,
+ bool Binary = true, bool RemoveFileOnSignal = true,
llvm::StringRef BaseInput = "",
llvm::StringRef Extension = "");
@@ -565,7 +573,8 @@ public:
///
/// If \arg OutputPath is empty, then createOutputFile will derive an output
/// path location as \arg BaseInput, with any suffix removed, and \arg
- /// Extension appended.
+ /// Extension appended. If OutputPath is not stdout createOutputFile will
+ /// create a new temporary file that must be renamed to OutputPath in the end.
///
/// \param OutputPath - If given, the path to the output file.
/// \param Error [out] - On failure, the error message.
@@ -573,13 +582,20 @@ public:
/// for deriving the output path.
/// \param Extension - The extension to use for derived output names.
/// \param Binary - The mode to open the file in.
+ /// \param RemoveFileOnSignal - Whether the file should be registered with
+ /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for
+ /// multithreaded use, as the underlying signal mechanism is not reentrant
/// \param ResultPathName [out] - If given, the result path name will be
/// stored here on success.
+ /// \param TempPathName [out] - If given, the temporary file path name
+ /// will be stored here on success.
static llvm::raw_fd_ostream *
createOutputFile(llvm::StringRef OutputPath, std::string &Error,
- bool Binary = true, llvm::StringRef BaseInput = "",
+ bool Binary = true, bool RemoveFileOnSignal = true,
+ llvm::StringRef BaseInput = "",
llvm::StringRef Extension = "",
- std::string *ResultPathName = 0);
+ std::string *ResultPathName = 0,
+ std::string *TempPathName = 0);
/// }
/// @name Initialization Utility Methods
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index d558ad391406..e0329dbc96ec 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -12,12 +12,14 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "clang/Frontend/AnalyzerOptions.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/StringRef.h"
@@ -52,6 +54,9 @@ class CompilerInvocation {
/// Options controlling the diagnostic engine.
DiagnosticOptions DiagnosticOpts;
+ /// Options controlling file system operations.
+ FileSystemOptions FileSystemOpts;
+
/// Options controlling the frontend itself.
FrontendOptions FrontendOpts;
@@ -83,8 +88,10 @@ public:
/// \param ArgBegin - The first element in the argument vector.
/// \param ArgEnd - The last element in the argument vector.
/// \param Diags - The diagnostic engine to use for errors.
- static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin,
- const char **ArgEnd, Diagnostic &Diags);
+ static void CreateFromArgs(CompilerInvocation &Res,
+ const char* const *ArgBegin,
+ const char* const *ArgEnd,
+ Diagnostic &Diags);
/// GetBuiltinIncludePath - Get the directory where the compiler headers
/// reside, relative to the compiler binary (found by the passed in
@@ -100,6 +107,25 @@ public:
/// passing to CreateFromArgs.
void toArgs(std::vector<std::string> &Res);
+ /// setLangDefaults - Set language defaults for the given input language and
+ /// language standard in this CompilerInvocation.
+ ///
+ /// \param IK - The input language.
+ /// \param LangStd - The input language standard.
+ void setLangDefaults(InputKind IK,
+ LangStandard::Kind LangStd = LangStandard::lang_unspecified) {
+ setLangDefaults(LangOpts, IK, LangStd);
+ }
+
+ /// setLangDefaults - Set language defaults for the given input language and
+ /// language standard in the given LangOptions object.
+ ///
+ /// \param LangOpts - The LangOptions object to set up.
+ /// \param IK - The input language.
+ /// \param LangStd - The input language standard.
+ static void setLangDefaults(LangOptions &Opts, InputKind IK,
+ LangStandard::Kind LangStd = LangStandard::lang_unspecified);
+
/// @}
/// @name Option Subgroups
/// @{
@@ -124,6 +150,11 @@ public:
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;
diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def
index 18451189bc06..1b158fdfafc0 100644
--- a/include/clang/Frontend/DeclXML.def
+++ b/include/clang/Frontend/DeclXML.def
@@ -103,6 +103,9 @@ NODE_XML(FunctionDecl, "Function")
ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
//ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
ATTRIBUTE_XML(getNumParams(), "num_args")
+ ATTRIBUTE_OPT_XML(isMain(), "main")
+ ATTRIBUTE_OPT_XML(isExternC(), "externc")
+ ATTRIBUTE_OPT_XML(isGlobal(), "global")
SUB_NODE_SEQUENCE_XML(ParmVarDecl)
SUB_NODE_FN_BODY_XML
END_NODE_XML
@@ -117,6 +120,7 @@ NODE_XML(CXXMethodDecl, "CXXMethod")
ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
ATTRIBUTE_OPT_XML(isStatic(), "static")
ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
+ ATTRIBUTE_OPT_XML(isPure(), "pure")
ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access")
ENUM_XML(AS_none, "")
ENUM_XML(AS_public, "public")
@@ -316,6 +320,7 @@ NODE_XML(LinkageSpecDecl, "LinkageSpec")
ENUM_XML(LinkageSpecDecl::lang_c, "C")
ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX")
END_ENUM_XML
+ SUB_NODE_XML(DeclContext)
END_NODE_XML
NODE_XML(TemplateDecl, "Template")
diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h
index ab8e49df9a88..35aa6c6aace6 100644
--- a/include/clang/Frontend/DependencyOutputOptions.h
+++ b/include/clang/Frontend/DependencyOutputOptions.h
@@ -20,13 +20,20 @@ namespace clang {
class DependencyOutputOptions {
public:
unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies.
+ unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H).
unsigned UsePhonyTargets : 1; ///< Include phony targets for each
/// dependency, which can avoid some 'make'
/// problems.
- /// The file to write depencency output to.
+ /// The file to write dependency output to.
std::string OutputFile;
+ /// The file to write header include output to. This is orthogonal to
+ /// ShowHeaderIncludes (-H) and will include headers mentioned in the
+ /// predefines buffer. If the output file is "-", output will be sent to
+ /// stderr.
+ std::string HeaderIncludeOutputFile;
+
/// A list of names to use as the targets in the dependency file; this list
/// must contain at least one entry.
std::vector<std::string> Targets;
@@ -34,6 +41,7 @@ public:
public:
DependencyOutputOptions() {
IncludeSystemHeaders = 0;
+ ShowHeaderIncludes = 0;
UsePhonyTargets = 0;
}
};
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
index c80bc037212b..f7f498bff024 100644
--- a/include/clang/Frontend/DiagnosticOptions.h
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -41,9 +41,6 @@ public:
unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected
/// diagnostics, indicated by markers in the
/// input source file.
- unsigned BinaryOutput : 1; /// Emit diagnostics via the diagnostic
- /// binary serialization mechanism, to be
- /// deserialized by, e.g., the CIndex library.
unsigned ErrorLimit; /// Limit # errors emitted.
unsigned MacroBacktraceLimit; /// Limit depth of macro instantiation
@@ -86,7 +83,6 @@ public:
ShowSourceRanges = 0;
ShowParseableFixits = 0;
VerifyDiagnostics = 0;
- BinaryOutput = 0;
ErrorLimit = 0;
TemplateBacktraceLimit = DefaultTemplateBacktraceLimit;
MacroBacktraceLimit = DefaultMacroBacktraceLimit;
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index 773543ac06a5..ee0863a4776f 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -37,6 +37,7 @@ enum InputKind {
IK_PreprocessedObjC,
IK_PreprocessedObjCXX,
IK_OpenCL,
+ IK_CUDA,
IK_AST,
IK_LLVM_IR
};
@@ -51,6 +52,10 @@ class FrontendAction {
CompilerInstance *Instance;
friend class ASTMergeAction;
+private:
+ ASTConsumer* CreateWrappedASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
protected:
/// @name Implementation Action Interface
/// @{
@@ -130,7 +135,7 @@ public:
}
ASTUnit &getCurrentASTUnit() const {
- assert(!CurrentASTUnit && "No current AST unit!");
+ assert(CurrentASTUnit && "No current AST unit!");
return *CurrentASTUnit;
}
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 7b8063ce549c..4df2e71571f7 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -54,6 +54,12 @@ protected:
llvm::StringRef InFile);
};
+class ASTDumpXMLAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
class ASTViewAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
@@ -83,16 +89,11 @@ public:
static bool ComputeASTConsumerArguments(CompilerInstance &CI,
llvm::StringRef InFile,
std::string &Sysroot,
+ std::string &OutputFile,
llvm::raw_ostream *&OS,
bool &Chaining);
};
-class InheritanceViewAction : public ASTFrontendAction {
-protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- llvm::StringRef InFile);
-};
-
class SyntaxOnlyAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
diff --git a/include/clang/Frontend/FrontendDiagnostic.h b/include/clang/Frontend/FrontendDiagnostic.h
index 61ad22cabb0d..2efbc818de1b 100644
--- a/include/clang/Frontend/FrontendDiagnostic.h
+++ b/include/clang/Frontend/FrontendDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define FRONTENDSTART
#include "clang/Basic/DiagnosticFrontendKinds.inc"
#undef DIAG
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 4c16d084fc0d..19d39c3ca1b2 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -21,6 +21,7 @@ namespace clang {
namespace frontend {
enum ActionKind {
ASTDump, ///< Parse ASTs and dump them.
+ ASTDumpXML, ///< Parse ASTs and dump them in XML.
ASTPrint, ///< Parse ASTs and print them.
ASTPrintXML, ///< Parse ASTs and print them in XML.
ASTView, ///< Parse ASTs and view them in Graphviz.
@@ -38,7 +39,6 @@ namespace frontend {
FixIt, ///< Parse and apply any fixits to the source.
GeneratePCH, ///< Generate pre-compiled header.
GeneratePTH, ///< Generate pre-tokenized header.
- InheritanceView, ///< View C++ inheritance for a specified class.
InitOnly, ///< Only execute frontend initialization.
ParseSyntaxOnly, ///< Parse and perform semantic analysis.
PluginAction, ///< Run a plugin action, \see ActionName.
@@ -56,8 +56,6 @@ namespace frontend {
/// FrontendOptions - Options for controlling the behavior of the frontend.
class FrontendOptions {
public:
- unsigned DebugCodeCompletionPrinter : 1; ///< Use the debug printer for code
- /// completion results.
unsigned DisableFree : 1; ///< Disable memory freeing on exit.
unsigned RelocatablePCH : 1; ///< When generating PCH files,
/// instruct the AST writer to create
@@ -86,9 +84,6 @@ public:
/// The output file, if any.
std::string OutputFile;
- /// If given, the name for a C++ class to view the inheritance of.
- std::string ViewClassInheritance;
-
/// If given, the new suffix for fix-it rewritten files.
std::string FixItSuffix;
@@ -101,9 +96,15 @@ public:
/// The name of the action to run when using a plugin action.
std::string ActionName;
- /// Arg to pass to the plugin
+ /// Args to pass to the plugin
std::vector<std::string> PluginArgs;
+ /// The list of plugin actions to run in addition to the normal action.
+ std::vector<std::string> AddPluginActions;
+
+ /// Args to pass to the additional plugins
+ std::vector<std::vector<std::string> > AddPluginArgs;
+
/// The list of plugins to load.
std::vector<std::string> Plugins;
@@ -119,7 +120,6 @@ public:
public:
FrontendOptions() {
- DebugCodeCompletionPrinter = 1;
DisableFree = 0;
ProgramAction = frontend::ParseSyntaxOnly;
ActionName = "";
diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h
index 588d32bf736e..cbb4a57993b7 100644
--- a/include/clang/Frontend/HeaderSearchOptions.h
+++ b/include/clang/Frontend/HeaderSearchOptions.h
@@ -54,6 +54,9 @@ public:
/// User specified include entries.
std::vector<Entry> UserEntries;
+ /// If non-empty, the list of C++ standard include paths to use.
+ std::vector<std::string> CXXSystemIncludes;
+
/// A (system-path) delimited list of include paths to be added from the
/// environment following the user specified includes (but prior to builtin
/// and standard includes). This is parsed in the same manner as the CPATH
diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def
index 52aa4636084d..d4046b3e5668 100644
--- a/include/clang/Frontend/LangStandards.def
+++ b/include/clang/Frontend/LangStandards.def
@@ -80,4 +80,9 @@ LANGSTANDARD(opencl, "cl",
"OpenCL 1.0",
BCPLComment | C99 | Digraphs | HexFloat)
+// CUDA
+LANGSTANDARD(cuda, "cuda",
+ "NVIDIA CUDA(tm)",
+ BCPLComment | CPlusPlus | Digraphs)
+
#undef LANGSTANDARD
diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h
new file mode 100644
index 000000000000..560178be9bf8
--- /dev/null
+++ b/include/clang/Frontend/MultiplexConsumer.h
@@ -0,0 +1,54 @@
+//===-- MultiplexConsumer.h - AST Consumer for PCH Generation ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the MultiplexConsumer class, which can be used to
+// multiplex ASTConsumer and SemaConsumer messages to many consumers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaConsumer.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <vector>
+
+namespace clang {
+
+class MultiplexASTMutationListener;
+class MultiplexASTDeserializationListener;
+
+// Has a list of ASTConsumers and calls each of them. Owns its children.
+class MultiplexConsumer : public SemaConsumer {
+public:
+ // Takes ownership of the pointers in C.
+ MultiplexConsumer(const std::vector<ASTConsumer*>& C);
+ ~MultiplexConsumer();
+
+ // ASTConsumer
+ virtual void Initialize(ASTContext &Context);
+ virtual void HandleTopLevelDecl(DeclGroupRef D);
+ virtual void HandleInterestingDecl(DeclGroupRef D);
+ virtual void HandleTranslationUnit(ASTContext &Ctx);
+ virtual void HandleTagDeclDefinition(TagDecl *D);
+ virtual void CompleteTentativeDefinition(VarDecl *D);
+ virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired);
+ virtual ASTMutationListener *GetASTMutationListener();
+ virtual ASTDeserializationListener *GetASTDeserializationListener();
+ virtual void PrintStats();
+
+ // SemaConsumer
+ virtual void InitializeSema(Sema &S);
+ virtual void ForgetSema();
+
+ static bool classof(const MultiplexConsumer *) { return true; }
+private:
+ std::vector<ASTConsumer*> Consumers; // Owns these.
+ llvm::OwningPtr<MultiplexASTMutationListener> MutationListener;
+ llvm::OwningPtr<MultiplexASTDeserializationListener> DeserializationListener;
+};
+
+} // end namespace clang
diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h
index 851c1f0108af..0d52e53ea16a 100644
--- a/include/clang/Frontend/PreprocessorOptions.h
+++ b/include/clang/Frontend/PreprocessorOptions.h
@@ -15,6 +15,7 @@
#include <string>
#include <utility>
#include <vector>
+#include <set>
namespace llvm {
class MemoryBuffer;
@@ -46,7 +47,18 @@ public:
/// \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 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<std::string> 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.
///
@@ -117,7 +129,8 @@ public:
public:
PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
- DisablePCHValidation(false),
+ DisablePCHValidation(false), DisableStatCache(false),
+ DumpDeserializedPCHDecls(false),
PrecompiledPreambleBytes(0, true),
RetainRemappedFileBuffers(false) { }
diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
index 82517c51d1c1..1eda0d40275e 100644
--- a/include/clang/Frontend/PreprocessorOutputOptions.h
+++ b/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -18,7 +18,6 @@ class PreprocessorOutputOptions {
public:
unsigned ShowCPP : 1; ///< Print normal preprocessed output.
unsigned ShowComments : 1; ///< Show comments.
- unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H).
unsigned ShowLineMarkers : 1; ///< Show #line markers.
unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
unsigned ShowMacros : 1; ///< Print macro definitions.
@@ -27,7 +26,6 @@ public:
PreprocessorOutputOptions() {
ShowCPP = 1;
ShowComments = 0;
- ShowHeaderIncludes = 0;
ShowLineMarkers = 1;
ShowMacroComments = 0;
ShowMacros = 0;
diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def
index c03a5a883569..8a859e6898b1 100644
--- a/include/clang/Frontend/StmtXML.def
+++ b/include/clang/Frontend/StmtXML.def
@@ -415,13 +415,6 @@ NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a s
SUB_NODE_XML(CompoundStmt)
END_NODE_XML
-NODE_XML(TypesCompatibleExpr, "TypesCompatibleExpr") // GNU builtin-in function __builtin_types_compatible_p
- ATTRIBUTE_FILE_LOCATION_XML
- TYPE_ATTRIBUTE_XML(getType())
- ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1
- ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2
-END_NODE_XML
-
NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def
index 1536c924a82f..b78e70f5aa86 100644
--- a/include/clang/Frontend/TypeXML.def
+++ b/include/clang/Frontend/TypeXML.def
@@ -98,7 +98,8 @@ NODE_XML(BuiltinType, "FundamentalType")
ENUM_XML(BuiltinType::Float, "float");
ENUM_XML(BuiltinType::Double, "double");
ENUM_XML(BuiltinType::LongDouble, "long double");
- ENUM_XML(BuiltinType::WChar, "wchar_t");
+ ENUM_XML(BuiltinType::WChar_U, "wchar_t");
+ ENUM_XML(BuiltinType::WChar_S, "wchar_t");
ENUM_XML(BuiltinType::Char16, "char16_t");
ENUM_XML(BuiltinType::Char32, "char32_t");
ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'.
@@ -130,6 +131,13 @@ NODE_XML(FunctionProtoType, "FunctionType")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getResultType(), "result_type")
ATTRIBUTE_OPT_XML(isVariadic(), "variadic")
+ ATTRIBUTE_ENUM_XML(getCallConv(), "call_conv")
+ ENUM_XML(CC_Default, "")
+ ENUM_XML(CC_C, "C")
+ ENUM_XML(CC_X86StdCall, "X86StdCall")
+ ENUM_XML(CC_X86FastCall, "X86FastCall")
+ ENUM_XML(CC_X86ThisCall, "X86ThisCall")
+ END_ENUM_XML
END_NODE_XML
NODE_XML(TypedefType, "Typedef")
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index fe722db381d0..485161b1bc38 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -73,6 +73,18 @@ bool CheckDiagnostics(Preprocessor &PP);
void AttachDependencyFileGen(Preprocessor &PP,
const DependencyOutputOptions &Opts);
+/// AttachHeaderIncludeGen - Create a header include list generator, and attach
+/// it to the given preprocessor.
+///
+/// \param ShowAllHeaders - If true, show all header information instead of just
+/// headers following the predefines buffer. This is useful for making sure
+/// includes mentioned on the command line are also reported, but differs from
+/// the default behavior used by -H.
+/// \param OutputPath - If non-empty, a path to write the header include
+/// information to, instead of writing to stderr.
+void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false,
+ llvm::StringRef OutputPath = "");
+
/// CacheTokens - Cache tokens for use with PCH. Note that this requires
/// a seekable stream.
void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS);
diff --git a/include/clang/Frontend/VerifyDiagnosticsClient.h b/include/clang/Frontend/VerifyDiagnosticsClient.h
index 6f45e49ec0ef..793cedd8578f 100644
--- a/include/clang/Frontend/VerifyDiagnosticsClient.h
+++ b/include/clang/Frontend/VerifyDiagnosticsClient.h
@@ -68,7 +68,6 @@ public:
llvm::OwningPtr<DiagnosticClient> PrimaryClient;
llvm::OwningPtr<TextDiagnosticBuffer> Buffer;
Preprocessor *CurrentPreprocessor;
- unsigned NumErrors;
private:
void CheckDiagnostics();
@@ -88,9 +87,6 @@ public:
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
-
- /// HadErrors - Check if there were any mismatches in expected diagnostics.
- bool HadErrors();
};
} // end namspace clang
diff --git a/include/clang/Lex/CMakeLists.txt b/include/clang/Lex/CMakeLists.txt
new file mode 100644
index 000000000000..b823e83f906b
--- /dev/null
+++ b/include/clang/Lex/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td)
+tablegen(AttrSpellings.inc
+ -gen-clang-attr-spelling-list
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
+add_custom_target(ClangAttrSpellings
+ DEPENDS AttrSpellings.inc)
diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h
index 791d3fe304ec..dbf738903371 100644
--- a/include/clang/Lex/ExternalPreprocessorSource.h
+++ b/include/clang/Lex/ExternalPreprocessorSource.h
@@ -27,6 +27,9 @@ 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;
};
}
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index 9837e296535f..8a5c83ecf495 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -43,7 +43,7 @@ public:
/// HeaderMap::Create - This attempts to load the specified file as a header
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
- static const HeaderMap *Create(const FileEntry *FE);
+ static const HeaderMap *Create(const FileEntry *FE, FileManager &FM);
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 80b38dee06af..30bd4f58549c 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -29,7 +29,7 @@ class IdentifierInfo;
/// file that is #included.
struct HeaderFileInfo {
/// isImport - True if this is a #import'd or #pragma once file.
- bool isImport : 1;
+ unsigned isImport : 1;
/// DirInfo - Keep track of whether this is a system header, and if so,
/// whether it is C++ clean or not. This can be set by the include paths or
@@ -37,10 +37,24 @@ struct HeaderFileInfo {
/// SrcMgr::CharacteristicKind.
unsigned DirInfo : 2;
+ /// \brief Whether this header file info was supplied by an external source.
+ unsigned External : 1;
+
+ /// \brief Whether this structure is considered to already have been
+ /// "resolved", meaning that it was loaded from the external source.
+ unsigned Resolved : 1;
+
/// NumIncludes - This is the number of times the file has been included
/// already.
unsigned short NumIncludes;
+ /// \brief The ID number of the controlling macro.
+ ///
+ /// This ID number will be non-zero when there is a controlling
+ /// macro whose IdentifierInfo may not yet have been loaded from
+ /// external storage.
+ unsigned ControllingMacroID;
+
/// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
/// that protects the entire contents of the file, this is the identifier
/// for the macro that controls whether or not it has any effect.
@@ -51,27 +65,40 @@ struct HeaderFileInfo {
/// external storage.
const IdentifierInfo *ControllingMacro;
- /// \brief The ID number of the controlling macro.
- ///
- /// This ID number will be non-zero when there is a controlling
- /// macro whose IdentifierInfo may not yet have been loaded from
- /// external storage.
- unsigned ControllingMacroID;
-
HeaderFileInfo()
- : isImport(false), DirInfo(SrcMgr::C_User),
- NumIncludes(0), ControllingMacro(0), ControllingMacroID(0) {}
+ : isImport(false), DirInfo(SrcMgr::C_User), External(false),
+ Resolved(false), NumIncludes(0), ControllingMacroID(0),
+ ControllingMacro(0) {}
/// \brief Retrieve the controlling macro for this header file, if
/// any.
const IdentifierInfo *getControllingMacro(ExternalIdentifierLookup *External);
+
+ /// \brief Determine whether this is a non-default header file info, e.g.,
+ /// it corresponds to an actual header we've included or tried to include.
+ bool isNonDefault() const {
+ return isImport || NumIncludes || ControllingMacro || ControllingMacroID;
+ }
};
+/// \brief An external source of header file information, which may supply
+/// information about header files already included.
+class ExternalHeaderFileInfoSource {
+public:
+ virtual ~ExternalHeaderFileInfoSource();
+
+ /// \brief Retrieve the header file information for the given file entry.
+ ///
+ /// \returns Header file information for the given file entry, with the
+ /// \c External bit set. If the file entry is not known, return a
+ /// default-constructed \c HeaderFileInfo.
+ virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
+};
+
/// HeaderSearch - This class encapsulates the information needed to find the
/// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
class HeaderSearch {
FileManager &FileMgr;
-
/// #include search path information. Requests for #include "x" search the
/// directory of the #including file first, then each directory in SearchDirs
/// consequtively. Requests for <x> search the current dir first, then each
@@ -108,6 +135,9 @@ class HeaderSearch {
/// macros into IdentifierInfo pointers, as needed.
ExternalIdentifierLookup *ExternalLookup;
+ /// \brief Entity used to look up stored header file information.
+ ExternalHeaderFileInfoSource *ExternalSource;
+
// Various statistics we track for performance analysis.
unsigned NumIncluded;
unsigned NumMultiIncludeFileOptzn;
@@ -142,6 +172,15 @@ public:
ExternalLookup = EIL;
}
+ ExternalIdentifierLookup *getExternalLookup() const {
+ return ExternalLookup;
+ }
+
+ /// \brief Set the external source of header information.
+ void SetExternalSource(ExternalHeaderFileInfoSource *ES) {
+ ExternalSource = ES;
+ }
+
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
/// return null on failure. isAngled indicates whether the file reference is
/// a <> reference. If successful, this returns 'UsedDir', the
diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h
index 2d941e4cf4fe..5fcb8eb2d1a4 100644
--- a/include/clang/Lex/LexDiagnostic.h
+++ b/include/clang/Lex/LexDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define LEXSTART
#include "clang/Basic/DiagnosticLexKinds.inc"
#undef DIAG
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 9e0fb7ee70ea..fc9a8de43482 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -211,6 +211,32 @@ public:
/// and " characters. This does not add surrounding ""'s to the string.
static void Stringify(llvm::SmallVectorImpl<char> &Str);
+
+ /// getSpelling - This method is used to get the spelling of a token into a
+ /// preallocated buffer, instead of as an std::string. The caller is required
+ /// to allocate enough space for the token, which is guaranteed to be at least
+ /// Tok.getLength() bytes long. The length of the actual result is returned.
+ ///
+ /// Note that this method may do two possible things: it may either fill in
+ /// the buffer specified with characters, or it may *change the input pointer*
+ /// to point to a constant buffer with the data already in it (avoiding a
+ /// copy). The caller is not allowed to modify the returned buffer pointer
+ /// if an internal buffer is returned.
+ static unsigned getSpelling(const Token &Tok, const char *&Buffer,
+ const SourceManager &SourceMgr,
+ const LangOptions &Features,
+ bool *Invalid = 0);
+
+ /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
+ /// token is the characters used to represent the token in the source file
+ /// after trigraph expansion and escaped-newline folding. In particular, this
+ /// wants to get the true, uncanonicalized, spelling of things like digraphs
+ /// UCNs, etc.
+ static std::string getSpelling(const Token &Tok,
+ const SourceManager &SourceMgr,
+ const LangOptions &Features,
+ bool *Invalid = 0);
+
/// MeasureTokenLength - Relex the token at the specified location and return
/// its length in bytes in the input file. If the token needs cleaning (e.g.
/// includes a trigraph or an escaped newline) then this count includes bytes
@@ -228,6 +254,33 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
+ /// AdvanceToTokenCharacter - If the current SourceLocation specifies a
+ /// location at the start of a token, return a new location that specifies a
+ /// character within the token. This handles trigraphs and escaped newlines.
+ static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
+ unsigned Character,
+ const SourceManager &SM,
+ const LangOptions &Features);
+
+ /// \brief Computes the source location just past the end of the
+ /// token at this source location.
+ ///
+ /// This routine can be used to produce a source location that
+ /// points just past the end of the token referenced by \p Loc, and
+ /// is generally used when a diagnostic needs to point just after a
+ /// token where it expected something different that it received. If
+ /// the returned source location would not be meaningful (e.g., if
+ /// it points into a macro), this routine returns an invalid
+ /// source location.
+ ///
+ /// \param Offset an offset from the end of the token, where the source
+ /// location should refer to. The default offset (0) produces a source
+ /// location pointing just past the end of the token; an offset of 1 produces
+ /// a source location pointing to the last character in the token, etc.
+ static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset,
+ const SourceManager &SM,
+ const LangOptions &Features);
+
/// \brief Compute the preamble of the given file.
///
/// The preamble of a file contains the initial comments, include directives,
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index ba46fb18a68a..bf2c06becdbf 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -15,10 +15,11 @@
#ifndef CLANG_LITERALSUPPORT_H
#define CLANG_LITERALSUPPORT_H
-#include <string>
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
+#include <cctype>
+#include <string>
namespace clang {
@@ -27,6 +28,8 @@ class Preprocessor;
class Token;
class SourceLocation;
class TargetInfo;
+class SourceManager;
+class LangOptions;
/// NumericLiteralParser - This performs strict semantic analysis of the content
/// of a ppnumber, classifying it as either integer, floating, or erroneous,
@@ -138,8 +141,11 @@ public:
/// wide string analysis and Translation Phase #6 (concatenation of string
/// literals) (C99 5.1.1.2p1).
class StringLiteralParser {
- Preprocessor &PP;
-
+ const SourceManager &SM;
+ const LangOptions &Features;
+ const TargetInfo &Target;
+ Diagnostic *Diags;
+
unsigned MaxTokenLength;
unsigned SizeBound;
unsigned wchar_tByteWidth;
@@ -148,6 +154,14 @@ class StringLiteralParser {
public:
StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
Preprocessor &PP, bool Complain = true);
+ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+ const SourceManager &sm, const LangOptions &features,
+ const TargetInfo &target, Diagnostic *diags = 0)
+ : SM(sm), Features(features), Target(target), Diags(diags) {
+ init(StringToks, NumStringToks);
+ }
+
+
bool hadError;
bool AnyWide;
bool Pascal;
@@ -163,8 +177,13 @@ public:
/// getOffsetOfStringByte - This function returns the offset of the
/// specified byte of the string data represented by Token. This handles
/// advancing over escape sequences in the string.
- static unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo,
- Preprocessor &PP, bool Complain = true);
+ ///
+ /// If the Diagnostics pointer is non-null, then this will do semantic
+ /// checking of the string literal and emit errors and warnings.
+ unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo) const;
+
+private:
+ void init(const Token *StringToks, unsigned NumStringToks);
};
} // end namespace clang
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 90f95b7acee3..717c3008eca9 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -82,6 +82,9 @@ private:
/// AllowRedefinitionsWithoutWarning - True if this macro can be redefined
/// without emitting a warning.
bool IsAllowRedefinitionsWithoutWarning : 1;
+
+ /// \brief Must warn if the macro is unused at the end of translation unit.
+ bool IsWarnIfUnused : 1;
~MacroInfo() {
assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
@@ -138,6 +141,11 @@ public:
IsAllowRedefinitionsWithoutWarning = Val;
}
+ /// \brief Set the value of the IsWarnIfUnused flag.
+ void setIsWarnIfUnused(bool val) {
+ IsWarnIfUnused = val;
+ }
+
/// setArgumentList - Set the specified list of identifiers as the argument
/// list for this macro.
void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs,
@@ -201,6 +209,11 @@ public:
return IsAllowRedefinitionsWithoutWarning;
}
+ /// \brief Return true if we should emit a warning if the macro is unused.
+ bool isWarnIfUnused() const {
+ return IsWarnIfUnused;
+ }
+
/// getNumTokens - Return the number of tokens that this macro expands to.
///
unsigned getNumTokens() const {
diff --git a/include/clang/Lex/Makefile b/include/clang/Lex/Makefile
new file mode 100644
index 000000000000..9874bcffb3e1
--- /dev/null
+++ b/include/clang/Lex/Makefile
@@ -0,0 +1,13 @@
+CLANG_LEVEL := ../../..
+TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
+BUILT_SOURCES = AttrSpellings.inc
+
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(CLANG_LEVEL)/Makefile
+
+$(ObjDir)/AttrSpellings.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang attribute spellings with tblgen"
+ $(Verb) $(TableGen) -gen-clang-attr-spelling-list -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 782f2d57a5c6..b2a80a62985f 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -54,12 +54,43 @@ public:
SrcMgr::CharacteristicKind FileType) {
}
+ /// \brief This callback is invoked whenever an inclusion directive of
+ /// any kind (\c #include, \c #import, etc.) has been processed, regardless
+ /// of whether the inclusion will actually result in an inclusion.
+ ///
+ /// \param HashLoc The location of the '#' that starts the inclusion
+ /// directive.
+ ///
+ /// \param IncludeTok The token that indicates the kind of inclusion
+ /// directive, e.g., 'include' or 'import'.
+ ///
+ /// \param FileName The name of the file being included, as written in the
+ /// source code.
+ ///
+ /// \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 EndLoc The location of the last token within the inclusion
+ /// directive.
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ SourceLocation EndLoc) {
+ }
+
/// EndOfMainFile - This callback is invoked when the end of the main file is
/// reach, no subsequent callbacks will be made.
virtual void EndOfMainFile() {
}
/// Ident - This callback is invoked when a #ident or #sccs directive is read.
+ /// \param Loc The location of the directive.
+ /// \param str The text of the directive.
///
virtual void Ident(SourceLocation Loc, const std::string &str) {
}
@@ -73,6 +104,8 @@ public:
/// PragmaMessage - This callback is invoked when a #pragma message directive
/// is read.
+ /// \param Loc The location of the message directive.
+ /// \param str The text of the message directive.
///
virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) {
}
@@ -80,17 +113,48 @@ public:
/// MacroExpands - This is called by
/// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
/// found.
- virtual void MacroExpands(const Token &Id, const MacroInfo* MI) {
+ virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) {
}
/// MacroDefined - This hook is called whenever a macro definition is seen.
- virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) {
+ virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
}
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
/// MI is released immediately following this callback.
- virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
- const MacroInfo *MI) {
+ virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ }
+
+ /// If -- This hook is called whenever an #if is seen.
+ /// \param Range The SourceRange of the expression being tested.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void If(SourceRange Range) {
+ }
+
+ /// Elif -- This hook is called whenever an #elif is seen.
+ /// \param Range The SourceRange of the expression being tested.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void Elif(SourceRange Range) {
+ }
+
+ /// Ifdef -- This hook is called whenever an #ifdef is seen.
+ /// \param Loc The location of the token being tested.
+ /// \param II Information on the token being tested.
+ virtual void Ifdef(const Token &MacroNameTok) {
+ }
+
+ /// Ifndef -- This hook is called whenever an #ifndef is seen.
+ /// \param Loc The location of the token being tested.
+ /// \param II Information on the token being tested.
+ virtual void Ifndef(const Token &MacroNameTok) {
+ }
+
+ /// Else -- This hook is called whenever an #else is seen.
+ virtual void Else() {
+ }
+
+ /// Endif -- This hook is called whenever an #endif is seen.
+ virtual void Endif() {
}
};
@@ -119,6 +183,18 @@ public:
Second->FileSkipped(ParentFile, FilenameTok, FileType);
}
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ SourceLocation EndLoc) {
+ First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
+ EndLoc);
+ Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
+ EndLoc);
+ }
+
virtual void EndOfMainFile() {
First->EndOfMainFile();
Second->EndOfMainFile();
@@ -140,20 +216,55 @@ public:
Second->PragmaMessage(Loc, Str);
}
- virtual void MacroExpands(const Token &Id, const MacroInfo* MI) {
- First->MacroExpands(Id, MI);
- Second->MacroExpands(Id, MI);
+ virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) {
+ First->MacroExpands(MacroNameTok, MI);
+ Second->MacroExpands(MacroNameTok, MI);
+ }
+
+ virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ First->MacroDefined(MacroNameTok, MI);
+ Second->MacroDefined(MacroNameTok, MI);
+ }
+
+ virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ First->MacroUndefined(MacroNameTok, MI);
+ Second->MacroUndefined(MacroNameTok, MI);
+ }
+
+ /// If -- This hook is called whenever an #if is seen.
+ virtual void If(SourceRange Range) {
+ First->If(Range);
+ Second->If(Range);
+ }
+
+ /// Elif -- This hook is called whenever an #if is seen.
+ virtual void Elif(SourceRange Range) {
+ First->Elif(Range);
+ Second->Elif(Range);
+ }
+
+ /// Ifdef -- This hook is called whenever an #ifdef is seen.
+ virtual void Ifdef(const Token &MacroNameTok) {
+ First->Ifdef(MacroNameTok);
+ Second->Ifdef(MacroNameTok);
+ }
+
+ /// Ifndef -- This hook is called whenever an #ifndef is seen.
+ virtual void Ifndef(const Token &MacroNameTok) {
+ First->Ifndef(MacroNameTok);
+ Second->Ifndef(MacroNameTok);
}
- virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) {
- First->MacroDefined(II, MI);
- Second->MacroDefined(II, MI);
+ /// Else -- This hook is called whenever an #else is seen.
+ virtual void Else() {
+ First->Else();
+ Second->Else();
}
- virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
- const MacroInfo *MI) {
- First->MacroUndefined(Loc, II, MI);
- Second->MacroUndefined(Loc, II, MI);
+ /// Endif -- This hook is called whenever an #endif is seen.
+ virtual void Endif() {
+ First->Endif();
+ Second->Endif();
}
};
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
index 5e8a4f144c96..094b7ef66798 100644
--- a/include/clang/Lex/PTHManager.h
+++ b/include/clang/Lex/PTHManager.h
@@ -31,7 +31,7 @@ namespace clang {
class FileEntry;
class PTHLexer;
class Diagnostic;
-class StatSysCallCache;
+class FileSystemStatCache;
class PTHManager : public IdentifierInfoLookup {
friend class PTHLexer;
@@ -128,11 +128,11 @@ public:
/// It is the responsibility of the caller to 'delete' the returned object.
PTHLexer *CreateLexer(FileID FID);
- /// createStatCache - Returns a StatSysCallCache object for use with
+ /// createStatCache - Returns a FileSystemStatCache object for use with
/// FileManager objects. These objects use the PTH data to speed up
/// calls to stat by memoizing their results from when the PTH file
/// was generated.
- StatSysCallCache *createStatCache();
+ FileSystemStatCache *createStatCache();
};
} // end namespace clang
diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h
index c68555b2f967..8bd22369476e 100644
--- a/include/clang/Lex/Pragma.h
+++ b/include/clang/Lex/Pragma.h
@@ -25,6 +25,28 @@ namespace clang {
class IdentifierInfo;
class PragmaNamespace;
+ /**
+ * \brief Describes how the pragma was introduced, e.g., with #pragma,
+ * _Pragma, or __pragma.
+ */
+ enum PragmaIntroducerKind {
+ /**
+ * \brief The pragma was introduced via #pragma.
+ */
+ PIK_HashPragma,
+
+ /**
+ * \brief The pragma was introduced via the C99 _Pragma(string-literal).
+ */
+ PIK__Pragma,
+
+ /**
+ * \brief The pragma was introduced via the Microsoft
+ * __pragma(token-string).
+ */
+ PIK___pragma
+ };
+
/// PragmaHandler - Instances of this interface defined to handle the various
/// pragmas that the language front-end uses. Each handler optionally has a
/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with
@@ -42,7 +64,8 @@ public:
virtual ~PragmaHandler();
llvm::StringRef getName() const { return Name; }
- virtual void HandlePragma(Preprocessor &PP, Token &FirstToken) = 0;
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) = 0;
/// getIfNamespace - If this is a namespace, return it. This is equivalent to
/// using a dynamic_cast, but doesn't require RTTI.
@@ -55,7 +78,8 @@ class EmptyPragmaHandler : public PragmaHandler {
public:
EmptyPragmaHandler();
- virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
};
/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
@@ -90,7 +114,8 @@ public:
return Handlers.empty();
}
- virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
virtual PragmaNamespace *getIfNamespace() { return this; }
};
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 730f04f2fa09..afd7ae1187cc 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -35,6 +35,7 @@ void operator delete(void* ptr, clang::PreprocessingRecord& PR,
namespace clang {
class MacroDefinition;
+ class FileEntry;
/// \brief Base class that describes a preprocessed entity, which may be a
/// preprocessor directive or macro instantiation.
@@ -54,8 +55,12 @@ namespace clang {
/// \brief A macro definition.
MacroDefinitionKind,
+ /// \brief An inclusion directive, such as \c #include, \c
+ /// #import, or \c #include_next.
+ InclusionDirectiveKind,
+
FirstPreprocessingDirective = PreprocessingDirectiveKind,
- LastPreprocessingDirective = MacroDefinitionKind
+ LastPreprocessingDirective = InclusionDirectiveKind
};
private:
@@ -173,6 +178,66 @@ namespace clang {
}
static bool classof(const MacroDefinition *) { return true; }
};
+
+ /// \brief Record the location of an inclusion directive, such as an
+ /// \c #include or \c #import statement.
+ class InclusionDirective : public PreprocessingDirective {
+ public:
+ /// \brief The kind of inclusion directives known to the
+ /// preprocessor.
+ enum InclusionKind {
+ /// \brief An \c #include directive.
+ Include,
+ /// \brief An Objective-C \c #import directive.
+ Import,
+ /// \brief A GNU \c #include_next directive.
+ IncludeNext,
+ /// \brief A Clang \c #__include_macros directive.
+ IncludeMacros
+ };
+
+ private:
+ /// \brief The name of the file that was included, as written in
+ /// the source.
+ llvm::StringRef FileName;
+
+ /// \brief Whether the file name was in quotation marks; otherwise, it was
+ /// in angle brackets.
+ unsigned InQuotes : 1;
+
+ /// \brief The kind of inclusion directive we have.
+ ///
+ /// This is a value of type InclusionKind.
+ unsigned Kind : 2;
+
+ /// \brief The file that was included.
+ const FileEntry *File;
+
+ public:
+ InclusionDirective(PreprocessingRecord &PPRec,
+ InclusionKind Kind, llvm::StringRef FileName,
+ bool InQuotes, const FileEntry *File, SourceRange Range);
+
+ /// \brief Determine what kind of inclusion directive this is.
+ InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); }
+
+ /// \brief Retrieve the included file name as it was written in the source.
+ llvm::StringRef getFileName() const { return FileName; }
+
+ /// \brief Determine whether the included file name was written in quotes;
+ /// otherwise, it was written in angle brackets.
+ bool wasInQuotes() const { return InQuotes; }
+
+ /// \brief Retrieve the file entry for the actual file that was included
+ /// by this directive.
+ const FileEntry *getFile() const { return File; }
+
+ // Implement isa/cast/dyncast/etc.
+ 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
/// of preprocessing record entries.
@@ -183,6 +248,10 @@ namespace clang {
/// \brief Read any preallocated preprocessed entities from the external
/// source.
virtual void ReadPreprocessedEntities() = 0;
+
+ /// \brief Read the preprocessed entity at the given offset.
+ virtual PreprocessedEntity *
+ ReadPreprocessedEntityAtOffset(uint64_t Offset) = 0;
};
/// \brief A record of the steps taken while preprocessing a source file,
@@ -229,13 +298,22 @@ namespace clang {
iterator end(bool OnlyLocalEntities = false);
const_iterator begin(bool OnlyLocalEntities = false) const;
const_iterator end(bool OnlyLocalEntities = false) const;
-
+
/// \brief Add a new preprocessed entity to this record.
void addPreprocessedEntity(PreprocessedEntity *Entity);
/// \brief Set the external source for preprocessed entities.
void SetExternalSource(ExternalPreprocessingRecordSource &Source,
unsigned NumPreallocatedEntities);
+
+ /// \brief Retrieve the external source for preprocessed entities.
+ ExternalPreprocessingRecordSource *getExternalSource() const {
+ return ExternalSource;
+ }
+
+ unsigned getNumPreallocatedEntities() const {
+ return NumPreallocatedEntities;
+ }
/// \brief Set the preallocated entry at the given index to the given
/// preprocessed entity.
@@ -256,9 +334,14 @@ namespace clang {
MacroDefinition *findMacroDefinition(const MacroInfo *MI);
virtual void MacroExpands(const Token &Id, const MacroInfo* MI);
- virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
- virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
- const MacroInfo *MI);
+ virtual void MacroDefined(const Token &Id, const MacroInfo *MI);
+ virtual void MacroUndefined(const Token &Id, const MacroInfo *MI);
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ SourceLocation EndLoc);
};
} // end namespace clang
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 6b9b89ea5eb9..018f7e9c8c02 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H
#define LLVM_CLANG_LEX_PREPROCESSOR_H
+#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/PPCallbacks.h"
@@ -24,6 +25,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
@@ -82,6 +84,7 @@ class Preprocessor {
IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
IdentifierInfo *Ident__has_feature; // __has_feature
IdentifierInfo *Ident__has_builtin; // __has_builtin
+ IdentifierInfo *Ident__has_attribute; // __has_attribute
IdentifierInfo *Ident__has_include; // __has_include
IdentifierInfo *Ident__has_include_next; // __has_include_next
@@ -194,10 +197,15 @@ class Preprocessor {
/// to the actual definition of the macro.
llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros;
- /// MICache - A "freelist" of MacroInfo objects that can be reused for quick
- /// allocation.
- /// FIXME: why not use a singly linked list?
- std::vector<MacroInfo*> MICache;
+ /// \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
+ /// deserializing from PCH, we don't need to deserialize identifier & macros
+ /// just so that we can report that they are unused, we just warn using
+ /// the SourceLocations of this set (that will be filled by the ASTReader).
+ /// We are using SmallPtrSet instead of a vector for faster removal.
+ typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy;
+ WarnUnusedMacroLocsTy WarnUnusedMacroLocs;
/// MacroArgCache - This is a "freelist" of MacroArg objects that can be
/// reused for quick allocation.
@@ -251,6 +259,22 @@ private: // Cached tokens state.
/// invoked (at which point the last position is popped).
std::vector<CachedTokensTy::size_type> BacktrackPositions;
+ struct MacroInfoChain {
+ MacroInfo MI;
+ MacroInfoChain *Next;
+ MacroInfoChain *Prev;
+ };
+
+ /// MacroInfos are managed as a chain for easy disposal. This is the head
+ /// of that list.
+ MacroInfoChain *MIChainHead;
+
+ /// MICache - A "freelist" of MacroInfo objects that can be reused for quick
+ /// allocation.
+ MacroInfoChain *MICache;
+
+ MacroInfo *getInfoForMacro(IdentifierInfo *II) const;
+
public:
Preprocessor(Diagnostic &diags, const LangOptions &opts,
const TargetInfo &target,
@@ -324,7 +348,10 @@ public:
/// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to
/// or null if it isn't #define'd.
MacroInfo *getMacroInfo(IdentifierInfo *II) const {
- return II->hasMacroDefinition() ? Macros.find(II)->second : 0;
+ if (!II->hasMacroDefinition())
+ return 0;
+
+ return getInfoForMacro(II);
}
/// setMacroInfo - Specify a macro for this identifier.
@@ -591,6 +618,9 @@ public:
/// for which we are performing code completion.
bool isCodeCompletionFile(SourceLocation FileLoc) const;
+ /// \brief Determine if we are performing code completion.
+ bool isCodeCompletionEnabled() const { return CodeCompletionFile != 0; }
+
/// \brief Instruct the preprocessor to skip part of the main
/// the main source file.
///
@@ -607,12 +637,11 @@ public:
/// the specified Token's location, translating the token's start
/// position in the current buffer into a SourcePosition object for rendering.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
- return Diags->Report(FullSourceLoc(Loc, getSourceManager()), DiagID);
+ return Diags->Report(Loc, DiagID);
}
DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) {
- return Diags->Report(FullSourceLoc(Tok.getLocation(), getSourceManager()),
- DiagID);
+ return Diags->Report(Tok.getLocation(), DiagID);
}
/// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
@@ -622,17 +651,9 @@ public:
/// UCNs, etc.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurs.
- std::string getSpelling(const Token &Tok, bool *Invalid = 0) const;
-
- /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
- /// token is the characters used to represent the token in the source file
- /// after trigraph expansion and escaped-newline folding. In particular, this
- /// wants to get the true, uncanonicalized, spelling of things like digraphs
- /// UCNs, etc.
- static std::string getSpelling(const Token &Tok,
- const SourceManager &SourceMgr,
- const LangOptions &Features,
- bool *Invalid = 0);
+ std::string getSpelling(const Token &Tok, bool *Invalid = 0) const {
+ return Lexer::getSpelling(Tok, SourceMgr, Features, Invalid);
+ }
/// getSpelling - This method is used to get the spelling of a token into a
/// preallocated buffer, instead of as an std::string. The caller is required
@@ -645,7 +666,9 @@ public:
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
unsigned getSpelling(const Token &Tok, const char *&Buffer,
- bool *Invalid = 0) const;
+ bool *Invalid = 0) const {
+ return Lexer::getSpelling(Tok, Buffer, SourceMgr, Features, Invalid);
+ }
/// getSpelling - This method is used to get the spelling of a token into a
/// SmallVector. Note that the returned StringRef may not point to the
@@ -692,7 +715,9 @@ public:
/// location should refer to. The default offset (0) produces a source
/// location pointing just past the end of the token; an offset of 1 produces
/// a source location pointing to the last character in the token, etc.
- SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
+ SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0) {
+ return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, Features);
+ }
/// DumpToken - Print the token to stderr, used for debugging.
///
@@ -702,7 +727,10 @@ public:
/// AdvanceToTokenCharacter - Given a location that specifies the start of a
/// token, return a new location that specifies a character within the token.
- SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,unsigned Char);
+ SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
+ unsigned Char) const {
+ return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, Features);
+ }
/// IncrementPasteCounter - Increment the counters for the number of token
/// paste operations performed. If fast was specified, this is a 'fast paste'
@@ -726,10 +754,10 @@ public:
// Preprocessor callback methods. These are invoked by a lexer as various
// directives and events are found.
- /// LookUpIdentifierInfo - Given a tok::identifier token, look up the
- /// identifier information for the token and install it into the token.
- IdentifierInfo *LookUpIdentifierInfo(Token &Identifier,
- const char *BufPtr = 0) const;
+ /// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the
+ /// identifier information for the token and install it into the token,
+ /// updating the token kind accordingly.
+ IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const;
/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier and has filled in the tokens IdentifierInfo member. This
@@ -812,7 +840,12 @@ public:
/// This code concatenates and consumes tokens up to the '>' token. It
/// returns false if the > was found, otherwise it returns true if it finds
/// and consumes the EOM marker.
- bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer);
+ bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer,
+ SourceLocation &End);
+
+ /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is
+ /// followed by EOM. Return true if the token is not a valid on-off-switch.
+ bool LexOnOffSwitch(tok::OnOffSwitch &OOS);
private:
@@ -909,8 +942,8 @@ private:
/// is not enclosed within a string literal.
void HandleMicrosoft__pragma(Token &Tok);
- void Handle_Pragma(const std::string &StrVal, SourceLocation PragmaLoc,
- SourceLocation RParenLoc);
+ void Handle_Pragma(unsigned Introducer, const std::string &StrVal,
+ SourceLocation PragmaLoc, SourceLocation RParenLoc);
/// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
@@ -961,12 +994,13 @@ private:
void HandleIdentSCCSDirective(Token &Tok);
// File inclusion.
- void HandleIncludeDirective(Token &Tok,
+ void HandleIncludeDirective(SourceLocation HashLoc,
+ Token &Tok,
const DirectoryLookup *LookupFrom = 0,
bool isImport = false);
- void HandleIncludeNextDirective(Token &Tok);
- void HandleIncludeMacrosDirective(Token &Tok);
- void HandleImportDirective(Token &Tok);
+ void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
// Macro handling.
void HandleDefineDirective(Token &Tok);
@@ -981,7 +1015,7 @@ private:
void HandleElifDirective(Token &Tok);
// Pragmas.
- void HandlePragmaDirective();
+ void HandlePragmaDirective(unsigned Introducer);
public:
void HandlePragmaOnce(Token &OnceTok);
void HandlePragmaMark();
@@ -997,6 +1031,10 @@ public:
// Return true and store the first token only if any CommentHandler
// has inserted some tokens and getCommentRetentionState() is false.
bool HandleComment(Token &Token, SourceRange Comment);
+
+ /// \brief A macro is used, update information about macros that need unused
+ /// warnings.
+ void markMacroAsUsed(MacroInfo *MI);
};
/// \brief Abstract base class that describes a handler that will receive
diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h
index 477a2130cf0e..d8332938a7ed 100644
--- a/include/clang/Lex/PreprocessorLexer.h
+++ b/include/clang/Lex/PreprocessorLexer.h
@@ -155,6 +155,18 @@ public:
/// getFileEntry - Return the FileEntry corresponding to this FileID. Like
/// getFileID(), this only works for lexers with attached preprocessors.
const FileEntry *getFileEntry() const;
+
+ /// \brief Iterator that traverses the current stack of preprocessor
+ /// conditional directives (#if/#ifdef/#ifndef).
+ typedef llvm::SmallVectorImpl<PPConditionalInfo>::const_iterator
+ conditional_iterator;
+
+ conditional_iterator conditional_begin() const {
+ return ConditionalStack.begin();
+ }
+ conditional_iterator conditional_end() const {
+ return ConditionalStack.end();
+ }
};
} // end namespace clang
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index 954b36ec6d11..edcfcc10d2ee 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -76,7 +76,8 @@ public:
StartOfLine = 0x01, // At start of line or only after whitespace.
LeadingSpace = 0x02, // Whitespace exists before this token.
DisableExpand = 0x04, // This identifier may never be macro expanded.
- NeedsCleaning = 0x08 // Contained an escaped newline or trigraph.
+ NeedsCleaning = 0x08, // Contained an escaped newline or trigraph.
+ LeadingEmptyMacro = 0x10 // Empty macro exists before this token.
};
tok::TokenKind getKind() const { return (tok::TokenKind)Kind; }
@@ -87,6 +88,12 @@ public:
bool is(tok::TokenKind K) const { return Kind == (unsigned) K; }
bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; }
+ /// isAnyIdentifier - 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);
+ }
+
/// isLiteral - Return true if this is a "literal", like a numeric
/// constant, string, etc.
bool isLiteral() const {
@@ -96,9 +103,11 @@ public:
}
bool isAnnotation() const {
- return is(tok::annot_typename) ||
- is(tok::annot_cxxscope) ||
- is(tok::annot_template_id);
+#define ANNOTATION(NAME) \
+ if (is(tok::annot_##NAME)) \
+ return true;
+#include "clang/Basic/TokenKinds.def"
+ return false;
}
/// getLocation - Return a source location identifier for the specified
@@ -153,7 +162,10 @@ public:
}
IdentifierInfo *getIdentifierInfo() const {
- assert(!isAnnotation() && "Used IdentInfo on annotation token!");
+ assert(isNot(tok::raw_identifier) &&
+ "getIdentifierInfo() on a tok::raw_identifier token!");
+ assert(!isAnnotation() &&
+ "getIdentifierInfo() on an annotation token!");
if (isLiteral()) return 0;
return (IdentifierInfo*) PtrData;
}
@@ -161,6 +173,18 @@ public:
PtrData = (void*) II;
}
+ /// getRawIdentifierData - For a raw identifier token (i.e., an identifier
+ /// lexed in raw mode), returns a pointer to the start of it in the text
+ /// buffer if known, null otherwise.
+ const char *getRawIdentifierData() const {
+ assert(is(tok::raw_identifier));
+ return reinterpret_cast<const char*>(PtrData);
+ }
+ void setRawIdentifierData(const char *Ptr) {
+ assert(is(tok::raw_identifier));
+ PtrData = const_cast<char*>(Ptr);
+ }
+
/// getLiteralData - For a literal token (numeric constant, string, etc), this
/// returns a pointer to the start of it in the text buffer if known, null
/// otherwise.
@@ -231,7 +255,13 @@ public:
/// newlines in it.
///
bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; }
-
+
+ /// \brief Return true if this token has an empty macro before it.
+ ///
+ bool hasLeadingEmptyMacro() const {
+ return (Flags & LeadingEmptyMacro) ? true : false;
+ }
+
};
/// PPConditionalInfo - Information about the conditional stack (#if directives)
diff --git a/include/clang/Makefile b/include/clang/Makefile
index 030b0720fd81..d6b9844285d2 100644
--- a/include/clang/Makefile
+++ b/include/clang/Makefile
@@ -1,5 +1,5 @@
CLANG_LEVEL := ../..
-DIRS := AST Basic Driver Serialization
+DIRS := AST Basic Driver Lex Serialization
include $(CLANG_LEVEL)/Makefile
diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h
index d7c5eee8d916..f640b37c1982 100644
--- a/include/clang/Parse/ParseDiagnostic.h
+++ b/include/clang/Parse/ParseDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define PARSESTART
#include "clang/Basic/DiagnosticParseKinds.inc"
#undef DIAG
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 41a2fb615791..758792097639 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -25,8 +25,6 @@
#include <list>
namespace clang {
- class AttributeList;
- struct CXX0XAttributeList;
class PragmaHandler;
class Scope;
class DeclGroupRef;
@@ -34,7 +32,8 @@ namespace clang {
class Parser;
class PragmaUnusedHandler;
class ColonProtectionRAIIObject;
-
+ class InMessageExpressionRAIIObject;
+
/// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
/// an entry is printed for it.
class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
@@ -75,6 +74,7 @@ namespace prec {
class Parser : public CodeCompletionHandler {
friend class PragmaUnusedHandler;
friend class ColonProtectionRAIIObject;
+ friend class InMessageExpressionRAIIObject;
friend class ParenBraceBracketBalancer;
PrettyStackTraceParserEntry CrashInfo;
@@ -112,12 +112,18 @@ class Parser : public CodeCompletionHandler {
IdentifierInfo *Ident_vector;
IdentifierInfo *Ident_pixel;
+ /// C++0x contextual keywords.
+ mutable IdentifierInfo *Ident_final;
+ mutable IdentifierInfo *Ident_override;
+
llvm::OwningPtr<PragmaHandler> AlignHandler;
llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler;
llvm::OwningPtr<PragmaHandler> OptionsHandler;
llvm::OwningPtr<PragmaHandler> PackHandler;
llvm::OwningPtr<PragmaHandler> UnusedHandler;
llvm::OwningPtr<PragmaHandler> WeakHandler;
+ llvm::OwningPtr<PragmaHandler> FPContractHandler;
+ llvm::OwningPtr<PragmaHandler> OpenCLExtensionHandler;
/// Whether the '>' token acts as an operator or not. This will be
/// true except when we are parsing an expression within a C++
@@ -131,8 +137,18 @@ class Parser : public CodeCompletionHandler {
/// ColonProtectionRAIIObject RAII object.
bool ColonIsSacred;
+ /// \brief When true, we are directly inside an Ojective-C messsage
+ /// send expression.
+ ///
+ /// This is managed by the \c InMessageExpressionRAIIObject class, and
+ /// should not be set directly.
+ bool InMessageExpression;
+
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;
+
+ /// Factory object for creating AttributeList objects.
+ AttributeList::Factory AttrFactory;
public:
Parser(Preprocessor &PP, Sema &Actions);
@@ -152,7 +168,7 @@ public:
typedef Stmt StmtTy;
typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
typedef CXXBaseSpecifier BaseTy;
- typedef CXXBaseOrMemberInitializer MemInitTy;
+ typedef CXXCtorInitializer MemInitTy;
typedef NestedNameSpecifier CXXScopeTy;
typedef TemplateParameterList TemplateParamsTy;
typedef OpaquePtr<TemplateName> TemplateTy;
@@ -227,6 +243,11 @@ private:
Tok.getKind() == tok::wide_string_literal;
}
+ /// \brief Returns true if the current token is a '=' or '==' and
+ /// false otherwise. If it's '==', we assume that it's a typo and we emit
+ /// DiagID and a fixit hint to turn '==' -> '='.
+ bool isTokenEqualOrMistypedEqualEqual(unsigned DiagID);
+
/// 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
@@ -330,6 +351,9 @@ private:
/// based on context.
void CodeCompletionRecovery();
+ /// \brief Handle the annotation token produced for #pragma unused(...)
+ void HandlePragmaUnused();
+
/// 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.
@@ -464,6 +488,13 @@ private:
const char *DiagMsg = "",
tok::TokenKind SkipToTok = tok::unknown);
+ /// \brief The parser expects a semicolon and, if present, will consume it.
+ ///
+ /// If the next token is not a semicolon, this emits the specified diagnostic,
+ /// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior
+ /// to the semicolon, consumes that extra token.
+ bool ExpectAndConsumeSemi(unsigned DiagID);
+
//===--------------------------------------------------------------------===//
// Scope manipulation
@@ -531,21 +562,59 @@ private:
/// If SkipUntil finds the specified token, it returns true, otherwise it
/// returns false.
bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true,
- bool DontConsume = false) {
- return SkipUntil(&T, 1, StopAtSemi, DontConsume);
+ bool DontConsume = false, bool StopAtCodeCompletion = false) {
+ return SkipUntil(&T, 1, StopAtSemi, DontConsume, StopAtCodeCompletion);
}
bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true,
- bool DontConsume = false) {
+ bool DontConsume = false, bool StopAtCodeCompletion = false) {
tok::TokenKind TokArray[] = {T1, T2};
- return SkipUntil(TokArray, 2, StopAtSemi, DontConsume);
+ return SkipUntil(TokArray, 2, StopAtSemi, DontConsume,StopAtCodeCompletion);
}
bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
- bool StopAtSemi = true, bool DontConsume = false);
+ bool StopAtSemi = true, bool DontConsume = false,
+ bool StopAtCodeCompletion = false);
//===--------------------------------------------------------------------===//
// Lexing and parsing of C++ inline methods.
- struct LexedMethod {
+ struct ParsingClass;
+
+ /// [class.mem]p1: "... the class is regarded as complete within
+ /// - function bodies
+ /// - default arguments
+ /// - exception-specifications (TODO: C++0x)
+ /// - and brace-or-equal-initializers (TODO: C++0x)
+ /// for non-static data members (including such things in nested classes)."
+ /// LateParsedDeclarations build the tree of those elements so they can
+ /// be parsed after parsing the top-level class.
+ class LateParsedDeclaration {
+ public:
+ virtual ~LateParsedDeclaration();
+
+ virtual void ParseLexedMethodDeclarations();
+ virtual void ParseLexedMethodDefs();
+ };
+
+ /// Inner node of the LateParsedDeclaration tree that parses
+ /// all its members recursively.
+ class LateParsedClass : public LateParsedDeclaration {
+ public:
+ LateParsedClass(Parser *P, ParsingClass *C);
+ virtual ~LateParsedClass();
+
+ virtual void ParseLexedMethodDeclarations();
+ virtual void ParseLexedMethodDefs();
+
+ private:
+ Parser *Self;
+ ParsingClass *Class;
+ };
+
+ /// Contains the lexed tokens of a member function definition
+ /// which needs to be parsed at the end of the class declaration
+ /// after parsing all other member declarations.
+ struct LexedMethod : public LateParsedDeclaration {
+ Parser *Self;
Decl *D;
CachedTokens Toks;
@@ -554,7 +623,10 @@ private:
/// othewise, it is a member function declaration.
bool TemplateScope;
- explicit LexedMethod(Decl *MD) : D(MD), TemplateScope(false) {}
+ explicit LexedMethod(Parser* P, Decl *MD)
+ : Self(P), D(MD), TemplateScope(false) {}
+
+ virtual void ParseLexedMethodDefs();
};
/// LateParsedDefaultArgument - Keeps track of a parameter that may
@@ -580,9 +652,13 @@ private:
/// contains at least one entity whose parsing needs to be delayed
/// until the class itself is completely-defined, such as a default
/// argument (C++ [class.mem]p2).
- struct LateParsedMethodDeclaration {
- explicit LateParsedMethodDeclaration(Decl *M)
- : Method(M), TemplateScope(false) { }
+ struct LateParsedMethodDeclaration : public LateParsedDeclaration {
+ explicit LateParsedMethodDeclaration(Parser *P, Decl *M)
+ : Self(P), Method(M), TemplateScope(false) { }
+
+ virtual void ParseLexedMethodDeclarations();
+
+ Parser* Self;
/// Method - The method declaration.
Decl *Method;
@@ -600,17 +676,12 @@ private:
llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
};
- /// LateParsedMethodDecls - During parsing of a top (non-nested) C++
- /// class, its method declarations that contain parts that won't be
+ /// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
+ /// C++ class, its method declarations that contain parts that won't be
/// parsed until after the definiton is completed (C++ [class.mem]p2),
- /// the method declarations will be stored here with the tokens that
- /// will be parsed to create those entities.
- typedef std::list<LateParsedMethodDeclaration> LateParsedMethodDecls;
-
- /// LexedMethodsForTopClass - During parsing of a top (non-nested) C++ class,
- /// its inline method definitions and the inline method definitions of its
- /// nested classes are lexed and stored here.
- typedef std::list<LexedMethod> LexedMethodsForTopClass;
+ /// the method declarations and possibly attached inline definitions
+ /// will be stored here with the tokens that will be parsed to create those entities.
+ typedef llvm::SmallVector<LateParsedDeclaration*, 2> LateParsedDeclarationsContainer;
/// \brief Representation of a class that has been parsed, including
/// any member function declarations or definitions that need to be
@@ -632,16 +703,10 @@ private:
/// \brief The class or class template whose definition we are parsing.
Decl *TagOrTemplate;
- /// MethodDecls - Method declarations that contain pieces whose
- /// parsing will be delayed until the class is fully defined.
- LateParsedMethodDecls MethodDecls;
-
- /// MethodDefs - Methods whose definitions will be parsed once the
- /// class has been fully defined.
- LexedMethodsForTopClass MethodDefs;
-
- /// \brief Nested classes inside this class.
- llvm::SmallVector<ParsingClass*, 4> NestedClasses;
+ /// LateParsedDeclarations - Method declarations, inline definitions and
+ /// nested classes that contain pieces whose parsing will be delayed until
+ /// the top-level class is fully defined.
+ LateParsedDeclarationsContainer LateParsedDeclarations;
};
/// \brief The stack of classes that is currently being
@@ -660,7 +725,7 @@ private:
/// class or function definition.
class ParsingDeclRAIIObject {
Sema &Actions;
- Sema::ParsingDeclStackState State;
+ Sema::ParsingDeclState State;
bool Popped;
public:
@@ -772,23 +837,24 @@ private:
class ParsingClassDefinition {
Parser &P;
bool Popped;
+ Sema::ParsingClassState State;
public:
ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass)
- : P(P), Popped(false) {
- P.PushParsingClass(TagOrTemplate, TopLevelClass);
+ : P(P), Popped(false),
+ State(P.PushParsingClass(TagOrTemplate, TopLevelClass)) {
}
/// \brief Pop this class of the stack.
void Pop() {
assert(!Popped && "Nested class has already been popped");
Popped = true;
- P.PopParsingClass();
+ P.PopParsingClass(State);
}
~ParsingClassDefinition() {
if (!Popped)
- P.PopParsingClass();
+ P.PopParsingClass(State);
}
};
@@ -838,16 +904,22 @@ private:
/// \brief Whether the last template parameter list was empty.
bool LastParameterListWasEmpty;
+
+ SourceRange getSourceRange() const;
};
- void PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass);
+ Sema::ParsingClassState
+ PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass);
void DeallocateParsedClasses(ParsingClass *Class);
- void PopParsingClass();
+ void PopParsingClass(Sema::ParsingClassState);
- Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
- const ParsedTemplateInfo &TemplateInfo);
+ Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo,
+ const VirtSpecifiers& VS);
void ParseLexedMethodDeclarations(ParsingClass &Class);
+ void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
void ParseLexedMethodDefs(ParsingClass &Class);
+ void ParseLexedMethodDef(LexedMethod &LM);
bool ConsumeAndStoreUntil(tok::TokenKind T1,
CachedTokens &Toks,
bool StopAtSemi = true,
@@ -861,14 +933,17 @@ private:
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
- DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr,
+ struct ParsedAttributesWithRange : ParsedAttributes {
+ SourceRange Range;
+ };
+
+ DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParsingDeclSpec *DS = 0);
bool isDeclarationAfterDeclarator() const;
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
- DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
- AccessSpecifier AS = AS_none);
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
+ AccessSpecifier AS = AS_none);
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
- AttributeList *Attr,
AccessSpecifier AS = AS_none);
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
@@ -883,7 +958,7 @@ private:
Decl *ParseObjCAtDirectives();
Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
- AttributeList *prefixAttrs = 0);
+ ParsedAttributes &prefixAttrs);
void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
tok::ObjCKeywordKind visibility,
SourceLocation atLoc);
@@ -892,10 +967,11 @@ private:
bool WarnOnDeclarations,
SourceLocation &LAngleLoc,
SourceLocation &EndProtoLoc);
+ bool ParseObjCProtocolQualifiers(DeclSpec &DS);
void ParseObjCInterfaceDeclList(Decl *interfaceDecl,
tok::ObjCKeywordKind contextKey);
Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
- AttributeList *prefixAttrs = 0);
+ ParsedAttributes &prefixAttrs);
Decl *ObjCImpDecl;
llvm::SmallVector<Decl *, 4> PendingObjCImpDecl;
@@ -923,8 +999,7 @@ private:
Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
Decl *classDecl,
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
- void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl,
- Decl **Methods, unsigned NumMethods);
+ void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl);
Decl *ParseObjCMethodDefinition();
@@ -1022,6 +1097,10 @@ private:
ExprResult ParseCXXTypeid();
//===--------------------------------------------------------------------===//
+ // C++ : Microsoft __uuidof Expression
+ ExprResult ParseCXXUuidof();
+
+ //===--------------------------------------------------------------------===//
// C++ 5.2.4: C++ Pseudo-Destructor Expressions
ExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
tok::TokenKind OpKind,
@@ -1042,6 +1121,10 @@ private:
bool &hasAnyExceptionSpec);
//===--------------------------------------------------------------------===//
+ // C++0x 8: Function declaration trailing-return-type
+ TypeResult ParseTrailingReturnType();
+
+ //===--------------------------------------------------------------------===//
// C++ 2.13.5: C++ Boolean Literals
ExprResult ParseCXXBoolLiteral();
@@ -1117,30 +1200,32 @@ private:
// C99 6.8: Statements and Blocks.
StmtResult ParseStatement() {
- return ParseStatementOrDeclaration(true);
+ StmtVector Stmts(Actions);
+ return ParseStatementOrDeclaration(Stmts, true);
}
- StmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
- StmtResult ParseLabeledStatement(AttributeList *Attr);
- StmtResult ParseCaseStatement(AttributeList *Attr);
- StmtResult ParseDefaultStatement(AttributeList *Attr);
- StmtResult ParseCompoundStatement(AttributeList *Attr,
+ StmtResult ParseStatementOrDeclaration(StmtVector& Stmts,
+ bool OnlyStatement = false);
+ StmtResult ParseLabeledStatement(ParsedAttributes &Attr);
+ StmtResult ParseCaseStatement(ParsedAttributes &Attr);
+ StmtResult ParseDefaultStatement(ParsedAttributes &Attr);
+ StmtResult ParseCompoundStatement(ParsedAttributes &Attr,
bool isStmtExpr = false);
StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(ExprResult &ExprResult,
Decl *&DeclResult,
SourceLocation Loc,
bool ConvertToBoolean);
- StmtResult ParseIfStatement(AttributeList *Attr);
- StmtResult ParseSwitchStatement(AttributeList *Attr);
- StmtResult ParseWhileStatement(AttributeList *Attr);
- StmtResult ParseDoStatement(AttributeList *Attr);
- StmtResult ParseForStatement(AttributeList *Attr);
- StmtResult ParseGotoStatement(AttributeList *Attr);
- StmtResult ParseContinueStatement(AttributeList *Attr);
- StmtResult ParseBreakStatement(AttributeList *Attr);
- StmtResult ParseReturnStatement(AttributeList *Attr);
+ StmtResult ParseIfStatement(ParsedAttributes &Attr);
+ StmtResult ParseSwitchStatement(ParsedAttributes &Attr);
+ StmtResult ParseWhileStatement(ParsedAttributes &Attr);
+ StmtResult ParseDoStatement(ParsedAttributes &Attr);
+ StmtResult ParseForStatement(ParsedAttributes &Attr);
+ StmtResult ParseGotoStatement(ParsedAttributes &Attr);
+ StmtResult ParseContinueStatement(ParsedAttributes &Attr);
+ StmtResult ParseBreakStatement(ParsedAttributes &Attr);
+ StmtResult ParseReturnStatement(ParsedAttributes &Attr);
StmtResult ParseAsmStatement(bool &msAsm);
- StmtResult FuzzyParseMicrosoftAsmStatement();
+ StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc);
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
llvm::SmallVectorImpl<ExprTy *> &Constraints,
llvm::SmallVectorImpl<ExprTy *> &Exprs);
@@ -1148,7 +1233,7 @@ private:
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
- StmtResult ParseCXXTryBlock(AttributeList *Attr);
+ StmtResult ParseCXXTryBlock(ParsedAttributes &Attr);
StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
StmtResult ParseCXXCatchBlock();
@@ -1173,11 +1258,13 @@ private:
DSC_top_level // top-level/namespace declaration context
};
- DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
- CXX0XAttributeList Attr);
- DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
+ DeclGroupPtrTy ParseDeclaration(StmtVector &Stmts,
+ unsigned Context, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs);
+ DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts,
+ unsigned Context,
SourceLocation &DeclEnd,
- AttributeList *Attr,
+ ParsedAttributes &attrs,
bool RequireSemi);
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
bool AllowFunctionDefinitions,
@@ -1187,6 +1274,12 @@ private:
Decl *ParseFunctionStatementBody(Decl *Decl);
Decl *ParseFunctionTryBlock(Decl *Decl);
+ /// \brief When in code-completion, skip parsing of the function/method body
+ /// unless the body contains the code-completion point.
+ ///
+ /// \returns true if the function body was skipped.
+ bool trySkippingFunctionBodyForCodeCompletion();
+
bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS);
@@ -1206,7 +1299,8 @@ private:
void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter);
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
- const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none);
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none);
void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
Decl *TagDecl);
@@ -1222,7 +1316,7 @@ private:
void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
- bool isDeclarationSpecifier();
+ bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
bool isTypeSpecifierQualifier();
bool isTypeQualifier() const;
@@ -1237,7 +1331,7 @@ private:
bool isDeclarationStatement() {
if (getLang().CPlusPlus)
return isCXXDeclarationStatement();
- return isDeclarationSpecifier();
+ return isDeclarationSpecifier(true);
}
/// isSimpleDeclaration - Disambiguates between a declaration or an
@@ -1247,9 +1341,13 @@ private:
bool isSimpleDeclaration() {
if (getLang().CPlusPlus)
return isCXXSimpleDeclaration();
- return isDeclarationSpecifier();
+ return isDeclarationSpecifier(true);
}
+ /// \brief Determine whether we are currently at the start of an Objective-C
+ /// class message that appears to be missing the open bracket '['.
+ bool isStartOfObjCClassMessageMissingOpenBracket();
+
/// \brief Starting with a scope specifier, identifier, or
/// template-id that refers to the current class, determine whether
/// this is a constructor declarator.
@@ -1333,6 +1431,18 @@ private:
bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; }
};
+ /// \brief Based only on the given token kind, determine whether we know that
+ /// we're at the start of an expression or a type-specifier-seq (which may
+ /// be an expression, in C++).
+ ///
+ /// This routine does not attempt to resolve any of the trick cases, e.g.,
+ /// those involving lookup of identifiers.
+ ///
+ /// \returns \c TPR_true if this token starts an expression, \c TPR_false if
+ /// this token starts a type-specifier-seq, or \c TPR_ambiguous if it cannot
+ /// tell.
+ TPResult isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind);
+
/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a
/// declaration specifier, TPResult::False() if it is not,
/// TPResult::Ambiguous() if it could be either a decl-specifier or a
@@ -1340,7 +1450,7 @@ private:
/// encountered.
/// Doesn't consume tokens.
TPResult isCXXDeclarationSpecifier();
-
+
// "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
@@ -1351,26 +1461,87 @@ private:
TPResult TryParseDeclarationSpecifier();
TPResult TryParseSimpleDeclaration();
TPResult TryParseTypeofSpecifier();
+ TPResult TryParseProtocolQualifiers();
TPResult TryParseInitDeclaratorList();
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
TPResult TryParseParameterDeclarationClause();
TPResult TryParseFunctionDeclarator();
TPResult TryParseBracketDeclarator();
- TypeResult ParseTypeName(SourceRange *Range = 0);
+ TypeResult ParseTypeName(SourceRange *Range = 0,
+ Declarator::TheContext Context
+ = Declarator::TypeNameContext);
void ParseBlockId();
- // EndLoc, if non-NULL, is filled with the location of the last token of
- // the attribute list.
- CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0);
- AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
- AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
- AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
- AttributeList *ParseBorlandTypeAttributes(AttributeList* CurrAttr = 0);
+
+ void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
+ if (!attrs.Range.isValid()) return;
+ DiagnoseProhibitedAttributes(attrs);
+ }
+ void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
+
+ void MaybeParseGNUAttributes(Declarator &D) {
+ if (Tok.is(tok::kw___attribute)) {
+ ParsedAttributes attrs;
+ SourceLocation endLoc;
+ ParseGNUAttributes(attrs, &endLoc);
+ D.addAttributes(attrs.getList(), endLoc);
+ }
+ }
+ void MaybeParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (Tok.is(tok::kw___attribute))
+ ParseGNUAttributes(attrs, endLoc);
+ }
+ void ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0);
+
+ void MaybeParseCXX0XAttributes(Declarator &D) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ ParsedAttributesWithRange attrs;
+ SourceLocation endLoc;
+ ParseCXX0XAttributes(attrs, &endLoc);
+ D.addAttributes(attrs.getList(), endLoc);
+ }
+ }
+ void MaybeParseCXX0XAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ ParsedAttributesWithRange attrsWithRange;
+ ParseCXX0XAttributes(attrsWithRange, endLoc);
+ attrs.append(attrsWithRange.getList());
+ }
+ }
+ void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ ParseCXX0XAttributes(attrs, endLoc);
+ }
+ void ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *EndLoc = 0);
+
+ void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().Microsoft && Tok.is(tok::l_square))
+ ParseMicrosoftAttributes(attrs, endLoc);
+ }
+ void ParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0);
+ void ParseMicrosoftDeclSpec(ParsedAttributes &attrs);
+ void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
+ void ParseOpenCLAttributes(ParsedAttributes &attrs);
+
void ParseTypeofSpecifier(DeclSpec &DS);
void ParseDecltypeSpecifier(DeclSpec &DS);
ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
+ VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const;
+ void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS);
+
+ ClassVirtSpecifiers::Specifier isCXX0XClassVirtSpecifier() const;
+ void ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS);
+
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
/// enter a new C++ declarator scope and exit it when the function is
/// finished.
@@ -1410,12 +1581,13 @@ private:
typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
void ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser);
+
void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
bool CXX0XAttributesAllowed = true);
void ParseDirectDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
- AttributeList *AttrList = 0,
+ ParsedAttributes &attrs,
bool RequiresArg = false);
void ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
IdentifierInfo *FirstIdent,
@@ -1433,11 +1605,16 @@ private:
SourceLocation InlineLoc = SourceLocation());
Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd,
- CXX0XAttributeList Attrs);
- Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
- SourceLocation &DeclEnd, AttributeList *Attr);
- Decl *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
+ ParsedAttributesWithRange &attrs);
+ Decl *ParseUsingDirective(unsigned Context,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &attrs);
+ Decl *ParseUsingDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc,
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none);
Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
@@ -1542,6 +1719,7 @@ private:
//===--------------------------------------------------------------------===//
// GNU G++: Type Traits [Type-Traits.html in the GCC manual]
ExprResult ParseUnaryTypeTrait();
+ ExprResult ParseBinaryTypeTrait();
//===--------------------------------------------------------------------===//
// Preprocessor code-completion pass-through
diff --git a/include/clang/Rewrite/ASTConsumers.h b/include/clang/Rewrite/ASTConsumers.h
index 5fb107ccbe0b..b7f642764b22 100644
--- a/include/clang/Rewrite/ASTConsumers.h
+++ b/include/clang/Rewrite/ASTConsumers.h
@@ -26,7 +26,7 @@ class Diagnostic;
class LangOptions;
class Preprocessor;
-// ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code.
+// 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,
llvm::raw_ostream *OS,
diff --git a/include/clang/Rewrite/FixItRewriter.h b/include/clang/Rewrite/FixItRewriter.h
index 9b2e0160c5d6..26a0d72baa2a 100644
--- a/include/clang/Rewrite/FixItRewriter.h
+++ b/include/clang/Rewrite/FixItRewriter.h
@@ -99,7 +99,7 @@ public:
const DiagnosticInfo &Info);
/// \brief Emit a diagnostic via the adapted diagnostic client.
- void Diag(FullSourceLoc Loc, unsigned DiagID);
+ void Diag(SourceLocation Loc, unsigned DiagID);
};
}
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h
index 53316477e1c5..45ee579a02d3 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_SEMA_ATTRLIST_H
#define LLVM_CLANG_SEMA_ATTRLIST_H
+#include "llvm/Support/Allocator.h"
#include "clang/Sema/Ownership.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
@@ -32,6 +33,9 @@ namespace clang {
/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
///
class AttributeList {
+public:
+ class Factory;
+private:
IdentifierInfo *AttrName;
SourceLocation AttrLoc;
IdentifierInfo *ScopeName;
@@ -42,17 +46,38 @@ class AttributeList {
unsigned NumArgs;
AttributeList *Next;
bool DeclspecAttribute, CXX0XAttribute;
- mutable bool Invalid; /// True if already diagnosed as invalid.
+
+ /// True if already diagnosed as invalid.
+ mutable bool Invalid;
+
AttributeList(const AttributeList &); // DO NOT IMPLEMENT
void operator=(const AttributeList &); // DO NOT IMPLEMENT
-public:
- AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
+ void operator delete(void *); // DO NOT IMPLEMENT
+ ~AttributeList(); // DO NOT IMPLEMENT
+ AttributeList(llvm::BumpPtrAllocator &Alloc,
+ IdentifierInfo *AttrName, SourceLocation AttrLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
IdentifierInfo *ParmName, SourceLocation ParmLoc,
Expr **args, unsigned numargs,
- AttributeList *Next, bool declspec = false, bool cxx0x = false);
- ~AttributeList();
-
+ bool declspec, bool cxx0x);
+public:
+ class Factory {
+ llvm::BumpPtrAllocator Alloc;
+ public:
+ Factory() {}
+ ~Factory() {}
+ AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ IdentifierInfo *ParmName, SourceLocation ParmLoc,
+ Expr **args, unsigned numargs, bool declspec = false, bool cxx0x = false) {
+ AttributeList *Mem = Alloc.Allocate<AttributeList>();
+ new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc,
+ ParmName, ParmLoc, args, numargs,
+ declspec, cxx0x);
+ return Mem;
+ }
+ };
+
enum Kind { // Please keep this list alphabetized.
AT_IBAction, // Clang-specific.
AT_IBOutlet, // Clang-specific.
@@ -68,35 +93,48 @@ public:
AT_carries_dependency,
AT_cdecl,
AT_cleanup,
+ AT_common,
AT_const,
+ AT_constant,
AT_constructor,
AT_deprecated,
AT_destructor,
+ AT_device,
AT_dllexport,
AT_dllimport,
AT_ext_vector_type,
AT_fastcall,
- AT_final,
AT_format,
AT_format_arg,
+ AT_global,
AT_gnu_inline,
- AT_hiding,
+ AT_host,
+ AT_launch_bounds,
AT_malloc,
+ AT_may_alias,
AT_mode,
+ AT_neon_polyvector_type, // Clang-specific.
+ AT_neon_vector_type, // Clang-specific.
+ AT_naked,
AT_nodebug,
AT_noinline,
AT_no_instrument_function,
+ AT_nocommon,
AT_nonnull,
AT_noreturn,
AT_nothrow,
AT_nsobject,
AT_objc_exception,
- AT_override,
AT_cf_returns_not_retained, // Clang-specific.
AT_cf_returns_retained, // Clang-specific.
AT_ns_returns_not_retained, // Clang-specific.
AT_ns_returns_retained, // Clang-specific.
+ AT_ns_returns_autoreleased, // Clang-specific.
+ AT_cf_consumed, // Clang-specific.
+ AT_ns_consumed, // Clang-specific.
+ AT_ns_consumes_self, // Clang-specific.
AT_objc_gc,
+ AT_opencl_kernel_function, // OpenCL-specific.
AT_overloadable, // Clang-specific.
AT_ownership_holds, // Clang-specific.
AT_ownership_returns, // Clang-specific.
@@ -107,12 +145,14 @@ public:
AT_regparm,
AT_section,
AT_sentinel,
+ AT_shared,
AT_stdcall,
AT_thiscall,
AT_transparent_union,
AT_unavailable,
AT_unused,
AT_used,
+ AT_uuid,
AT_vecreturn, // PS3 PPU-specific.
AT_vector_size,
AT_visibility,
@@ -134,6 +174,7 @@ public:
SourceLocation getScopeLoc() const { return ScopeLoc; }
IdentifierInfo *getParameterName() const { return ParmName; }
+ SourceLocation getParameterLoc() const { return ParmLoc; }
bool isDeclspecAttribute() const { return DeclspecAttribute; }
bool isCXX0XAttribute() const { return CXX0XAttribute; }
@@ -199,8 +240,8 @@ public:
/// The right-hand list is appended to the left-hand list, if any
/// A pointer to the joined list is returned.
/// Note: the lists are not left unmodified.
-inline AttributeList* addAttributeLists (AttributeList *Left,
- AttributeList *Right) {
+inline AttributeList *addAttributeLists(AttributeList *Left,
+ AttributeList *Right) {
if (!Left)
return Right;
@@ -229,6 +270,51 @@ struct CXX0XAttributeList {
}
};
+/// ParsedAttributes - A collection of parsed attributes. Currently
+/// we don't differentiate between the various attribute syntaxes,
+/// which is basically silly.
+///
+/// Right now this is a very lightweight container, but the expectation
+/// is that this will become significantly more serious.
+class ParsedAttributes {
+public:
+ ParsedAttributes() : list(0) {}
+
+ bool empty() const { return list == 0; }
+
+ void add(AttributeList *newAttr) {
+ assert(newAttr);
+ assert(newAttr->getNext() == 0);
+ newAttr->setNext(list);
+ list = newAttr;
+ }
+
+ void append(AttributeList *newList) {
+ if (!newList) return;
+
+ AttributeList *lastInNewList = newList;
+ while (AttributeList *next = lastInNewList->getNext())
+ lastInNewList = next;
+
+ lastInNewList->setNext(list);
+ list = newList;
+ }
+
+ void set(AttributeList *newList) {
+ list = newList;
+ }
+
+ void clear() { list = 0; }
+ AttributeList *getList() const { return list; }
+
+ /// Returns a reference to the attribute list. Try not to introduce
+ /// dependencies on this method, it may not be long-lived.
+ AttributeList *&getListRef() { return list; }
+
+private:
+ AttributeList *list;
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 6c1ecbf2cc29..882440b78c7c 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -17,12 +17,13 @@
#include "clang/AST/CanonicalType.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
#include "clang-c/Index.h"
-#include <memory>
#include <string>
namespace llvm {
class raw_ostream;
+ class Twine;
}
namespace clang {
@@ -35,31 +36,37 @@ enum {
/// \brief Priority for the next initialization in a constructor initializer
/// list.
CCP_NextInitializer = 7,
+ /// \brief Priority for an enumeration constant inside a switch whose
+ /// condition is of the enumeration type.
+ CCP_EnumInCase = 7,
/// \brief Priority for a send-to-super completion.
- CCP_SuperCompletion = 8,
+ CCP_SuperCompletion = 20,
/// \brief Priority for a declaration that is in the local scope.
- CCP_LocalDeclaration = 8,
+ CCP_LocalDeclaration = 34,
/// \brief Priority for a member declaration found from the current
/// method or member function.
- CCP_MemberDeclaration = 20,
+ CCP_MemberDeclaration = 35,
/// \brief Priority for a language keyword (that isn't any of the other
/// categories).
- CCP_Keyword = 30,
+ CCP_Keyword = 40,
/// \brief Priority for a code pattern.
- CCP_CodePattern = 30,
+ CCP_CodePattern = 40,
/// \brief Priority for a non-type declaration.
CCP_Declaration = 50,
- /// \brief Priority for a constant value (e.g., enumerator).
- CCP_Constant = 60,
/// \brief Priority for a type.
- CCP_Type = 65,
+ CCP_Type = CCP_Declaration,
+ /// \brief Priority for a constant value (e.g., enumerator).
+ CCP_Constant = 65,
/// \brief Priority for a preprocessor macro.
CCP_Macro = 70,
/// \brief Priority for a nested-name-specifier.
CCP_NestedNameSpecifier = 75,
/// \brief Priority for a result that isn't likely to be what the user wants,
/// but is included for completeness.
- CCP_Unlikely = 80
+ CCP_Unlikely = 80,
+
+ /// \brief Priority for the Objective-C "_cmd" implicit parameter.
+ CCP_ObjC_cmd = CCP_Unlikely
};
/// \brief Priority value deltas that are added to code-completion results
@@ -67,18 +74,21 @@ enum {
enum {
/// \brief The result is in a base class.
CCD_InBaseClass = 2,
- /// \brief The result is a type match against void.
- ///
- /// Since everything converts to "void", we don't give as drastic an
- /// adjustment for matching void.
- CCD_VoidMatch = -5,
/// \brief The result is a C++ non-static member function whose qualifiers
/// exactly match the object type on which the member function can be called.
CCD_ObjectQualifierMatch = -1,
/// \brief The selector of the given message exactly matches the selector
/// of the current method, which might imply that some kind of delegation
/// is occurring.
- CCD_SelectorMatch = -3
+ CCD_SelectorMatch = -3,
+
+ /// \brief Adjustment to the "bool" type in Objective-C, where the typedef
+ /// "BOOL" is preferred.
+ CCD_bool_in_ObjC = 1,
+
+ /// \brief Adjustment for KVC code pattern priorities when it doesn't look
+ /// like the
+ CCD_ProbablyNotObjCCollection = 15
};
/// \brief Priority value factors by which we will divide or multiply the
@@ -119,9 +129,12 @@ QualType getDeclUsageType(ASTContext &C, NamedDecl *ND);
///
/// \param MacroName The name of the macro.
///
+/// \param LangOpts Options describing the current language dialect.
+///
/// \param PreferredTypeIsPointer Whether the preferred type for the context
/// of this macro is a pointer type.
unsigned getMacroUsagePriority(llvm::StringRef MacroName,
+ const LangOptions &LangOpts,
bool PreferredTypeIsPointer = false);
/// \brief Determine the libclang cursor kind associated with the given
@@ -143,6 +156,9 @@ public:
enum Kind {
/// \brief An unspecified code-completion context.
CCC_Other,
+ /// \brief An unspecified code-completion context where we should also add
+ /// macro completions.
+ CCC_OtherWithMacros,
/// \brief Code completion occurred within a "top-level" completion context,
/// e.g., at namespace or global scope.
CCC_TopLevel,
@@ -212,7 +228,13 @@ public:
/// \brief Code completion for a selector, as in an @selector expression.
CCC_SelectorName,
/// \brief Code completion within a type-qualifier list.
- CCC_TypeQualifiers
+ CCC_TypeQualifiers,
+ /// \brief Code completion in a parenthesized expression, which means that
+ /// we may also have types here in C and Objective-C (as well as in C++).
+ CCC_ParenthesizedExpression,
+ /// \brief An unknown context, in which we are recovering from a parsing
+ /// error and don't know which completions we should give.
+ CCC_Recovery
};
private:
@@ -248,6 +270,10 @@ public:
/// \brief Retrieve the type of the base object in a member-access
/// expression.
QualType getBaseType() const { return BaseType; }
+
+ /// \brief Determines whether we want C++ constructors as results within this
+ /// context.
+ bool wantConstructorResults() const;
};
@@ -339,127 +365,163 @@ public:
Chunk() : Kind(CK_Text), Text(0) { }
- Chunk(ChunkKind Kind, llvm::StringRef Text = "");
+ Chunk(ChunkKind Kind, const char *Text = "");
/// \brief Create a new text chunk.
- static Chunk CreateText(llvm::StringRef Text);
+ static Chunk CreateText(const char *Text);
/// \brief Create a new optional chunk.
- static Chunk CreateOptional(std::auto_ptr<CodeCompletionString> Optional);
+ static Chunk CreateOptional(CodeCompletionString *Optional);
/// \brief Create a new placeholder chunk.
- static Chunk CreatePlaceholder(llvm::StringRef Placeholder);
+ static Chunk CreatePlaceholder(const char *Placeholder);
/// \brief Create a new informative chunk.
- static Chunk CreateInformative(llvm::StringRef Informative);
+ static Chunk CreateInformative(const char *Informative);
/// \brief Create a new result type chunk.
- static Chunk CreateResultType(llvm::StringRef ResultType);
+ static Chunk CreateResultType(const char *ResultType);
/// \brief Create a new current-parameter chunk.
- static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter);
-
- /// \brief Clone the given chunk.
- Chunk Clone() const;
-
- /// \brief Destroy this chunk, deallocating any memory it owns.
- void Destroy();
+ static Chunk CreateCurrentParameter(const char *CurrentParameter);
};
private:
- /// \brief The chunks stored in this string.
- llvm::SmallVector<Chunk, 4> Chunks;
+ /// \brief The number of chunks stored in this string.
+ unsigned NumChunks;
+
+ /// \brief The priority of this code-completion string.
+ unsigned Priority : 30;
+
+ /// \brief The availability of this code-completion result.
+ unsigned Availability : 2;
CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT
CodeCompletionString &operator=(const CodeCompletionString &); // DITTO
-public:
- CodeCompletionString() { }
- ~CodeCompletionString() { clear(); }
+ CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
+ unsigned Priority, CXAvailabilityKind Availability);
+ ~CodeCompletionString() { }
- typedef llvm::SmallVector<Chunk, 4>::const_iterator iterator;
- iterator begin() const { return Chunks.begin(); }
- iterator end() const { return Chunks.end(); }
- bool empty() const { return Chunks.empty(); }
- unsigned size() const { return Chunks.size(); }
- void clear();
+ friend class CodeCompletionBuilder;
+ friend class CodeCompletionResult;
- Chunk &operator[](unsigned I) {
+public:
+ typedef const Chunk *iterator;
+ iterator begin() const { return reinterpret_cast<const Chunk *>(this + 1); }
+ iterator end() const { return begin() + NumChunks; }
+ bool empty() const { return NumChunks == 0; }
+ unsigned size() const { return NumChunks; }
+
+ const Chunk &operator[](unsigned I) const {
assert(I < size() && "Chunk index out-of-range");
- return Chunks[I];
+ return begin()[I];
}
+
+ /// \brief Returns the text in the TypedText chunk.
+ const char *getTypedText() const;
- const Chunk &operator[](unsigned I) const {
- assert(I < size() && "Chunk index out-of-range");
- return Chunks[I];
+ /// \brief Retrieve the priority of this code completion result.
+ unsigned getPriority() const { return Priority; }
+
+ /// \brief Reteirve the availability of this code completion result.
+ unsigned getAvailability() const { return Availability; }
+
+ /// \brief Retrieve a string representation of the code completion string,
+ /// which is mainly useful for debugging.
+ std::string getAsString() const;
+};
+
+/// \brief An allocator used specifically for the purpose of code completion.
+class CodeCompletionAllocator : public llvm::BumpPtrAllocator {
+public:
+ /// \brief Copy the given string into this allocator.
+ const char *CopyString(llvm::StringRef String);
+
+ /// \brief Copy the given string into this allocator.
+ const char *CopyString(llvm::Twine String);
+
+ // \brief Copy the given string into this allocator.
+ const char *CopyString(const char *String) {
+ return CopyString(llvm::StringRef(String));
+ }
+
+ /// \brief Copy the given string into this allocator.
+ const char *CopyString(const std::string &String) {
+ return CopyString(llvm::StringRef(String));
+ }
+};
+
+/// \brief A builder class used to construct new code-completion strings.
+class CodeCompletionBuilder {
+public:
+ typedef CodeCompletionString::Chunk Chunk;
+
+private:
+ CodeCompletionAllocator &Allocator;
+ unsigned Priority;
+ CXAvailabilityKind Availability;
+
+ /// \brief The chunks stored in this string.
+ llvm::SmallVector<Chunk, 4> Chunks;
+
+public:
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator)
+ : Allocator(Allocator), Priority(0), Availability(CXAvailability_Available){
}
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
+ unsigned Priority, CXAvailabilityKind Availability)
+ : Allocator(Allocator), Priority(Priority), Availability(Availability) { }
+
+ /// \brief Retrieve the allocator into which the code completion
+ /// strings should be allocated.
+ CodeCompletionAllocator &getAllocator() const { return Allocator; }
+
+ /// \brief Take the resulting completion string.
+ ///
+ /// This operation can only be performed once.
+ CodeCompletionString *TakeString();
+
/// \brief Add a new typed-text chunk.
- /// The text string will be copied.
- void AddTypedTextChunk(llvm::StringRef Text) {
- Chunks.push_back(Chunk(CK_TypedText, Text));
+ void AddTypedTextChunk(const char *Text) {
+ Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
}
/// \brief Add a new text chunk.
- /// The text string will be copied.
- void AddTextChunk(llvm::StringRef Text) {
+ void AddTextChunk(const char *Text) {
Chunks.push_back(Chunk::CreateText(Text));
}
-
+
/// \brief Add a new optional chunk.
- void AddOptionalChunk(std::auto_ptr<CodeCompletionString> Optional) {
+ void AddOptionalChunk(CodeCompletionString *Optional) {
Chunks.push_back(Chunk::CreateOptional(Optional));
}
/// \brief Add a new placeholder chunk.
- /// The placeholder text will be copied.
- void AddPlaceholderChunk(llvm::StringRef Placeholder) {
+ void AddPlaceholderChunk(const char *Placeholder) {
Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
}
-
+
/// \brief Add a new informative chunk.
- /// The text will be copied.
- void AddInformativeChunk(llvm::StringRef Text) {
+ void AddInformativeChunk(const char *Text) {
Chunks.push_back(Chunk::CreateInformative(Text));
}
-
+
/// \brief Add a new result-type chunk.
- /// The text will be copied.
- void AddResultTypeChunk(llvm::StringRef ResultType) {
+ void AddResultTypeChunk(const char *ResultType) {
Chunks.push_back(Chunk::CreateResultType(ResultType));
}
/// \brief Add a new current-parameter chunk.
- /// The text will be copied.
- void AddCurrentParameterChunk(llvm::StringRef CurrentParameter) {
+ void AddCurrentParameterChunk(const char *CurrentParameter) {
Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
}
/// \brief Add a new chunk.
void AddChunk(Chunk C) { Chunks.push_back(C); }
-
- /// \brief Returns the text in the TypedText chunk.
- const char *getTypedText() const;
-
- /// \brief Retrieve a string representation of the code completion string,
- /// which is mainly useful for debugging.
- std::string getAsString() const;
-
- /// \brief Clone this code-completion string.
- ///
- /// \param Result If non-NULL, points to an empty code-completion
- /// result that will be given a cloned copy of
- CodeCompletionString *Clone(CodeCompletionString *Result = 0) const;
-
- /// \brief Serialize this code-completion string to the given stream.
- void Serialize(llvm::raw_ostream &OS) const;
-
- /// \brief Deserialize a code-completion string from the given string.
- ///
- /// \returns true if successful, false otherwise.
- bool Deserialize(const char *&Str, const char *StrEnd);
};
-
+
/// \brief Captures a result of code completion.
class CodeCompletionResult {
public:
@@ -590,15 +652,12 @@ public:
///
/// \param S The semantic analysis that created the result.
///
- /// \param Result If non-NULL, the already-allocated, empty
- /// code-completion string that will be populated with the
- /// appropriate code completion string for this result.
+ /// \param Allocator The allocator that will be used to allocate the
+ /// string itself.
CodeCompletionString *CreateCodeCompletionString(Sema &S,
- CodeCompletionString *Result = 0);
-
- void Destroy();
+ CodeCompletionAllocator &Allocator);
- /// brief Determine a base priority for the given declaration.
+ /// \brief Determine a base priority for the given declaration.
static unsigned getPriorityFromDecl(NamedDecl *ND);
private:
@@ -682,7 +741,7 @@ public:
: Kind(CK_Function), Function(Function) { }
OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl)
- : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplate) { }
+ : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { }
OverloadCandidate(const FunctionType *Type)
: Kind(CK_FunctionType), Type(Type) { }
@@ -707,7 +766,8 @@ public:
/// \brief Create a new code-completion string that describes the function
/// signature of this overload candidate.
CodeCompletionString *CreateSignatureString(unsigned CurrentArg,
- Sema &S) const;
+ Sema &S,
+ CodeCompletionAllocator &Allocator) const;
};
CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
@@ -753,6 +813,10 @@ public:
OverloadCandidate *Candidates,
unsigned NumCandidates) { }
//@}
+
+ /// \brief Retrieve the allocator that will be used to allocate
+ /// code completion strings.
+ virtual CodeCompletionAllocator &getAllocator() = 0;
};
/// \brief A simple code-completion consumer that prints the results it
@@ -761,6 +825,8 @@ class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
/// \brief The raw output stream.
llvm::raw_ostream &OS;
+ CodeCompletionAllocator Allocator;
+
public:
/// \brief Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
@@ -779,34 +845,10 @@ public:
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates);
-};
-
-/// \brief A code-completion consumer that prints the results it receives
-/// in a format that is parsable by the CIndex library.
-class CIndexCodeCompleteConsumer : public CodeCompleteConsumer {
- /// \brief The raw output stream.
- llvm::raw_ostream &OS;
-
-public:
- /// \brief Create a new CIndex code-completion consumer that prints its
- /// results to the given raw output stream in a format readable to the CIndex
- /// library.
- CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
- bool IncludeGlobals, llvm::raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
- true), OS(OS) {}
- /// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S,
- CodeCompletionContext Context,
- CodeCompletionResult *Results,
- unsigned NumResults);
-
- virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
- OverloadCandidate *Candidates,
- unsigned NumCandidates);
+ virtual CodeCompletionAllocator &getAllocator() { return Allocator; }
};
-
+
} // end namespace clang
#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 0893ae7e4958..9c4bb646949b 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -26,6 +26,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ErrorHandling.h"
namespace clang {
class LangOptions;
@@ -169,32 +170,32 @@ private:
// storage-class-specifier
/*SCS*/unsigned StorageClassSpec : 3;
- bool SCS_thread_specified : 1;
- bool SCS_extern_in_linkage_spec : 1;
+ unsigned SCS_thread_specified : 1;
+ unsigned SCS_extern_in_linkage_spec : 1;
// type-specifier
/*TSW*/unsigned TypeSpecWidth : 2;
/*TSC*/unsigned TypeSpecComplex : 2;
/*TSS*/unsigned TypeSpecSign : 2;
/*TST*/unsigned TypeSpecType : 5;
- bool TypeAltiVecVector : 1;
- bool TypeAltiVecPixel : 1;
- bool TypeAltiVecBool : 1;
- bool TypeSpecOwned : 1;
+ unsigned TypeAltiVecVector : 1;
+ unsigned TypeAltiVecPixel : 1;
+ unsigned TypeAltiVecBool : 1;
+ unsigned TypeSpecOwned : 1;
// type-qualifiers
unsigned TypeQualifiers : 3; // Bitwise OR of TQ.
// function-specifier
- bool FS_inline_specified : 1;
- bool FS_virtual_specified : 1;
- bool FS_explicit_specified : 1;
+ unsigned FS_inline_specified : 1;
+ unsigned FS_virtual_specified : 1;
+ unsigned FS_explicit_specified : 1;
// friend-specifier
- bool Friend_specified : 1;
+ unsigned Friend_specified : 1;
// constexpr-specifier
- bool Constexpr_specified : 1;
+ unsigned Constexpr_specified : 1;
/*SCS*/unsigned StorageClassSpecAsWritten : 3;
@@ -205,7 +206,7 @@ private:
};
// attributes.
- AttributeList *AttrList;
+ ParsedAttributes Attrs;
// Scope specifier for the type spec, if applicable.
CXXScopeSpec TypeScope;
@@ -267,14 +268,12 @@ public:
Friend_specified(false),
Constexpr_specified(false),
StorageClassSpecAsWritten(SCS_unspecified),
- AttrList(0),
ProtocolQualifiers(0),
NumProtocolQualifiers(0),
ProtocolLocs(0),
writtenBS() {
}
~DeclSpec() {
- delete AttrList;
delete [] ProtocolQualifiers;
delete [] ProtocolLocs;
}
@@ -404,7 +403,7 @@ public:
/// TODO: use a more general approach that still allows these
/// diagnostics to be ignored when desired.
bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID);
+ unsigned &DiagID, const LangOptions &Lang);
bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec,
@@ -473,19 +472,29 @@ public:
/// short __attribute__((unused)) __attribute__((deprecated))
/// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
///
- void AddAttributes(AttributeList *alist) {
- AttrList = addAttributeLists(AttrList, alist);
+ void addAttributes(AttributeList *AL) {
+ Attrs.append(AL);
+ }
+ void aetAttributes(AttributeList *AL) {
+ Attrs.set(AL);
}
- void SetAttributes(AttributeList *AL) { AttrList = AL; }
- const AttributeList *getAttributes() const { return AttrList; }
- AttributeList *getAttributes() { return AttrList; }
+
+ bool hasAttributes() const { return !Attrs.empty(); }
+
+ ParsedAttributes &getAttributes() { return Attrs; }
+ const ParsedAttributes &getAttributes() const { return Attrs; }
/// TakeAttributes - Return the current attribute list and remove them from
/// the DeclSpec so that it doesn't own them.
- AttributeList *TakeAttributes() {
- AttributeList *AL = AttrList;
- AttrList = 0;
- return AL;
+ ParsedAttributes takeAttributes() {
+ ParsedAttributes saved = Attrs;
+ Attrs.clear();
+ return saved;
+ }
+
+ void takeAttributesFrom(ParsedAttributes &attrs) {
+ Attrs.append(attrs.getList());
+ attrs.clear();
}
typedef Decl * const *ProtocolQualifierListTy;
@@ -539,7 +548,8 @@ public:
DQ_PR_retain = 0x10,
DQ_PR_copy = 0x20,
DQ_PR_nonatomic = 0x40,
- DQ_PR_setter = 0x80
+ DQ_PR_setter = 0x80,
+ DQ_PR_atomic = 0x100
};
@@ -573,7 +583,7 @@ private:
ObjCDeclQualifier objcDeclQualifier : 6;
// NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind
- unsigned PropertyAttributes : 8;
+ unsigned PropertyAttributes : 9;
IdentifierInfo *GetterName; // getter name of NULL if no getter
IdentifierInfo *SetterName; // setter name of NULL if no setter
};
@@ -800,7 +810,7 @@ typedef llvm::SmallVector<Token, 4> CachedTokens;
/// This is intended to be a small value object.
struct DeclaratorChunk {
enum {
- Pointer, Reference, Array, Function, BlockPointer, MemberPointer
+ Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren
} Kind;
/// Loc - The place where this type was defined.
@@ -808,27 +818,27 @@ struct DeclaratorChunk {
/// EndLoc - If valid, the place where this chunck ends.
SourceLocation EndLoc;
- struct PointerTypeInfo {
+ struct TypeInfoCommon {
+ AttributeList *AttrList;
+ };
+
+ struct PointerTypeInfo : TypeInfoCommon {
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
- AttributeList *AttrList;
void destroy() {
- delete AttrList;
}
};
- struct ReferenceTypeInfo {
+ struct ReferenceTypeInfo : TypeInfoCommon {
/// The type qualifier: restrict. [GNU] C++ extension
bool HasRestrict : 1;
/// True if this is an lvalue reference, false if it's an rvalue reference.
bool LValueRef : 1;
- AttributeList *AttrList;
void destroy() {
- delete AttrList;
}
};
- struct ArrayTypeInfo {
+ struct ArrayTypeInfo : TypeInfoCommon {
/// The type qualifiers for the array: const/volatile/restrict.
unsigned TypeQuals : 3;
@@ -842,6 +852,7 @@ struct DeclaratorChunk {
/// Since the parser is multi-purpose, and we don't want to impose a root
/// expression class on all clients, NumElts is untyped.
Expr *NumElts;
+
void destroy() {}
};
@@ -876,29 +887,33 @@ struct DeclaratorChunk {
SourceRange Range;
};
- struct FunctionTypeInfo {
+ struct FunctionTypeInfo : TypeInfoCommon {
/// hasPrototype - This is true if the function had at least one typed
/// argument. If the function is () or (a,b,c), then it has no prototype,
/// and is treated as a K&R-style function.
- bool hasPrototype : 1;
+ unsigned hasPrototype : 1;
/// isVariadic - If this function has a prototype, and if that
/// proto ends with ',...)', this is true. When true, EllipsisLoc
/// contains the location of the ellipsis.
- bool isVariadic : 1;
+ unsigned isVariadic : 1;
+ /// \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;
/// hasExceptionSpec - True if the function has an exception specification.
- bool hasExceptionSpec : 1;
+ unsigned hasExceptionSpec : 1;
/// hasAnyExceptionSpec - True if the function has a throw(...) specifier.
- bool hasAnyExceptionSpec : 1;
+ unsigned hasAnyExceptionSpec : 1;
/// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
- bool DeleteArgInfo : 1;
+ unsigned DeleteArgInfo : 1;
/// When isVariadic is true, the location of the ellipsis in the source.
unsigned EllipsisLoc;
@@ -911,6 +926,11 @@ struct DeclaratorChunk {
/// the function has one.
unsigned NumExceptions;
+ /// \brief The location of the ref-qualifier, if any.
+ ///
+ /// If this is an invalid location, there is no ref-qualifier.
+ unsigned RefQualifierLoc;
+
/// ThrowLoc - When hasExceptionSpec is true, the location of the throw
/// keyword introducing the spec.
unsigned ThrowLoc;
@@ -925,6 +945,11 @@ struct DeclaratorChunk {
/// specification and their locations.
TypeAndRange *Exceptions;
+ /// TrailingReturnType - If this isn't null, it's the trailing return type
+ /// specified. This is actually a ParsedType, but stored as void* to
+ /// allow union storage.
+ void *TrailingReturnType;
+
/// freeArgs - reset the argument list to having zero arguments. This is
/// used in various places for error recovery.
void freeArgs() {
@@ -954,22 +979,29 @@ struct DeclaratorChunk {
SourceLocation getThrowLoc() const {
return SourceLocation::getFromRawEncoding(ThrowLoc);
}
+
+ /// \brief Retrieve the location of the ref-qualifier, if any.
+ SourceLocation getRefQualifierLoc() const {
+ return SourceLocation::getFromRawEncoding(RefQualifierLoc);
+ }
+
+ /// \brief Determine whether this function declaration contains a
+ /// ref-qualifier.
+ bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); }
};
- struct BlockPointerTypeInfo {
+ struct BlockPointerTypeInfo : TypeInfoCommon {
/// For now, sema will catch these as invalid.
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
- AttributeList *AttrList;
+
void destroy() {
- delete AttrList;
}
};
- struct MemberPointerTypeInfo {
+ struct MemberPointerTypeInfo : TypeInfoCommon {
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
- AttributeList *AttrList;
// CXXScopeSpec has a constructor, so it can't be a direct member.
// So we need some pointer-aligned storage and a bit of trickery.
union {
@@ -983,12 +1015,12 @@ struct DeclaratorChunk {
return *reinterpret_cast<const CXXScopeSpec*>(ScopeMem.Mem);
}
void destroy() {
- delete AttrList;
Scope().~CXXScopeSpec();
}
};
union {
+ TypeInfoCommon Common;
PointerTypeInfo Ptr;
ReferenceTypeInfo Ref;
ArrayTypeInfo Arr;
@@ -1006,58 +1038,57 @@ struct DeclaratorChunk {
case DeclaratorChunk::Reference: return Ref.destroy();
case DeclaratorChunk::Array: return Arr.destroy();
case DeclaratorChunk::MemberPointer: return Mem.destroy();
+ case DeclaratorChunk::Paren: return;
}
}
/// getAttrs - If there are attributes applied to this declaratorchunk, return
/// them.
const AttributeList *getAttrs() const {
- switch (Kind) {
- default: assert(0 && "Unknown declarator kind!");
- case Pointer: return Ptr.AttrList;
- case Reference: return Ref.AttrList;
- case MemberPointer: return Mem.AttrList;
- case Array: return 0;
- case Function: return 0;
- case BlockPointer: return Cls.AttrList;
- }
+ return Common.AttrList;
}
+ AttributeList *&getAttrListRef() {
+ return Common.AttrList;
+ }
/// getPointer - Return a DeclaratorChunk for a pointer.
///
static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
- AttributeList *AL) {
+ const ParsedAttributes &attrs) {
DeclaratorChunk I;
I.Kind = Pointer;
I.Loc = Loc;
I.Ptr.TypeQuals = TypeQuals;
- I.Ptr.AttrList = AL;
+ I.Ptr.AttrList = attrs.getList();
return I;
}
/// getReference - Return a DeclaratorChunk for a reference.
///
static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
- AttributeList *AL, bool lvalue) {
+ const ParsedAttributes &attrs,
+ bool lvalue) {
DeclaratorChunk I;
I.Kind = Reference;
I.Loc = Loc;
I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
I.Ref.LValueRef = lvalue;
- I.Ref.AttrList = AL;
+ I.Ref.AttrList = attrs.getList();
return I;
}
/// getArray - Return a DeclaratorChunk for an array.
///
- static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic,
- bool isStar, Expr *NumElts,
+ static DeclaratorChunk getArray(unsigned TypeQuals,
+ const ParsedAttributes &attrs,
+ bool isStatic, bool isStar, Expr *NumElts,
SourceLocation LBLoc, SourceLocation RBLoc) {
DeclaratorChunk I;
I.Kind = Array;
I.Loc = LBLoc;
I.EndLoc = RBLoc;
+ I.Arr.AttrList = attrs.getList();
I.Arr.TypeQuals = TypeQuals;
I.Arr.hasStatic = isStatic;
I.Arr.isStar = isStar;
@@ -1067,42 +1098,60 @@ 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(const ParsedAttributes &attrs,
+ bool hasProto, bool isVariadic,
SourceLocation EllipsisLoc,
ParamInfo *ArgInfo, unsigned NumArgs,
- unsigned TypeQuals, bool hasExceptionSpec,
+ unsigned TypeQuals,
+ bool RefQualifierIsLvalueRef,
+ SourceLocation RefQualifierLoc,
+ bool hasExceptionSpec,
SourceLocation ThrowLoc,
bool hasAnyExceptionSpec,
ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
SourceLocation LPLoc, SourceLocation RPLoc,
- Declarator &TheDeclarator);
+ Declarator &TheDeclarator,
+ ParsedType TrailingReturnType = ParsedType());
/// getBlockPointer - Return a DeclaratorChunk for a block.
///
static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc,
- AttributeList *AL) {
+ const ParsedAttributes &attrs) {
DeclaratorChunk I;
I.Kind = BlockPointer;
I.Loc = Loc;
I.Cls.TypeQuals = TypeQuals;
- I.Cls.AttrList = AL;
+ I.Cls.AttrList = attrs.getList();
return I;
}
static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
unsigned TypeQuals,
SourceLocation Loc,
- AttributeList *AL) {
+ const ParsedAttributes &attrs) {
DeclaratorChunk I;
I.Kind = MemberPointer;
I.Loc = Loc;
I.Mem.TypeQuals = TypeQuals;
- I.Mem.AttrList = AL;
+ I.Mem.AttrList = attrs.getList();
new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
return I;
}
+
+ /// getParen - Return a DeclaratorChunk for a paren.
+ ///
+ static DeclaratorChunk getParen(SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ DeclaratorChunk I;
+ I.Kind = Paren;
+ I.Loc = LParenLoc;
+ I.EndLoc = RParenLoc;
+ I.Common.AttrList = 0;
+ return I;
+ }
+
};
/// Declarator - Information about one declarator, including the parsed type
@@ -1128,7 +1177,8 @@ public:
ConditionContext, // Condition declaration in a C++ if/switch/while/for.
TemplateParamContext,// Within a template parameter list.
CXXCatchContext, // C++ catch exception-declaration
- BlockLiteralContext // Block literal declarator.
+ BlockLiteralContext, // Block literal declarator.
+ TemplateTypeArgContext // Template type argument.
};
private:
@@ -1168,6 +1218,10 @@ private:
/// Extension - true if the declaration is preceded by __extension__.
bool Extension : 1;
+ /// \brief If provided, the source location of the ellipsis used to describe
+ /// this declarator as a parameter pack.
+ SourceLocation EllipsisLoc;
+
friend struct DeclaratorChunk;
public:
@@ -1238,7 +1292,6 @@ public:
for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
DeclTypeInfo[i].destroy();
DeclTypeInfo.clear();
- delete AttrList;
AttrList = 0;
AsmLabel = 0;
InlineParamsUsed = false;
@@ -1250,14 +1303,15 @@ public:
bool mayOmitIdentifier() const {
return Context == TypeNameContext || Context == PrototypeContext ||
Context == TemplateParamContext || Context == CXXCatchContext ||
- Context == BlockLiteralContext;
+ Context == BlockLiteralContext || Context == TemplateTypeArgContext;
}
/// mayHaveIdentifier - Return true if the identifier is either optional or
/// required. This is true for normal declarators and prototypes, but not
/// typenames.
bool mayHaveIdentifier() const {
- return Context != TypeNameContext && Context != BlockLiteralContext;
+ return Context != TypeNameContext && Context != BlockLiteralContext &&
+ Context != TemplateTypeArgContext;
}
/// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
@@ -1301,6 +1355,11 @@ public:
SetRangeEnd(EndLoc);
}
+ /// AddInnermostTypeInfo - Add a new innermost chunk to this declarator.
+ void AddInnermostTypeInfo(const DeclaratorChunk &TI) {
+ DeclTypeInfo.insert(DeclTypeInfo.begin(), TI);
+ }
+
/// getNumTypeObjects() - Return the number of types applied to this
/// declarator.
unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
@@ -1323,11 +1382,52 @@ public:
DeclTypeInfo.erase(DeclTypeInfo.begin());
}
+ /// isFunctionDeclarator - This method returns true if the declarator
+ /// is a function declarator (looking through parentheses).
+ /// If true is returned, then the reference type parameter idx is
+ /// assigned with the index of the declaration chunk.
+ bool isFunctionDeclarator(unsigned& idx) const {
+ for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+ switch (DeclTypeInfo[i].Kind) {
+ case DeclaratorChunk::Function:
+ idx = i;
+ return true;
+ case DeclaratorChunk::Paren:
+ continue;
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ return false;
+ }
+ llvm_unreachable("Invalid type chunk");
+ return false;
+ }
+ return false;
+ }
+
/// isFunctionDeclarator - Once this declarator is fully parsed and formed,
- /// this method returns true if the identifier is a function declarator.
+ /// this method returns true if the identifier is a function declarator
+ /// (looking through parentheses).
bool isFunctionDeclarator() const {
- return !DeclTypeInfo.empty() &&
- DeclTypeInfo[0].Kind == DeclaratorChunk::Function;
+ unsigned index;
+ return isFunctionDeclarator(index);
+ }
+
+ /// getFunctionTypeInfo - Retrieves the function type info object
+ /// (looking through parentheses).
+ DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() {
+ assert(isFunctionDeclarator() && "Not a function declarator!");
+ unsigned index = 0;
+ isFunctionDeclarator(index);
+ return DeclTypeInfo[index].Fun;
+ }
+
+ /// getFunctionTypeInfo - Retrieves the function type info object
+ /// (looking through parentheses).
+ const DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() const {
+ return const_cast<Declarator*>(this)->getFunctionTypeInfo();
}
/// AddAttributes - simply adds the attribute list to the Declarator.
@@ -1337,19 +1437,25 @@ public:
/// __attribute__((common,deprecated));
///
/// Also extends the range of the declarator.
- void AddAttributes(AttributeList *alist, SourceLocation LastLoc) {
+ void addAttributes(AttributeList *alist, SourceLocation LastLoc) {
AttrList = addAttributeLists(AttrList, alist);
if (!LastLoc.isInvalid())
SetRangeEnd(LastLoc);
}
+ void addAttributes(const ParsedAttributes &attrs) {
+ addAttributes(attrs.getList(), SourceLocation());
+ }
+
const AttributeList *getAttributes() const { return AttrList; }
AttributeList *getAttributes() { return AttrList; }
+ AttributeList *&getAttrListRef() { return AttrList; }
+
/// hasAttributes - do we contain any attributes?
bool hasAttributes() const {
- if (getAttributes() || getDeclSpec().getAttributes()) return true;
+ if (getAttributes() || getDeclSpec().hasAttributes()) return true;
for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i)
if (getTypeObject(i).getAttrs())
return true;
@@ -1369,6 +1475,10 @@ public:
void setGroupingParens(bool flag) { GroupingParens = flag; }
bool hasGroupingParens() const { return GroupingParens; }
+
+ bool hasEllipsis() const { return EllipsisLoc.isValid(); }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; }
};
/// FieldDeclarator - This little struct is used to capture information about
@@ -1380,7 +1490,69 @@ struct FieldDeclarator {
BitfieldSize = 0;
}
};
-
+
+/// VirtSpecifiers - Represents a C++0x virt-specifier-seq.
+class VirtSpecifiers {
+public:
+ enum Specifier {
+ VS_None = 0,
+ VS_Override = 1,
+ VS_Final = 2,
+ VS_New = 4
+ };
+
+ VirtSpecifiers() : Specifiers(0) { }
+
+ bool SetSpecifier(Specifier VS, SourceLocation Loc,
+ const char *&PrevSpec);
+
+ bool isOverrideSpecified() const { return Specifiers & VS_Override; }
+ SourceLocation getOverrideLoc() const { return VS_overrideLoc; }
+
+ bool isFinalSpecified() const { return Specifiers & VS_Final; }
+ SourceLocation getFinalLoc() const { return VS_finalLoc; }
+
+ bool isNewSpecified() const { return Specifiers & VS_New; }
+ SourceLocation getNewLoc() const { return VS_newLoc; }
+
+ void clear() { Specifiers = 0; }
+
+ static const char *getSpecifierName(Specifier VS);
+
+private:
+ unsigned Specifiers;
+
+ SourceLocation VS_overrideLoc, VS_finalLoc, VS_newLoc;
+};
+
+/// ClassVirtSpecifiers - Represents a C++0x class-virt-specifier-seq.
+class ClassVirtSpecifiers {
+public:
+ enum Specifier {
+ CVS_None = 0,
+ CVS_Final = 1,
+ CVS_Explicit = 2
+ };
+
+ ClassVirtSpecifiers() : Specifiers(0) { }
+
+ bool SetSpecifier(Specifier CVS, SourceLocation Loc,
+ const char *&PrevSpec);
+
+ bool isFinalSpecified() const { return Specifiers & CVS_Final; }
+ SourceLocation getFinalLoc() const { return CVS_finalLoc; }
+
+ bool isExplicitSpecified() const { return Specifiers & CVS_Explicit; }
+ SourceLocation getExplicitLoc() const { return CVS_explicitLoc; }
+
+ static const char *getSpecifierName(Specifier CVS);
+
+private:
+ unsigned Specifiers;
+
+ SourceLocation CVS_finalLoc, CVS_explicitLoc;
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index 6a9a1bf5b608..6e808de9a147 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -101,7 +101,7 @@ public:
private:
unsigned Access : 2;
- bool IsMember;
+ unsigned IsMember : 1;
NamedDecl *Target;
CXXRecordDecl *NamingClass;
QualType BaseObjectType;
@@ -119,14 +119,6 @@ public:
SourceLocation Loc;
- union {
- /// Deprecation.
- struct { NamedDecl *Decl; } DeprecationData;
-
- /// Access control.
- char AccessData[sizeof(AccessedEntity)];
- };
-
void destroy() {
switch (Kind) {
case Access: getAccessData().~AccessedEntity(); break;
@@ -135,12 +127,15 @@ public:
}
static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
- NamedDecl *D) {
+ const NamedDecl *D,
+ llvm::StringRef Msg) {
DelayedDiagnostic DD;
DD.Kind = Deprecation;
DD.Triggered = false;
DD.Loc = Loc;
DD.DeprecationData.Decl = D;
+ DD.DeprecationData.Message = Msg.data();
+ DD.DeprecationData.MessageLen = Msg.size();
return DD;
}
@@ -155,11 +150,37 @@ public:
}
AccessedEntity &getAccessData() {
+ assert(Kind == Access && "Not an access diagnostic.");
return *reinterpret_cast<AccessedEntity*>(AccessData);
}
const AccessedEntity &getAccessData() const {
+ assert(Kind == Access && "Not an access diagnostic.");
return *reinterpret_cast<const AccessedEntity*>(AccessData);
}
+
+ const NamedDecl *getDeprecationDecl() const {
+ assert(Kind == Deprecation && "Not a deprecation diagnostic.");
+ return DeprecationData.Decl;
+ }
+
+ llvm::StringRef getDeprecationMessage() const {
+ assert(Kind == Deprecation && "Not a deprecation diagnostic.");
+ return llvm::StringRef(DeprecationData.Message,
+ DeprecationData.MessageLen);
+ }
+
+private:
+ union {
+ /// Deprecation.
+ struct {
+ const NamedDecl *Decl;
+ const char *Message;
+ size_t MessageLen;
+ } DeprecationData;
+
+ /// Access control.
+ char AccessData[sizeof(AccessedEntity)];
+ };
};
}
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index 7be003390b10..6d7bc6316bd2 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -14,10 +14,11 @@
#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
#include "clang/AST/ExternalASTSource.h"
-#include "clang/Sema/ObjCMethodList.h"
+#include <utility>
namespace clang {
+struct ObjCMethodList;
class Sema;
/// \brief An abstract interface that should be implemented by
@@ -44,10 +45,7 @@ public:
///
/// \returns a pair of Objective-C methods lists containing the
/// instance and factory methods, respectively, with this selector.
- virtual std::pair<ObjCMethodList, ObjCMethodList>
- ReadMethodPool(Selector Sel) {
- return std::pair<ObjCMethodList, ObjCMethodList>();
- }
+ virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel);
// isa/cast/dyn_cast support
static bool classof(const ExternalASTSource *Source) {
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 0062b3a29adc..c1915659905b 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -88,6 +88,10 @@ private:
/// the VarDecl, ParmVarDecl, or FieldDecl, respectively.
DeclaratorDecl *VariableOrMember;
+ /// \brief When Kind == EK_Temporary, the type source information for
+ /// the temporary.
+ TypeSourceInfo *TypeInfo;
+
struct {
/// \brief When Kind == EK_Result, EK_Exception, or EK_New, the
/// location of the 'return', 'throw', or 'new' keyword,
@@ -114,12 +118,12 @@ private:
/// \brief Create the initialization entity for a variable.
InitializedEntity(VarDecl *Var)
: Kind(EK_Variable), Parent(0), Type(Var->getType()),
- VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Var)) { }
+ VariableOrMember(Var) { }
/// \brief Create the initialization entity for a parameter.
InitializedEntity(ParmVarDecl *Parm)
: Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()),
- VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Parm)) { }
+ VariableOrMember(Parm) { }
/// \brief Create the initialization entity for the result of a
/// function, throwing an object, performing an explicit cast, or
@@ -135,7 +139,7 @@ private:
/// \brief Create the initialization entity for a member subobject.
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
: Kind(EK_Member), Parent(Parent), Type(Member->getType()),
- VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Member)) { }
+ VariableOrMember(Member) { }
/// \brief Create the initialization entity for an array element.
InitializedEntity(ASTContext &Context, unsigned Index,
@@ -148,16 +152,20 @@ public:
}
/// \brief Create the initialization entity for a parameter.
- static InitializedEntity InitializeParameter(ParmVarDecl *Parm) {
- return InitializedEntity(Parm);
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ ParmVarDecl *Parm) {
+ InitializedEntity Res(Parm);
+ Res.Type = Context.getVariableArrayDecayedType(Res.Type);
+ return Res;
}
/// \brief Create the initialization entity for a parameter that is
/// only known by its type.
- static InitializedEntity InitializeParameter(QualType Type) {
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ QualType Type) {
InitializedEntity Entity;
Entity.Kind = EK_Parameter;
- Entity.Type = Type;
+ Entity.Type = Context.getVariableArrayDecayedType(Type);
Entity.Parent = 0;
Entity.VariableOrMember = 0;
return Entity;
@@ -189,7 +197,15 @@ public:
static InitializedEntity InitializeTemporary(QualType Type) {
return InitializedEntity(EK_Temporary, SourceLocation(), Type);
}
-
+
+ /// \brief Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) {
+ InitializedEntity Result(EK_Temporary, SourceLocation(),
+ TypeInfo->getType());
+ Result.TypeInfo = TypeInfo;
+ return Result;
+ }
+
/// \brief Create the initialization entity for a base class subobject.
static InitializedEntity InitializeBase(ASTContext &Context,
CXXBaseSpecifier *Base,
@@ -201,6 +217,12 @@ public:
return InitializedEntity(Member, Parent);
}
+ /// \brief Create the initialization entity for a member subobject.
+ static InitializedEntity InitializeMember(IndirectFieldDecl *Member,
+ const InitializedEntity *Parent = 0) {
+ return InitializedEntity(Member->getAnonField(), Parent);
+ }
+
/// \brief Create the initialization entity for an array element.
static InitializedEntity InitializeElement(ASTContext &Context,
unsigned Index,
@@ -219,6 +241,15 @@ public:
/// \brief Retrieve type being initialized.
QualType getType() const { return Type; }
+ /// \brief Retrieve complete type-source information for the object being
+ /// constructed, if known.
+ TypeSourceInfo *getTypeSourceInfo() const {
+ if (Kind == EK_Temporary)
+ return TypeInfo;
+
+ return 0;
+ }
+
/// \brief Retrieve the name of the entity being initialized.
DeclarationName getName() const;
@@ -760,12 +791,18 @@ public:
return FailedCandidateSet;
}
+ /// brief Get the overloading result, for when the initialization
+ /// sequence failed due to a bad overload.
+ OverloadingResult getFailedOverloadResult() const {
+ return FailedOverloadResult;
+ }
+
/// \brief Determine why initialization failed.
FailureKind getFailureKind() const {
assert(getKind() == FailedSequence && "Not an initialization failure!");
return Failure;
}
-
+
/// \brief Dump a representation of this initialization sequence to
/// the given stream, for debugging purposes.
void dump(llvm::raw_ostream &OS) const;
diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index 1c7720abb1e1..aa58d14fac73 100644
--- a/include/clang/Sema/Lookup.h
+++ b/include/clang/Sema/Lookup.h
@@ -365,6 +365,11 @@ public:
if (Decls.empty()) {
if (ResultKind != NotFoundInCurrentInstantiation)
ResultKind = NotFound;
+
+ if (Paths) {
+ deletePaths(Paths);
+ Paths = 0;
+ }
} else {
AmbiguityKind SavedAK = Ambiguity;
ResultKind = Found;
@@ -492,25 +497,18 @@ public:
LookupResult &Results;
LookupResult::iterator I;
bool Changed;
-#ifndef NDEBUG
bool CalledDone;
-#endif
friend class LookupResult;
Filter(LookupResult &Results)
- : Results(Results), I(Results.begin()), Changed(false)
-#ifndef NDEBUG
- , CalledDone(false)
-#endif
+ : Results(Results), I(Results.begin()), Changed(false), CalledDone(false)
{}
public:
-#ifndef NDEBUG
~Filter() {
assert(CalledDone &&
"LookupResult::Filter destroyed without done() call");
}
-#endif
bool hasNext() const {
return I != Results.end();
@@ -541,10 +539,8 @@ public:
}
void done() {
-#ifndef NDEBUG
assert(!CalledDone && "done() called twice");
CalledDone = true;
-#endif
if (Changed)
Results.resolveKindAfterFilter();
@@ -573,11 +569,7 @@ private:
void configure();
// Sanity checks.
-#ifndef NDEBUG
void sanity() const;
-#else
- void sanity() const {}
-#endif
bool sanityCheckUnresolved() const {
for (iterator I = begin(), E = end(); I != E; ++I)
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 851d68ac4d79..3ce3513c21ae 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -75,6 +75,7 @@ namespace clang {
ICK_Vector_Conversion, ///< Vector conversions
ICK_Vector_Splat, ///< A vector splat from an arithmetic type
ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7)
+ ICK_Block_Pointer_Conversion, ///< Block Pointer conversions
ICK_Num_Conversion_Kinds ///< The number of conversion kinds
};
@@ -130,27 +131,37 @@ namespace clang {
/// Third - The third conversion can be a qualification conversion.
ImplicitConversionKind Third : 8;
- /// Deprecated - Whether this the deprecated conversion of a
+ /// \brief Whether this is the deprecated conversion of a
/// string literal to a pointer to non-const character data
/// (C++ 4.2p2).
- bool DeprecatedStringLiteralToCharPtr : 1;
+ unsigned DeprecatedStringLiteralToCharPtr : 1;
/// IncompatibleObjC - Whether this is an Objective-C conversion
/// that we should warn about (if we actually use it).
- bool IncompatibleObjC : 1;
+ unsigned IncompatibleObjC : 1;
/// ReferenceBinding - True when this is a reference binding
/// (C++ [over.ics.ref]).
- bool ReferenceBinding : 1;
+ unsigned ReferenceBinding : 1;
/// DirectBinding - True when this is a reference binding that is a
/// direct binding (C++ [dcl.init.ref]).
- bool DirectBinding : 1;
-
- /// RRefBinding - True when this is a reference binding of an rvalue
- /// reference to an rvalue (C++0x [over.ics.rank]p3b4).
- bool RRefBinding : 1;
+ unsigned DirectBinding : 1;
+ /// \brief Whether this is an lvalue reference binding (otherwise, it's
+ /// an rvalue reference binding).
+ unsigned IsLvalueReference : 1;
+
+ /// \brief Whether we're binding to a function lvalue.
+ unsigned BindsToFunctionLvalue : 1;
+
+ /// \brief Whether we're binding to an rvalue.
+ unsigned BindsToRvalue : 1;
+
+ /// \brief Whether this binds an implicit object argument to a
+ /// non-static member function without a ref-qualifier.
+ unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1;
+
/// FromType - The type that this conversion is converting
/// from. This is an opaque pointer that can be translated into a
/// QualType.
@@ -231,6 +242,11 @@ namespace clang {
/// user-defined conversion.
FunctionDecl* ConversionFunction;
+ /// \brief The declaration that we found via name lookup, which might be
+ /// the same as \c ConversionFunction or it might be a using declaration
+ /// that refers to \c ConversionFunction.
+ NamedDecl *FoundConversionFunction;
+
void DebugPrint() const;
};
@@ -283,7 +299,9 @@ namespace clang {
no_conversion,
unrelated_class,
suppressed_user,
- bad_qualifiers
+ bad_qualifiers,
+ lvalue_ref_to_rvalue,
+ rvalue_ref_to_lvalue
};
// This can be null, e.g. for implicit object arguments.
@@ -549,6 +567,10 @@ namespace clang {
/// Actually an OverloadFailureKind.
unsigned char FailureKind;
+ /// \brief The number of call arguments that were explicitly provided,
+ /// to be used while performing partial ordering of function templates.
+ unsigned ExplicitCallArguments;
+
/// A structure used to record information about a failed
/// template argument deduction.
struct DeductionFailureInfo {
@@ -630,7 +652,8 @@ namespace clang {
/// Find the best viable function on this overload set, if it exists.
OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
- OverloadCandidateSet::iterator& Best);
+ OverloadCandidateSet::iterator& Best,
+ bool UserDefinedConversion = false);
void NoteCandidates(Sema &S,
OverloadCandidateDisplayKind OCD,
@@ -642,7 +665,8 @@ namespace clang {
bool isBetterOverloadCandidate(Sema &S,
const OverloadCandidate& Cand1,
const OverloadCandidate& Cand2,
- SourceLocation Loc);
+ SourceLocation Loc,
+ bool UserDefinedConversion = false);
} // end namespace clang
#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
index 7739f3a5d229..5f2f0eba7124 100644
--- a/include/clang/Sema/Ownership.h
+++ b/include/clang/Sema/Ownership.h
@@ -23,7 +23,7 @@
namespace clang {
class Attr;
- class CXXBaseOrMemberInitializer;
+ class CXXCtorInitializer;
class CXXBaseSpecifier;
class Decl;
class DeclGroupRef;
@@ -106,6 +106,9 @@ namespace llvm {
}
enum { NumLowBitsAvailable = 0 };
};
+
+ template <class T>
+ struct isPodLike<clang::OpaquePtr<T> > { static const bool value = true; };
}
@@ -414,7 +417,7 @@ namespace clang {
template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
static const bool value = true;
};
- template<> struct IsResultPtrLowBitFree<CXXBaseOrMemberInitializer*> {
+ template<> struct IsResultPtrLowBitFree<CXXCtorInitializer*> {
static const bool value = true;
};
@@ -427,7 +430,7 @@ namespace clang {
typedef ActionResult<Stmt*> StmtResult;
typedef ActionResult<ParsedType> TypeResult;
typedef ActionResult<CXXBaseSpecifier*> BaseResult;
- typedef ActionResult<CXXBaseOrMemberInitializer*> MemInitResult;
+ typedef ActionResult<CXXCtorInitializer*> MemInitResult;
typedef ActionResult<Decl*> DeclResult;
typedef OpaquePtr<TemplateName> ParsedTemplateTy;
diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h
index da68a494bf7b..5aa6f47425aa 100644
--- a/include/clang/Sema/ParsedTemplate.h
+++ b/include/clang/Sema/ParsedTemplate.h
@@ -32,7 +32,9 @@ namespace clang {
Template
};
- /// \brief Build an empty template argument. This template argument
+ /// \brief Build an empty template argument.
+ ///
+ /// This template argument is invalid.
ParsedTemplateArgument() : Kind(Type), Arg(0) { }
/// \brief Create a template type argument or non-type template argument.
@@ -56,7 +58,7 @@ namespace clang {
SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template),
Arg(Template.getAsOpaquePtr()),
- Loc(TemplateLoc), SS(SS) { }
+ Loc(TemplateLoc), SS(SS), EllipsisLoc() { }
/// \brief Determine whether the given template argument is invalid.
bool isInvalid() const { return Arg == 0; }
@@ -93,6 +95,21 @@ namespace clang {
return SS;
}
+ /// \brief Retrieve the location of the ellipsis that makes a template
+ /// template argument into a pack expansion.
+ SourceLocation getEllipsisLoc() const {
+ assert(Kind == Template &&
+ "Only template template arguments can have an ellipsis");
+ return EllipsisLoc;
+ }
+
+ /// \brief Retrieve a pack expansion of the given template template
+ /// argument.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ParsedTemplateArgument getTemplatePackExpansion(
+ SourceLocation EllipsisLoc) const;
+
private:
KindType Kind;
@@ -107,6 +124,10 @@ namespace clang {
/// \brief The nested-name-specifier that can accompany a template template
/// argument.
CXXScopeSpec SS;
+
+ /// \brief The ellipsis location that can accompany a template template
+ /// argument (turning it into a template template argument expansion).
+ SourceLocation EllipsisLoc;
};
/// \brief Information about a template-id annotation
@@ -161,7 +182,10 @@ namespace clang {
void Destroy() { free(this); }
};
-
+
+ /// 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 {
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index 4229c6c62748..d7fda35cdb87 100644
--- a/include/clang/Sema/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_SEMA_SCOPE_H
#define LLVM_CLANG_SEMA_SCOPE_H
+#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallPtrSet.h"
namespace clang {
@@ -52,7 +53,7 @@ public:
/// ClassScope - The scope of a struct/union/class definition.
ClassScope = 0x20,
- /// BlockScope - This is a scope that corresponds to a block object.
+ /// BlockScope - This is a scope that corresponds to a block/closure object.
/// Blocks serve as top-level scopes for some objects like labels, they
/// also prevent things like break and continue. BlockScopes always have
/// the FnScope, BreakScope, ContinueScope, and DeclScope flags set as well.
@@ -131,11 +132,12 @@ private:
typedef llvm::SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy;
UsingDirectivesTy UsingDirectives;
- /// \brief The number of errors at the start of the given scope.
- unsigned NumErrorsAtStart;
+ /// \brief Used to determine if errors occurred in this scope.
+ DiagnosticErrorTrap ErrorTrap;
public:
- Scope(Scope *Parent, unsigned ScopeFlags) {
+ Scope(Scope *Parent, unsigned ScopeFlags, Diagnostic &Diag)
+ : ErrorTrap(Diag) {
Init(Parent, ScopeFlags);
}
@@ -144,8 +146,7 @@ public:
unsigned getFlags() const { return Flags; }
void setFlags(unsigned F) { Flags = F; }
- /// isBlockScope - Return true if this scope does not correspond to a
- /// closure.
+ /// isBlockScope - Return true if this scope correspond to a closure.
bool isBlockScope() const { return Flags & BlockScope; }
/// getParent - Return the scope that this is nested in.
@@ -214,13 +215,7 @@ public:
void* getEntity() const { return Entity; }
void setEntity(void *E) { Entity = E; }
- /// \brief Retrieve the number of errors that had been emitted when we
- /// entered this scope.
- unsigned getNumErrorsAtStart() const { return NumErrorsAtStart; }
-
- void setNumErrorsAtStart(unsigned NumErrors) {
- NumErrorsAtStart = NumErrors;
- }
+ bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); }
/// isClassScope - Return true if this scope is a class/struct/union scope.
bool isClassScope() const {
@@ -318,7 +313,7 @@ public:
DeclsInScope.clear();
UsingDirectives.clear();
Entity = 0;
- NumErrorsAtStart = 0;
+ ErrorTrap.reset();
}
};
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 50cfa9bb5672..b0bb95509a91 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -17,12 +17,13 @@
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SetVector.h"
namespace clang {
class BlockDecl;
class IdentifierInfo;
-class LabelStmt;
+class LabelDecl;
class ReturnStmt;
class Scope;
class SwitchStmt;
@@ -48,14 +49,8 @@ public:
/// \brief Whether this function contains any indirect gotos.
bool HasIndirectGoto;
- /// \brief The number of errors that had occurred before starting this
- /// function or block.
- unsigned NumErrorsAtStartOfFunction;
-
- /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
- /// it (which acts like the label decl in some ways). Forward referenced
- /// labels have a LabelStmt created for them with a null location & SubStmt.
- llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
+ /// \brief Used to determine if errors occurred in this function or block.
+ DiagnosticErrorTrap ErrorTrap;
/// SwitchStack - This is the current set of active switch statements in the
/// block.
@@ -64,7 +59,7 @@ public:
/// \brief The list of return statements that occur within the function or
/// block, if there is any chance of applying the named return value
/// optimization.
- llvm::SmallVector<ReturnStmt *, 4> Returns;
+ llvm::SmallVector<ReturnStmt*, 4> Returns;
void setHasBranchIntoScope() {
HasBranchIntoScope = true;
@@ -83,18 +78,18 @@ public:
(HasBranchProtectedScope && HasBranchIntoScope);
}
- FunctionScopeInfo(unsigned NumErrors)
+ FunctionScopeInfo(Diagnostic &Diag)
: IsBlockInfo(false),
HasBranchProtectedScope(false),
HasBranchIntoScope(false),
HasIndirectGoto(false),
- NumErrorsAtStartOfFunction(NumErrors) { }
+ ErrorTrap(Diag) { }
virtual ~FunctionScopeInfo();
/// \brief Clear out the information in this function scope, making it
/// suitable for reuse.
- void Clear(unsigned NumErrors);
+ void Clear();
static bool classof(const FunctionScopeInfo *FSI) { return true; }
};
@@ -102,8 +97,6 @@ public:
/// \brief Retains information about a block that is currently being parsed.
class BlockScopeInfo : public FunctionScopeInfo {
public:
- bool hasBlockDeclRefExprs;
-
BlockDecl *TheDecl;
/// TheScope - This is the scope for the block itself, which contains
@@ -118,9 +111,18 @@ public:
/// Its return type may be BuiltinType::Dependent.
QualType FunctionType;
- BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block)
- : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false),
- TheDecl(Block), TheScope(BlockScope)
+ /// CaptureMap - A map of captured variables to (index+1) into Captures.
+ llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
+
+ /// Captures - The captured variables.
+ llvm::SmallVector<BlockDecl::Capture, 4> Captures;
+
+ /// CapturesCXXThis - Whether this block captures 'this'.
+ bool CapturesCXXThis;
+
+ BlockScopeInfo(Diagnostic &Diag, Scope *BlockScope, BlockDecl *Block)
+ : FunctionScopeInfo(Diag), TheDecl(Block), TheScope(BlockScope),
+ CapturesCXXThis(false)
{
IsBlockInfo = true;
}
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 4741028cb0c9..91d6914f24e3 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -20,9 +20,10 @@
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/DeclSpec.h"
-#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TypeTraits.h"
@@ -62,6 +63,7 @@ namespace clang {
class ClassTemplatePartialSpecializationDecl;
class ClassTemplateSpecializationDecl;
class CodeCompleteConsumer;
+ class CodeCompletionAllocator;
class CodeCompletionResult;
class Decl;
class DeclAccessPair;
@@ -78,7 +80,6 @@ namespace clang {
class ExternalSemaSource;
class FormatAttr;
class FriendDecl;
- class FullExpr;
class FunctionDecl;
class FunctionProtoType;
class FunctionTemplateDecl;
@@ -121,7 +122,6 @@ namespace clang {
class TargetAttributesSema;
class TemplateArgument;
class TemplateArgumentList;
- class TemplateArgumentListBuilder;
class TemplateArgumentLoc;
class TemplateDecl;
class TemplateParameterList;
@@ -129,6 +129,7 @@ namespace clang {
class TemplateTemplateParmDecl;
class Token;
class TypedefDecl;
+ class TypeLoc;
class UnqualifiedId;
class UnresolvedLookupExpr;
class UnresolvedMemberExpr;
@@ -140,7 +141,8 @@ namespace clang {
class VarDecl;
class VisibilityAttr;
class VisibleDeclConsumer;
-
+ class IndirectFieldDecl;
+
namespace sema {
class AccessedEntity;
class BlockScopeInfo;
@@ -165,7 +167,10 @@ class LocInfoType : public Type {
TypeSourceInfo *DeclInfo;
LocInfoType(QualType ty, TypeSourceInfo *TInfo)
- : Type((TypeClass)LocInfo, ty, ty->isDependentType()), DeclInfo(TInfo) {
+ : Type((TypeClass)LocInfo, ty, ty->isDependentType(),
+ ty->isVariablyModifiedType(),
+ ty->containsUnexpandedParameterPack()),
+ DeclInfo(TInfo) {
assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
}
friend class Sema;
@@ -183,6 +188,11 @@ public:
static bool classof(const LocInfoType *) { return true; }
};
+// FIXME: No way to easily map from TemplateTypeParmTypes to
+// TemplateTypeParmDecls, so we have this horrible PointerUnion.
+typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
+ SourceLocation> UnexpandedParameterPack;
+
/// Sema - This implements semantic analysis and AST building for C.
class Sema {
Sema(const Sema&); // DO NOT IMPLEMENT
@@ -194,12 +204,15 @@ public:
typedef OpaquePtr<QualType> TypeTy;
typedef Attr AttrTy;
typedef CXXBaseSpecifier BaseTy;
- typedef CXXBaseOrMemberInitializer MemInitTy;
+ typedef CXXCtorInitializer MemInitTy;
typedef Expr ExprTy;
typedef Stmt StmtTy;
typedef TemplateParameterList TemplateParamsTy;
typedef NestedNameSpecifier CXXScopeTy;
+ OpenCLOptions OpenCLFeatures;
+ FPOptions FPFeatures;
+
const LangOptions &LangOpts;
Preprocessor &PP;
ASTContext &Context;
@@ -220,30 +233,6 @@ public:
/// This is used as part of a hack to omit that class from ADL results.
DeclarationName VAListTagName;
- /// A RAII object to temporarily push a declaration context.
- class ContextRAII {
- private:
- Sema &S;
- DeclContext *SavedContext;
-
- public:
- ContextRAII(Sema &S, DeclContext *ContextToPush)
- : S(S), SavedContext(S.CurContext) {
- assert(ContextToPush && "pushing null context");
- S.CurContext = ContextToPush;
- }
-
- void pop() {
- if (!SavedContext) return;
- S.CurContext = SavedContext;
- SavedContext = 0;
- }
-
- ~ContextRAII() {
- pop();
- }
- };
-
/// PackContext - Manages the stack for #pragma pack. An alignment
/// of 0 indicates default alignment.
void *PackContext; // Really a "PragmaPackStack*"
@@ -312,14 +301,125 @@ public:
/// and must warn if not used. Only contains the first declaration.
llvm::SmallVector<const DeclaratorDecl*, 4> UnusedFileScopedDecls;
- /// \brief The stack of diagnostics that were delayed due to being
- /// produced during the parsing of a declaration.
- llvm::SmallVector<sema::DelayedDiagnostic, 0> DelayedDiagnostics;
+ class DelayedDiagnostics;
+
+ class ParsingDeclState {
+ unsigned SavedStackSize;
+ friend class Sema::DelayedDiagnostics;
+ };
+
+ class ProcessingContextState {
+ unsigned SavedParsingDepth;
+ unsigned SavedActiveStackBase;
+ friend class Sema::DelayedDiagnostics;
+ };
+
+ /// A class which encapsulates the logic for delaying diagnostics
+ /// during parsing and other processing.
+ class DelayedDiagnostics {
+ /// \brief The stack of diagnostics that were delayed due to being
+ /// produced during the parsing of a declaration.
+ sema::DelayedDiagnostic *Stack;
+
+ /// \brief The number of objects on the delayed-diagnostics stack.
+ unsigned StackSize;
+
+ /// \brief The current capacity of the delayed-diagnostics stack.
+ unsigned StackCapacity;
+
+ /// \brief The index of the first "active" delayed diagnostic in
+ /// the stack. When parsing class definitions, we ignore active
+ /// delayed diagnostics from the surrounding context.
+ unsigned ActiveStackBase;
+
+ /// \brief The depth of the declarations we're currently parsing.
+ /// This gets saved and reset whenever we enter a class definition.
+ unsigned ParsingDepth;
+
+ public:
+ DelayedDiagnostics() : Stack(0), StackSize(0), StackCapacity(0),
+ ActiveStackBase(0), ParsingDepth(0) {}
+
+ ~DelayedDiagnostics() {
+ delete[] reinterpret_cast<char*>(Stack);
+ }
- /// \brief The depth of the current ParsingDeclaration stack.
- /// If nonzero, we are currently parsing a declaration (and
- /// hence should delay deprecation warnings).
- unsigned ParsingDeclDepth;
+ /// Adds a delayed diagnostic.
+ void add(const sema::DelayedDiagnostic &diag);
+
+ /// Determines whether diagnostics should be delayed.
+ bool shouldDelayDiagnostics() { return ParsingDepth > 0; }
+
+ /// Observe that we've started parsing a declaration. Access and
+ /// deprecation diagnostics will be delayed; when the declaration
+ /// is completed, all active delayed diagnostics will be evaluated
+ /// in its context, and then active diagnostics stack will be
+ /// popped down to the saved depth.
+ ParsingDeclState pushParsingDecl() {
+ ParsingDepth++;
+
+ ParsingDeclState state;
+ state.SavedStackSize = StackSize;
+ return state;
+ }
+
+ /// Observe that we're completed parsing a declaration.
+ static void popParsingDecl(Sema &S, ParsingDeclState state, Decl *decl);
+
+ /// Observe that we've started processing a different context, the
+ /// contents of which are semantically separate from the
+ /// declarations it may lexically appear in. This sets aside the
+ /// current stack of active diagnostics and starts afresh.
+ ProcessingContextState pushContext() {
+ assert(StackSize >= ActiveStackBase);
+
+ ProcessingContextState state;
+ state.SavedParsingDepth = ParsingDepth;
+ state.SavedActiveStackBase = ActiveStackBase;
+
+ ActiveStackBase = StackSize;
+ ParsingDepth = 0;
+
+ return state;
+ }
+
+ /// Observe that we've stopped processing a context. This
+ /// restores the previous stack of active diagnostics.
+ void popContext(ProcessingContextState state) {
+ assert(ActiveStackBase == StackSize);
+ assert(ParsingDepth == 0);
+ ActiveStackBase = state.SavedActiveStackBase;
+ ParsingDepth = state.SavedParsingDepth;
+ }
+ } DelayedDiagnostics;
+
+ /// A RAII object to temporarily push a declaration context.
+ class ContextRAII {
+ private:
+ Sema &S;
+ DeclContext *SavedContext;
+ ProcessingContextState SavedContextState;
+
+ public:
+ ContextRAII(Sema &S, DeclContext *ContextToPush)
+ : S(S), SavedContext(S.CurContext),
+ SavedContextState(S.DelayedDiagnostics.pushContext())
+ {
+ assert(ContextToPush && "pushing null context");
+ S.CurContext = ContextToPush;
+ }
+
+ void pop() {
+ if (!SavedContext) return;
+ S.CurContext = SavedContext;
+ S.DelayedDiagnostics.popContext(SavedContextState);
+ SavedContext = 0;
+ }
+
+ ~ContextRAII() {
+ pop();
+ }
+ };
/// WeakUndeclaredIdentifiers - Identifiers contained in
/// #pragma weak before declared. rare. may alias another
@@ -365,6 +465,12 @@ public:
/// standard library.
LazyDeclPtr StdBadAlloc;
+ /// \brief The C++ "type_info" declaration, which is defined in <typeinfo>.
+ RecordDecl *CXXTypeInfoDecl;
+
+ /// \brief The MSVC "_GUID" struct, which is defined in MSVC header files.
+ RecordDecl *MSVCGuidDecl;
+
/// A flag to remember whether the implicit forms of operator new and delete
/// have been declared.
bool GlobalNewDeleteDeclared;
@@ -398,7 +504,17 @@ public:
/// This evaluation context is used primary for the operand of the C++
/// \c typeid expression, whose argument is potentially evaluated only when
/// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
- PotentiallyPotentiallyEvaluated
+ PotentiallyPotentiallyEvaluated,
+
+ /// \brief The current expression is potentially evaluated, but any
+ /// declarations referenced inside that expression are only used if
+ /// in fact the current expression is used.
+ ///
+ /// This value is used when parsing default function arguments, for which
+ /// we would like to provide diagnostics (e.g., passing non-POD arguments
+ /// through varargs) but do not want to mark declarations as "referenced"
+ /// until the default argument is used.
+ PotentiallyEvaluatedIfUsed
};
/// \brief Data structure used to record current or nested
@@ -468,6 +584,26 @@ public:
/// \brief The number of SFINAE diagnostics that have been trapped.
unsigned NumSFINAEErrors;
+ typedef llvm::DenseMap<ParmVarDecl *, llvm::SmallVector<ParmVarDecl *, 1> >
+ UnparsedDefaultArgInstantiationsMap;
+
+ /// \brief A mapping from parameters with unparsed default arguments to the
+ /// set of instantiations of each parameter.
+ ///
+ /// This mapping is a temporary data structure used when parsing
+ /// nested class templates or nested classes of class templates,
+ /// where we might end up instantiating an inner class before the
+ /// default arguments of its methods have been parsed.
+ UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations;
+
+ // Contains the locations of the beginning of unparsed default
+ // argument locations.
+ llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
+
+ /// UndefinedInternals - all the used, undefined objects with
+ /// internal linkage in this translation unit.
+ llvm::DenseMap<NamedDecl*, SourceLocation> UndefinedInternals;
+
typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
@@ -481,7 +617,6 @@ public:
/// of -Wselector.
llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors;
-
GlobalMethodPool::iterator ReadMethodPool(Selector Sel);
/// Private Helper predicate to check for 'self'.
@@ -497,6 +632,9 @@ public:
void Initialize();
const LangOptions &getLangOptions() const { return LangOpts; }
+ OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
+ FPOptions &getFPOptions() { return FPFeatures; }
+
Diagnostic &getDiagnostics() const { return Diags; }
SourceManager &getSourceManager() const { return SourceMgr; }
const TargetAttributesSema &getTargetAttributesSema() const;
@@ -580,16 +718,20 @@ public:
SourceLocation AttrLoc);
QualType BuildFunctionType(QualType T,
QualType *ParamTypes, unsigned NumParamTypes,
- bool Variadic, unsigned Quals,
+ bool Variadic, unsigned Quals,
+ RefQualifierKind RefQualifier,
SourceLocation Loc, DeclarationName Entity,
- const FunctionType::ExtInfo &Info);
+ FunctionType::ExtInfo Info);
QualType BuildMemberPointerType(QualType T, QualType Class,
SourceLocation Loc,
DeclarationName Entity);
QualType BuildBlockPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity);
+ QualType BuildParenType(QualType T);
+
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S,
- TagDecl **OwnedDecl = 0);
+ TagDecl **OwnedDecl = 0,
+ bool AllowAutoInTypeName = false);
TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo);
/// \brief Package the given type and TSI into a ParsedType.
@@ -630,8 +772,8 @@ public:
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
const CXXScopeSpec &SS, QualType T);
- QualType BuildTypeofExprType(Expr *E);
- QualType BuildDecltypeType(Expr *E);
+ QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
+ QualType BuildDecltypeType(Expr *E, SourceLocation Loc);
//===--------------------------------------------------------------------===//
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
@@ -644,6 +786,7 @@ public:
ParsedType getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS = 0,
bool isClassName = false,
+ bool HasTrailingDot = false,
ParsedType ObjectType = ParsedType());
TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
@@ -674,18 +817,19 @@ public:
bool &Redeclaration);
void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
bool &Redeclaration);
+ void CheckCompleteVariableDeclaration(VarDecl *var);
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, TypeSourceInfo *TInfo,
LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition,
bool &Redeclaration);
- void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
void CheckFunctionDeclaration(Scope *S,
FunctionDecl *NewFD, LookupResult &Previous,
bool IsExplicitSpecialization,
- bool &Redeclaration,
- bool &OverloadableAttrRequired);
+ bool &Redeclaration);
void CheckMain(FunctionDecl *FD);
Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
@@ -707,14 +851,9 @@ public:
bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
SourceLocation EqualLoc);
-
- // Contains the locations of the beginning of unparsed default
- // argument locations.
- llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
-
- void AddInitializerToDecl(Decl *dcl, Expr *init);
- void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
- void ActOnUninitializedDecl(Decl *dcl, bool TypeContainsUndeducedAuto);
+ void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit,
+ bool TypeMayContainAuto);
+ void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
void ActOnInitializerError(Decl *Dcl);
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
@@ -734,6 +873,14 @@ public:
void DiagnoseUnusedParameters(ParmVarDecl * const *Begin,
ParmVarDecl * const *End);
+ /// \brief Diagnose whether the size of parameters or return value of a
+ /// function or obj-c method definition is pass-by-value and larger than a
+ /// specified threshold.
+ void DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Begin,
+ ParmVarDecl * const *End,
+ QualType ReturnTy,
+ NamedDecl *D);
+
void DiagnoseInvalidJumps(Stmt *Body);
Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr);
@@ -745,11 +892,16 @@ public:
/// no declarator (e.g. "struct foo;") is parsed.
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DeclSpec &DS);
+
+ StmtResult ActOnVlaStmt(const DeclSpec &DS);
Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
AccessSpecifier AS,
RecordDecl *Record);
+ Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+ RecordDecl *Record);
+
bool isAcceptableTagRedeclaration(const TagDecl *Previous,
TagTypeKind NewTag,
SourceLocation NewTagLoc,
@@ -767,7 +919,15 @@ public:
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent);
+ bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
+ bool ScopedEnumUsesClassTag, TypeResult UnderlyingType);
+
+ Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
+ unsigned TagSpec, SourceLocation TagLoc,
+ CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TempParamLists);
TypeResult ActOnDependentTag(Scope *S,
unsigned TagSpec,
@@ -826,6 +986,7 @@ public:
/// C++ record definition's base-specifiers clause and are starting its
/// member declarations.
void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl,
+ ClassVirtSpecifiers &CVS,
SourceLocation LBraceLoc);
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
@@ -845,6 +1006,7 @@ public:
Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
SourceLocation IdLoc, IdentifierInfo *Id,
+ AttributeList *Attrs,
SourceLocation EqualLoc, Expr *Val);
void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
SourceLocation RBraceLoc, Decl *EnumDecl,
@@ -897,6 +1059,7 @@ public:
void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
+ void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
@@ -927,7 +1090,7 @@ public:
Ovl_NonFunction
};
OverloadKind CheckOverload(Scope *S,
- FunctionDecl *New,
+ FunctionDecl *New,
const LookupResult &OldDecls,
NamedDecl *&OldDecl,
bool IsForUsingDecl);
@@ -938,7 +1101,8 @@ public:
Expr *From,
bool SuppressUserConversions,
bool AllowExplicit,
- bool InOverloadResolution);
+ bool InOverloadResolution,
+ bool CStyle);
bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
@@ -948,8 +1112,10 @@ public:
QualType& ConvertedType, bool &IncompatibleObjC);
bool isObjCPointerConversion(QualType FromType, QualType ToType,
QualType& ConvertedType, bool &IncompatibleObjC);
- bool FunctionArgTypesAreEqual (FunctionProtoType* OldType,
- FunctionProtoType* NewType);
+ bool IsBlockPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType);
+ bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType);
bool CheckPointerConversion(Expr *From, QualType ToType,
CastKind &Kind,
@@ -962,10 +1128,16 @@ public:
CastKind &Kind,
CXXCastPath &BasePath,
bool IgnoreBaseAccess);
- bool IsQualificationConversion(QualType FromType, QualType ToType);
+ bool IsQualificationConversion(QualType FromType, QualType ToType,
+ bool CStyle);
bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
+ ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *Value);
+
ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
SourceLocation EqualLoc,
ExprResult Init);
@@ -1014,12 +1186,14 @@ public:
bool SuppressUserConversions = false);
void AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
+ Expr::Classification ObjectClassification,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversion = false);
void AddMethodCandidate(CXXMethodDecl *Method,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
@@ -1028,6 +1202,7 @@ public:
CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
+ Expr::Classification ObjectClassification,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
@@ -1051,7 +1226,7 @@ public:
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
- QualType ObjectTy, Expr **Args, unsigned NumArgs,
+ Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet);
void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
SourceLocation OpLoc,
@@ -1074,12 +1249,28 @@ public:
OverloadCandidateSet& CandidateSet,
bool PartialOverloading = false);
+ // Emit as a 'note' the specific overload candidate
void NoteOverloadCandidate(FunctionDecl *Fn);
-
- FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
+
+ // Emit as a series of 'note's all template and non-templates
+ // identified by the expression Expr
+ void NoteAllOverloadCandidates(Expr* E);
+
+ // [PossiblyAFunctionType] --> [Return]
+ // NonFunctionType --> NonFunctionType
+ // R (A) --> R(A)
+ // R (*)(A) --> R (A)
+ // R (&)(A) --> R (A)
+ // R (S::*)(A) --> R (A)
+ QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType);
+
+ FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
bool Complain,
DeclAccessPair &Found);
- FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
+
+ FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From,
+ bool Complain = false,
+ DeclAccessPair* Found = 0);
Expr *FixOverloadedFunctionReference(Expr *E,
DeclAccessPair FoundDecl,
@@ -1097,8 +1288,8 @@ public:
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ Expr *ExecConfig);
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
unsigned Opc,
@@ -1117,12 +1308,10 @@ public:
ExprResult
BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
SourceLocation LParenLoc, Expr **Args,
- unsigned NumArgs, SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ unsigned NumArgs, SourceLocation RParenLoc);
ExprResult
BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
SourceLocation RParenLoc);
ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
@@ -1135,7 +1324,8 @@ public:
CallExpr *CE, FunctionDecl *FD);
/// Helpers for dealing with blocks and functions.
- bool CheckParmsForFunctionDef(FunctionDecl *FD);
+ bool CheckParmsForFunctionDef(ParmVarDecl **Param, ParmVarDecl **ParamEnd,
+ bool CheckParameterNames);
void CheckCXXDefaultArguments(FunctionDecl *FD);
void CheckExtraCXXDefaultArguments(Declarator &D);
Scope *getNonFieldDeclScope(Scope *S);
@@ -1176,13 +1366,14 @@ public:
/// Tag name lookup, which finds the names of enums, classes,
/// structs, and unions.
LookupTagName,
+ /// Label name lookup.
+ LookupLabel,
/// Member name lookup, which finds the names of
/// class/struct/union members.
LookupMemberName,
- // Look up of an operator name (e.g., operator+) for use with
- // operator overloading. This lookup is similar to ordinary name
- // lookup, but will ignore any declarations that are class
- // members.
+ /// Look up of an operator name (e.g., operator+) for use with
+ /// operator overloading. This lookup is similar to ordinary name
+ /// lookup, but will ignore any declarations that are class members.
LookupOperatorName,
/// Look up of a name that precedes the '::' scope resolution
/// operator in C++. This lookup completely ignores operator, object,
@@ -1245,6 +1436,9 @@ public:
QualType T1, QualType T2,
UnresolvedSetImpl &Functions);
+ LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
+ bool isLocalLabel = false);
+
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
@@ -1277,6 +1471,10 @@ public:
CTC_CXXCasts,
/// \brief A member lookup context.
CTC_MemberLookup,
+ /// \brief An Objective-C ivar lookup context (e.g., self->ivar).
+ CTC_ObjCIvarLookup,
+ /// \brief An Objective-C property lookup context (e.g., self.prop).
+ CTC_ObjCPropertyLookup,
/// \brief The receiver of an Objective-C message send within an
/// Objective-C method where 'super' is a valid keyword.
CTC_ObjCMessageReceiver
@@ -1308,8 +1506,14 @@ public:
// More parsing and symbol table subroutines.
// Decl attributes - this routine is the top level dispatcher.
- void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
- void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL);
+ void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
+ bool NonInheritable = true, bool Inheritable = true);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
+ bool NonInheritable = true, bool Inheritable = true);
+
+ bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
+ bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC);
+ bool CheckNoReturnAttr(const AttributeList &attr);
void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
bool &IncompleteImpl, unsigned DiagID);
@@ -1338,6 +1542,14 @@ public:
ObjCIvarDecl **Fields, unsigned nIvars,
SourceLocation Loc);
+ /// \brief Determine whether we can synthesize a provisional ivar for the
+ /// given name.
+ ObjCPropertyDecl *canSynthesizeProvisionalIvar(IdentifierInfo *II);
+
+ /// \brief Determine whether we can synthesize a provisional ivar for the
+ /// given property.
+ bool canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property);
+
/// ImplMethodsVsClassMethods - This is main routine to warn if any method
/// remains unimplemented in the class or category @implementation.
void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
@@ -1484,7 +1696,7 @@ public:
// FIXME: The const_cast here is ugly. RValue references would make this
// much nicer (or we could duplicate a bunch of the move semantics
// emulation code from Ownership.h).
- FullExprArg(const FullExprArg& Other): E(Other.E) {}
+ FullExprArg(const FullExprArg& Other) : E(Other.E) {}
ExprResult release() {
return move(E);
@@ -1498,7 +1710,7 @@ public:
private:
// FIXME: No need to make the entire Sema class a friend when it's just
- // Sema::FullExpr that needs access to the constructor below.
+ // Sema::MakeFullExpr that needs access to the constructor below.
friend class Sema;
explicit FullExprArg(Expr *expr) : E(expr) {}
@@ -1512,7 +1724,8 @@ public:
StmtResult ActOnExprStmt(FullExprArg Expr);
- StmtResult ActOnNullStmt(SourceLocation SemiLoc);
+ StmtResult ActOnNullStmt(SourceLocation SemiLoc,
+ bool LeadingEmptyMacro = false);
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
MultiStmtArg Elts,
bool isStmtExpr);
@@ -1520,6 +1733,7 @@ public:
SourceLocation StartLoc,
SourceLocation EndLoc);
void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
+ StmtResult ActOnForEachLValueExpr(Expr *E);
StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
SourceLocation DotDotDotLoc, Expr *RHSVal,
SourceLocation ColonLoc);
@@ -1528,22 +1742,21 @@ public:
StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
SourceLocation ColonLoc,
Stmt *SubStmt, Scope *CurScope);
- StmtResult ActOnLabelStmt(SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation ColonLoc,
- Stmt *SubStmt);
+ StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+ SourceLocation ColonLoc, Stmt *SubStmt);
+
StmtResult ActOnIfStmt(SourceLocation IfLoc,
- FullExprArg CondVal, Decl *CondVar,
- Stmt *ThenVal,
- SourceLocation ElseLoc, Stmt *ElseVal);
+ FullExprArg CondVal, Decl *CondVar,
+ Stmt *ThenVal,
+ SourceLocation ElseLoc, Stmt *ElseVal);
StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
Expr *Cond,
Decl *CondVar);
StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
Stmt *Switch, Stmt *Body);
StmtResult ActOnWhileStmt(SourceLocation WhileLoc,
- FullExprArg Cond,
- Decl *CondVar, Stmt *Body);
+ FullExprArg Cond,
+ Decl *CondVar, Stmt *Body);
StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
SourceLocation WhileLoc,
SourceLocation CondLParen, Expr *Cond,
@@ -1563,13 +1776,16 @@ public:
StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
- IdentifierInfo *LabelII);
+ LabelDecl *TheDecl);
StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
SourceLocation StarLoc,
Expr *DestExp);
StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
StmtResult ActOnBreakStmt(SourceLocation GotoLoc, Scope *CurScope);
+ const VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
+ bool AllowFunctionParameters);
+
StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
StmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
@@ -1606,11 +1822,10 @@ public:
Expr *SynchExpr,
Stmt *SynchBody);
- VarDecl *BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
+ VarDecl *BuildExceptionDeclaration(Scope *S,
TypeSourceInfo *TInfo,
IdentifierInfo *Name,
- SourceLocation Loc,
- SourceRange Range);
+ SourceLocation Loc);
Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
@@ -1630,18 +1845,31 @@ public:
void DiagnoseUnusedExprResult(const Stmt *S);
void DiagnoseUnusedDecl(const NamedDecl *ND);
- typedef uintptr_t ParsingDeclStackState;
+ ParsingDeclState PushParsingDeclaration() {
+ return DelayedDiagnostics.pushParsingDecl();
+ }
+ void PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
+ DelayedDiagnostics::popParsingDecl(*this, state, decl);
+ }
+
+ typedef ProcessingContextState ParsingClassState;
+ ParsingClassState PushParsingClass() {
+ return DelayedDiagnostics.pushContext();
+ }
+ void PopParsingClass(ParsingClassState state) {
+ DelayedDiagnostics.popContext(state);
+ }
- ParsingDeclStackState PushParsingDeclaration();
- void PopParsingDeclaration(ParsingDeclStackState S, Decl *D);
- void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
+ void EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
+ SourceLocation Loc, bool UnknownObjCClass=false);
void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
- bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc);
+ bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ bool UnknownObjCClass=false);
bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
ObjCMethodDecl *Getter,
SourceLocation Loc);
@@ -1654,6 +1882,7 @@ public:
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
+ void MarkDeclarationsReferencedInExpr(Expr *E);
bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
// Primary Expressions.
@@ -1674,18 +1903,19 @@ public:
const TemplateArgumentListInfo *TemplateArgs);
ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ ExprValueKind VK,
SourceLocation Loc,
const CXXScopeSpec *SS = 0);
ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS = 0);
- VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
- llvm::SmallVectorImpl<FieldDecl *> &Path);
ExprResult
- BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
- FieldDecl *Field,
- Expr *BaseObjectExpr = 0,
- SourceLocation OpLoc = SourceLocation());
+ BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
+ SourceLocation nameLoc,
+ IndirectFieldDecl *indirectField,
+ Expr *baseObjectExpr = 0,
+ SourceLocation opLoc = SourceLocation());
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs);
@@ -1724,7 +1954,7 @@ public:
ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks);
// Binary/Unary Operators. 'Tok' is the token for the operator.
- ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+ ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
Expr *InputArg);
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
UnaryOperatorKind Opc, Expr *input);
@@ -1740,10 +1970,15 @@ public:
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange);
- bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R);
- bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
- const SourceRange &R, bool isSizeof);
+ ExprResult CheckPlaceholderExpr(Expr *E, SourceLocation Loc);
+ bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
+ SourceRange R, bool isSizeof);
+ ExprResult ActOnSizeofParameterPackExpr(Scope *S,
+ SourceLocation OpLoc,
+ IdentifierInfo &Name,
+ SourceLocation NameLoc,
+ SourceLocation RParenLoc);
ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Kind, Expr *Input);
@@ -1803,12 +2038,16 @@ public:
/// This provides the location of the left/right parens and a list of comma
/// locations.
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
- MultiExprArg Args, SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ MultiExprArg Args, SourceLocation RParenLoc,
+ Expr *ExecConfig = 0);
ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ Expr *ExecConfig = 0);
+
+ ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+ MultiExprArg ExecConfig, SourceLocation GGGLoc);
ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
ParsedType Ty, SourceLocation RParenLoc,
@@ -1851,7 +2090,7 @@ public:
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
BinaryOperatorKind Opc, Expr *lhs, Expr *rhs);
ExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
- unsigned Opc, Expr *lhs, Expr *rhs);
+ BinaryOperatorKind Opc, Expr *lhs, Expr *rhs);
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
@@ -1860,10 +2099,9 @@ public:
Expr *Cond, Expr *LHS, Expr *RHS);
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
- ExprResult ActOnAddrLabel(SourceLocation OpLoc,
- SourceLocation LabLoc,
- IdentifierInfo *LabelII);
-
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+ LabelDecl *LD);
+
ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
SourceLocation RPLoc); // "({..})"
@@ -1891,16 +2129,6 @@ public:
unsigned NumComponents,
SourceLocation RParenLoc);
- // __builtin_types_compatible_p(type1, type2)
- ExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
- ParsedType arg1,
- ParsedType arg2,
- SourceLocation RPLoc);
- ExprResult BuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
- TypeSourceInfo *argTInfo1,
- TypeSourceInfo *argTInfo2,
- SourceLocation RPLoc);
-
// __builtin_choose_expr(constExpr, expr1, expr2)
ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
Expr *cond, Expr *expr1,
@@ -1993,6 +2221,8 @@ public:
bool IsTypeName,
SourceLocation TypenameLoc);
+ bool CheckInheritedConstructorUsingDecl(UsingDecl *UD);
+
Decl *ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
bool HasUsingKeyword,
@@ -2009,8 +2239,8 @@ public:
void AddCXXDirectInitializerToDecl(Decl *Dcl,
SourceLocation LParenLoc,
MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ bool TypeMayContainAuto);
/// InitializeVarWithConstructor - Creates an CXXConstructExpr
/// and sets it as the initializer for the the passed in VarDecl.
@@ -2025,7 +2255,8 @@ public:
ExprResult
BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, MultiExprArg Exprs,
- bool RequiresZeroInit, unsigned ConstructKind);
+ bool RequiresZeroInit, unsigned ConstructKind,
+ SourceRange ParenRange);
// FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
// the constructor can be elidable?
@@ -2033,7 +2264,8 @@ public:
BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
MultiExprArg Exprs, bool RequiresZeroInit,
- unsigned ConstructKind);
+ unsigned ConstructKind,
+ SourceRange ParenRange);
/// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
/// the default expr if needed.
@@ -2072,6 +2304,12 @@ public:
void DefineImplicitDestructor(SourceLocation CurrentLocation,
CXXDestructorDecl *Destructor);
+ /// \brief Declare all inherited constructors for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the inherited
+ /// constructors will be added.
+ void DeclareInheritedConstructors(CXXRecordDecl *ClassDecl);
+
/// \brief Declare the implicit copy constructor for the given class.
///
/// \param S The scope of the class, which may be NULL if this is a
@@ -2156,8 +2394,29 @@ public:
void *TyOrExpr,
SourceLocation RParenLoc);
+ ExprResult BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc);
+
+ /// ActOnCXXUuidof - Parse __uuidof( something ).
+ ExprResult ActOnCXXUuidof(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc);
+
+
//// ActOnCXXThis - Parse 'this' pointer.
- ExprResult ActOnCXXThis(SourceLocation ThisLoc);
+ ExprResult ActOnCXXThis(SourceLocation loc);
+
+ /// tryCaptureCXXThis - Try to capture a 'this' pointer. Returns a
+ /// pointer to an instance method whose 'this' pointer is
+ /// capturable, or null if this is not possible.
+ CXXMethodDecl *tryCaptureCXXThis();
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
@@ -2173,11 +2432,14 @@ public:
/// Can be interpreted either as function-style casting ("int(x)")
/// or class type construction ("ClassType(x,y,z)")
/// or creation of a value-initialized type ("int()").
- ExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
- ParsedType TypeRep,
+ ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
MultiExprArg Exprs,
- SourceLocation *CommaLocs,
SourceLocation RParenLoc);
/// ActOnCXXNew - Parsed a C++ 'new' expression.
@@ -2195,12 +2457,12 @@ public:
SourceLocation PlacementRParen,
SourceRange TypeIdParens,
QualType AllocType,
- SourceLocation TypeLoc,
- SourceRange TypeRange,
+ TypeSourceInfo *AllocTypeInfo,
Expr *ArraySize,
SourceLocation ConstructorLParen,
MultiExprArg ConstructorArgs,
- SourceLocation ConstructorRParen);
+ SourceLocation ConstructorRParen,
+ bool TypeMayContainAuto = true);
bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
SourceRange R);
@@ -2231,14 +2493,37 @@ public:
SourceLocation StmtLoc,
bool ConvertToBoolean);
+ ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
+ Expr *Operand, SourceLocation RParen);
+ ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+ SourceLocation RParen);
+
/// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
/// pseudo-functions.
ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
SourceLocation KWLoc,
- SourceLocation LParen,
ParsedType Ty,
SourceLocation RParen);
+ ExprResult BuildUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *T,
+ SourceLocation RParen);
+
+ /// ActOnBinaryTypeTrait - Parsed one of the bianry type trait support
+ /// pseudo-functions.
+ ExprResult ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ ParsedType LhsTy,
+ ParsedType RhsTy,
+ SourceLocation RParen);
+
+ ExprResult BuildBinaryTypeTrait(BinaryTypeTrait BTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *LhsT,
+ TypeSourceInfo *RhsT,
+ SourceLocation RParen);
+
ExprResult ActOnStartCXXMemberReference(Scope *S,
Expr *Base,
SourceLocation OpLoc,
@@ -2268,14 +2553,15 @@ public:
UnqualifiedId &SecondTypeName,
bool HasTrailingLParen);
- /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
- /// non-empty, will create a new CXXExprWithTemporaries expression.
- /// Otherwise, just returs the passed in expression.
- Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr);
- ExprResult MaybeCreateCXXExprWithTemporaries(ExprResult SubExpr);
- FullExpr CreateFullExpr(Expr *SubExpr);
+ /// MaybeCreateExprWithCleanups - If the current full-expression
+ /// requires any cleanups, surround it with a ExprWithCleanups node.
+ /// Otherwise, just returns the passed-in expression.
+ Expr *MaybeCreateExprWithCleanups(Expr *SubExpr);
+ Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt);
+ ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr);
ExprResult ActOnFinishFullExpr(Expr *Expr);
+ StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type.
bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
@@ -2373,9 +2659,8 @@ public:
Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
TypeSourceInfo *EncodedTypeInfo,
SourceLocation RParenLoc);
- CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp,
- NamedDecl *FoundDecl,
- CXXMethodDecl *Method);
+ ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
SourceLocation EncodeLoc,
@@ -2423,7 +2708,7 @@ public:
Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
- Expr *BitfieldWidth,
+ Expr *BitfieldWidth, const VirtSpecifiers &VS,
Expr *Init, bool IsDefinition,
bool Deleted = false);
@@ -2435,10 +2720,10 @@ public:
SourceLocation IdLoc,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ SourceLocation EllipsisLoc);
- MemInitResult BuildMemberInitializer(FieldDecl *Member, Expr **Args,
+ MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc);
@@ -2448,11 +2733,19 @@ public:
Expr **Args, unsigned NumArgs,
SourceLocation LParenLoc,
SourceLocation RParenLoc,
- CXXRecordDecl *ClassDecl);
-
- bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers, bool AnyErrors);
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ SourceLocation LParenLoc,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc);
+
+ bool SetCtorInitializers(CXXConstructorDecl *Constructor,
+ CXXCtorInitializer **Initializers,
+ unsigned NumInitializers, bool AnyErrors);
void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
@@ -2466,8 +2759,11 @@ public:
/// \brief The list of classes whose vtables have been used within
/// this translation unit, and the source locations at which the
/// first use occurred.
- llvm::SmallVector<std::pair<CXXRecordDecl *, SourceLocation>, 16>
- VTableUses;
+ typedef std::pair<CXXRecordDecl*, SourceLocation> VTableUse;
+
+ /// \brief The list of vtables that are required but have not yet been
+ /// materialized.
+ llvm::SmallVector<VTableUse, 16> VTableUses;
/// \brief The set of classes whose vtables have been used within
/// this translation unit, and a bit that will be true if the vtable is
@@ -2546,20 +2842,15 @@ public:
CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- TypeSourceInfo *TInfo);
-
- /// SetClassDeclAttributesFromBase - Copies class decl traits
- /// (such as whether the class has a trivial constructor,
- /// trivial destructor etc) from the given base class.
- void SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
- const CXXRecordDecl *BaseClass,
- bool BaseIsVirtual);
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc);
BaseResult ActOnBaseSpecifier(Decl *classdecl,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- ParsedType basetype, SourceLocation
- BaseLoc);
+ ParsedType basetype,
+ SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc);
bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
unsigned NumBases);
@@ -2596,13 +2887,18 @@ public:
bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
const CXXMethodDecl *Old);
- /// CheckOverridingFunctionAttributes - Checks whether attributes are
- /// incompatible or prevent overriding.
- bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
- const CXXMethodDecl *Old);
-
bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+ /// CheckOverrideControl - Check C++0x override control semantics.
+ void CheckOverrideControl(const Decl *D);
+
+ /// CheckForFunctionMarkedFinal - Checks whether a virtual member function
+ /// overrides a virtual member function marked 'final', according to
+ /// C++0x [class.virtual]p3.
+ bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+
//===--------------------------------------------------------------------===//
// C++ Access Control
//
@@ -2661,6 +2957,10 @@ public:
/// A flag to suppress access checking.
bool SuppressAccessChecking;
+ /// \brief When true, access checking violations are treated as SFINAE
+ /// failures rather than hard errors.
+ bool AccessCheckingSFINAE;
+
void ActOnStartSuppressingAccessChecks();
void ActOnStopSuppressingAccessChecks();
@@ -2732,12 +3032,13 @@ public:
Decl *ActOnTemplateTemplateParameter(Scope *S,
SourceLocation TmpLoc,
TemplateParamsTy *Params,
+ SourceLocation EllipsisLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
unsigned Depth,
unsigned Position,
SourceLocation EqualLoc,
- const ParsedTemplateArgument &DefaultArg);
+ ParsedTemplateArgument DefaultArg);
TemplateParamsTy *
ActOnTemplateParameterList(unsigned Depth,
@@ -2753,7 +3054,8 @@ public:
TPC_ClassTemplate,
TPC_FunctionTemplate,
TPC_ClassTemplateMember,
- TPC_FriendFunctionTemplate
+ TPC_FriendFunctionTemplate,
+ TPC_FriendFunctionTemplateDefinition
};
bool CheckTemplateParameterList(TemplateParameterList *NewParams,
@@ -2788,10 +3090,11 @@ public:
ASTTemplateArgsPtr TemplateArgs,
SourceLocation RAngleLoc);
- TypeResult ActOnTagTemplateIdType(TypeResult Type,
- TagUseKind TUK,
- TypeSpecifierType TagSpec,
- SourceLocation TagLoc);
+ TypeResult ActOnTagTemplateIdType(CXXScopeSpec &SS,
+ TypeResult Type,
+ TagUseKind TUK,
+ TypeSpecifierType TagSpec,
+ SourceLocation TagLoc);
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
LookupResult &R,
@@ -2809,11 +3112,6 @@ public:
bool EnteringContext,
TemplateTy &Template);
- bool CheckClassTemplatePartialSpecializationArgs(
- TemplateParameterList *TemplateParams,
- const TemplateArgumentListBuilder &TemplateArgs,
- bool &MirrorsPrimaryTemplate);
-
DeclResult
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc,
@@ -2886,7 +3184,7 @@ public:
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
Decl *Param,
- TemplateArgumentListBuilder &Converted);
+ llvm::SmallVectorImpl<TemplateArgument> &Converted);
/// \brief Specifies the context in which a particular template
/// argument is being checked.
@@ -2906,21 +3204,22 @@ public:
bool CheckTemplateArgument(NamedDecl *Param,
const TemplateArgumentLoc &Arg,
- TemplateDecl *Template,
+ NamedDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
- TemplateArgumentListBuilder &Converted,
+ unsigned ArgumentPackIndex,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted,
CheckTemplateArgumentKind CTAK = CTAK_Specified);
bool CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
const TemplateArgumentListInfo &TemplateArgs,
bool PartialTemplateArgs,
- TemplateArgumentListBuilder &Converted);
+ llvm::SmallVectorImpl<TemplateArgument> &Converted);
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
const TemplateArgumentLoc &Arg,
- TemplateArgumentListBuilder &Converted);
+ llvm::SmallVectorImpl<TemplateArgument> &Converted);
bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
TypeSourceInfo *Arg);
@@ -3034,6 +3333,289 @@ public:
const TemplateArgument *Args,
unsigned NumArgs);
+ //===--------------------------------------------------------------------===//
+ // C++ Variadic Templates (C++0x [temp.variadic])
+ //===--------------------------------------------------------------------===//
+
+ /// \brief The context in which an unexpanded parameter pack is
+ /// being diagnosed.
+ ///
+ /// Note that the values of this enumeration line up with the first
+ /// argument to the \c err_unexpanded_parameter_pack diagnostic.
+ enum UnexpandedParameterPackContext {
+ /// \brief An arbitrary expression.
+ UPPC_Expression = 0,
+
+ /// \brief The base type of a class type.
+ UPPC_BaseType,
+
+ /// \brief The type of an arbitrary declaration.
+ UPPC_DeclarationType,
+
+ /// \brief The type of a data member.
+ UPPC_DataMemberType,
+
+ /// \brief The size of a bit-field.
+ UPPC_BitFieldWidth,
+
+ /// \brief The expression in a static assertion.
+ UPPC_StaticAssertExpression,
+
+ /// \brief The fixed underlying type of an enumeration.
+ UPPC_FixedUnderlyingType,
+
+ /// \brief The enumerator value.
+ UPPC_EnumeratorValue,
+
+ /// \brief A using declaration.
+ UPPC_UsingDeclaration,
+
+ /// \brief A friend declaration.
+ UPPC_FriendDeclaration,
+
+ /// \brief A declaration qualifier.
+ UPPC_DeclarationQualifier,
+
+ /// \brief An initializer.
+ UPPC_Initializer,
+
+ /// \brief A default argument.
+ UPPC_DefaultArgument,
+
+ /// \brief The type of a non-type template parameter.
+ UPPC_NonTypeTemplateParameterType,
+
+ /// \brief The type of an exception.
+ UPPC_ExceptionType,
+
+ /// \brief Partial specialization.
+ UPPC_PartialSpecialization
+ };
+
+ /// \brief If the given type contains an unexpanded parameter pack,
+ /// diagnose the error.
+ ///
+ /// \param Loc The source location where a diagnostc should be emitted.
+ ///
+ /// \param T The type that is being checked for unexpanded parameter
+ /// packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given expression contains an unexpanded parameter
+ /// pack, diagnose the error.
+ ///
+ /// \param E The expression that is being checked for unexpanded
+ /// parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(Expr *E,
+ UnexpandedParameterPackContext UPPC = UPPC_Expression);
+
+ /// \brief If the given nested-name-specifier contains an unexpanded
+ /// parameter pack, diagnose the error.
+ ///
+ /// \param SS The nested-name-specifier that is being checked for
+ /// unexpanded parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given name contains an unexpanded parameter pack,
+ /// diagnose the error.
+ ///
+ /// \param NameInfo The name (with source location information) that
+ /// is being checked for unexpanded parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given template name contains an unexpanded parameter pack,
+ /// diagnose the error.
+ ///
+ /// \param Loc The location of the template name.
+ ///
+ /// \param Template The template name that is being checked for unexpanded
+ /// parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+ TemplateName Template,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given template argument contains an unexpanded parameter
+ /// pack, diagnose the error.
+ ///
+ /// \param Arg The template argument that is being checked for unexpanded
+ /// parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// template argument.
+ ///
+ /// \param Arg The template argument that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TemplateArgument Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// template argument.
+ ///
+ /// \param Arg The template argument that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// type.
+ ///
+ /// \param T The type that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(QualType T,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// type.
+ ///
+ /// \param TL The type that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TypeLoc TL,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Invoked when parsing a template argument followed by an
+ /// ellipsis, which creates a pack expansion.
+ ///
+ /// \param Arg The template argument preceding the ellipsis, which
+ /// may already be invalid.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg,
+ SourceLocation EllipsisLoc);
+
+ /// \brief Invoked when parsing a type followed by an ellipsis, which
+ /// creates a pack expansion.
+ ///
+ /// \param Type The type preceding the ellipsis, which will become
+ /// the pattern of the pack expansion.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc);
+
+ /// \brief Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
+
+ /// \brief Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ QualType CheckPackExpansion(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
+
+ /// \brief Invoked when parsing an expression followed by an ellipsis, which
+ /// creates a pack expansion.
+ ///
+ /// \param Pattern The expression preceding the ellipsis, which will become
+ /// the pattern of the pack expansion.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc);
+
+ /// \brief Invoked when parsing an expression followed by an ellipsis, which
+ /// creates a pack expansion.
+ ///
+ /// \param Pattern The expression preceding the ellipsis, which will become
+ /// the pattern of the pack expansion.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
+
+ /// \brief Determine whether we could expand a pack expansion with the
+ /// given set of parameter packs into separate arguments by repeatedly
+ /// transforming the pattern.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis that identifies the
+ /// pack expansion.
+ ///
+ /// \param PatternRange The source range that covers the entire pattern of
+ /// the pack expansion.
+ ///
+ /// \param Unexpanded The set of unexpanded parameter packs within the
+ /// pattern.
+ ///
+ /// \param NumUnexpanded The number of unexpanded parameter packs in
+ /// \p Unexpanded.
+ ///
+ /// \param ShouldExpand Will be set to \c true if the transformer should
+ /// expand the corresponding pack expansions into separate arguments. When
+ /// set, \c NumExpansions must also be set.
+ ///
+ /// \param RetainExpansion Whether the caller should add an unexpanded
+ /// pack expansion after all of the expanded arguments. This is used
+ /// when extending explicitly-specified template argument packs per
+ /// C++0x [temp.arg.explicit]p9.
+ ///
+ /// \param NumExpansions The number of separate arguments that will be in
+ /// the expanded form of the corresponding pack expansion. This is both an
+ /// input and an output parameter, which can be set by the caller if the
+ /// number of expansions is known a priori (e.g., due to a prior substitution)
+ /// and will be set by the callee when the number of expansions is known.
+ /// The callee must set this value when \c ShouldExpand is \c true; it may
+ /// set this value in other cases.
+ ///
+ /// \returns true if an error occurred (e.g., because the parameter packs
+ /// are to be instantiated with arguments of different lengths), false
+ /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions)
+ /// must be set.
+ bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool &ShouldExpand,
+ bool &RetainExpansion,
+ llvm::Optional<unsigned> &NumExpansions);
+
+ /// \brief Determine the number of arguments in the given pack expansion
+ /// type.
+ ///
+ /// This routine already assumes that the pack expansion type can be
+ /// expanded and that the number of arguments in the expansion is
+ /// consistent across all of the unexpanded parameter packs in its pattern.
+ unsigned getNumArgumentsInExpansion(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ /// \brief Determine whether the given declarator contains any unexpanded
+ /// parameter packs.
+ ///
+ /// This routine is used by the parser to disambiguate function declarators
+ /// with an ellipsis prior to the ')', e.g.,
+ ///
+ /// \code
+ /// void f(T...);
+ /// \endcode
+ ///
+ /// To determine whether we have an (unnamed) function parameter pack or
+ /// a variadic function.
+ ///
+ /// \returns true if the declarator contains any unexpanded parameter packs,
+ /// false otherwise.
+ bool containsUnexpandedParameterPacks(Declarator &D);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Argument Deduction (C++ [temp.deduct])
+ //===--------------------------------------------------------------------===//
+
/// \brief Describes the result of template argument deduction.
///
/// The TemplateDeductionResult enumeration describes the result of
@@ -3128,17 +3710,22 @@ public:
FunctionDecl *&Specialization,
sema::TemplateDeductionInfo &Info);
+ bool DeduceAutoType(QualType AutoType, Expr *Initializer, QualType &Result);
+
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
SourceLocation Loc,
- TemplatePartialOrderingContext TPOC);
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments);
UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
UnresolvedSetIterator SEnd,
TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments,
SourceLocation Loc,
const PartialDiagnostic &NoneDiag,
const PartialDiagnostic &AmbigDiag,
- const PartialDiagnostic &CandidateDiag);
+ const PartialDiagnostic &CandidateDiag,
+ bool Complain = true);
ClassTemplatePartialSpecializationDecl *
getMoreSpecializedPartialSpecialization(
@@ -3206,9 +3793,10 @@ public:
/// \brief The point of instantiation within the source code.
SourceLocation PointOfInstantiation;
- /// \brief The template in which we are performing the instantiation,
- /// for substitutions of prior template arguments.
- TemplateDecl *Template;
+ /// \brief The template (or partial specialization) in which we are
+ /// performing the instantiation, for substitutions of prior template
+ /// arguments.
+ NamedDecl *Template;
/// \brief The entity that is being instantiated.
uintptr_t Entity;
@@ -3220,6 +3808,10 @@ public:
/// \brief The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;
+ /// \brief The template deduction info object associated with the
+ /// substitution or checking of explicit or deduced template arguments.
+ sema::TemplateDeductionInfo *DeductionInfo;
+
/// \brief The source range that covers the construct that cause
/// the instantiation, e.g., the template-id that causes a class
/// template instantiation.
@@ -3227,7 +3819,7 @@ public:
ActiveTemplateInstantiation()
: Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0),
- NumTemplateArgs(0) {}
+ NumTemplateArgs(0), DeductionInfo(0) {}
/// \brief Determines whether this template is an actual instantiation
/// that should be counted toward the maximum instantiation depth.
@@ -3278,6 +3870,13 @@ public:
llvm::SmallVector<ActiveTemplateInstantiation, 16>
ActiveTemplateInstantiations;
+ /// \brief Whether we are in a SFINAE context that is not associated with
+ /// template instantiation.
+ ///
+ /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside
+ /// of a template instantiation or template argument deduction.
+ bool InNonInstantiationSFINAEContext;
+
/// \brief The number of ActiveTemplateInstantiation entries in
/// \c ActiveTemplateInstantiations that are not actual instantiations and,
/// therefore, should not be counted as part of the instantiation depth.
@@ -3292,12 +3891,49 @@ public:
/// to implement it anywhere else.
ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
+ /// \brief The current index into pack expansion arguments that will be
+ /// used for substitution of parameter packs.
+ ///
+ /// The pack expansion index will be -1 to indicate that parameter packs
+ /// should be instantiated as themselves. Otherwise, the index specifies
+ /// which argument within the parameter pack will be used for substitution.
+ int ArgumentPackSubstitutionIndex;
+
+ /// \brief RAII object used to change the argument pack substitution index
+ /// within a \c Sema object.
+ ///
+ /// See \c ArgumentPackSubstitutionIndex for more information.
+ class ArgumentPackSubstitutionIndexRAII {
+ Sema &Self;
+ int OldSubstitutionIndex;
+
+ public:
+ ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
+ : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+ Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
+ }
+
+ ~ArgumentPackSubstitutionIndexRAII() {
+ Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
+ }
+ };
+
+ friend class ArgumentPackSubstitutionRAII;
+
/// \brief The stack of calls expression undergoing template instantiation.
///
/// The top of this stack is used by a fixit instantiating unresolved
/// function calls to fix the AST to match the textual change it prints.
llvm::SmallVector<CallExpr *, 8> CallsUndergoingInstantiation;
-
+
+ /// \brief For each declaration that involved template argument deduction, the
+ /// set of diagnostics that were suppressed during that template argument
+ /// deduction.
+ ///
+ /// FIXME: Serialize this structure to the AST file.
+ llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >
+ SuppressedDiagnostics;
+
/// \brief A stack object to be created when performing template
/// instantiation.
///
@@ -3331,6 +3967,7 @@ public:
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
ActiveTemplateInstantiation::InstantiationKind Kind,
+ sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we are instantiating as part of template
@@ -3340,6 +3977,7 @@ public:
ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -3351,14 +3989,14 @@ public:
/// \brief Note that we are substituting prior template arguments into a
/// non-type or template template parameter.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateDecl *Template,
+ NamedDecl *Template,
NonTypeTemplateParmDecl *Param,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceRange InstantiationRange);
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateDecl *Template,
+ NamedDecl *Template,
TemplateTemplateParmDecl *Param,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
@@ -3386,7 +4024,7 @@ public:
private:
Sema &SemaRef;
bool Invalid;
-
+ bool SavedInNonInstantiationSFINAEContext;
bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
SourceRange InstantiationRange);
@@ -3402,21 +4040,39 @@ public:
/// template argument substitution failures are not considered
/// errors.
///
- /// When this routine returns true, the emission of most diagnostics
- /// will be suppressed and there will be no local error recovery.
- bool isSFINAEContext() const;
+ /// \returns An empty \c llvm::Optional if we're not in a SFINAE context.
+ /// Otherwise, contains a pointer that, if non-NULL, contains the nearest
+ /// template-deduction context object, which can be used to capture
+ /// diagnostics that will be suppressed.
+ llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const;
/// \brief RAII class used to determine whether SFINAE has
/// trapped any errors that occur during template argument
- /// deduction.
+ /// deduction.`
class SFINAETrap {
Sema &SemaRef;
unsigned PrevSFINAEErrors;
+ bool PrevInNonInstantiationSFINAEContext;
+ bool PrevAccessCheckingSFINAE;
+
public:
- explicit SFINAETrap(Sema &SemaRef)
- : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors) { }
+ explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false)
+ : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors),
+ PrevInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext),
+ PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE)
+ {
+ if (!SemaRef.isSFINAEContext())
+ SemaRef.InNonInstantiationSFINAEContext = true;
+ SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE;
+ }
- ~SFINAETrap() { SemaRef.NumSFINAEErrors = PrevSFINAEErrors; }
+ ~SFINAETrap() {
+ SemaRef.NumSFINAEErrors = PrevSFINAEErrors;
+ SemaRef.InNonInstantiationSFINAEContext
+ = PrevInNonInstantiationSFINAEContext;
+ SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
+ }
/// \brief Determine whether any SFINAE errors have been trapped.
bool hasErrorOccurred() const {
@@ -3424,24 +4080,6 @@ public:
}
};
- /// \brief RAII class that determines when any errors have occurred
- /// between the time the instance was created and the time it was
- /// queried.
- class ErrorTrap {
- Sema &SemaRef;
- unsigned PrevErrors;
-
- public:
- explicit ErrorTrap(Sema &SemaRef)
- : SemaRef(SemaRef), PrevErrors(SemaRef.getDiagnostics().getNumErrors()) {}
-
- /// \brief Determine whether any errors have occurred since this
- /// object instance was created.
- bool hasErrorOccurred() const {
- return SemaRef.getDiagnostics().getNumErrors() > PrevErrors;
- }
- };
-
/// \brief The current instantiation scope used to store local
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
@@ -3449,6 +4087,17 @@ public:
/// \brief The number of typos corrected by CorrectTypo.
unsigned TyposCorrected;
+ typedef llvm::DenseMap<IdentifierInfo *, std::pair<llvm::StringRef, bool> >
+ UnqualifiedTyposCorrectedMap;
+
+ /// \brief A cache containing the results of typo correction for unqualified
+ /// name lookup.
+ ///
+ /// The string is the string that we corrected to (which may be empty, if
+ /// there was no correction), while the boolean will be true when the
+ /// string represents a keyword.
+ UnqualifiedTyposCorrectedMap UnqualifiedTyposCorrected;
+
/// \brief Worker object for performing CFG-based warnings.
sema::AnalysisBasedWarnings AnalysisWarnings;
@@ -3485,14 +4134,43 @@ public:
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity);
+ TypeSourceInfo *SubstType(TypeLoc TL,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc,
DeclarationName Entity);
ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::Optional<unsigned> NumExpansions);
+ bool SubstParmTypes(SourceLocation Loc,
+ ParmVarDecl **Params, unsigned NumParams,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<QualType> &ParamTypes,
+ llvm::SmallVectorImpl<ParmVarDecl *> *OutParams = 0);
ExprResult SubstExpr(Expr *E,
const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ /// \brief Substitute the given template arguments into a list of
+ /// expressions, expanding pack expansions if required.
+ ///
+ /// \param Exprs The list of expressions to substitute into.
+ ///
+ /// \param NumExprs The number of expressions in \p Exprs.
+ ///
+ /// \param IsCall Whether this is some form of call, in which case
+ /// default arguments will be dropped.
+ ///
+ /// \param TemplateArgs The set of template arguments to substitute.
+ ///
+ /// \param Outputs Will receive all of the substituted arguments.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<Expr *> &Outputs);
StmtResult SubstStmt(Stmt *S,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -3541,7 +4219,8 @@ public:
TemplateName
SubstTemplateName(TemplateName Name, SourceLocation Loc,
const MultiLevelTemplateArgumentList &TemplateArgs);
- bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result,
+ bool Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ TemplateArgumentListInfo &Result,
const MultiLevelTemplateArgumentList &TemplateArgs);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
@@ -3636,7 +4315,19 @@ public:
void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
SourceLocation Loc,
unsigned &Attributes);
- void ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *DC);
+
+ /// Process the specified property declaration and create decls for the
+ /// setters and getters as needed.
+ /// \param property The property declaration being processed
+ /// \param DC The semantic container for the property
+ /// \param redeclaredProperty Declaration for property if redeclared
+ /// in class extension.
+ /// \param lexicalDC Container for redeclaredProperty.
+ void ProcessPropertyDecl(ObjCPropertyDecl *property,
+ ObjCContainerDecl *DC,
+ ObjCPropertyDecl *redeclaredProperty = 0,
+ ObjCContainerDecl *lexicalDC = 0);
+
void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
ObjCPropertyDecl *SuperProperty,
const IdentifierInfo *Name);
@@ -3664,14 +4355,16 @@ public:
Selector GetterSel, Selector SetterSel,
Decl *ClassCategory,
bool *OverridingProperty,
- tok::ObjCKeywordKind MethodImplKind);
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC = 0);
Decl *ActOnPropertyImplDecl(Scope *S,
SourceLocation AtLoc,
SourceLocation PropertyLoc,
bool ImplKind,Decl *ClassImplDecl,
IdentifierInfo *PropertyId,
- IdentifierInfo *PropertyIvar);
+ IdentifierInfo *PropertyIvar,
+ SourceLocation PropertyIvarLoc);
struct ObjCArgInfo {
IdentifierInfo *Name;
@@ -3686,6 +4379,7 @@ public:
};
Decl *ActOnMethodDeclaration(
+ Scope *S,
SourceLocation BeginLoc, // location of the + or -.
SourceLocation EndLoc, // location of the ; or {.
tok::TokenKind MethodType,
@@ -3711,7 +4405,9 @@ public:
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Expr *BaseExpr,
DeclarationName MemberName,
- SourceLocation MemberLoc);
+ SourceLocation MemberLoc,
+ SourceLocation SuperLoc, QualType SuperType,
+ bool Super);
ExprResult
ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
@@ -3719,6 +4415,8 @@ public:
SourceLocation receiverNameLoc,
SourceLocation propertyNameLoc);
+ ObjCMethodDecl *tryCaptureObjCSelf();
+
/// \brief Describes the kind of message expression indicated by a message
/// send that starts with an identifier.
enum ObjCMessageKind {
@@ -3751,6 +4449,7 @@ public:
Selector Sel,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
SourceLocation RBracLoc,
MultiExprArg Args);
@@ -3768,6 +4467,7 @@ public:
Selector Sel,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
SourceLocation RBracLoc,
MultiExprArg Args);
@@ -3810,11 +4510,9 @@ public:
SourceLocation RParenLoc);
/// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
- void ActOnPragmaUnused(const Token *Identifiers,
- unsigned NumIdentifiers, Scope *curScope,
- SourceLocation PragmaLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ void ActOnPragmaUnused(const Token &Identifier,
+ Scope *curScope,
+ SourceLocation PragmaLoc);
/// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... .
void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
@@ -3835,6 +4533,10 @@ public:
SourceLocation WeakNameLoc,
SourceLocation AliasNameLoc);
+ /// ActOnPragmaFPContract - Called on well formed
+ /// #pragma {STDC,OPENCL} FP_CONTRACT
+ void ActOnPragmaFPContract(tok::OnOffSwitch OOS);
+
/// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
/// a the record decl, to handle '#pragma pack' and '#pragma options align'.
void AddAlignmentAttributesForRecord(RecordDecl *RD);
@@ -3842,9 +4544,9 @@ public:
/// FreePackedContext - Deallocate and null out PackContext.
void FreePackedContext();
- /// PushVisibilityAttr - Note that we've entered a context with a
- /// visibility attribute.
- void PushVisibilityAttr(const VisibilityAttr *Attr);
+ /// PushNamespaceVisibilityAttr - Note that we've entered a
+ /// namespace with a visibility attribute.
+ void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr);
/// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used,
/// add an appropriate visibility attribute.
@@ -3872,6 +4574,11 @@ public:
ExprValueKind VK = VK_RValue,
const CXXCastPath *BasePath = 0);
+ /// IgnoredValueConversions - Given that an expression's result is
+ /// syntactically ignored, perform any conversions that are
+ /// required.
+ void IgnoredValueConversions(Expr *&expr);
+
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
// functions and arrays to their respective pointers (C99 6.3.2.1).
Expr *UsualUnaryConversions(Expr *&expr);
@@ -3885,6 +4592,12 @@ public:
// lvalue-to-rvalue conversion.
void DefaultFunctionArrayLvalueConversion(Expr *&expr);
+ // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on
+ // the operand. This is DefaultFunctionArrayLvalueConversion,
+ // except that it assumes the operand isn't of function or array
+ // type.
+ void DefaultLvalueConversion(Expr *&expr);
+
// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
// do not have a prototype. Integer promotions are performed on each
// argument, and arguments that have type float are promoted to double.
@@ -3957,6 +4670,11 @@ public:
/// c/v/r qualifiers, which we accept as an extension.
CompatiblePointerDiscardsQualifiers,
+ /// IncompatiblePointerDiscardsQualifiers - The assignment
+ /// discards qualifiers that we don't permit to be discarded,
+ /// like address spaces.
+ IncompatiblePointerDiscardsQualifiers,
+
/// IncompatibleNestedPointerQualifiers - The assignment is between two
/// nested pointer types, and the qualifiers other than the first two
/// levels differ e.g. char ** -> const char **, but we accept them as an
@@ -3996,8 +4714,14 @@ public:
/// CheckAssignmentConstraints - Perform type checking for assignment,
/// argument passing, variable initialization, and function return values.
- /// This routine is only used by the following two methods. C99 6.5.16.
- AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs);
+ /// C99 6.5.16.
+ AssignConvertType CheckAssignmentConstraints(SourceLocation Loc,
+ QualType lhs, QualType rhs);
+
+ /// Check assignment constraints and prepare for a conversion of the
+ /// RHS to the LHS type.
+ AssignConvertType CheckAssignmentConstraints(QualType lhs, Expr *&rhs,
+ CastKind &Kind);
// CheckSingleAssignmentConstraints - Currently used by
// CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
@@ -4010,18 +4734,6 @@ public:
AssignConvertType CheckTransparentUnionArgumentConstraints(QualType lhs,
Expr *&rExpr);
- // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
- AssignConvertType CheckPointerTypesForAssignment(QualType lhsType,
- QualType rhsType);
-
- AssignConvertType CheckObjCPointerTypesForAssignment(QualType lhsType,
- QualType rhsType);
-
- // Helper function for CheckAssignmentConstraints involving two
- // block pointer types.
- AssignConvertType CheckBlockPointerTypesForAssignment(QualType lhsType,
- QualType rhsType);
-
bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
@@ -4036,10 +4748,11 @@ public:
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const ImplicitConversionSequence& ICS,
AssignmentAction Action,
- bool IgnoreBaseAccess = false);
+ bool CStyle = false);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const StandardConversionSequence& SCS,
- AssignmentAction Action,bool IgnoreBaseAccess);
+ AssignmentAction Action,
+ bool CStyle);
/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).
@@ -4047,7 +4760,8 @@ public:
/// type checking binary operators (subroutines of CreateBuiltinBinOp).
QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex);
QualType CheckPointerToMemberOperands( // C++ 5.5
- Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isIndirect);
+ Expr *&lex, Expr *&rex, ExprValueKind &VK,
+ SourceLocation OpLoc, bool isIndirect);
QualType CheckMultiplyDivideOperands( // C99 6.5.5
Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign,
bool isDivide);
@@ -4071,36 +4785,30 @@ public:
// For compound assignment, pass both expressions and the converted type.
QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType);
- QualType CheckCommaOperands( // C99 6.5.17
- Expr *lex, Expr *&rex, SourceLocation OpLoc);
+
+ void ConvertPropertyForRValue(Expr *&E);
+ void ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType& LHSTy);
+
QualType CheckConditionalOperands( // C99 6.5.15
- Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+ Expr *&cond, Expr *&lhs, Expr *&rhs,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
QualType CXXCheckConditionalOperands( // C++ 5.16
- Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+ Expr *&cond, Expr *&lhs, Expr *&rhs,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
bool *NonStandardCompositeType = 0);
QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
SourceLocation questionLoc);
+ bool DiagnoseConditionalForNull(Expr *LHS, Expr *RHS,
+ SourceLocation QuestionLoc);
+
/// type checking for vector binary operators.
QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx,
SourceLocation l, bool isRel);
- /// type checking unary operators (subroutines of ActOnUnaryOp).
- /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
- QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
- bool isInc, bool isPrefix);
- QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
- QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
- QualType CheckRealImagOperand(Expr *&Op, SourceLocation OpLoc, bool isReal);
-
- /// type checking primary expressions.
- QualType CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
- const IdentifierInfo *Comp,
- SourceLocation CmpLoc);
-
/// type checking declaration initializers (C99 6.7.8)
bool CheckInitList(const InitializedEntity &Entity,
InitListExpr *&InitList, QualType &DeclType);
@@ -4137,7 +4845,7 @@ public:
/// CheckCastTypes - Check type constraints for casting between types under
/// C semantics, or forward to CXXCheckCStyleCast in C++.
bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
- CastKind &Kind, CXXCastPath &BasePath,
+ CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath,
bool FunctionalStyle = false);
// CheckVectorCast - check type constraints for vectors.
@@ -4157,9 +4865,9 @@ public:
/// CXXCheckCStyleCast - Check constraints of a C-style or function-style
/// cast under C++ semantics.
- bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
- CastKind &Kind, CXXCastPath &BasePath,
- bool FunctionalStyle);
+ bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
+ Expr *&CastExpr, CastKind &Kind,
+ CXXCastPath &BasePath, bool FunctionalStyle);
/// CheckMessageArgumentTypes - Check types in an Obj-C message send.
/// \param Method - May be null.
@@ -4168,7 +4876,7 @@ public:
bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel,
ObjCMethodDecl *Method, bool isClassMessage,
SourceLocation lbrac, SourceLocation rbrac,
- QualType &ReturnType);
+ QualType &ReturnType, ExprValueKind &VK);
/// CheckBooleanCondition - Diagnose problems involving the use of
/// the given expression as a boolean condition (e.g. in an if
@@ -4187,6 +4895,10 @@ public:
/// being used as a boolean condition, warn if it's an assignment.
void DiagnoseAssignmentAsCondition(Expr *E);
+ /// \brief Redundant parentheses over an equality comparison can indicate
+ /// that the user intended an assignment used as condition.
+ void DiagnoseEqualityWithExtraParens(ParenExpr *parenE);
+
/// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
bool CheckCXXBooleanCondition(Expr *&CondExpr);
@@ -4202,8 +4914,6 @@ public:
/// in the global scope.
bool CheckObjCDeclScope(Decl *D);
- void InitBuiltinVaListType();
-
/// VerifyIntegerConstantExpression - verifies that an expression is an ICE,
/// and reports the appropriate diagnostics. Returns false on success.
/// Can optionally return the value of the expression.
@@ -4256,14 +4966,20 @@ public:
/// in the grammar.
PCC_RecoveryInFunction,
/// \brief Code completion occurs where only a type is permitted.
- PCC_Type
+ PCC_Type,
+ /// \brief Code completion occurs in a parenthesized expression, which
+ /// might also be a type cast.
+ PCC_ParenthesizedExpression,
+ /// \brief Code completion occurs within a sequence of declaration
+ /// specifiers within a function, method, or block.
+ PCC_LocalDeclarationSpecifiers
};
void CodeCompleteOrdinaryName(Scope *S,
ParserCompletionContext CompletionContext);
- void CodeCompleteDeclarator(Scope *S,
- bool AllowNonIdentifiers,
- bool AllowNestedNameSpecifiers);
+ void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers);
struct CodeCompleteExpressionData;
void CodeCompleteExpression(Scope *S,
@@ -4271,6 +4987,7 @@ public:
void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
bool IsArrow);
+ void CodeCompletePostfixExpression(Scope *S, ExprResult LHS);
void CodeCompleteTag(Scope *S, unsigned TagSpec);
void CodeCompleteTypeQualifiers(DeclSpec &DS);
void CodeCompleteCase(Scope *S);
@@ -4287,7 +5004,7 @@ public:
void CodeCompleteNamespaceAliasDecl(Scope *S);
void CodeCompleteOperatorName(Scope *S);
void CodeCompleteConstructorInitializer(Decl *Constructor,
- CXXBaseOrMemberInitializer** Initializers,
+ CXXCtorInitializer** Initializers,
unsigned NumInitializers);
void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
@@ -4296,31 +5013,25 @@ public:
void CodeCompleteObjCAtStatement(Scope *S);
void CodeCompleteObjCAtExpression(Scope *S);
void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
- void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
- Decl **Methods,
- unsigned NumMethods);
- void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl,
- Decl **Methods,
- unsigned NumMethods);
- void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS);
+ void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl);
+ void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl);
+ void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
+ bool IsParameter);
void CodeCompleteObjCMessageReceiver(Scope *S);
void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
- void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
+ unsigned NumSelIdents,
+ bool AtArgumentExpression);
void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
IdentifierInfo **SelIdents,
unsigned NumSelIdents,
- bool IsSuper);
+ bool AtArgumentExpression,
+ bool IsSuper = false);
void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
- void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
- bool IsSuper);
+ unsigned NumSelIdents,
+ bool AtArgumentExpression,
+ ObjCInterfaceDecl *Super = 0);
void CodeCompleteObjCForCollection(Scope *S,
DeclGroupPtrTy IterationVar);
void CodeCompleteObjCSelector(Scope *S,
@@ -4363,7 +5074,7 @@ public:
MacroInfo *MacroInfo,
unsigned Argument);
void CodeCompleteNaturalLanguage();
- void GatherGlobalCodeCompletions(
+ void GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
llvm::SmallVectorImpl<CodeCompletionResult> &Results);
//@}
@@ -4376,7 +5087,8 @@ public:
SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
unsigned ByteNo) const;
-private:
+private:
+ void CheckArrayAccess(const ArraySubscriptExpr *E);
bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
@@ -4385,7 +5097,6 @@ private:
ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
- bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStart(CallExpr *TheCall);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
@@ -4422,7 +5133,10 @@ private:
void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc);
void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
- void CheckImplicitConversions(Expr *E);
+ void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+
+ void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
+ Expr *Init);
/// \brief The parser's current scope.
///
@@ -4431,6 +5145,7 @@ private:
protected:
friend class Parser;
+ friend class InitializationSequence;
/// \brief Retrieve the parser's current scope.
Scope *getCurScope() const { return CurScope; }
diff --git a/include/clang/Sema/SemaDiagnostic.h b/include/clang/Sema/SemaDiagnostic.h
index a5a136427fb9..ae5aa33db766 100644
--- a/include/clang/Sema/SemaDiagnostic.h
+++ b/include/clang/Sema/SemaDiagnostic.h
@@ -15,7 +15,7 @@
namespace clang {
namespace diag {
enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
#define SEMASTART
#include "clang/Basic/DiagnosticSemaKinds.inc"
#undef DIAG
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index a7b3b8461854..53f4a9d8c8fa 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -13,8 +13,10 @@
#define LLVM_CLANG_SEMA_TEMPLATE_H
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
+#include <utility>
namespace clang {
/// \brief Data structure that captures multiple levels of template argument
@@ -79,12 +81,21 @@ namespace clang {
return !(*this)(Depth, Index).isNull();
}
+ /// \brief Clear out a specific template argument.
+ void setArgument(unsigned Depth, unsigned Index,
+ TemplateArgument Arg) {
+ assert(Depth < TemplateArgumentLists.size());
+ assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
+ const_cast<TemplateArgument&>(
+ TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index])
+ = Arg;
+ }
+
/// \brief Add a new outermost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
- TemplateArgumentLists.push_back(
- ArgList(TemplateArgs->getFlatArgumentList(),
- TemplateArgs->flat_size()));
+ TemplateArgumentLists.push_back(ArgList(TemplateArgs->data(),
+ TemplateArgs->size()));
}
/// \brief Add a new outmost level to the multi-level template argument
@@ -140,7 +151,7 @@ namespace clang {
: TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { }
/// \brief Construct an integral non-type template argument that
- /// has been deduced, possible from an array bound.
+ /// has been deduced, possibly from an array bound.
DeducedTemplateArgument(const llvm::APSInt &Value,
QualType ValueType,
bool DeducedFromArrayBound)
@@ -165,10 +176,19 @@ namespace clang {
/// instantiate a new function declaration, which will have its own
/// set of parameter declarations.
class LocalInstantiationScope {
+ public:
+ /// \brief A set of declarations.
+ typedef llvm::SmallVector<Decl *, 4> DeclArgumentPack;
+
+ private:
/// \brief Reference to the semantic analysis that is performing
/// this template instantiation.
Sema &SemaRef;
+ typedef llvm::DenseMap<const Decl *,
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> >
+ LocalDeclsMap;
+
/// \brief A mapping from local declarations that occur
/// within a template to their instantiations.
///
@@ -183,8 +203,15 @@ namespace clang {
/// when we instantiate add<int>, we will introduce a mapping from
/// the ParmVarDecl for 'x' that occurs in the template to the
/// instantiated ParmVarDecl for 'x'.
- llvm::DenseMap<const Decl *, Decl *> LocalDecls;
+ ///
+ /// For a parameter pack, the local instantiation scope may contain a
+ /// set of instantiated parameters. This is stored as a DeclArgumentPack
+ /// pointer.
+ LocalDeclsMap LocalDecls;
+ /// \brief The set of argument packs we've allocated.
+ llvm::SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
+
/// \brief The outer scope, which contains local variable
/// definitions from some other instantiation (that may not be
/// relevant to this particular scope).
@@ -197,6 +224,19 @@ namespace clang {
/// lookup will search our outer scope.
bool CombineWithOuterScope;
+ /// \brief If non-NULL, the template parameter pack that has been
+ /// partially substituted per C++0x [temp.arg.explicit]p9.
+ NamedDecl *PartiallySubstitutedPack;
+
+ /// \brief If \c PartiallySubstitutedPack is non-null, the set of
+ /// explicitly-specified template arguments in that pack.
+ const TemplateArgument *ArgsInPartiallySubstitutedPack;
+
+ /// \brief If \c PartiallySubstitutedPack, the number of
+ /// explicitly-specified template arguments in
+ /// ArgsInPartiallySubstitutedPack.
+ unsigned NumArgsInPartiallySubstitutedPack;
+
// This class is non-copyable
LocalInstantiationScope(const LocalInstantiationScope &);
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
@@ -204,7 +244,8 @@ namespace clang {
public:
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
- Exited(false), CombineWithOuterScope(CombineWithOuterScope)
+ Exited(false), CombineWithOuterScope(CombineWithOuterScope),
+ PartiallySubstitutedPack(0)
{
SemaRef.CurrentInstantiationScope = this;
}
@@ -212,33 +253,171 @@ namespace clang {
~LocalInstantiationScope() {
Exit();
}
+
+ const Sema &getSema() const { return SemaRef; }
/// \brief Exit this local instantiation scope early.
void Exit() {
if (Exited)
return;
+ for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
+ delete ArgumentPacks[I];
+
SemaRef.CurrentInstantiationScope = Outer;
Exited = true;
}
- Decl *getInstantiationOf(const Decl *D);
+ /// \brief Find the instantiation of the declaration D within the current
+ /// instantiation scope.
+ ///
+ /// \param D The declaration whose instantiation we are searching for.
+ ///
+ /// \returns A pointer to the declaration or argument pack of declarations
+ /// to which the declaration \c D is instantiataed, if found. Otherwise,
+ /// returns NULL.
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *
+ findInstantiationOf(const Decl *D);
+
+ void InstantiatedLocal(const Decl *D, Decl *Inst);
+ void InstantiatedLocalPackArg(const Decl *D, Decl *Inst);
+ void MakeInstantiatedLocalArgPack(const Decl *D);
+
+ /// \brief Note that the given parameter pack has been partially substituted
+ /// via explicit specification of template arguments
+ /// (C++0x [temp.arg.explicit]p9).
+ ///
+ /// \param Pack The parameter pack, which will always be a template
+ /// parameter pack.
+ ///
+ /// \param ExplicitArgs The explicitly-specified template arguments provided
+ /// for this parameter pack.
+ ///
+ /// \param NumExplicitArgs The number of explicitly-specified template
+ /// arguments provided for this parameter pack.
+ void SetPartiallySubstitutedPack(NamedDecl *Pack,
+ const TemplateArgument *ExplicitArgs,
+ unsigned NumExplicitArgs);
+
+ /// \brief Retrieve the partially-substitued template parameter pack.
+ ///
+ /// If there is no partially-substituted parameter pack, returns NULL.
+ NamedDecl *getPartiallySubstitutedPack(
+ const TemplateArgument **ExplicitArgs = 0,
+ unsigned *NumExplicitArgs = 0) const;
+ };
+
+ class TemplateDeclInstantiator
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *>
+ {
+ Sema &SemaRef;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
+ DeclContext *Owner;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
- VarDecl *getInstantiationOf(const VarDecl *Var) {
- return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
+ /// \brief A list of out-of-line class template partial
+ /// specializations that will need to be instantiated after the
+ /// enclosing class's instantiation is complete.
+ llvm::SmallVector<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>, 4>
+ OutOfLinePartialSpecs;
+
+ public:
+ TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs)
+ : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner),
+ TemplateArgs(TemplateArgs) { }
+
+ // FIXME: Once we get closer to completion, replace these manually-written
+ // declarations with automatically-generated ones from
+ // clang/AST/DeclNodes.inc.
+ Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ Decl *VisitLabelDecl(LabelDecl *D);
+ Decl *VisitNamespaceDecl(NamespaceDecl *D);
+ Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ Decl *VisitTypedefDecl(TypedefDecl *D);
+ Decl *VisitVarDecl(VarDecl *D);
+ Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+ Decl *VisitFieldDecl(FieldDecl *D);
+ Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
+ Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
+ Decl *VisitEnumDecl(EnumDecl *D);
+ Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+ Decl *VisitFriendDecl(FriendDecl *D);
+ Decl *VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams = 0);
+ Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams = 0);
+ Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
+ Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
+ Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
+ ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
+ Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
+ Decl *VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ Decl *VisitUsingDecl(UsingDecl *D);
+ Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
+ Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+ // Base case. FIXME: Remove once we can instantiate everything.
+ Decl *VisitDecl(Decl *D) {
+ unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
+ Diagnostic::Error,
+ "cannot instantiate %0 yet");
+ SemaRef.Diag(D->getLocation(), DiagID)
+ << D->getDeclKindName();
+
+ return 0;
}
+
+ typedef
+ llvm::SmallVectorImpl<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> >
+ ::iterator
+ delayed_partial_spec_iterator;
- ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
- return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
+ /// \brief Return an iterator to the beginning of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_begin() {
+ return OutOfLinePartialSpecs.begin();
}
- NonTypeTemplateParmDecl *getInstantiationOf(
- const NonTypeTemplateParmDecl *Var) {
- return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
+ /// \brief Return an iterator to the end of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_end() {
+ return OutOfLinePartialSpecs.end();
}
- void InstantiatedLocal(const Decl *D, Decl *Inst);
- };
+ // Helper functions for instantiating methods.
+ TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
+ llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+ bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
+ bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
+
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *List);
+
+ bool SubstQualifier(const DeclaratorDecl *OldDecl,
+ DeclaratorDecl *NewDecl);
+ bool SubstQualifier(const TagDecl *OldDecl,
+ TagDecl *NewDecl);
+
+ ClassTemplatePartialSpecializationDecl *
+ InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec);
+ };
}
#endif // LLVM_CLANG_SEMA_TEMPLATE_H
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
index ac32e9c24f6d..7cc35713aace 100644
--- a/include/clang/Sema/TemplateDeduction.h
+++ b/include/clang/Sema/TemplateDeduction.h
@@ -13,7 +13,9 @@
#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
+#include "clang/Basic/PartialDiagnostic.h"
#include "clang/AST/DeclTemplate.h"
+#include "llvm/ADT/SmallVector.h"
namespace clang {
@@ -21,7 +23,7 @@ class ASTContext;
class TemplateArgumentList;
namespace sema {
-
+
/// \brief Provides information about an attempted template argument
/// deduction, whose success or failure was described by a
/// TemplateDeductionResult value.
@@ -37,6 +39,10 @@ class TemplateDeductionInfo {
/// deduction is occurring.
SourceLocation Loc;
+ /// \brief Warnings (and follow-on notes) that were suppressed due to
+ /// SFINAE while performing template argument deduction.
+ llvm::SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
+
// do not implement these
TemplateDeductionInfo(const TemplateDeductionInfo&);
TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
@@ -69,6 +75,23 @@ public:
Deduced = NewDeduced;
}
+ /// \brief Add a new diagnostic to the set of diagnostics
+ void addSuppressedDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) {
+ SuppressedDiagnostics.push_back(std::make_pair(Loc, PD));
+ }
+
+ /// \brief Iterator over the set of suppressed diagnostics.
+ typedef llvm::SmallVectorImpl<PartialDiagnosticAt>::const_iterator
+ diag_iterator;
+
+ /// \brief Returns an iterator at the beginning of the sequence of suppressed
+ /// diagnostics.
+ diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
+
+ /// \brief Returns an iterator at the end of the sequence of suppressed
+ /// diagnostics.
+ diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
+
/// \brief The template parameter to which a template argument
/// deduction failure refers.
///
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 0fa446dd34de..68fd91d4c069 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -19,7 +19,7 @@
#include "clang/AST/Type.h"
#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
@@ -54,6 +54,9 @@ namespace clang {
/// reserved for the translation unit declaration.
typedef uint32_t DeclID;
+ /// \brief a Decl::Kind/DeclID pair.
+ typedef std::pair<uint32_t, DeclID> KindDeclIDPair;
+
/// \brief An ID number that refers to a type in an AST file.
///
/// The ID of a type is partitioned into two parts: the lower
@@ -112,12 +115,19 @@ namespace clang {
typedef llvm::DenseMap<QualType, TypeIdx, UnsafeQualTypeDenseMapInfo>
TypeIdxMap;
- /// \brief An ID number that refers to an identifier in an AST
- /// file.
+ /// \brief An ID number that refers to an identifier in an AST file.
typedef uint32_t IdentID;
+ /// \brief An ID number that refers to a macro in an AST file.
+ typedef uint32_t MacroID;
+
+ /// \brief An ID number that refers to an ObjC selctor in an AST file.
typedef uint32_t SelectorID;
+ /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an
+ /// AST file.
+ typedef uint32_t CXXBaseSpecifiersID;
+
/// \brief Describes the various kinds of blocks that occur within
/// an AST file.
enum BlockIDs {
@@ -135,7 +145,13 @@ namespace clang {
/// \brief The block containing the definitions of all of the
/// types and decls used within the AST file.
- DECLTYPES_BLOCK_ID
+ DECLTYPES_BLOCK_ID,
+
+ /// \brief The block containing DECL_UPDATES records.
+ DECL_UPDATES_BLOCK_ID,
+
+ /// \brief The block containing the detailed preprocessing record.
+ PREPROCESSOR_DETAIL_BLOCK_ID
};
/// \brief Record types that occur within the AST block itself.
@@ -318,9 +334,35 @@ namespace clang {
/// In practice, this should only be used for the TU and namespaces.
UPDATE_VISIBLE = 34,
- /// \brief Record code for template specializations introduced after
- /// serializations of the original template decl.
- ADDITIONAL_TEMPLATE_SPECIALIZATIONS = 35
+ /// \brief Record for offsets of DECL_UPDATES records for declarations
+ /// that were modified after being deserialized and need updates.
+ DECL_UPDATE_OFFSETS = 35,
+
+ /// \brief Record of updates for a declaration that was modified after
+ /// being deserialized.
+ DECL_UPDATES = 36,
+
+ /// \brief Record code for the table of offsets to CXXBaseSpecifier
+ /// sets.
+ CXX_BASE_SPECIFIER_OFFSETS = 37,
+
+ /// \brief Record code for #pragma diagnostic mappings.
+ DIAG_PRAGMA_MAPPINGS = 38,
+
+ /// \brief Record code for special CUDA declarations.
+ CUDA_SPECIAL_DECL_REFS = 39,
+
+ /// \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,
+
+ /// \brief Record code for floating point #pragma options.
+ FP_PRAGMA_OPTIONS = 42,
+
+ /// \brief Record code for enabled OpenCL extensions.
+ OPENCL_EXTENSIONS = 43
};
/// \brief Record types used within a source manager block.
@@ -359,16 +401,23 @@ namespace clang {
/// \brief Describes one token.
/// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
- PP_TOKEN = 3,
+ PP_TOKEN = 3
+ };
+ /// \brief Record types used within a preprocessor detail block.
+ enum PreprocessorDetailRecordTypes {
/// \brief Describes a macro instantiation within the preprocessing
/// record.
- PP_MACRO_INSTANTIATION = 4,
+ PPD_MACRO_INSTANTIATION = 0,
/// \brief Describes a macro definition within the preprocessing record.
- PP_MACRO_DEFINITION = 5
+ PPD_MACRO_DEFINITION = 1,
+
+ /// \brief Describes an inclusion directive within the preprocessing
+ /// record.
+ PPD_INCLUSION_DIRECTIVE = 2
};
-
+
/// \defgroup ASTAST AST file AST constants
///
/// The constants in this group describe various components of the
@@ -521,7 +570,17 @@ namespace clang {
/// \brief A DependentTemplateSpecializationType record.
TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
/// \brief A DependentSizedArrayType record.
- TYPE_DEPENDENT_SIZED_ARRAY = 33
+ TYPE_DEPENDENT_SIZED_ARRAY = 33,
+ /// \brief A ParenType record.
+ TYPE_PAREN = 34,
+ /// \brief A PackExpansionType record.
+ TYPE_PACK_EXPANSION = 35,
+ /// \brief An AttributedType record.
+ TYPE_ATTRIBUTED = 36,
+ /// \brief A SubstTemplateTypeParmPackType record.
+ TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
+ /// \brief A AutoType record.
+ TYPE_AUTO = 38
};
/// \brief The type IDs for special types constructed by semantic
@@ -573,10 +632,8 @@ namespace clang {
/// constant describes a record for a specific declaration class
/// in the AST.
enum DeclCode {
- /// \brief Attributes attached to a declaration.
- DECL_ATTR = 50,
/// \brief A TranslationUnitDecl record.
- DECL_TRANSLATION_UNIT,
+ DECL_TRANSLATION_UNIT = 50,
/// \brief A TypedefDecl record.
DECL_TYPEDEF,
/// \brief An EnumDecl record.
@@ -642,7 +699,9 @@ namespace clang {
/// IDs. This data is used when performing qualified name lookup
/// into a DeclContext via DeclContext::lookup.
DECL_CONTEXT_VISIBLE,
- /// \brief A NamespaceDecl rcord.
+ /// \brief A LabelDecl record.
+ DECL_LABEL,
+ /// \brief A NamespaceDecl record.
DECL_NAMESPACE,
/// \brief A NamespaceAliasDecl record.
DECL_NAMESPACE_ALIAS,
@@ -690,7 +749,14 @@ namespace clang {
/// \brief A TemplateTemplateParmDecl record.
DECL_TEMPLATE_TEMPLATE_PARM,
/// \brief A StaticAssertDecl record.
- DECL_STATIC_ASSERT
+ DECL_STATIC_ASSERT,
+ /// \brief A record containing CXXBaseSpecifiers.
+ DECL_CXX_BASE_SPECIFIERS,
+ /// \brief A IndirectFieldDecl record.
+ DECL_INDIRECTFIELD,
+ /// \brief A NonTypeTemplateParmDecl record that stores an expanded
+ /// non-type template parameter pack.
+ DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK
};
/// \brief Record codes for each kind of statement or expression.
@@ -796,8 +862,6 @@ namespace clang {
EXPR_ADDR_LABEL,
/// \brief A StmtExpr record.
EXPR_STMT,
- /// \brief A TypesCompatibleExpr record.
- EXPR_TYPES_COMPATIBLE,
/// \brief A ChooseExpr record.
EXPR_CHOOSE,
/// \brief A GNUNullExpr record.
@@ -823,12 +887,10 @@ namespace clang {
EXPR_OBJC_IVAR_REF_EXPR,
/// \brief An ObjCPropertyRefExpr record.
EXPR_OBJC_PROPERTY_REF_EXPR,
- /// \brief An ObjCImplicitSetterGetterRefExpr record.
+ /// \brief UNUSED
EXPR_OBJC_KVC_REF_EXPR,
/// \brief An ObjCMessageExpr record.
EXPR_OBJC_MESSAGE_EXPR,
- /// \brief An ObjCSuperExpr record.
- EXPR_OBJC_SUPER_EXPR,
/// \brief An ObjCIsa Expr record.
EXPR_OBJC_ISA,
@@ -875,6 +937,8 @@ namespace clang {
EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).
+ EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
+ EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
EXPR_CXX_THIS, // CXXThisExpr
EXPR_CXX_THROW, // CXXThrowExpr
EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
@@ -885,15 +949,28 @@ namespace clang {
EXPR_CXX_DELETE, // CXXDeleteExpr
EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
- EXPR_CXX_EXPR_WITH_TEMPORARIES, // CXXExprWithTemporaries
+ EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
- EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr
- EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
- EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr
- EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr
- EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
+ EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr
+ EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
+ EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr
+ EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr
+ EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
+
+ EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr
+ EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
+
+ EXPR_OPAQUE_VALUE, // OpaqueValueExpr
+ EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
+ EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
+
+ EXPR_PACK_EXPANSION, // PackExpansionExpr
+ EXPR_SIZEOF_PACK, // SizeOfPackExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
+
+ // CUDA
- EXPR_CXX_UNARY_TYPE_TRAIT // UnaryTypeTraitExpr
+ EXPR_CUDA_KERNEL_CALL // CUDAKernelCallExpr
};
/// \brief The kinds of designators that can occur in a
diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h
index f8114de5f15a..f8cdebe5a913 100644
--- a/include/clang/Serialization/ASTDeserializationListener.h
+++ b/include/clang/Serialization/ASTDeserializationListener.h
@@ -22,26 +22,31 @@ namespace clang {
class Decl;
class ASTReader;
class QualType;
-
+class MacroDefinition;
+
class ASTDeserializationListener {
protected:
- virtual ~ASTDeserializationListener() {}
+ virtual ~ASTDeserializationListener();
public:
- /// \brief Tell the listener about the reader.
- virtual void SetReader(ASTReader *Reader) = 0;
+
+ /// \brief The ASTReader was initialized.
+ virtual void ReaderInitialized(ASTReader *Reader) { }
/// \brief An identifier was deserialized from the AST file.
virtual void IdentifierRead(serialization::IdentID ID,
- IdentifierInfo *II) = 0;
+ IdentifierInfo *II) { }
/// \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.
- virtual void TypeRead(serialization::TypeIdx Idx, QualType T) = 0;
+ virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { }
/// \brief A decl was deserialized from the AST file.
- virtual void DeclRead(serialization::DeclID ID, const Decl *D) = 0;
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D) { }
/// \brief A selector was read from the AST file.
- virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) = 0;
+ virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) { }
+ /// \brief A macro definition was read from the AST file.
+ virtual void MacroDefinitionRead(serialization::MacroID,
+ MacroDefinition *MD) { }
};
}
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index d31be88a3e3d..9799b8d852c2 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
@@ -31,7 +32,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitstreamReader.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include <deque>
#include <map>
#include <string>
@@ -47,22 +48,26 @@ namespace clang {
class AddrLabelExpr;
class ASTConsumer;
class ASTContext;
+class ASTIdentifierIterator;
class Attr;
class Decl;
class DeclContext;
class NestedNameSpecifier;
class CXXBaseSpecifier;
-class CXXBaseOrMemberInitializer;
+class CXXCtorInitializer;
class GotoStmt;
-class LabelStmt;
class MacroDefinition;
class NamedDecl;
-class ASTDeserializationListener;
+class OpaqueValueExpr;
class Preprocessor;
class Sema;
class SwitchCase;
+class ASTDeserializationListener;
class ASTReader;
class ASTDeclReader;
+class ASTStmtReader;
+class ASTIdentifierLookupTrait;
+class TypeLocReader;
struct HeaderFileInfo;
struct PCHPredefinesBlock {
@@ -161,14 +166,27 @@ private:
class ASTReader
: public ExternalPreprocessorSource,
public ExternalPreprocessingRecordSource,
+ public ExternalHeaderFileInfoSource,
public ExternalSemaSource,
public IdentifierInfoLookup,
public ExternalIdentifierLookup,
- public ExternalSLocEntrySource {
+ public ExternalSLocEntrySource
+{
public:
enum ASTReadResult { Success, Failure, IgnorePCH };
+ /// \brief Types of AST files.
+ enum ASTFileType {
+ Module, ///< File is a module proper.
+ PCH, ///< File is a PCH file treated as such.
+ Preamble, ///< File is a PCH file treated as the preamble.
+ MainFile ///< File is a PCH file treated as the actual main file.
+ };
friend class PCHValidator;
friend class ASTDeclReader;
+ friend class ASTStmtReader;
+ friend class ASTIdentifierIterator;
+ friend class ASTIdentifierLookupTrait;
+ friend class TypeLocReader;
private:
/// \brief The receiver of some callbacks invoked by ASTReader.
llvm::OwningPtr<ASTReaderListener> Listener;
@@ -193,31 +211,15 @@ private:
/// \brief The AST consumer.
ASTConsumer *Consumer;
- /// \brief Information that is needed for every file in the chain.
+ /// \brief Information that is needed for every module.
struct PerFileData {
- PerFileData();
+ PerFileData(ASTFileType Ty);
~PerFileData();
- /// \brief The AST stat cache installed for this file, if any.
- ///
- /// The dynamic type of this stat cache is always ASTStatCache
- void *StatCache;
-
- /// \brief The bitstream reader from which we'll read the AST file.
- llvm::BitstreamReader StreamFile;
- llvm::BitstreamCursor Stream;
-
- /// \brief The size of this file, in bits.
- uint64_t SizeInBits;
+ // === General information ===
- /// \brief The cursor to the start of the preprocessor block, which stores
- /// all of the macro definitions.
- llvm::BitstreamCursor MacroCursor;
-
- /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
- /// has read all the abbreviations at the start of the block and is ready to
- /// jump around with these in context.
- llvm::BitstreamCursor DeclsCursor;
+ /// \brief The type of this AST file.
+ ASTFileType Type;
/// \brief The file name of the AST file.
std::string FileName;
@@ -226,6 +228,17 @@ private:
/// this AST file.
llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ /// \brief The size of this file, in bits.
+ uint64_t SizeInBits;
+
+ /// \brief The bitstream reader from which we'll read the AST file.
+ llvm::BitstreamReader StreamFile;
+
+ /// \brief The main bitstream cursor for the main block.
+ llvm::BitstreamCursor Stream;
+
+ // === Source Locations ===
+
/// \brief Cursor used to read source location entries.
llvm::BitstreamCursor SLocEntryCursor;
@@ -236,19 +249,10 @@ private:
/// AST file.
const uint32_t *SLocOffsets;
- /// \brief The number of types in this AST file.
- unsigned LocalNumTypes;
-
- /// \brief Offset of each type within the bitstream, indexed by the
- /// type ID, or the representation of a Type*.
- const uint32_t *TypeOffsets;
-
- /// \brief The number of declarations in this AST file.
- unsigned LocalNumDecls;
+ /// \brief The entire size of this module's source location offset range.
+ unsigned LocalSLocSize;
- /// \brief Offset of each declaration within the bitstream, indexed
- /// by the declaration ID (-1).
- const uint32_t *DeclOffsets;
+ // === Identifiers ===
/// \brief The number of identifiers in this AST file.
unsigned LocalNumIdentifiers;
@@ -260,26 +264,72 @@ private:
/// stored.
const uint32_t *IdentifierOffsets;
- /// \brief Actual data for the on-disk hash table.
+ /// \brief Actual data for the on-disk hash table of identifiers.
///
- // This pointer points into a memory buffer, where the on-disk hash
- // table for identifiers actually lives.
+ /// This pointer points into a memory buffer, where the on-disk hash
+ /// table for identifiers actually lives.
const char *IdentifierTableData;
/// \brief A pointer to an on-disk hash table of opaque type
/// IdentifierHashTable.
void *IdentifierLookupTable;
+ // === Macros ===
+
+ /// \brief The cursor to the start of the preprocessor block, which stores
+ /// all of the macro definitions.
+ llvm::BitstreamCursor MacroCursor;
+
+ /// \brief The offset of the start of the set of defined macros.
+ uint64_t MacroStartOffset;
+
+ // === Detailed PreprocessingRecord ===
+
+ /// \brief The cursor to the start of the (optional) detailed preprocessing
+ /// record block.
+ llvm::BitstreamCursor PreprocessorDetailCursor;
+
+ /// \brief The offset of the start of the preprocessor detail cursor.
+ uint64_t PreprocessorDetailStartOffset;
+
/// \brief The number of macro definitions in this file.
unsigned LocalNumMacroDefinitions;
-
+
/// \brief Offsets of all of the macro definitions in the preprocessing
/// record in the AST file.
const uint32_t *MacroDefinitionOffsets;
-
- /// \brief The number of preallocated preprocessing entities in the
- /// preprocessing record.
- unsigned NumPreallocatedPreprocessingEntities;
+
+ // === Header search information ===
+
+ /// \brief The number of local HeaderFileInfo structures.
+ unsigned LocalNumHeaderFileInfos;
+
+ /// \brief Actual data for the on-disk hash table of header file
+ /// information.
+ ///
+ /// This pointer points into a memory buffer, where the on-disk hash
+ /// table for header file information actually lives.
+ const char *HeaderFileInfoTableData;
+
+ /// \brief The on-disk hash table that contains information about each of
+ /// the header files.
+ void *HeaderFileInfoTable;
+
+ // === Selectors ===
+
+ /// \brief The number of selectors new to this file.
+ ///
+ /// This is the number of entries in SelectorOffsets.
+ unsigned LocalNumSelectors;
+
+ /// \brief Offsets into the selector lookup table's data array
+ /// where each selector resides.
+ const uint32_t *SelectorOffsets;
+
+ /// \brief A pointer to the character data that comprises the selector table
+ ///
+ /// The SelectorOffsets table refers into this memory.
+ const unsigned char *SelectorLookupTableData;
/// \brief A pointer to an on-disk hash table of opaque type
/// ASTSelectorLookupTable.
@@ -288,26 +338,81 @@ private:
/// instance and factory methods.
void *SelectorLookupTable;
- /// \brief A pointer to the character data that comprises the selector table
+ /// \brief Method selectors used in a @selector expression. Used for
+ /// implementation of -Wselector.
+ llvm::SmallVector<uint64_t, 64> ReferencedSelectorsData;
+
+ // === Declarations ===
+
+ /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
+ /// has read all the abbreviations at the start of the block and is ready to
+ /// jump around with these in context.
+ llvm::BitstreamCursor DeclsCursor;
+
+ /// \brief The number of declarations in this AST file.
+ unsigned LocalNumDecls;
+
+ /// \brief Offset of each declaration within the bitstream, indexed
+ /// by the declaration ID (-1).
+ const uint32_t *DeclOffsets;
+
+ /// \brief A snapshot of the pending instantiations in the chain.
///
- /// The SelectorOffsets table refers into this memory.
- const unsigned char *SelectorLookupTableData;
+ /// This record tracks the instantiations that Sema has to perform at the
+ /// end of the TU. It consists of a pair of values for every pending
+ /// instantiation where the first value is the ID of the decl and the second
+ /// is the instantiation location.
+ llvm::SmallVector<uint64_t, 64> PendingInstantiations;
+
+ /// \brief The number of C++ base specifier sets in this AST file.
+ unsigned LocalNumCXXBaseSpecifiers;
+
+ /// \brief Offset of each C++ base specifier set within the bitstream,
+ /// indexed by the C++ base specifier set ID (-1).
+ const uint32_t *CXXBaseSpecifiersOffsets;
+
+ // === Types ===
- /// \brief Offsets into the method pool lookup table's data array
- /// where each selector resides.
- const uint32_t *SelectorOffsets;
+ /// \brief The number of types in this AST file.
+ unsigned LocalNumTypes;
- /// \brief The number of selectors new to this file.
+ /// \brief Offset of each type within the bitstream, indexed by the
+ /// type ID, or the representation of a Type*.
+ const uint32_t *TypeOffsets;
+
+ // === Miscellaneous ===
+
+ /// \brief The AST stat cache installed for this file, if any.
///
- /// This is the number of entries in SelectorOffsets.
- unsigned LocalNumSelectors;
+ /// The dynamic type of this stat cache is always ASTStatCache
+ void *StatCache;
+
+ /// \brief The number of preallocated preprocessing entities in the
+ /// preprocessing record.
+ unsigned NumPreallocatedPreprocessingEntities;
+
+ /// \brief The next module in source order.
+ PerFileData *NextInSource;
+
+ /// \brief All the modules that loaded this one. Can contain NULL for
+ /// directly loaded modules.
+ llvm::SmallVector<PerFileData *, 1> Loaders;
};
+ /// \brief All loaded modules, indexed by name.
+ llvm::StringMap<PerFileData*> Modules;
+
+ /// \brief The first module in source order.
+ PerFileData *FirstInSource;
+
/// \brief The chain of AST files. The first entry is the one named by the
/// user, the last one is the one that doesn't depend on anything further.
/// That is, the entry I was created with -include-pch I+1.
llvm::SmallVector<PerFileData*, 2> Chain;
+ /// \brief SLocEntries that we're going to preload.
+ llvm::SmallVector<uint64_t, 64> PreloadSLocEntries;
+
/// \brief Types that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the type with
@@ -331,6 +436,14 @@ private:
/// = I + 1 has already been loaded.
std::vector<Decl *> DeclsLoaded;
+ typedef std::pair<PerFileData *, uint64_t> FileOffset;
+ typedef llvm::SmallVector<FileOffset, 2> FileOffsetsTy;
+ typedef llvm::DenseMap<serialization::DeclID, FileOffsetsTy>
+ DeclUpdateOffsetsMap;
+ /// \brief Declarations that have modifications residing in a later file
+ /// in the chain.
+ DeclUpdateOffsetsMap DeclUpdateOffsets;
+
typedef llvm::DenseMap<serialization::DeclID,
std::pair<PerFileData *, uint64_t> >
DeclReplacementMap;
@@ -340,7 +453,7 @@ private:
/// \brief Information about the contents of a DeclContext.
struct DeclContextInfo {
void *NameLookupTableData; // a ASTDeclContextNameLookupTable.
- const serialization::DeclID *LexicalDecls;
+ const serialization::KindDeclIDPair *LexicalDecls;
unsigned NumLexicalDecls;
};
// In a full chain, there could be multiple updates to every decl context,
@@ -366,22 +479,20 @@ private:
/// haven't been loaded yet.
DeclContextVisibleUpdatesPending PendingVisibleUpdates;
+ typedef llvm::SmallVector<CXXRecordDecl *, 4> ForwardRefs;
+ typedef llvm::DenseMap<const CXXRecordDecl *, ForwardRefs>
+ PendingForwardRefsMap;
+ /// \brief Forward references that have a definition but the definition decl
+ /// is still initializing. When the definition gets read it will update
+ /// the DefinitionData pointer of all pending references.
+ PendingForwardRefsMap PendingForwardRefs;
+
typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
FirstLatestDeclIDMap;
/// \brief Map of first declarations from a chained PCH that point to the
/// most recent declarations in another AST file.
FirstLatestDeclIDMap FirstLatestDeclIDs;
- typedef llvm::SmallVector<serialization::DeclID, 4>
- AdditionalTemplateSpecializations;
- typedef llvm::DenseMap<serialization::DeclID,
- AdditionalTemplateSpecializations>
- AdditionalTemplateSpecializationsMap;
-
- /// \brief Additional specializations (including partial) of templates that
- /// were introduced after the template was serialized.
- AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializationsPending;
-
/// \brief Read the records that describe the contents of declcontexts.
bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
const std::pair<uint64_t, uint64_t> &Offsets,
@@ -405,6 +516,11 @@ private:
/// \brief The macro definitions we have already loaded.
llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded;
+ /// \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<IdentifierInfo *, uint64_t> UnreadMacroRecordOffsets;
+
/// \name CodeGen-relevant special data
/// \brief Fields containing data that is relevant to CodeGen.
//@{
@@ -437,10 +553,6 @@ private:
/// \brief Fields containing data that is used for generating diagnostics
//@{
- /// \brief Method selectors used in a @selector expression. Used for
- /// implementation of -Wselector.
- llvm::SmallVector<uint64_t, 64> ReferencedSelectorsData;
-
/// \brief A snapshot of Sema's unused file-scoped variable tracking, for
/// generating warnings.
llvm::SmallVector<uint64_t, 16> UnusedFileScopedDecls;
@@ -466,14 +578,6 @@ private:
/// local external declarations.
llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls;
- /// \brief A snapshot of the pwnsinf instantiations in the chain.
- ///
- /// This record tracks the instantiations that Sema has to perform at the end
- /// of the TU. It consists of a pair of values for every pending instantiation
- /// where the first value is the ID of the decl and the second is the
- /// instantiation location.
- llvm::SmallVector<uint64_t, 64> PendingInstantiations;
-
/// \brief The IDs of all dynamic class declarations in the chain.
///
/// Sema tracks these because it checks for the key functions being defined
@@ -490,8 +594,23 @@ private:
/// The AST context tracks a few important types, such as va_list, directly.
llvm::SmallVector<uint64_t, 16> SpecialTypes;
+ /// \brief The IDs of CUDA-specific declarations ASTContext stores directly.
+ ///
+ /// The AST context tracks a few important decls, currently cudaConfigureCall,
+ /// directly.
+ llvm::SmallVector<uint64_t, 2> CUDASpecialDeclRefs;
+
+ /// \brief The floating point pragma option settings.
+ llvm::SmallVector<uint64_t, 1> FPPragmaOptions;
+
+ /// \brief The OpenCL extension settings.
+ llvm::SmallVector<uint64_t, 1> OpenCLExtensions;
+
//@}
+ /// \brief Diagnostic IDs and their mappings that the user changed.
+ llvm::SmallVector<uint64_t, 8> PragmaDiagMappings;
+
/// \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;
@@ -500,6 +619,13 @@ private:
/// AST file.
std::string ActualOriginalFileName;
+ /// \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;
@@ -511,27 +637,17 @@ private:
/// headers when they are loaded.
bool DisableValidation;
+ /// \brief Whether to disable the use of stat caches in AST files.
+ bool DisableStatCache;
+
/// \brief Mapping from switch-case IDs in the chain to switch-case statements
///
/// Statements usually don't have IDs, but switch cases need them, so that the
/// switch statement can refer to them.
std::map<unsigned, SwitchCase *> SwitchCaseStmts;
- /// \brief Mapping from label statement IDs in the chain to label statements.
- ///
- /// Statements usually don't have IDs, but labeled statements need them, so
- /// that goto statements and address-of-label expressions can refer to them.
- std::map<unsigned, LabelStmt *> LabelStmts;
-
- /// \brief Mapping from label IDs to the set of "goto" statements
- /// that point to that label before the label itself has been
- /// de-serialized.
- std::multimap<unsigned, GotoStmt *> UnresolvedGotoStmts;
-
- /// \brief Mapping from label IDs to the set of address label
- /// expressions that point to that label before the label itself has
- /// been de-serialized.
- std::multimap<unsigned, AddrLabelExpr *> UnresolvedAddrLabelExprs;
+ /// \brief Mapping from opaque value IDs to OpaqueValueExprs.
+ std::map<unsigned, OpaqueValueExpr*> OpaqueValueExprs;
/// \brief The number of stat() calls that hit/missed the stat
/// cache.
@@ -544,6 +660,9 @@ private:
/// \brief The number of source location entries in the chain.
unsigned TotalNumSLocEntries;
+ /// \brief The next offset for a SLocEntry after everything in this reader.
+ unsigned NextSLocOffset;
+
/// \brief The number of statements (and expressions) de-serialized
/// from the chain.
unsigned NumStatementsRead;
@@ -602,6 +721,13 @@ private:
/// Objective-C protocols.
std::deque<Decl *> InterestingDecls;
+ /// \brief We delay loading of the previous declaration chain to avoid
+ /// deeply nested calls when there are many redeclarations.
+ std::deque<std::pair<Decl *, serialization::DeclID> > PendingPreviousDecls;
+
+ /// \brief Ready to load the previous declaration of the given Decl.
+ void loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID);
+
/// \brief When reading a Stmt tree, Stmt operands are placed in this stack.
llvm::SmallVector<Stmt *, 16> StmtStack;
@@ -645,20 +771,26 @@ private:
std::string SuggestedPredefines;
/// \brief Reads a statement from the specified cursor.
- Stmt *ReadStmtFromStream(llvm::BitstreamCursor &Cursor);
+ Stmt *ReadStmtFromStream(PerFileData &F);
void MaybeAddSystemRootToFilename(std::string &Filename);
- ASTReadResult ReadASTCore(llvm::StringRef FileName);
+ ASTReadResult ReadASTCore(llvm::StringRef FileName, ASTFileType Type);
ASTReadResult ReadASTBlock(PerFileData &F);
bool CheckPredefinesBuffers();
- bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record);
+ bool ParseLineTable(PerFileData &F, llvm::SmallVectorImpl<uint64_t> &Record);
ASTReadResult ReadSourceManagerBlock(PerFileData &F);
ASTReadResult ReadSLocEntryRecord(unsigned ID);
- llvm::BitstreamCursor &SLocCursorForID(unsigned ID);
+ PerFileData *SLocCursorForID(unsigned ID);
+ SourceLocation getImportLocation(PerFileData *F);
bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
- typedef std::pair<llvm::BitstreamCursor *, uint64_t> RecordLocation;
+ struct RecordLocation {
+ RecordLocation(PerFileData *M, uint64_t O)
+ : F(M), Offset(O) {}
+ PerFileData *F;
+ uint64_t Offset;
+ };
QualType ReadTypeRecord(unsigned Index);
RecordLocation TypeCursorForIndex(unsigned Index);
@@ -695,8 +827,14 @@ public:
/// \param DisableValidation If true, the AST reader will suppress most
/// 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.
ASTReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0,
- bool DisableValidation = false);
+ bool DisableValidation = false, bool DisableStatCache = false);
/// \brief Load the AST file without using any pre-initialized Preprocessor.
///
@@ -717,14 +855,20 @@ public:
/// \param DisableValidation If true, the AST reader will suppress most
/// of its regular consistency checking, allowing the use of precompiled
/// headers that cannot be determined to be compatible.
- ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ ///
+ /// \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.
+ ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
Diagnostic &Diags, const char *isysroot = 0,
- bool DisableValidation = false);
+ bool DisableValidation = false, bool DisableStatCache = false);
~ASTReader();
/// \brief Load the precompiled header designated by the given file
/// name.
- ASTReadResult ReadAST(const std::string &FileName);
+ ASTReadResult ReadAST(const std::string &FileName, ASTFileType Type);
/// \brief Set the AST callbacks listener.
void setListener(ASTReaderListener *listener) {
@@ -749,6 +893,7 @@ public:
/// \brief Retrieve the name of the original source file name directly from
/// the AST file, without actually loading the AST file.
static std::string getOriginalSourceFile(const std::string &ASTFileName,
+ FileManager &FileMgr,
Diagnostic &Diags);
/// \brief Returns the suggested contents of the predefines buffer,
@@ -756,14 +901,27 @@ public:
/// build prior to including the precompiled header.
const std::string &getSuggestedPredefines() { return SuggestedPredefines; }
- /// \brief Read preprocessed entities into the
+ /// \brief Read preprocessed entities into the preprocessing record.
virtual void ReadPreprocessedEntities();
+ /// \brief Read the preprocessed entity at the given offset.
+ virtual PreprocessedEntity *ReadPreprocessedEntityAtOffset(uint64_t Offset);
+
+ /// \brief Read the header file information for the given file entry.
+ virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE);
+
+ void ReadPragmaDiagnosticMappings(Diagnostic &Diag);
+
/// \brief Returns the number of source locations found in the chain.
unsigned getTotalNumSLocs() const {
return TotalNumSLocEntries;
}
+ /// \brief Returns the next SLocEntry offset after the chain.
+ unsigned getNextSLocOffset() const {
+ return NextSLocOffset;
+ }
+
/// \brief Returns the number of identifiers found in the chain.
unsigned getTotalNumIdentifiers() const {
return static_cast<unsigned>(IdentifiersLoaded.size());
@@ -784,20 +942,27 @@ public:
return static_cast<unsigned>(SelectorsLoaded.size());
}
+ /// \brief Returns the number of macro definitions found in the chain.
+ unsigned getTotalNumMacroDefinitions() const {
+ return static_cast<unsigned>(MacroDefinitionsLoaded.size());
+ }
+
+ /// \brief Returns the number of C++ base specifiers found in the chain.
+ unsigned getTotalNumCXXBaseSpecifiers() const;
+
/// \brief Reads a TemplateArgumentLocInfo appropriate for the
/// given TemplateArgument kind.
TemplateArgumentLocInfo
- GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
- llvm::BitstreamCursor &DeclsCursor,
+ GetTemplateArgumentLocInfo(PerFileData &F, TemplateArgument::ArgKind Kind,
const RecordData &Record, unsigned &Idx);
/// \brief Reads a TemplateArgumentLoc.
TemplateArgumentLoc
- ReadTemplateArgumentLoc(llvm::BitstreamCursor &DeclsCursor,
+ ReadTemplateArgumentLoc(PerFileData &F,
const RecordData &Record, unsigned &Idx);
/// \brief Reads a declarator info from the given record.
- TypeSourceInfo *GetTypeSourceInfo(llvm::BitstreamCursor &DeclsCursor,
+ TypeSourceInfo *GetTypeSourceInfo(PerFileData &F,
const RecordData &Record, unsigned &Idx);
/// \brief Resolve and return the translation unit declaration.
@@ -822,6 +987,12 @@ public:
Decl *GetDecl(serialization::DeclID ID);
virtual Decl *GetExternalDecl(uint32_t ID);
+ /// \brief Resolve a CXXBaseSpecifiers ID into an offset into the chain
+ /// of loaded AST files.
+ uint64_t GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID);
+
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
+
/// \brief Resolve the offset of a statement into a statement.
///
/// This operation will read a new statement from the external
@@ -857,6 +1028,7 @@ public:
/// \returns true if there was an error while reading the
/// declarations for this declaration context.
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
llvm::SmallVectorImpl<Decl*> &Decls);
/// \brief Notify ASTReader that we started deserialization of
@@ -897,6 +1069,10 @@ public:
return get(Name.begin(), Name.end());
}
+ /// \brief Retrieve an iterator into the set of all identifiers
+ /// in all loaded AST files.
+ virtual IdentifierIterator *getIdentifiers() const;
+
/// \brief Load the contents of the global method pool for a given
/// selector.
///
@@ -943,47 +1119,65 @@ public:
/// \brief Read a declaration name.
DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx);
+ void ReadDeclarationNameLoc(PerFileData &F,
+ DeclarationNameLoc &DNLoc, DeclarationName Name,
+ const RecordData &Record, unsigned &Idx);
+ void ReadDeclarationNameInfo(PerFileData &F, DeclarationNameInfo &NameInfo,
+ const RecordData &Record, unsigned &Idx);
+
+ void ReadQualifierInfo(PerFileData &F, QualifierInfo &Info,
+ const RecordData &Record, unsigned &Idx);
NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record,
unsigned &Idx);
/// \brief Read a template name.
- TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx);
+ TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record,
+ unsigned &Idx);
/// \brief Read a template argument.
- TemplateArgument ReadTemplateArgument(llvm::BitstreamCursor &DeclsCursor,
+ TemplateArgument ReadTemplateArgument(PerFileData &F,
const RecordData &Record,unsigned &Idx);
/// \brief Read a template parameter list.
- TemplateParameterList *ReadTemplateParameterList(const RecordData &Record,
+ TemplateParameterList *ReadTemplateParameterList(PerFileData &F,
+ const RecordData &Record,
unsigned &Idx);
/// \brief Read a template argument array.
void
ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs,
- llvm::BitstreamCursor &DeclsCursor,
- const RecordData &Record, unsigned &Idx);
+ PerFileData &F, const RecordData &Record,
+ unsigned &Idx);
/// \brief Read a UnresolvedSet structure.
void ReadUnresolvedSet(UnresolvedSetImpl &Set,
const RecordData &Record, unsigned &Idx);
/// \brief Read a C++ base specifier.
- CXXBaseSpecifier ReadCXXBaseSpecifier(llvm::BitstreamCursor &DeclsCursor,
+ CXXBaseSpecifier ReadCXXBaseSpecifier(PerFileData &F,
const RecordData &Record,unsigned &Idx);
- /// \brief Read a CXXBaseOrMemberInitializer array.
- std::pair<CXXBaseOrMemberInitializer **, unsigned>
- ReadCXXBaseOrMemberInitializers(llvm::BitstreamCursor &DeclsCursor,
- const RecordData &Record, unsigned &Idx);
+ /// \brief Read a CXXCtorInitializer array.
+ std::pair<CXXCtorInitializer **, unsigned>
+ ReadCXXCtorInitializers(PerFileData &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a source location from raw form.
+ SourceLocation ReadSourceLocation(PerFileData &Module, unsigned Raw) {
+ (void)Module; // No remapping yet
+ return SourceLocation::getFromRawEncoding(Raw);
+ }
/// \brief Read a source location.
- SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) {
- return SourceLocation::getFromRawEncoding(Record[Idx++]);
+ SourceLocation ReadSourceLocation(PerFileData &Module,
+ const RecordData &Record, unsigned& Idx) {
+ return ReadSourceLocation(Module, Record[Idx++]);
}
/// \brief Read a source range.
- SourceRange ReadSourceRange(const RecordData &Record, unsigned& Idx);
+ SourceRange ReadSourceRange(PerFileData &F,
+ const RecordData &Record, unsigned& Idx);
/// \brief Read an integral value
llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx);
@@ -1000,13 +1194,14 @@ public:
CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
/// \brief Reads attributes from the current stream position.
- void ReadAttributes(llvm::BitstreamCursor &DeclsCursor, AttrVec &Attrs);
+ void ReadAttributes(PerFileData &F, AttrVec &Attrs,
+ const RecordData &Record, unsigned &Idx);
/// \brief Reads a statement.
- Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);
+ Stmt *ReadStmt(PerFileData &F);
/// \brief Reads an expression.
- Expr *ReadExpr(llvm::BitstreamCursor &Cursor);
+ Expr *ReadExpr(PerFileData &F);
/// \brief Reads a sub-statement operand during statement reading.
Stmt *ReadSubStmt() {
@@ -1022,13 +1217,30 @@ public:
Expr *ReadSubExpr();
/// \brief Reads the macro record located at the given offset.
- void ReadMacroRecord(llvm::BitstreamCursor &Stream, uint64_t Offset);
+ PreprocessedEntity *ReadMacroRecord(PerFileData &F, uint64_t Offset);
+ /// \brief Reads the preprocessed entity located at the current stream
+ /// position.
+ PreprocessedEntity *LoadPreprocessedEntity(PerFileData &F);
+
+ /// \brief Note that the identifier is a macro whose record will be loaded
+ /// from the given AST file at the given (file-local) offset.
+ void SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F,
+ uint64_t Offset);
+
/// \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 Read the macro definition corresponding to this iterator
+ /// into the unread macro record offsets table.
+ void LoadMacroDefinition(
+ llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos);
+
/// \brief Retrieve the macro definition with the given ID.
- MacroDefinition *getMacroDefinition(serialization::IdentID ID);
+ MacroDefinition *getMacroDefinition(serialization::MacroID ID);
/// \brief Retrieve the AST context that this AST reader supplements.
ASTContext *getContext() { return Context; }
@@ -1053,27 +1265,7 @@ public:
/// \brief Retrieve the switch-case statement with the given ID.
SwitchCase *getSwitchCaseWithID(unsigned ID);
- /// \brief Record that the given label statement has been
- /// deserialized and has the given ID.
- void RecordLabelStmt(LabelStmt *S, unsigned ID);
-
- /// \brief Set the label of the given statement to the label
- /// identified by ID.
- ///
- /// Depending on the order in which the label and other statements
- /// referencing that label occur, this operation may complete
- /// immediately (updating the statement) or it may queue the
- /// statement to be back-patched later.
- void SetLabelOf(GotoStmt *S, unsigned ID);
-
- /// \brief Set the label of the given expression to the label
- /// identified by ID.
- ///
- /// Depending on the order in which the label and other statements
- /// referencing that label occur, this operation may complete
- /// immediately (updating the statement) or it may queue the
- /// statement to be back-patched later.
- void SetLabelOf(AddrLabelExpr *S, unsigned ID);
+ void ClearSwitchCaseIDs();
};
/// \brief Helper class that saves the current stream position and
diff --git a/include/clang/Serialization/ASTSerializationListener.h b/include/clang/Serialization/ASTSerializationListener.h
new file mode 100644
index 000000000000..0c62e0b9ca5a
--- /dev/null
+++ b/include/clang/Serialization/ASTSerializationListener.h
@@ -0,0 +1,44 @@
+//===- ASTSerializationListener.h - Decl/Type PCH Write Events -*- 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 ASTSerializationListener class, which is notified
+// by the ASTWriter when an entity is serialized.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_AST_SERIALIZATION_LISTENER_H
+#define LLVM_CLANG_FRONTEND_AST_SERIALIZATION_LISTENER_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+
+class PreprocessedEntity;
+
+/// \brief Listener object that receives callbacks when certain kinds of
+/// entities are serialized.
+class ASTSerializationListener {
+public:
+ virtual ~ASTSerializationListener();
+
+ /// \brief Callback invoked whenever a preprocessed entity is serialized.
+ ///
+ /// This callback will only occur when the translation unit was created with
+ /// a detailed preprocessing record.
+ ///
+ /// \param Entity The entity that has been serialized.
+ ///
+ /// \param Offset The offset (in bits) of this entity in the resulting
+ /// AST file.
+ virtual void SerializedPreprocessedEntity(PreprocessedEntity *Entity,
+ uint64_t Offset) = 0;
+};
+
+}
+
+#endif
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 426fc4780148..beb493625e87 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -17,11 +17,13 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Sema/SemaConsumer.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include <map>
#include <queue>
@@ -36,13 +38,19 @@ namespace llvm {
namespace clang {
class ASTContext;
+class ASTSerializationListener;
class NestedNameSpecifier;
class CXXBaseSpecifier;
-class CXXBaseOrMemberInitializer;
-class LabelStmt;
+class CXXCtorInitializer;
+class FPOptions;
+class HeaderSearch;
class MacroDefinition;
class MemorizeStatCalls;
+class OpaqueValueExpr;
+class OpenCLOptions;
class ASTReader;
+class PreprocessedEntity;
+class PreprocessingRecord;
class Preprocessor;
class Sema;
class SourceManager;
@@ -55,9 +63,11 @@ class TargetInfo;
/// representation of a given abstract syntax tree and its supporting
/// data structures. This bitstream can be de-serialized via an
/// instance of the ASTReader class.
-class ASTWriter : public ASTDeserializationListener {
+class ASTWriter : public ASTDeserializationListener,
+ public ASTMutationListener {
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
+ typedef llvm::SmallVectorImpl<uint64_t> RecordDataImpl;
friend class ASTDeclWriter;
private:
@@ -67,6 +77,10 @@ private:
/// \brief The reader of existing AST files, if we're chaining.
ASTReader *Chain;
+ /// \brief A listener object that receives notifications when certain
+ /// entities are serialized.
+ ASTSerializationListener *SerializationListener;
+
/// \brief Stores a declaration or a type to be written to the AST file.
class DeclOrType {
public:
@@ -163,7 +177,7 @@ private:
/// \brief Offset of each selector within the method pool/selector
/// table, indexed by the Selector ID (-1).
std::vector<uint32_t> SelectorOffsets;
-
+
/// \brief Offsets of each of the macro identifiers into the
/// bitstream.
///
@@ -172,15 +186,30 @@ private:
/// defined.
llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets;
+ /// \brief The set of identifiers that had macro definitions at some point.
+ std::vector<const IdentifierInfo *> DeserializedMacroNames;
+
+ /// \brief The first ID number we can use for our own macro definitions.
+ serialization::MacroID FirstMacroID;
+
+ /// \brief The decl ID that will be assigned to the next new macro definition.
+ serialization::MacroID NextMacroID;
+
/// \brief Mapping from macro definitions (as they occur in the preprocessing
- /// record) to the index into the macro definitions table.
- llvm::DenseMap<const MacroDefinition *, serialization::IdentID>
+ /// record) to the macro IDs.
+ llvm::DenseMap<const MacroDefinition *, serialization::MacroID>
MacroDefinitions;
/// \brief Mapping from the macro definition indices in \c MacroDefinitions
/// to the corresponding offsets within the preprocessor block.
std::vector<uint32_t> MacroDefinitionOffsets;
+ typedef llvm::SmallVector<uint64_t, 2> UpdateRecord;
+ typedef llvm::DenseMap<const Decl *, UpdateRecord> DeclUpdateMap;
+ /// \brief Mapping from declarations that came from a chained PCH to the
+ /// record containing modifications to them.
+ DeclUpdateMap DeclUpdates;
+
typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap;
/// \brief Map of first declarations from a chained PCH that point to the
/// most recent declarations in another PCH.
@@ -200,13 +229,17 @@ private:
/// record.
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
- /// \brief Namespaces that have received extensions since their serialized
+ /// \brief DeclContexts that have received extensions since their serialized
/// form.
///
- /// Basically, when we're chaining and encountering a namespace, we check if
+ /// For namespaces, when we're chaining and encountering a namespace, we check if
/// its primary namespace comes from the chain. If it does, we add the primary
/// to this set, so that we can write out lexical content updates for it.
- llvm::SmallPtrSet<const NamespaceDecl *, 16> UpdatedNamespaces;
+ llvm::SmallPtrSet<const DeclContext *, 16> UpdatedDeclContexts;
+
+ typedef llvm::SmallPtrSet<const Decl *, 16> DeclsToRewriteTy;
+ /// \brief Decls that will be replaced in the current dependent AST file.
+ DeclsToRewriteTy DeclsToRewrite;
/// \brief Decls that have been replaced in the current dependent AST file.
///
@@ -217,16 +250,6 @@ private:
llvm::SmallVector<std::pair<serialization::DeclID, uint64_t>, 16>
ReplacedDecls;
- typedef llvm::SmallVector<serialization::DeclID, 4>
- AdditionalTemplateSpecializationsList;
- typedef llvm::DenseMap<serialization::DeclID,
- AdditionalTemplateSpecializationsList>
- AdditionalTemplateSpecializationsMap;
-
- /// \brief Additional specializations (including partial) of templates that
- /// were introduced after the template was serialized.
- AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializations;
-
/// \brief Statements that we've encountered while serializing a
/// declaration or type.
llvm::SmallVector<Stmt *, 16> StmtsToEmit;
@@ -238,8 +261,8 @@ private:
/// \brief Mapping from SwitchCase statements to IDs.
std::map<SwitchCase *, unsigned> SwitchCaseIDs;
- /// \brief Mapping from LabelStmt statements to IDs.
- std::map<LabelStmt *, unsigned> LabelIDs;
+ /// \brief Mapping from OpaqueValueExpr expressions to IDs.
+ llvm::DenseMap<OpaqueValueExpr *, unsigned> OpaqueValues;
/// \brief The number of statements written to the AST file.
unsigned NumStatements;
@@ -255,17 +278,50 @@ private:
/// file.
unsigned NumVisibleDeclContexts;
+ /// \brief The offset of each CXXBaseSpecifier set within the AST.
+ llvm::SmallVector<uint32_t, 4> CXXBaseSpecifiersOffsets;
+
+ /// \brief The first ID number we can use for our own base specifiers.
+ serialization::CXXBaseSpecifiersID FirstCXXBaseSpecifiersID;
+
+ /// \brief The base specifiers ID that will be assigned to the next new
+ /// set of C++ base specifiers.
+ serialization::CXXBaseSpecifiersID NextCXXBaseSpecifiersID;
+
+ /// \brief A set of C++ base specifiers that is queued to be written into the
+ /// AST file.
+ struct QueuedCXXBaseSpecifiers {
+ QueuedCXXBaseSpecifiers() : ID(), Bases(), BasesEnd() { }
+
+ QueuedCXXBaseSpecifiers(serialization::CXXBaseSpecifiersID ID,
+ CXXBaseSpecifier const *Bases,
+ CXXBaseSpecifier const *BasesEnd)
+ : ID(ID), Bases(Bases), BasesEnd(BasesEnd) { }
+
+ serialization::CXXBaseSpecifiersID ID;
+ CXXBaseSpecifier const * Bases;
+ CXXBaseSpecifier const * BasesEnd;
+ };
+
+ /// \brief Queue of C++ base specifiers to be written to the AST file,
+ /// in the order they should be written.
+ llvm::SmallVector<QueuedCXXBaseSpecifiers, 2> CXXBaseSpecifiersToWrite;
+
/// \brief Write the given subexpression to the bitstream.
void WriteSubStmt(Stmt *S);
void WriteBlockInfoBlock();
- void WriteMetadata(ASTContext &Context, const char *isysroot);
+ void WriteMetadata(ASTContext &Context, const char *isysroot,
+ const std::string &OutputFile);
void WriteLanguageOptions(const LangOptions &LangOpts);
void WriteStatCache(MemorizeStatCalls &StatCalls);
void WriteSourceManagerBlock(SourceManager &SourceMgr,
const Preprocessor &PP,
const char* isysroot);
void WritePreprocessor(const Preprocessor &PP);
+ void WriteHeaderSearch(HeaderSearch &HS, const char* isysroot);
+ void WritePreprocessorDetail(PreprocessingRecord &PPRec);
+ void WritePragmaDiagnosticMappings(const Diagnostic &Diag);
void WriteType(QualType T);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
@@ -273,10 +329,12 @@ private:
void WriteSelectors(Sema &SemaRef);
void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP);
- void WriteAttributeRecord(const AttrVec &Attrs);
- void WriteDeclUpdateBlock();
+ void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
+ void WriteDeclUpdatesBlocks();
+ void WriteDeclReplacementsBlock();
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
- void WriteAdditionalTemplateSpecializations();
+ void WriteFPPragmaOptions(const FPOptions &Opts);
+ void WriteOpenCLExtensions(Sema &SemaRef);
unsigned ParmVarDeclAbbrev;
unsigned DeclContextLexicalAbbrev;
@@ -286,7 +344,7 @@ private:
void WriteDecl(ASTContext &Context, Decl *D);
void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
- const char* isysroot);
+ const char* isysroot, const std::string &OutputFile);
void WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char* isysroot);
@@ -295,6 +353,12 @@ public:
/// the given bitstream.
ASTWriter(llvm::BitstreamWriter &Stream);
+ /// \brief Set the listener that will receive notification of serialization
+ /// events.
+ void SetSerializationListener(ASTSerializationListener *Listener) {
+ SerializationListener = Listener;
+ }
+
/// \brief Write a precompiled header for the given semantic analysis.
///
/// \param SemaRef a reference to the semantic analysis object that processed
@@ -309,32 +373,38 @@ public:
/// \param PPRec Record of the preprocessing actions that occurred while
/// preprocessing this file, e.g., macro instantiations
void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ const std::string &OutputFile,
const char* isysroot);
/// \brief Emit a source location.
- void AddSourceLocation(SourceLocation Loc, RecordData &Record);
+ void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record);
/// \brief Emit a source range.
- void AddSourceRange(SourceRange Range, RecordData &Record);
+ void AddSourceRange(SourceRange Range, RecordDataImpl &Record);
/// \brief Emit an integral value.
- void AddAPInt(const llvm::APInt &Value, RecordData &Record);
+ void AddAPInt(const llvm::APInt &Value, RecordDataImpl &Record);
/// \brief Emit a signed integral value.
- void AddAPSInt(const llvm::APSInt &Value, RecordData &Record);
+ void AddAPSInt(const llvm::APSInt &Value, RecordDataImpl &Record);
/// \brief Emit a floating-point value.
- void AddAPFloat(const llvm::APFloat &Value, RecordData &Record);
+ void AddAPFloat(const llvm::APFloat &Value, RecordDataImpl &Record);
/// \brief Emit a reference to an identifier.
- void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record);
+ void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record);
/// \brief Emit a Selector (which is a smart pointer reference).
- void AddSelectorRef(Selector, RecordData &Record);
+ void AddSelectorRef(Selector, RecordDataImpl &Record);
/// \brief Emit a CXXTemporary.
- void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record);
+ void AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record);
+ /// \brief Emit a set of C++ base specifiers to the record.
+ void AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases,
+ CXXBaseSpecifier const *BasesEnd,
+ RecordDataImpl &Record);
+
/// \brief Get the unique number used to refer to the given selector.
serialization::SelectorID getSelectorRef(Selector Sel);
@@ -353,10 +423,10 @@ public:
/// \brief Retrieve the ID number corresponding to the given macro
/// definition.
- serialization::IdentID getMacroDefinitionID(MacroDefinition *MD);
+ serialization::MacroID getMacroDefinitionID(MacroDefinition *MD);
/// \brief Emit a reference to a type.
- void AddTypeRef(QualType T, RecordData &Record);
+ void AddTypeRef(QualType T, RecordDataImpl &Record);
/// \brief Force a type to be emitted and get its ID.
serialization::TypeID GetOrCreateTypeID(QualType T);
@@ -371,20 +441,21 @@ public:
serialization::TypeIdx getTypeIdx(QualType T) const;
/// \brief Emits a reference to a declarator info.
- void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record);
+ void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record);
/// \brief Emits a template argument location info.
void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
const TemplateArgumentLocInfo &Arg,
- RecordData &Record);
+ RecordDataImpl &Record);
/// \brief Emits a template argument location.
void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
- RecordData &Record);
+ RecordDataImpl &Record);
/// \brief Emit a reference to a declaration.
- void AddDeclRef(const Decl *D, RecordData &Record);
+ void AddDeclRef(const Decl *D, RecordDataImpl &Record);
+
/// \brief Force a declaration to be emitted and get its ID.
serialization::DeclID GetDeclRef(const Decl *D);
@@ -393,49 +464,57 @@ public:
serialization::DeclID getDeclID(const Decl *D);
/// \brief Emit a declaration name.
- void AddDeclarationName(DeclarationName Name, RecordData &Record);
+ void AddDeclarationName(DeclarationName Name, RecordDataImpl &Record);
+ void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
+ DeclarationName Name, RecordDataImpl &Record);
+ void AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ RecordDataImpl &Record);
+
+ void AddQualifierInfo(const QualifierInfo &Info, RecordDataImpl &Record);
/// \brief Emit a nested name specifier.
- void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordData &Record);
+ void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record);
/// \brief Emit a template name.
- void AddTemplateName(TemplateName Name, RecordData &Record);
+ void AddTemplateName(TemplateName Name, RecordDataImpl &Record);
/// \brief Emit a template argument.
- void AddTemplateArgument(const TemplateArgument &Arg, RecordData &Record);
+ void AddTemplateArgument(const TemplateArgument &Arg, RecordDataImpl &Record);
/// \brief Emit a template parameter list.
void AddTemplateParameterList(const TemplateParameterList *TemplateParams,
- RecordData &Record);
+ RecordDataImpl &Record);
/// \brief Emit a template argument list.
void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
- RecordData &Record);
+ RecordDataImpl &Record);
/// \brief Emit a UnresolvedSet structure.
- void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record);
+ void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record);
/// \brief Emit a C++ base specifier.
- void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordData &Record);
+ void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordDataImpl &Record);
+
+ /// \brief Emit a CXXCtorInitializer array.
+ void AddCXXCtorInitializers(
+ const CXXCtorInitializer * const *CtorInitializers,
+ unsigned NumCtorInitializers,
+ RecordDataImpl &Record);
- /// \brief Emit a CXXBaseOrMemberInitializer array.
- void AddCXXBaseOrMemberInitializers(
- const CXXBaseOrMemberInitializer * const *BaseOrMembers,
- unsigned NumBaseOrMembers, RecordData &Record);
+ void AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record);
/// \brief Add a string to the given record.
- void AddString(llvm::StringRef Str, RecordData &Record);
+ void AddString(llvm::StringRef Str, RecordDataImpl &Record);
- /// \brief Mark a namespace as needing an update.
- void AddUpdatedNamespace(const NamespaceDecl *NS) {
- UpdatedNamespaces.insert(NS);
+ /// \brief Mark a declaration context as needing an update.
+ void AddUpdatedDeclContext(const DeclContext *DC) {
+ UpdatedDeclContexts.insert(DC);
}
- /// \brief Record a template specialization or partial specialization of
- /// a template from a previous PCH file.
- void AddAdditionalTemplateSpecialization(serialization::DeclID Templ,
- serialization::DeclID Spec) {
- AdditionalTemplateSpecializations[Templ].push_back(Spec);
+ void RewriteDecl(const Decl *D) {
+ DeclsToRewrite.insert(D);
+ // Reset the flag, so that we don't add this decl multiple times.
+ const_cast<Decl *>(D)->setChangedSinceDeserialization(false);
}
/// \brief Note that the identifier II occurs at the given offset
@@ -462,32 +541,46 @@ public:
/// been added to the queue via AddStmt().
void FlushStmts();
+ /// \brief Flush all of the C++ base specifier sets that have been added
+ /// via \c AddCXXBaseSpecifiersRef().
+ void FlushCXXBaseSpecifiers();
+
/// \brief Record an ID for the given switch-case statement.
unsigned RecordSwitchCaseID(SwitchCase *S);
/// \brief Retrieve the ID for the given switch-case statement.
unsigned getSwitchCaseID(SwitchCase *S);
- /// \brief Retrieve the ID for the given label statement, which may
- /// or may not have been emitted yet.
- unsigned GetLabelID(LabelStmt *S);
+ void ClearSwitchCaseIDs();
+
+ /// \brief Retrieve the ID for the given opaque value expression.
+ unsigned getOpaqueValueID(OpaqueValueExpr *e);
unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
bool hasChain() const { return Chain; }
// ASTDeserializationListener implementation
- void SetReader(ASTReader *Reader);
+ void ReaderInitialized(ASTReader *Reader);
void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II);
void TypeRead(serialization::TypeIdx Idx, QualType T);
void DeclRead(serialization::DeclID ID, const Decl *D);
- void SelectorRead(serialization::SelectorID iD, Selector Sel);
+ void SelectorRead(serialization::SelectorID ID, Selector Sel);
+ void MacroDefinitionRead(serialization::MacroID ID, MacroDefinition *MD);
+
+ // ASTMutationListener implementation.
+ virtual void CompletedTagDefinition(const TagDecl *D);
+ virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D);
+ virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
+ virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D);
};
/// \brief AST and semantic-analysis consumer that generates a
/// precompiled header from the parsed source code.
class PCHGenerator : public SemaConsumer {
const Preprocessor &PP;
+ std::string OutputFile;
const char *isysroot;
llvm::raw_ostream *Out;
Sema *SemaPtr;
@@ -495,16 +588,19 @@ class PCHGenerator : public SemaConsumer {
std::vector<unsigned char> Buffer;
llvm::BitstreamWriter Stream;
ASTWriter Writer;
+ bool Chaining;
protected:
ASTWriter &getWriter() { return Writer; }
const ASTWriter &getWriter() const { return Writer; }
public:
- PCHGenerator(const Preprocessor &PP, bool Chaining,
+ PCHGenerator(const Preprocessor &PP, const std::string &OutputFile, bool Chaining,
const char *isysroot, llvm::raw_ostream *Out);
virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
virtual void HandleTranslationUnit(ASTContext &Ctx);
+ virtual ASTMutationListener *GetASTMutationListener();
+ virtual ASTSerializationListener *GetASTSerializationListener();
virtual ASTDeserializationListener *GetASTDeserializationListener();
};
diff --git a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
new file mode 100644
index 000000000000..e452ccfb6ceb
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
@@ -0,0 +1,38 @@
+//===--- CheckerBase.td - Checker TableGen classes ------------------------===//
+//
+// 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 TableGen core definitions for checkers
+//
+//===----------------------------------------------------------------------===//
+
+class Package<string name> {
+ string PackageName = name;
+ bit Hidden = 0;
+ Package ParentPackage;
+}
+class InPackage<Package P> { Package ParentPackage = P; }
+
+class CheckerGroup<string name> {
+ string GroupName = name;
+}
+class InGroup<CheckerGroup G> { CheckerGroup Group = G; }
+
+// All checkers are an indirect subclass of this.
+class Checker<string name = ""> {
+ string CheckerName = name;
+ string DescFile;
+ string HelpText;
+ bit Hidden = 0;
+ Package ParentPackage;
+ CheckerGroup Group;
+}
+
+class DescFile<string filename> { string DescFile = filename; }
+class HelpText<string text> { string HelpText = text; }
+class Hidden { bit Hidden = 1; }
diff --git a/include/clang/Checker/Checkers/DereferenceChecker.h b/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h
index a84183e7f27f..f9cce9ca9c62 100644
--- a/include/clang/Checker/Checkers/DereferenceChecker.h
+++ b/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h
@@ -8,23 +8,27 @@
//===----------------------------------------------------------------------===//
//
// This defines NullDerefChecker and UndefDerefChecker, two builtin checks
-// in GRExprEngine that check for null and undefined pointers at loads
+// in ExprEngine that check for null and undefined pointers at loads
// and stores.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_DEREFCHECKER
-#define LLVM_CLANG_DEREFCHECKER
+#ifndef LLVM_CLANG_GR_DEREFCHECKER
+#define LLVM_CLANG_GR_DEREFCHECKER
#include <utility>
namespace clang {
-class GRExprEngine;
+namespace ento {
+
+class ExprEngine;
class ExplodedNode;
std::pair<ExplodedNode * const *, ExplodedNode * const *>
-GetImplicitNullDereferences(GRExprEngine &Eng);
+GetImplicitNullDereferences(ExprEngine &Eng);
+
+} // end GR namespace
} // end clang namespace
diff --git a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
new file mode 100644
index 000000000000..42feb78b4174
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
@@ -0,0 +1,51 @@
+//==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- 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 interface to call a set of intra-procedural (local)
+// checkers that use flow/path-sensitive analyses to find bugs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_LOCALCHECKERS_H
+#define LLVM_CLANG_GR_LOCALCHECKERS_H
+
+namespace clang {
+
+class CFG;
+class Decl;
+class Diagnostic;
+class ASTContext;
+class LangOptions;
+class ParentMap;
+class LiveVariables;
+class ObjCImplementationDecl;
+class LangOptions;
+class TranslationUnitDecl;
+
+namespace ento {
+
+class PathDiagnosticClient;
+class TransferFuncs;
+class BugType;
+class BugReporter;
+class ExprEngine;
+
+TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+ const LangOptions& lopts);
+
+void RegisterExperimentalChecks(ExprEngine &Eng);
+void RegisterExperimentalInternalChecks(ExprEngine &Eng);
+
+void RegisterCallInliner(ExprEngine &Eng);
+
+} // end GR namespace
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 370d96552c45..1786fe610d6b 100644
--- a/include/clang/Checker/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
-#define LLVM_CLANG_ANALYSIS_BUGREPORTER
+#ifndef LLVM_CLANG_GR_BUGREPORTER
+#define LLVM_CLANG_GR_BUGREPORTER
#include "clang/Basic/SourceLocation.h"
-#include "clang/Checker/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/ImmutableSet.h"
@@ -25,20 +25,23 @@
namespace clang {
+class ASTContext;
+class Diagnostic;
+class Stmt;
+class ParentMap;
+
+namespace ento {
+
class PathDiagnostic;
class PathDiagnosticPiece;
class PathDiagnosticClient;
-class ASTContext;
-class Diagnostic;
class ExplodedNode;
class ExplodedGraph;
class BugReporter;
class BugReporterContext;
-class GRExprEngine;
+class ExprEngine;
class GRState;
-class Stmt;
class BugType;
-class ParentMap;
//===----------------------------------------------------------------------===//
// Interface for individual bug reports.
@@ -61,8 +64,8 @@ protected:
BugType& BT;
std::string ShortDescription;
std::string Description;
- const ExplodedNode *EndNode;
- SourceRange R;
+ const ExplodedNode *ErrorNode;
+ mutable SourceRange R;
protected:
friend class BugReporter;
@@ -81,12 +84,13 @@ public:
getOriginalNode(const ExplodedNode* N) = 0;
};
- BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *n)
- : BT(bt), Description(desc), EndNode(n) {}
+ BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *errornode)
+ : BT(bt), Description(desc), ErrorNode(errornode) {}
BugReport(BugType& bt, llvm::StringRef shortDesc, llvm::StringRef desc,
- const ExplodedNode *n)
- : BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {}
+ const ExplodedNode *errornode)
+ : BT(bt), ShortDescription(shortDesc), Description(desc),
+ ErrorNode(errornode) {}
virtual ~BugReport();
@@ -96,7 +100,7 @@ public:
BugType& getBugType() { return BT; }
// FIXME: Perhaps this should be moved into a subclass?
- const ExplodedNode* getEndNode() const { return EndNode; }
+ const ExplodedNode* getErrorNode() const { return ErrorNode; }
// FIXME: Do we need this? Maybe getLocation() should return a ProgramPoint
// object.
@@ -125,8 +129,10 @@ public:
/// This location is used by clients rendering diagnostics.
virtual SourceLocation getLocation() const;
+ typedef const SourceRange *ranges_iterator;
+
/// getRanges - Returns the source ranges associated with this bug.
- virtual void getRanges(const SourceRange*& beg, const SourceRange*& end);
+ virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const;
virtual PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
const ExplodedNode* PrevN,
@@ -191,14 +197,15 @@ public:
// FIXME: Collapse this with the default BugReport class.
class RangedBugReport : public BugReport {
- std::vector<SourceRange> Ranges;
+ llvm::SmallVector<SourceRange, 4> Ranges;
public:
- RangedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n)
- : BugReport(D, description, n) {}
+ RangedBugReport(BugType& D, llvm::StringRef description,
+ ExplodedNode *errornode)
+ : BugReport(D, description, errornode) {}
RangedBugReport(BugType& D, llvm::StringRef shortDescription,
- llvm::StringRef description, ExplodedNode *n)
- : BugReport(D, shortDescription, description, n) {}
+ llvm::StringRef description, ExplodedNode *errornode)
+ : BugReport(D, shortDescription, description, errornode) {}
~RangedBugReport();
@@ -208,17 +215,8 @@ public:
Ranges.push_back(R);
}
- // FIXME: Move this out of line.
- void getRanges(const SourceRange*& beg, const SourceRange*& end) {
-
- if (Ranges.empty()) {
- beg = NULL;
- end = NULL;
- }
- else {
- beg = &Ranges[0];
- end = beg + Ranges.size();
- }
+ virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const {
+ return std::make_pair(Ranges.begin(), Ranges.end());
}
};
@@ -232,12 +230,13 @@ private:
Creators creators;
public:
- EnhancedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n)
- : RangedBugReport(D, description, n) {}
+ EnhancedBugReport(BugType& D, llvm::StringRef description,
+ ExplodedNode *errornode)
+ : RangedBugReport(D, description, errornode) {}
EnhancedBugReport(BugType& D, llvm::StringRef shortDescription,
- llvm::StringRef description, ExplodedNode *n)
- : RangedBugReport(D, shortDescription, description, n) {}
+ llvm::StringRef description, ExplodedNode *errornode)
+ : RangedBugReport(D, shortDescription, description, errornode) {}
~EnhancedBugReport() {}
@@ -279,10 +278,12 @@ private:
void FlushReport(BugReportEquivClass& EQ);
protected:
- BugReporter(BugReporterData& d, Kind k) : BugTypes(F.GetEmptySet()), kind(k), D(d) {}
+ BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
+ D(d) {}
public:
- BugReporter(BugReporterData& d) : BugTypes(F.GetEmptySet()), kind(BaseBRKind), D(d) {}
+ BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind),
+ D(d) {}
virtual ~BugReporter();
void FlushReports();
@@ -305,8 +306,8 @@ public:
SourceManager& getSourceManager() { return D.getSourceManager(); }
- virtual void GeneratePathDiagnostic(PathDiagnostic& PD,
- BugReportEquivClass& EQ) {}
+ virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic,
+ llvm::SmallVectorImpl<BugReport *> &bugReports) {}
void Register(BugType *BT);
@@ -347,17 +348,17 @@ public:
// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
class GRBugReporter : public BugReporter {
- GRExprEngine& Eng;
+ ExprEngine& Eng;
llvm::SmallSet<SymbolRef, 10> NotableSymbols;
public:
- GRBugReporter(BugReporterData& d, GRExprEngine& eng)
+ GRBugReporter(BugReporterData& d, ExprEngine& eng)
: BugReporter(d, GRBugReporterKind), Eng(eng) {}
virtual ~GRBugReporter();
/// getEngine - Return the analysis engine used to analyze a given
/// function or method.
- GRExprEngine &getEngine() { return Eng; }
+ ExprEngine &getEngine() { return Eng; }
/// getGraph - Get the exploded graph created by the analysis engine
/// for the analyzed method or function.
@@ -367,8 +368,8 @@ public:
/// engine.
GRStateManager &getStateManager();
- virtual void GeneratePathDiagnostic(PathDiagnostic& PD,
- BugReportEquivClass& R);
+ virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
+ llvm::SmallVectorImpl<BugReport*> &bugReports);
void addNotableSymbol(SymbolRef Sym) {
NotableSymbols.insert(Sym);
@@ -392,7 +393,7 @@ class BugReporterContext {
llvm::ImmutableList<BugReporterVisitor*> Callbacks;
llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
public:
- BugReporterContext(GRBugReporter& br) : BR(br), Callbacks(F.GetEmptyList()) {}
+ BugReporterContext(GRBugReporter& br) : BR(br), Callbacks(F.getEmptyList()) {}
virtual ~BugReporterContext();
void addVisitor(BugReporterVisitor* visitor);
@@ -419,8 +420,8 @@ public:
return BR.getStateManager();
}
- ValueManager& getValueManager() {
- return getStateManager().getValueManager();
+ SValBuilder& getSValBuilder() {
+ return getStateManager().getSValBuilder();
}
ASTContext& getASTContext() {
@@ -478,6 +479,8 @@ void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
//===----------------------------------------------------------------------===//
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index afc07c89e86f..2793284e298f 100644
--- a/include/clang/Checker/BugReporter/BugType.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -14,14 +14,16 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
#define LLVM_CLANG_ANALYSIS_BUGTYPE
-#include "clang/Checker/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "llvm/ADT/FoldingSet.h"
#include <string>
namespace clang {
+namespace ento {
+
class ExplodedNode;
-class GRExprEngine;
+class ExprEngine;
class BugType {
private:
@@ -68,5 +70,7 @@ public:
llvm::StringRef getDescription() const { return desc; }
};
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 24c75ce7b228..6d53c097d29f 100644
--- a/include/clang/Checker/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -27,6 +27,8 @@ class Decl;
class SourceManager;
class Stmt;
+namespace ento {
+
//===----------------------------------------------------------------------===//
// High-level interface for handlers of path-sensitive diagnostics.
//===----------------------------------------------------------------------===//
@@ -490,5 +492,9 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const;
};
+
+} // end GR namespace
+
} //end clang namespace
+
#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
new file mode 100644
index 000000000000..65c8b80aa2a8
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -0,0 +1,109 @@
+//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Static Analyzer Checker Manager.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
+#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+
+namespace clang {
+ class Decl;
+
+namespace ento {
+ class ExprEngine;
+ class AnalysisManager;
+ class BugReporter;
+
+class CheckerManager {
+public:
+ ~CheckerManager();
+
+ typedef void *CheckerRef;
+
+//===----------------------------------------------------------------------===//
+// registerChecker
+//===----------------------------------------------------------------------===//
+
+ /// \brief Used to register checkers.
+ template <typename CHECKER>
+ void registerChecker() {
+ CHECKER *checker = new CHECKER();
+ Checkers.push_back(std::pair<CheckerRef, Dtor>(checker, destruct<CHECKER>));
+ CHECKER::_register(checker, *this);
+ }
+
+ typedef void (*RegisterToEngFunc)(ExprEngine &Eng);
+ void addCheckerRegisterFunction(RegisterToEngFunc fn) {
+ Funcs.push_back(fn);
+ }
+
+//===----------------------------------------------------------------------===//
+// Functions for running checkers.
+//===----------------------------------------------------------------------===//
+
+ /// \brief Run checkers handling Decls.
+ void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR);
+
+ /// \brief Run checkers handling Decls containing a Stmt body.
+ void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions.
+//===----------------------------------------------------------------------===//
+
+ // Functions used by the registration mechanism, checkers should not touch
+ // these directly.
+
+ typedef void (*CheckDeclFunc)(CheckerRef checker, const Decl *D,
+ AnalysisManager& mgr, BugReporter &BR);
+ typedef bool (*HandlesDeclFunc)(const Decl *D);
+ void _registerForDecl(CheckerRef checker, CheckDeclFunc checkfn,
+ HandlesDeclFunc isForDeclFn);
+
+ void _registerForBody(CheckerRef checker, CheckDeclFunc checkfn);
+
+ void registerCheckersToEngine(ExprEngine &eng);
+
+private:
+ template <typename CHECKER>
+ static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
+
+ std::vector<RegisterToEngFunc> Funcs;
+
+ struct DeclCheckerInfo {
+ CheckerRef Checker;
+ CheckDeclFunc CheckFn;
+ HandlesDeclFunc IsForDeclFn;
+ };
+ std::vector<DeclCheckerInfo> DeclCheckers;
+
+ std::vector<std::pair<CheckerRef, CheckDeclFunc> > BodyCheckers;
+
+ typedef void (*Dtor)(void *);
+ std::vector<std::pair<CheckerRef, Dtor> > Checkers;
+
+ typedef llvm::SmallVector<std::pair<CheckerRef, CheckDeclFunc>, 4>
+ CachedDeclCheckers;
+ typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
+ CachedDeclCheckersMapTy CachedDeclCheckersMap;
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/include/clang/StaticAnalyzer/Core/CheckerProvider.h
new file mode 100644
index 000000000000..414ad92b2a5a
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/CheckerProvider.h
@@ -0,0 +1,54 @@
+//===--- CheckerProvider.h - Static Analyzer Checkers Provider --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Static Analyzer Checker Provider.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_CHECKERPROVIDER_H
+#define LLVM_CLANG_SA_CORE_CHECKERPROVIDER_H
+
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+
+namespace ento {
+ class CheckerManager;
+
+class CheckerOptInfo {
+ const char *Name;
+ bool Enable;
+ bool Claimed;
+
+public:
+ CheckerOptInfo(const char *name, bool enable)
+ : Name(name), Enable(enable), Claimed(false) { }
+
+ const char *getName() const { return Name; }
+ bool isEnabled() const { return Enable; }
+ bool isDisabled() const { return !isEnabled(); }
+
+ bool isClaimed() const { return Claimed; }
+ bool isUnclaimed() const { return !isClaimed(); }
+ void claim() { Claimed = true; }
+};
+
+class CheckerProvider {
+public:
+ virtual ~CheckerProvider();
+ virtual void registerCheckers(CheckerManager &checkerMgr,
+ CheckerOptInfo *checkOpts, unsigned numCheckOpts) = 0;
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerV2.h b/include/clang/StaticAnalyzer/Core/CheckerV2.h
new file mode 100644
index 000000000000..8c96866f1c99
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/CheckerV2.h
@@ -0,0 +1,93 @@
+//== CheckerV2.h - Registration mechanism for checkers -----------*- 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 CheckerV2, used to create and register checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_CHECKERV2
+#define LLVM_CLANG_SA_CORE_CHECKERV2
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/Support/Casting.h"
+
+namespace clang {
+namespace ento {
+ class BugReporter;
+
+namespace check {
+
+struct _VoidCheck {
+ static void _register(void *checker, CheckerManager &mgr) { }
+};
+
+template <typename DECL>
+class ASTDecl {
+ template <typename CHECKER>
+ static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) {
+ ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR);
+ }
+
+ static bool _handlesDecl(const Decl *D) {
+ return llvm::isa<DECL>(D);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForDecl(checker, _checkDecl<CHECKER>, _handlesDecl);
+ }
+};
+
+class ASTCodeBody {
+ template <typename CHECKER>
+ static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) {
+ ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForBody(checker, _checkBody<CHECKER>);
+ }
+};
+
+} // end check namespace
+
+template <typename CHECK1, typename CHECK2=check::_VoidCheck,
+ typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
+ typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
+ typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
+ typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
+ typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck>
+class CheckerV2 {
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ CHECK1::_register(checker, mgr);
+ CHECK2::_register(checker, mgr);
+ CHECK3::_register(checker, mgr);
+ CHECK4::_register(checker, mgr);
+ CHECK5::_register(checker, mgr);
+ CHECK6::_register(checker, mgr);
+ CHECK7::_register(checker, mgr);
+ CHECK8::_register(checker, mgr);
+ CHECK9::_register(checker, mgr);
+ CHECK10::_register(checker, mgr);
+ CHECK11::_register(checker, mgr);
+ CHECK12::_register(checker, mgr);
+ }
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Checker/PathDiagnosticClients.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h
index d3aa3b211433..2713e31fc0d1 100644
--- a/include/clang/Checker/PathDiagnosticClients.h
+++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h
@@ -11,22 +11,32 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CHECKER_PATH_DIAGNOSTIC_CLIENTS_H
-#define LLVM_CLANG_CHECKER_PATH_DIAGNOSTIC_CLiENTS_H
+#ifndef LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H
+#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLiENTS_H
#include <string>
namespace clang {
-class PathDiagnosticClient;
class Preprocessor;
+namespace ento {
+
+class PathDiagnosticClient;
+
PathDiagnosticClient*
-CreateHTMLDiagnosticClient(const std::string& prefix, const Preprocessor &PP);
+createHTMLDiagnosticClient(const std::string& prefix, const Preprocessor &PP);
PathDiagnosticClient*
-CreatePlistDiagnosticClient(const std::string& prefix, const Preprocessor &PP,
+createPlistDiagnosticClient(const std::string& prefix, const Preprocessor &PP,
PathDiagnosticClient *SubPD = 0);
+PathDiagnosticClient*
+createTextPathDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP);
+
+} // end GR namespace
+
} // end clang namespace
+
#endif
diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 38550798b812..1ba038e6da2d 100644
--- a/include/clang/Checker/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -12,12 +12,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H
-#define LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H
+#ifndef LLVM_CLANG_GR_ANALYSISMANAGER_H
+#define LLVM_CLANG_GR_ANALYSISMANAGER_H
#include "clang/Analysis/AnalysisContext.h"
-#include "clang/Checker/BugReporter/BugReporter.h"
-#include "clang/Checker/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
namespace clang {
@@ -26,6 +26,9 @@ namespace idx {
class TranslationUnit;
}
+namespace ento {
+ class CheckerManager;
+
class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr;
@@ -40,6 +43,8 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
+ CheckerManager *CheckerMgr;
+
/// \brief Provide function definitions in other translation units. This is
/// NULL if we don't have multiple translation units. AnalysisManager does
/// not own the Indexer.
@@ -50,8 +55,8 @@ class AnalysisManager : public BugReporterData {
// The maximum number of exploded nodes the analyzer will generate.
unsigned MaxNodes;
- // The maximum number of times the analyzer will go through a loop.
- unsigned MaxLoop;
+ // The maximum number of times the analyzer visit a block.
+ unsigned MaxVisit;
bool VisualizeEGDot;
bool VisualizeEGUbi;
@@ -67,23 +72,29 @@ class AnalysisManager : public BugReporterData {
bool EagerlyAssume;
bool TrimGraph;
bool InlineCall;
+ bool EagerlyTrimEGraph;
public:
AnalysisManager(ASTContext &ctx, Diagnostic &diags,
const LangOptions &lang, PathDiagnosticClient *pd,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
+ CheckerManager *checkerMgr,
idx::Indexer *idxer,
- unsigned maxnodes, unsigned maxloop,
+ unsigned maxnodes, unsigned maxvisit,
bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
- bool inlinecall, bool useUnoptimizedCFG)
-
- : AnaCtxMgr(useUnoptimizedCFG), Ctx(ctx), Diags(diags), LangInfo(lang),
- PD(pd),
- CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),Idxer(idxer),
- AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop),
+ bool inlinecall, bool useUnoptimizedCFG,
+ bool addImplicitDtors, bool addInitializers,
+ bool eagerlyTrimEGraph)
+
+ : AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, addInitializers),
+ Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
+ CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
+ CheckerMgr(checkerMgr), Idxer(idxer),
+ AScope(ScopeDecl), MaxNodes(maxnodes), MaxVisit(maxvisit),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
- EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {}
+ EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall),
+ EagerlyTrimEGraph(eagerlyTrimEGraph) {}
~AnalysisManager() { FlushDiagnostics(); }
@@ -104,6 +115,8 @@ public:
return CreateConstraintMgr;
}
+ CheckerManager *getCheckerManager() const { return CheckerMgr; }
+
idx::Indexer *getIndexer() const { return Idxer; }
virtual ASTContext &getASTContext() {
@@ -133,7 +146,7 @@ public:
unsigned getMaxNodes() const { return MaxNodes; }
- unsigned getMaxLoop() const { return MaxLoop; }
+ unsigned getMaxVisit() const { return MaxVisit; }
bool shouldVisualizeGraphviz() const { return VisualizeEGDot; }
@@ -143,6 +156,8 @@ public:
return VisualizeEGDot || VisualizeEGUbi;
}
+ bool shouldEagerlyTrimExplodedGraph() const { return EagerlyTrimEGraph; }
+
bool shouldTrimGraph() const { return TrimGraph; }
bool shouldPurgeDead() const { return PurgeDead; }
@@ -153,7 +168,7 @@ public:
bool hasIndexer() const { return Idxer != 0; }
- const AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
+ AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
@@ -177,8 +192,8 @@ public:
const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
LocationContext const *Parent,
- Stmt const *S, const CFGBlock *Blk,
- unsigned Idx) {
+ const Stmt *S,
+ const CFGBlock *Blk, unsigned Idx) {
return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
}
@@ -189,14 +204,17 @@ public:
}
// Get a stack frame with parent.
- StackFrameContext const *getStackFrame(Decl const *D,
+ StackFrameContext const *getStackFrame(const Decl *D,
LocationContext const *Parent,
- Stmt const *S, const CFGBlock *Blk,
- unsigned Idx) {
- return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx);
+ const Stmt *S,
+ const CFGBlock *Blk, unsigned Idx) {
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S,
+ Blk,Idx);
}
};
-}
+} // end GR namespace
+
+} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 59dd9190d25e..a4327e127f5f 100644
--- a/include/clang/Checker/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -8,15 +8,15 @@
//===----------------------------------------------------------------------===//
//
// This file defines BasicValueFactory, a class that manages the lifetime
-// of APSInt objects and symbolic constraints used by GRExprEngine
+// of APSInt objects and symbolic constraints used by ExprEngine
// and related classes.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
-#define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
+#ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H
+#define LLVM_CLANG_GR_BASICVALUEFACTORY_H
-#include "clang/Checker/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/APSInt.h"
@@ -24,6 +24,8 @@
namespace clang {
+namespace ento {
+
class GRState;
class CompoundValData : public llvm::FoldingSetNode {
@@ -102,9 +104,9 @@ public:
}
const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
- assert(T->isIntegerType() || Loc::IsLocType(T));
+ assert(T->isIntegerType() || Loc::isLocType(T));
unsigned bitwidth = Ctx.getTypeSize(T);
- bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth())
return From;
@@ -126,14 +128,14 @@ public:
}
inline const llvm::APSInt& getMaxValue(QualType T) {
- assert(T->isIntegerType() || Loc::IsLocType(T));
- bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
+ assert(T->isIntegerType() || Loc::isLocType(T));
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned));
}
inline const llvm::APSInt& getMinValue(QualType T) {
- assert(T->isIntegerType() || Loc::IsLocType(T));
- bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
+ assert(T->isIntegerType() || Loc::isLocType(T));
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned));
}
@@ -162,7 +164,7 @@ public:
}
inline const llvm::APSInt& getTruthValue(bool b) {
- return getTruthValue(b, Ctx.IntTy);
+ return getTruthValue(b, Ctx.getLogicalOperationType());
}
const CompoundValData *getCompoundValData(QualType T,
@@ -172,14 +174,14 @@ public:
const TypedRegion *region);
llvm::ImmutableList<SVal> getEmptySValList() {
- return SValListFactory.GetEmptyList();
+ return SValListFactory.getEmptyList();
}
llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
- return SValListFactory.Add(X, L);
+ return SValListFactory.add(X, L);
}
- const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op,
+ const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1,
const llvm::APSInt& V2);
@@ -192,6 +194,8 @@ public:
const SVal* getPersistentSVal(SVal X);
};
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/GRBlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
index b7d0e8ae0c71..7d0fdfb5f11f 100644
--- a/include/clang/Checker/PathSensitive/GRBlockCounter.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
@@ -1,4 +1,4 @@
-//==- GRBlockCounter.h - ADT for counting block visits -------------*- C++ -*-//
+//==- BlockCounter.h - ADT for counting block visits ---------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,14 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines GRBlockCounter, an abstract data type used to count
+// This file defines BlockCounter, an abstract data type used to count
// the number of times a given block has been visited along a path
-// analyzed by GRCoreEngine.
+// analyzed by CoreEngine.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
-#define LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
+#ifndef LLVM_CLANG_GR_BLOCKCOUNTER
+#define LLVM_CLANG_GR_BLOCKCOUNTER
namespace llvm {
class BumpPtrAllocator;
@@ -24,13 +24,15 @@ namespace clang {
class StackFrameContext;
-class GRBlockCounter {
+namespace ento {
+
+class BlockCounter {
void* Data;
- GRBlockCounter(void* D) : Data(D) {}
+ BlockCounter(void* D) : Data(D) {}
public:
- GRBlockCounter() : Data(0) {}
+ BlockCounter() : Data(0) {}
unsigned getNumVisited(const StackFrameContext *CallSite,
unsigned BlockID) const;
@@ -41,8 +43,8 @@ public:
Factory(llvm::BumpPtrAllocator& Alloc);
~Factory();
- GRBlockCounter GetEmptyCounter();
- GRBlockCounter IncrementCount(GRBlockCounter BC,
+ BlockCounter GetEmptyCounter();
+ BlockCounter IncrementCount(BlockCounter BC,
const StackFrameContext *CallSite,
unsigned BlockID);
};
@@ -50,6 +52,8 @@ public:
friend class Factory;
};
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
index 136a29da5f2a..22c202749ba7 100644
--- a/include/clang/Checker/PathSensitive/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_CHECKER
-#define LLVM_CLANG_ANALYSIS_CHECKER
+#ifndef LLVM_CLANG_GR_CHECKER
+#define LLVM_CLANG_GR_CHECKER
#include "clang/Analysis/Support/SaveAndRestore.h"
-#include "clang/Checker/PathSensitive/GRExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
//===----------------------------------------------------------------------===//
// Checker interface.
@@ -24,13 +24,15 @@
namespace clang {
+namespace ento {
+
class CheckerContext {
ExplodedNodeSet &Dst;
- GRStmtNodeBuilder &B;
- GRExprEngine &Eng;
+ StmtNodeBuilder &B;
+ ExprEngine &Eng;
ExplodedNode *Pred;
SaveAndRestore<bool> OldSink;
- SaveAndRestore<const void*> OldTag;
+ const void *checkerTag;
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
SaveOr OldHasGen;
const GRState *ST;
@@ -39,22 +41,22 @@ class CheckerContext {
public:
bool *respondsToCallback;
public:
- CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder,
- GRExprEngine &eng, ExplodedNode *pred,
+ CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
+ ExprEngine &eng, ExplodedNode *pred,
const void *tag, ProgramPoint::Kind K,
bool *respondsToCB = 0,
const Stmt *stmt = 0, const GRState *st = 0)
: Dst(dst), B(builder), Eng(eng), Pred(pred),
OldSink(B.BuildSinks),
- OldTag(B.Tag, tag),
+ checkerTag(tag),
OldPointKind(B.PointKind, K),
- OldHasGen(B.HasGeneratedNode),
+ OldHasGen(B.hasGeneratedNode),
ST(st), statement(stmt), size(Dst.size()),
respondsToCallback(respondsToCB) {}
~CheckerContext();
- GRExprEngine &getEngine() {
+ ExprEngine &getEngine() {
return Eng;
}
@@ -71,7 +73,7 @@ public:
}
ExplodedNodeSet &getNodeSet() { return Dst; }
- GRStmtNodeBuilder &getNodeBuilder() { return B; }
+ StmtNodeBuilder &getNodeBuilder() { return B; }
ExplodedNode *&getPredecessor() { return Pred; }
const GRState *getState() { return ST ? ST : B.GetState(Pred); }
@@ -87,80 +89,74 @@ public:
return getBugReporter().getSourceManager();
}
- ValueManager &getValueManager() {
- return Eng.getValueManager();
- }
-
- SValuator &getSValuator() {
- return Eng.getSValuator();
+ SValBuilder &getSValBuilder() {
+ return Eng.getSValBuilder();
}
- ExplodedNode *GenerateNode(bool autoTransition = true) {
+ ExplodedNode *generateNode(bool autoTransition = true) {
assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = GenerateNodeImpl(statement, getState(), false);
+ ExplodedNode *N = generateNodeImpl(statement, getState(), false,
+ checkerTag);
if (N && autoTransition)
Dst.Add(N);
return N;
}
- ExplodedNode *GenerateNode(const Stmt *stmt, const GRState *state,
- bool autoTransition = true) {
+ ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
+ bool autoTransition = true, const void *tag = 0) {
assert(state);
- ExplodedNode *N = GenerateNodeImpl(stmt, state, false);
+ ExplodedNode *N = generateNodeImpl(stmt, state, false,
+ tag ? tag : checkerTag);
if (N && autoTransition)
addTransition(N);
return N;
}
- ExplodedNode *GenerateNode(const GRState *state, ExplodedNode *pred,
+ ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
bool autoTransition = true) {
assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = GenerateNodeImpl(statement, state, pred, false);
+ ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
if (N && autoTransition)
addTransition(N);
return N;
}
- ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) {
+ ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
+ const void *tag = 0) {
assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = GenerateNodeImpl(statement, state, false);
+ ExplodedNode *N = generateNodeImpl(statement, state, false,
+ tag ? tag : checkerTag);
if (N && autoTransition)
addTransition(N);
return N;
}
- ExplodedNode *GenerateSink(const Stmt *stmt, const GRState *state = 0) {
- return GenerateNodeImpl(stmt, state ? state : getState(), true);
+ ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
+ return generateNodeImpl(stmt, state ? state : getState(), true,
+ checkerTag);
}
- ExplodedNode *GenerateSink(const GRState *state = 0) {
+ ExplodedNode *generateSink(const GRState *state = 0) {
assert(statement && "Only transitions with statements currently supported");
- return GenerateNodeImpl(statement, state ? state : getState(), true);
+ return generateNodeImpl(statement, state ? state : getState(), true,
+ checkerTag);
}
void addTransition(ExplodedNode *node) {
Dst.Add(node);
}
- void addTransition(const GRState *state) {
+ void addTransition(const GRState *state, const void *tag = 0) {
assert(state);
// If the 'state' is not new, we need to check if the cached state 'ST'
// is new.
if (state != getState() || (ST && ST != B.GetState(Pred)))
// state is new or equals to ST.
- GenerateNode(state, true);
+ generateNode(state, true, tag);
else
Dst.Add(Pred);
}
- // Generate a node with a new program point different from the one that will
- // be created by the GRStmtNodeBuilder.
- void addTransition(const GRState *state, ProgramPoint Loc) {
- ExplodedNode *N = B.generateNode(Loc, state, Pred);
- if (N)
- addTransition(N);
- }
-
void EmitReport(BugReport *R) {
Eng.getBugReporter().EmitReport(R);
}
@@ -170,17 +166,17 @@ public:
}
private:
- ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
- bool markAsSink) {
- ExplodedNode *node = B.generateNode(stmt, state, Pred);
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
+ bool markAsSink, const void *tag) {
+ ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
if (markAsSink && node)
node->markAsSink();
return node;
}
- ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
ExplodedNode *pred, bool markAsSink) {
- ExplodedNode *node = B.generateNode(stmt, state, pred);
+ ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
if (markAsSink && node)
node->markAsSink();
return node;
@@ -189,12 +185,12 @@ private:
class Checker {
private:
- friend class GRExprEngine;
+ friend class ExprEngine;
// FIXME: Remove the 'tag' option.
void GR_Visit(ExplodedNodeSet &Dst,
- GRStmtNodeBuilder &Builder,
- GRExprEngine &Eng,
+ StmtNodeBuilder &Builder,
+ ExprEngine &Eng,
const Stmt *S,
ExplodedNode *Pred, void *tag, bool isPrevisit,
bool& respondsToCallback) {
@@ -207,25 +203,39 @@ private:
_PostVisit(C, S);
}
- bool GR_EvalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
- GRExprEngine &Eng, const ObjCMessageExpr *ME,
+ void GR_visitObjCMessage(ExplodedNodeSet &Dst,
+ StmtNodeBuilder &Builder,
+ ExprEngine &Eng,
+ const ObjCMessage &msg,
+ ExplodedNode *Pred, void *tag, bool isPrevisit) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, 0, msg.getOriginExpr());
+ if (isPrevisit)
+ preVisitObjCMessage(C, msg);
+ else
+ postVisitObjCMessage(C, msg);
+ }
+
+ bool GR_evalNilReceiver(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
+ ExprEngine &Eng, const ObjCMessage &msg,
ExplodedNode *Pred, const GRState *state, void *tag) {
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
- 0, ME, state);
- return EvalNilReceiver(C, ME);
+ 0, msg.getOriginExpr(), state);
+ return evalNilReceiver(C, msg);
}
- bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
- GRExprEngine &Eng, const CallExpr *CE,
+ bool GR_evalCallExpr(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
+ ExprEngine &Eng, const CallExpr *CE,
ExplodedNode *Pred, void *tag) {
CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
0, CE);
- return EvalCallExpr(C, CE);
+ return evalCallExpr(C, CE);
}
// FIXME: Remove the 'tag' option.
void GR_VisitBind(ExplodedNodeSet &Dst,
- GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
+ StmtNodeBuilder &Builder, ExprEngine &Eng,
const Stmt *StoreE, ExplodedNode *Pred, void *tag,
SVal location, SVal val,
bool isPrevisit) {
@@ -237,9 +247,9 @@ private:
}
// FIXME: Remove the 'tag' option.
- void GR_VisitLocation(ExplodedNodeSet &Dst,
- GRStmtNodeBuilder &Builder,
- GRExprEngine &Eng,
+ void GR_visitLocation(ExplodedNodeSet &Dst,
+ StmtNodeBuilder &Builder,
+ ExprEngine &Eng,
const Stmt *S,
ExplodedNode *Pred, const GRState *state,
SVal location,
@@ -247,49 +257,52 @@ private:
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isLoad ? ProgramPoint::PreLoadKind :
ProgramPoint::PreStoreKind, 0, S, state);
- VisitLocation(C, S, location);
+ visitLocation(C, S, location, isLoad);
}
- void GR_EvalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
- GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
+ void GR_evalDeadSymbols(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
+ ExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
SymbolReaper &SymReaper, void *tag) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
- EvalDeadSymbols(C, SymReaper);
+ evalDeadSymbols(C, SymReaper);
}
public:
virtual ~Checker();
virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
- virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
+ virtual void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {}
+ virtual void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {}
+ virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
+ bool isLoad) {}
virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
SVal location, SVal val) {}
- virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
- virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
- GRExprEngine &Eng) {}
+ virtual void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
+ virtual void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
+ ExprEngine &Eng) {}
virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
- virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
- GRExprEngine &Eng,
+ virtual void VisitBranchCondition(BranchNodeBuilder &Builder,
+ ExprEngine &Eng,
const Stmt *Condition, void *tag) {}
- virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
+ virtual bool evalNilReceiver(CheckerContext &C, ObjCMessage msg) {
return false;
}
- virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
+ virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE) {
return false;
}
- virtual const GRState *EvalAssume(const GRState *state, SVal Cond,
+ virtual const GRState *evalAssume(const GRState *state, SVal Cond,
bool Assumption, bool *respondsToCallback) {
*respondsToCallback = false;
return state;
}
- virtual bool WantsRegionChangeUpdate(const GRState *state) { return false; }
+ virtual bool wantsRegionChangeUpdate(const GRState *state) { return false; }
virtual const GRState *EvalRegionChanges(const GRState *state,
const MemRegion * const *Begin,
@@ -300,8 +313,11 @@ public:
}
virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
- GRExprEngine &Eng) {}
+ ExprEngine &Eng) {}
};
+
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/CheckerHelpers.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
index ea3c842ffc1f..12547e0969a1 100644
--- a/include/clang/Checker/PathSensitive/CheckerHelpers.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -11,13 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
-#define LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
+#ifndef LLVM_CLANG_GR_PATHSENSITIVE_CHECKERHELPERS
+#define LLVM_CLANG_GR_PATHSENSITIVE_CHECKERHELPERS
#include "clang/AST/Stmt.h"
namespace clang {
+namespace ento {
+
bool containsMacro(const Stmt *S);
bool containsEnum(const Stmt *S);
bool containsStaticLocal(const Stmt *S);
@@ -26,8 +28,7 @@ template <class T> bool containsStmt(const Stmt *S) {
if (isa<T>(S))
return true;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
+ for (Stmt::const_child_range I = S->children(); I; ++I)
if (const Stmt *child = *I)
if (containsStmt<T>(child))
return true;
@@ -35,6 +36,8 @@ template <class T> bool containsStmt(const Stmt *S) {
return false;
}
-}
+} // end GR namespace
+
+} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/CheckerVisitor.def b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def
index 2edc4a37b7eb..9b3c263e7d53 100644
--- a/include/clang/Checker/PathSensitive/CheckerVisitor.def
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def
@@ -21,17 +21,28 @@
PREVISIT(ArraySubscriptExpr, Stmt)
PREVISIT(BinaryOperator, Stmt)
-PREVISIT(CallExpr, Stmt)
-PREVISIT(CXXOperatorCallExpr, CallExpr)
+PREVISIT(CallExpr, GenericCall)
+PREVISIT(CompoundAssignOperator, BinaryOperator)
+PREVISIT(CStyleCastExpr, CastExpr)
+PREVISIT(CXXConstCastExpr, CastExpr)
+PREVISIT(CXXDynamicCastExpr, CastExpr)
+PREVISIT(CXXFunctionalCastExpr, CastExpr)
+PREVISIT(CXXOperatorCallExpr, GenericCall)
+PREVISIT(CXXMemberCallExpr, GenericCall)
+PREVISIT(CXXReinterpretCastExpr, CastExpr)
+PREVISIT(CXXStaticCastExpr, CastExpr)
PREVISIT(DeclStmt, Stmt)
-PREVISIT(ObjCMessageExpr, Stmt)
+PREVISIT(ImplicitCastExpr, CastExpr)
+PREVISIT(ObjCAtSynchronizedStmt, Stmt)
PREVISIT(ReturnStmt, Stmt)
POSTVISIT(BlockExpr, Stmt)
POSTVISIT(BinaryOperator, Stmt)
-POSTVISIT(CallExpr, Stmt)
-POSTVISIT(CXXOperatorCallExpr, CallExpr)
-POSTVISIT(ObjCMessageExpr, Stmt)
+POSTVISIT(CallExpr, GenericCall)
+POSTVISIT(CompoundAssignOperator, BinaryOperator)
+POSTVISIT(CXXOperatorCallExpr, GenericCall)
+POSTVISIT(CXXMemberCallExpr, GenericCall)
+POSTVISIT(ObjCIvarRefExpr, Stmt)
#undef PREVISIT
#undef POSTVISIT
diff --git a/include/clang/Checker/PathSensitive/CheckerVisitor.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h
index e2ba89bca1b8..dc76c9604741 100644
--- a/include/clang/Checker/PathSensitive/CheckerVisitor.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h
@@ -11,12 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_CHECKERVISITOR
-#define LLVM_CLANG_ANALYSIS_CHECKERVISITOR
-#include "clang/Checker/PathSensitive/Checker.h"
+#ifndef LLVM_CLANG_GR_CHECKERVISITOR
+#define LLVM_CLANG_GR_CHECKERVISITOR
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
namespace clang {
+namespace ento {
+
//===----------------------------------------------------------------------===//
// Checker visitor interface. Used by subclasses of Checker to specify their
// own checker visitor logic.
@@ -41,22 +43,11 @@ public:
assert(false && "Unsupport statement.");
return;
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass:
- static_cast<ImplClass*>(this)->PreVisitCastExpr(C,
- static_cast<const CastExpr*>(S));
- break;
-
- case Stmt::CompoundAssignOperatorClass:
- static_cast<ImplClass*>(this)->PreVisitBinaryOperator(C,
- static_cast<const BinaryOperator*>(S));
- break;
-
#define PREVISIT(NAME, FALLBACK) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\
break;
-#include "clang/Checker/PathSensitive/CheckerVisitor.def"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def"
}
}
@@ -65,20 +56,23 @@ break;
default:
assert(false && "Unsupport statement.");
return;
- case Stmt::CompoundAssignOperatorClass:
- static_cast<ImplClass*>(this)->PostVisitBinaryOperator(C,
- static_cast<const BinaryOperator*>(S));
- break;
#define POSTVISIT(NAME, FALLBACK) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->\
PostVisit ## NAME(C,static_cast<const NAME*>(S));\
break;
-#include "clang/Checker/PathSensitive/CheckerVisitor.def"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def"
}
}
+ void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE) {
+ static_cast<ImplClass*>(this)->PreVisitStmt(C, CE);
+ }
+ void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE) {
+ static_cast<ImplClass*>(this)->PostVisitStmt(C, CE);
+ }
+
void PreVisitStmt(CheckerContext &C, const Stmt *S) {
*C.respondsToCallback = false;
}
@@ -99,9 +93,11 @@ void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\
void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\
static_cast<ImplClass*>(this)->PostVisit ## FALLBACK(C, S);\
}
-#include "clang/Checker/PathSensitive/CheckerVisitor.def"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def"
};
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index 97535f55bfb9..199b41afefae 100644
--- a/include/clang/Checker/PathSensitive/ConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -11,11 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H
-#define LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H
+#ifndef LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
+#define LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
// FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place.
-#include "clang/Checker/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
namespace llvm {
class APSInt;
@@ -23,21 +23,23 @@ class APSInt;
namespace clang {
+namespace ento {
+
class GRState;
class GRStateManager;
-class GRSubEngine;
+class SubEngine;
class SVal;
class ConstraintManager {
public:
virtual ~ConstraintManager();
- virtual const GRState *Assume(const GRState *state, DefinedSVal Cond,
+ virtual const GRState *assume(const GRState *state, DefinedSVal Cond,
bool Assumption) = 0;
- std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state,
+ std::pair<const GRState*, const GRState*> assumeDual(const GRState *state,
DefinedSVal Cond) {
- return std::make_pair(Assume(state, Cond, true),
- Assume(state, Cond, false));
+ return std::make_pair(assume(state, Cond, true),
+ assume(state, Cond, false));
}
virtual const llvm::APSInt* getSymVal(const GRState *state,
@@ -46,7 +48,7 @@ public:
virtual bool isEqual(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) const = 0;
- virtual const GRState *RemoveDeadBindings(const GRState *state,
+ virtual const GRState *removeDeadBindings(const GRState *state,
SymbolReaper& SymReaper) = 0;
virtual void print(const GRState *state, llvm::raw_ostream& Out,
@@ -57,15 +59,17 @@ public:
/// 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
- /// GRExprEngine to determine if the value should be replaced with a
+ /// 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;
};
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr,
- GRSubEngine &subengine);
+ SubEngine &subengine);
ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr,
- GRSubEngine &subengine);
+ SubEngine &subengine);
+
+} // end GR namespace
} // end clang namespace
diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 216ecac73653..800e63a4cdeb 100644
--- a/include/clang/Checker/PathSensitive/GRCoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -1,4 +1,4 @@
-//==- GRCoreEngine.h - Path-Sensitive Dataflow Engine --------------*- C++ -*-//
+//==- CoreEngine.h - Path-Sensitive Dataflow Engine ----------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
@@ -12,43 +12,45 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_GRENGINE
-#define LLVM_CLANG_ANALYSIS_GRENGINE
+#ifndef LLVM_CLANG_GR_COREENGINE
+#define LLVM_CLANG_GR_COREENGINE
#include "clang/AST/Expr.h"
-#include "clang/Checker/PathSensitive/ExplodedGraph.h"
-#include "clang/Checker/PathSensitive/GRWorkList.h"
-#include "clang/Checker/PathSensitive/GRBlockCounter.h"
-#include "clang/Checker/PathSensitive/GRAuditor.h"
-#include "clang/Checker/PathSensitive/GRSubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "llvm/ADT/OwningPtr.h"
namespace clang {
+namespace ento {
+
//===----------------------------------------------------------------------===//
-/// GRCoreEngine - Implements the core logic of the graph-reachability
+/// CoreEngine - Implements the core logic of the graph-reachability
/// analysis. It traverses the CFG and generates the ExplodedGraph.
/// Program "states" are treated as opaque void pointers.
-/// The template class GRCoreEngine (which subclasses GRCoreEngine)
+/// The template class CoreEngine (which subclasses CoreEngine)
/// provides the matching component to the engine that knows the actual types
/// for states. Note that this engine only dispatches to transfer functions
/// at the statement and block-level. The analyses themselves must implement
/// any transfer function logic and the sub-expression level (if any).
-class GRCoreEngine {
- friend class GRStmtNodeBuilder;
- friend class GRBranchNodeBuilder;
- friend class GRIndirectGotoNodeBuilder;
- friend class GRSwitchNodeBuilder;
- friend class GREndPathNodeBuilder;
- friend class GRCallEnterNodeBuilder;
- friend class GRCallExitNodeBuilder;
+class CoreEngine {
+ friend class StmtNodeBuilder;
+ friend class GenericNodeBuilderImpl;
+ friend class BranchNodeBuilder;
+ friend class IndirectGotoNodeBuilder;
+ friend class SwitchNodeBuilder;
+ friend class EndOfFunctionNodeBuilder;
+ friend class CallEnterNodeBuilder;
+ friend class CallExitNodeBuilder;
public:
typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
BlocksAborted;
private:
- GRSubEngine& SubEngine;
+ SubEngine& SubEng;
/// G - The simulation graph. Each node is a (location,state) pair.
llvm::OwningPtr<ExplodedGraph> G;
@@ -56,25 +58,24 @@ private:
/// WList - A set of queued nodes that need to be processed by the
/// worklist algorithm. It is up to the implementation of WList to decide
/// the order that nodes are processed.
- GRWorkList* WList;
+ WorkList* WList;
- /// BCounterFactory - A factory object for created GRBlockCounter objects.
+ /// BCounterFactory - A factory object for created BlockCounter objects.
/// These are used to record for key nodes in the ExplodedGraph the
/// number of times different CFGBlocks have been visited along a path.
- GRBlockCounter::Factory BCounterFactory;
+ BlockCounter::Factory BCounterFactory;
/// The locations where we stopped doing work because we visited a location
/// too many times.
BlocksAborted blocksAborted;
- void GenerateNode(const ProgramPoint& Loc, const GRState* State,
+ void generateNode(const ProgramPoint& Loc, const GRState* State,
ExplodedNode* Pred);
void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred);
- void HandlePostStmt(const PostStmt& S, const CFGBlock* B,
- unsigned StmtIdx, ExplodedNode *Pred);
+ void HandlePostStmt(const CFGBlock* B, unsigned StmtIdx, ExplodedNode *Pred);
void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B,
ExplodedNode* Pred);
@@ -82,68 +83,26 @@ private:
unsigned Index, ExplodedNode *Pred);
void HandleCallExit(const CallExit &L, ExplodedNode *Pred);
- /// Get the initial state from the subengine.
- const GRState* getInitialState(const LocationContext *InitLoc) {
- return SubEngine.getInitialState(InitLoc);
- }
-
- void ProcessEndPath(GREndPathNodeBuilder& Builder) {
- SubEngine.ProcessEndPath(Builder);
- }
-
- void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& Builder) {
- SubEngine.ProcessStmt(E, Builder);
- }
-
- bool ProcessBlockEntrance(const CFGBlock* Blk, const ExplodedNode *Pred,
- GRBlockCounter BC) {
- return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
- }
-
-
- void ProcessBranch(const Stmt* Condition, const Stmt* Terminator,
- GRBranchNodeBuilder& Builder) {
- SubEngine.ProcessBranch(Condition, Terminator, Builder);
- }
-
-
- void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
- SubEngine.ProcessIndirectGoto(Builder);
- }
-
-
- void ProcessSwitch(GRSwitchNodeBuilder& Builder) {
- SubEngine.ProcessSwitch(Builder);
- }
-
- void ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
- SubEngine.ProcessCallEnter(Builder);
- }
-
- void ProcessCallExit(GRCallExitNodeBuilder &Builder) {
- SubEngine.ProcessCallExit(Builder);
- }
-
private:
- GRCoreEngine(const GRCoreEngine&); // Do not implement.
- GRCoreEngine& operator=(const GRCoreEngine&);
+ CoreEngine(const CoreEngine&); // Do not implement.
+ CoreEngine& operator=(const CoreEngine&);
public:
- /// Construct a GRCoreEngine object to analyze the provided CFG using
+ /// Construct a CoreEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
- GRCoreEngine(GRSubEngine& subengine)
- : SubEngine(subengine), G(new ExplodedGraph()),
- WList(GRWorkList::MakeBFS()),
+ CoreEngine(SubEngine& subengine)
+ : SubEng(subengine), G(new ExplodedGraph()),
+ WList(WorkList::makeBFS()),
BCounterFactory(G->getAllocator()) {}
- /// Construct a GRCoreEngine object to analyze the provided CFG and to
+ /// Construct a CoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
- /// The GRCoreEngine object assumes ownership of 'wlist'.
- GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine)
- : SubEngine(subengine), G(new ExplodedGraph()), WList(wlist),
+ /// The CoreEngine object assumes ownership of 'wlist'.
+ CoreEngine(WorkList* wlist, SubEngine& subengine)
+ : SubEng(subengine), G(new ExplodedGraph()), WList(wlist),
BCounterFactory(G->getAllocator()) {}
- ~GRCoreEngine() {
+ ~CoreEngine() {
delete WList;
}
@@ -166,7 +125,7 @@ public:
bool wasBlockAborted() const { return !blocksAborted.empty(); }
bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
- GRWorkList *getWorkList() const { return WList; }
+ WorkList *getWorkList() const { return WList; }
BlocksAborted::const_iterator blocks_aborted_begin() const {
return blocksAborted.begin();
@@ -176,18 +135,17 @@ public:
}
};
-class GRStmtNodeBuilder {
- GRCoreEngine& Eng;
+class StmtNodeBuilder {
+ CoreEngine& Eng;
const CFGBlock& B;
const unsigned Idx;
ExplodedNode* Pred;
GRStateManager& Mgr;
- GRAuditor* Auditor;
public:
bool PurgingDeadSymbols;
bool BuildSinks;
- bool HasGeneratedNode;
+ bool hasGeneratedNode;
ProgramPoint::Kind PointKind;
const void *Tag;
@@ -200,21 +158,21 @@ public:
void GenerateAutoTransition(ExplodedNode* N);
public:
- GRStmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N,
- GRCoreEngine* e, GRStateManager &mgr);
+ StmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N,
+ CoreEngine* e, GRStateManager &mgr);
- ~GRStmtNodeBuilder();
+ ~StmtNodeBuilder();
- ExplodedNode* getBasePredecessor() const { return Pred; }
+ ExplodedNode* getPredecessor() const { return Pred; }
// FIXME: This should not be exposed.
- GRWorkList *getWorkList() { return Eng.WList; }
+ WorkList *getWorkList() { return Eng.WList; }
void SetCleanedState(const GRState* St) {
CleanedState = St;
}
- GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+ BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
unsigned getCurrentBlockCount() const {
return getBlockCounter().getNumVisited(
@@ -223,28 +181,29 @@ public:
}
ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) {
- HasGeneratedNode = true;
+ hasGeneratedNode = true;
return generateNodeInternal(PP, St, Pred);
}
ExplodedNode* generateNode(const Stmt *S, const GRState *St,
- ExplodedNode *Pred, ProgramPoint::Kind K) {
- HasGeneratedNode = true;
+ ExplodedNode *Pred, ProgramPoint::Kind K,
+ const void *tag = 0) {
+ hasGeneratedNode = true;
if (PurgingDeadSymbols)
K = ProgramPoint::PostPurgeDeadSymbolsKind;
- return generateNodeInternal(S, St, Pred, K, Tag);
+ return generateNodeInternal(S, St, Pred, K, tag ? tag : Tag);
}
ExplodedNode* generateNode(const Stmt *S, const GRState *St,
- ExplodedNode *Pred) {
- return generateNode(S, St, Pred, PointKind);
+ ExplodedNode *Pred, const void *tag = 0) {
+ return generateNode(S, St, Pred, PointKind, tag);
}
ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State,
ExplodedNode* Pred) {
- HasGeneratedNode = true;
+ hasGeneratedNode = true;
return generateNodeInternal(PP, State, Pred);
}
@@ -259,7 +218,13 @@ public:
/// getStmt - Return the current block-level expression associated with
/// this builder.
- const Stmt* getStmt() const { return B[Idx]; }
+ const Stmt* getStmt() const {
+ CFGStmt CS = B[Idx].getAs<CFGStmt>();
+ if (CS)
+ return CS.getStmt();
+ else
+ return 0;
+ }
/// getBlock - Return the CFGBlock associated with the block-level expression
/// of this builder.
@@ -267,10 +232,8 @@ public:
unsigned getIndex() const { return Idx; }
- void setAuditor(GRAuditor* A) { Auditor = A; }
-
const GRState* GetState(ExplodedNode* Pred) const {
- if (Pred == getBasePredecessor())
+ if (Pred == getPredecessor())
return CleanedState;
else
return Pred->getState();
@@ -294,8 +257,8 @@ public:
}
};
-class GRBranchNodeBuilder {
- GRCoreEngine& Eng;
+class BranchNodeBuilder {
+ CoreEngine& Eng;
const CFGBlock* Src;
const CFGBlock* DstT;
const CFGBlock* DstF;
@@ -310,19 +273,19 @@ class GRBranchNodeBuilder {
bool InFeasibleFalse;
public:
- GRBranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT,
- const CFGBlock* dstF, ExplodedNode* pred, GRCoreEngine* e)
+ BranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT,
+ const CFGBlock* dstF, ExplodedNode* pred, CoreEngine* e)
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
GeneratedTrue(false), GeneratedFalse(false),
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
- ~GRBranchNodeBuilder();
+ ~BranchNodeBuilder();
ExplodedNode* getPredecessor() const { return Pred; }
const ExplodedGraph& getGraph() const { return *Eng.G; }
- GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+ BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
ExplodedNode* generateNode(const GRState* State, bool branch);
@@ -346,33 +309,33 @@ public:
}
};
-class GRIndirectGotoNodeBuilder {
- GRCoreEngine& Eng;
+class IndirectGotoNodeBuilder {
+ CoreEngine& Eng;
const CFGBlock* Src;
const CFGBlock& DispatchBlock;
const Expr* E;
ExplodedNode* Pred;
public:
- GRIndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
- const Expr* e, const CFGBlock* dispatch, GRCoreEngine* eng)
+ IndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* e, const CFGBlock* dispatch, CoreEngine* eng)
: Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
class iterator {
CFGBlock::const_succ_iterator I;
- friend class GRIndirectGotoNodeBuilder;
+ friend class IndirectGotoNodeBuilder;
iterator(CFGBlock::const_succ_iterator i) : I(i) {}
public:
iterator& operator++() { ++I; return *this; }
bool operator!=(const iterator& X) const { return I != X.I; }
- const LabelStmt* getLabel() const {
- return llvm::cast<LabelStmt>((*I)->getLabel());
+ const LabelDecl *getLabel() const {
+ return llvm::cast<LabelStmt>((*I)->getLabel())->getDecl();
}
- const CFGBlock* getBlock() const {
+ const CFGBlock *getBlock() const {
return *I;
}
};
@@ -388,21 +351,21 @@ public:
const GRState* getState() const { return Pred->State; }
};
-class GRSwitchNodeBuilder {
- GRCoreEngine& Eng;
+class SwitchNodeBuilder {
+ CoreEngine& Eng;
const CFGBlock* Src;
const Expr* Condition;
ExplodedNode* Pred;
public:
- GRSwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
- const Expr* condition, GRCoreEngine* eng)
+ SwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* condition, CoreEngine* eng)
: Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
class iterator {
CFGBlock::const_succ_reverse_iterator I;
- friend class GRSwitchNodeBuilder;
+ friend class SwitchNodeBuilder;
iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
public:
@@ -422,6 +385,10 @@ public:
iterator begin() { return iterator(Src->succ_rbegin()+1); }
iterator end() { return iterator(Src->succ_rend()); }
+ const SwitchStmt *getSwitch() const {
+ return llvm::cast<SwitchStmt>(Src->getTerminator());
+ }
+
ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State);
ExplodedNode* generateDefaultCaseNode(const GRState* State,
@@ -432,25 +399,69 @@ public:
const GRState* getState() const { return Pred->State; }
};
-class GREndPathNodeBuilder {
- GRCoreEngine &Eng;
+class GenericNodeBuilderImpl {
+protected:
+ CoreEngine &engine;
+ ExplodedNode *pred;
+ ProgramPoint pp;
+ llvm::SmallVector<ExplodedNode*, 2> sinksGenerated;
+
+ ExplodedNode *generateNodeImpl(const GRState *state, ExplodedNode *pred,
+ ProgramPoint programPoint, bool asSink);
+
+ GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p)
+ : engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {}
+
+public:
+ bool hasGeneratedNode;
+
+ WorkList &getWorkList() { return *engine.WList; }
+
+ ExplodedNode* getPredecessor() const { return pred; }
+
+ BlockCounter getBlockCounter() const {
+ return engine.WList->getBlockCounter();
+ }
+
+ const llvm::SmallVectorImpl<ExplodedNode*> &sinks() const {
+ return sinksGenerated;
+ }
+};
+
+template <typename PP_T>
+class GenericNodeBuilder : public GenericNodeBuilderImpl {
+public:
+ GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p)
+ : GenericNodeBuilderImpl(eng, pr, p) {}
+
+ ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
+ const void *tag, bool asSink) {
+ return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag),
+ asSink);
+ }
+
+ const PP_T &getProgramPoint() const { return cast<PP_T>(pp); }
+};
+
+class EndOfFunctionNodeBuilder {
+ CoreEngine &Eng;
const CFGBlock& B;
ExplodedNode* Pred;
public:
- bool HasGeneratedNode;
+ bool hasGeneratedNode;
public:
- GREndPathNodeBuilder(const CFGBlock* b, ExplodedNode* N, GRCoreEngine* e)
- : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
+ EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e)
+ : Eng(*e), B(*b), Pred(N), hasGeneratedNode(false) {}
- ~GREndPathNodeBuilder();
+ ~EndOfFunctionNodeBuilder();
- GRWorkList &getWorkList() { return *Eng.WList; }
+ WorkList &getWorkList() { return *Eng.WList; }
ExplodedNode* getPredecessor() const { return Pred; }
- GRBlockCounter getBlockCounter() const {
+ BlockCounter getBlockCounter() const {
return Eng.WList->getBlockCounter();
}
@@ -472,16 +483,17 @@ public:
}
};
-class GRCallEnterNodeBuilder {
- GRCoreEngine &Eng;
+class CallEnterNodeBuilder {
+ CoreEngine &Eng;
const ExplodedNode *Pred;
- // The call site.
+ // The call site. For implicit automatic object dtor, this is the trigger
+ // statement.
const Stmt *CE;
- // The AnalysisContext of the callee.
- AnalysisContext *CalleeCtx;
+ // The context of the callee.
+ const StackFrameContext *CalleeCtx;
// The parent block of the CallExpr.
const CFGBlock *Block;
@@ -490,8 +502,8 @@ class GRCallEnterNodeBuilder {
unsigned Index;
public:
- GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
- const Stmt *s, AnalysisContext *callee,
+ CallEnterNodeBuilder(CoreEngine &eng, const ExplodedNode *pred,
+ const Stmt *s, const StackFrameContext *callee,
const CFGBlock *blk, unsigned idx)
: Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
@@ -503,29 +515,32 @@ public:
const Stmt *getCallExpr() const { return CE; }
- AnalysisContext *getCalleeContext() const { return CalleeCtx; }
+ const StackFrameContext *getCalleeContext() const { return CalleeCtx; }
const CFGBlock *getBlock() const { return Block; }
unsigned getIndex() const { return Index; }
- void GenerateNode(const GRState *state, const LocationContext *LocCtx);
+ void generateNode(const GRState *state);
};
-class GRCallExitNodeBuilder {
- GRCoreEngine &Eng;
+class CallExitNodeBuilder {
+ CoreEngine &Eng;
const ExplodedNode *Pred;
public:
- GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred)
+ CallExitNodeBuilder(CoreEngine &eng, const ExplodedNode *pred)
: Eng(eng), Pred(pred) {}
const ExplodedNode *getPredecessor() const { return Pred; }
const GRState *getState() const { return Pred->getState(); }
- void GenerateNode(const GRState *state);
+ void generateNode(const GRState *state);
};
+
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index 611f5079452a..732a40cb2145 100644
--- a/include/clang/Checker/PathSensitive/Environment.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -11,23 +11,25 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_ENVIRONMENT_H
-#define LLVM_CLANG_ANALYSIS_ENVIRONMENT_H
+#ifndef LLVM_CLANG_GR_ENVIRONMENT_H
+#define LLVM_CLANG_GR_ENVIRONMENT_H
-// For using typedefs in StoreManager. Should find a better place for these
-// typedefs.
-#include "clang/Checker/PathSensitive/Store.h"
-
-#include "clang/Checker/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/ImmutableMap.h"
namespace clang {
-class EnvironmentManager;
-class ValueManager;
class LiveVariables;
+namespace ento {
+
+class EnvironmentManager;
+class SValBuilder;
+/// Environment - An immutable map from Stmts to their current
+/// symbolic values (SVals).
+///
class Environment {
private:
friend class EnvironmentManager;
@@ -41,22 +43,22 @@ private:
Environment(BindingsTy eb)
: ExprBindings(eb) {}
+ SVal lookupExpr(const Stmt* E) const;
+
public:
typedef BindingsTy::iterator iterator;
iterator begin() const { return ExprBindings.begin(); }
iterator end() const { return ExprBindings.end(); }
- SVal LookupExpr(const Stmt* E) const {
- const SVal* X = ExprBindings.lookup(E);
- return X ? *X : UnknownVal();
- }
- SVal GetSVal(const Stmt* Ex, ValueManager& ValMgr) const;
+ /// GetSVal - Fetches the current binding of the expression in the
+ /// Environment.
+ SVal getSVal(const Stmt* Ex, SValBuilder& svalBuilder) const;
/// Profile - Profile the contents of an Environment object for use
/// in a FoldingSet.
- static void Profile(llvm::FoldingSetNodeID& ID, const Environment* E) {
- E->ExprBindings.Profile(ID);
+ static void Profile(llvm::FoldingSetNodeID& ID, const Environment* env) {
+ env->ExprBindings.Profile(ID);
}
/// Profile - Used to profile the contents of this object for inclusion
@@ -80,7 +82,7 @@ public:
~EnvironmentManager() {}
Environment getInitialEnvironment() {
- return Environment(F.GetEmptyMap());
+ return Environment(F.getEmptyMap());
}
/// Bind the value 'V' to the statement 'S'.
@@ -92,11 +94,13 @@ public:
Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location,
SVal V);
- Environment RemoveDeadBindings(Environment Env,
+ Environment removeDeadBindings(Environment Env,
SymbolReaper &SymReaper, const GRState *ST,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
};
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index c875a2308ba3..e5d6876fa6b2 100644
--- a/include/clang/Checker/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -16,8 +16,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
-#define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
+#ifndef LLVM_CLANG_GR_EXPLODEDGRAPH
+#define LLVM_CLANG_GR_EXPLODEDGRAPH
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Analysis/AnalysisContext.h"
@@ -31,11 +31,14 @@
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/Support/Casting.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
namespace clang {
-class GRState;
class CFG;
+
+namespace ento {
+
class ExplodedGraph;
//===----------------------------------------------------------------------===//
@@ -44,14 +47,17 @@ class ExplodedGraph;
// on top of these classes.
//===----------------------------------------------------------------------===//
+// ExplodedNode is not constified all over the engine because we need to add
+// successors to it at any time after creating it.
+
class ExplodedNode : public llvm::FoldingSetNode {
friend class ExplodedGraph;
- friend class GRCoreEngine;
- friend class GRStmtNodeBuilder;
- friend class GRBranchNodeBuilder;
- friend class GRIndirectGotoNodeBuilder;
- friend class GRSwitchNodeBuilder;
- friend class GREndPathNodeBuilder;
+ friend class CoreEngine;
+ friend class StmtNodeBuilder;
+ friend class BranchNodeBuilder;
+ friend class IndirectGotoNodeBuilder;
+ friend class SwitchNodeBuilder;
+ friend class EndOfFunctionNodeBuilder;
class NodeGroup {
enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
@@ -69,7 +75,7 @@ class ExplodedNode : public llvm::FoldingSetNode {
ExplodedNode *getNode() const {
return reinterpret_cast<ExplodedNode*>(getPtr());
}
-
+
public:
NodeGroup() : P(0) {}
@@ -83,6 +89,8 @@ class ExplodedNode : public llvm::FoldingSetNode {
void addNode(ExplodedNode* N, ExplodedGraph &G);
+ void replaceNode(ExplodedNode *node);
+
void setFlag() {
assert(P == 0);
P = AuxFlag;
@@ -109,7 +117,13 @@ class ExplodedNode : public llvm::FoldingSetNode {
public:
explicit ExplodedNode(const ProgramPoint& loc, const GRState* state)
- : Location(loc), State(state) {}
+ : Location(loc), State(state) {
+ const_cast<GRState*>(State)->incrementReferenceCount();
+ }
+
+ ~ExplodedNode() {
+ const_cast<GRState*>(State)->decrementReferenceCount();
+ }
/// getLocation - Returns the edge associated with the given node.
ProgramPoint getLocation() const { return Location; }
@@ -200,6 +214,10 @@ public:
};
static void SetAuditor(Auditor* A);
+
+private:
+ void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
+ void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
};
// FIXME: Is this class necessary?
@@ -216,7 +234,7 @@ public:
class ExplodedGraph {
protected:
- friend class GRCoreEngine;
+ friend class CoreEngine;
// Type definitions.
typedef llvm::SmallVector<ExplodedNode*,2> RootsTy;
@@ -241,6 +259,15 @@ protected:
/// NumNodes - The number of nodes in the graph.
unsigned NumNodes;
+
+ /// A list of recently allocated nodes that can potentially be recycled.
+ void *recentlyAllocatedNodes;
+
+ /// A list of nodes that can be reused.
+ void *freeNodes;
+
+ /// A flag that indicates whether nodes should be recycled.
+ bool reclaimNodes;
public:
/// getNode - Retrieve the node associated with a (Location,State) pair,
@@ -267,10 +294,12 @@ public:
return V;
}
- ExplodedGraph() : NumNodes(0) {}
-
- ~ExplodedGraph() {}
+ ExplodedGraph()
+ : NumNodes(0), recentlyAllocatedNodes(0),
+ freeNodes(0), reclaimNodes(false) {}
+ ~ExplodedGraph();
+
unsigned num_roots() const { return Roots.size(); }
unsigned num_eops() const { return EndNodes.size(); }
@@ -324,6 +353,14 @@ public:
const ExplodedNode* const * NEnd,
InterExplodedGraphMap *M,
llvm::DenseMap<const void*, const void*> *InverseMap) const;
+
+ /// Enable tracking of recently allocated nodes for potential reclamation
+ /// when calling reclaimRecentlyAllocatedNodes().
+ void enableNodeReclamation() { reclaimNodes = true; }
+
+ /// Reclaim "uninteresting" nodes created since the last time this method
+ /// was called.
+ void reclaimRecentlyAllocatedNodes();
};
class ExplodedNodeSet {
@@ -368,13 +405,15 @@ public:
inline const_iterator end() const { return Impl.end(); }
};
+} // end GR namespace
+
} // end clang namespace
// GraphTraits
namespace llvm {
- template<> struct GraphTraits<clang::ExplodedNode*> {
- typedef clang::ExplodedNode NodeType;
+ template<> struct GraphTraits<clang::ento::ExplodedNode*> {
+ typedef clang::ento::ExplodedNode NodeType;
typedef NodeType::succ_iterator ChildIteratorType;
typedef llvm::df_iterator<NodeType*> nodes_iterator;
@@ -399,8 +438,8 @@ namespace llvm {
}
};
- template<> struct GraphTraits<const clang::ExplodedNode*> {
- typedef const clang::ExplodedNode NodeType;
+ template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
+ typedef const clang::ento::ExplodedNode NodeType;
typedef NodeType::const_succ_iterator ChildIteratorType;
typedef llvm::df_iterator<NodeType*> nodes_iterator;
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 5ba0b36b315d..767644a03292 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -1,4 +1,4 @@
-//===-- GRExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=
+//===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -8,41 +8,45 @@
//===----------------------------------------------------------------------===//
//
// This file defines a meta-engine for path-sensitive dataflow analysis that
-// is built on GRCoreEngine, but provides the boilerplate to execute transfer
+// is built on CoreEngine, but provides the boilerplate to execute transfer
// functions and build the ExplodedGraph at the expression level.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE
-#define LLVM_CLANG_ANALYSIS_GREXPRENGINE
+#ifndef LLVM_CLANG_GR_EXPRENGINE
+#define LLVM_CLANG_GR_EXPRENGINE
-#include "clang/Checker/PathSensitive/AnalysisManager.h"
-#include "clang/Checker/PathSensitive/GRSubEngine.h"
-#include "clang/Checker/PathSensitive/GRCoreEngine.h"
-#include "clang/Checker/PathSensitive/GRState.h"
-#include "clang/Checker/PathSensitive/GRSimpleAPICheck.h"
-#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
-#include "clang/Checker/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/Type.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
namespace clang {
+
+class ObjCForCollectionStmt;
+
+namespace ento {
+
class AnalysisManager;
class Checker;
-class ObjCForCollectionStmt;
-class GRExprEngine : public GRSubEngine {
+class ExprEngine : public SubEngine {
AnalysisManager &AMgr;
- GRCoreEngine CoreEngine;
+ CoreEngine Engine;
/// G - the simulation graph.
ExplodedGraph& G;
- /// Builder - The current GRStmtNodeBuilder which is used when building the
+ /// Builder - The current StmtNodeBuilder which is used when building the
/// nodes for a given statement.
- GRStmtNodeBuilder* Builder;
+ StmtNodeBuilder* Builder;
/// StateMgr - Object that manages the data for all created states.
GRStateManager StateMgr;
@@ -50,11 +54,8 @@ class GRExprEngine : public GRSubEngine {
/// SymMgr - Object that manages the symbol information.
SymbolManager& SymMgr;
- /// ValMgr - Object that manages/creates SVals.
- ValueManager &ValMgr;
-
- /// SVator - SValuator object that creates SVals from expressions.
- SValuator &SVator;
+ /// svalBuilder - SValBuilder object that creates SVals from expressions.
+ SValBuilder &svalBuilder;
/// EntryNode - The immediate predecessor node.
ExplodedNode* EntryNode;
@@ -63,8 +64,8 @@ class GRExprEngine : public GRSubEngine {
/// variables and symbols (as determined by a liveness analysis).
const GRState* CleanedState;
- /// CurrentStmt - The current block-level statement.
- const Stmt* CurrentStmt;
+ /// currentStmt - The current block-level statement.
+ const Stmt* currentStmt;
// Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII;
@@ -73,12 +74,10 @@ class GRExprEngine : public GRSubEngine {
Selector* NSExceptionInstanceRaiseSelectors;
Selector RaiseSel;
- llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
-
enum CallbackKind {
PreVisitStmtCallback,
PostVisitStmtCallback,
- ProcessAssumeCallback,
+ processAssumeCallback,
EvalRegionChangesCallback
};
@@ -110,27 +109,18 @@ class GRExprEngine : public GRSubEngine {
/// The BugReporter associated with this engine. It is important that
/// this object be placed at the very end of member variables so that its
- /// destructor is called before the rest of the GRExprEngine is destroyed.
+ /// destructor is called before the rest of the ExprEngine is destroyed.
GRBugReporter BR;
- llvm::OwningPtr<GRTransferFuncs> TF;
-
- class CallExprWLItem {
- public:
- CallExpr::const_arg_iterator I;
- ExplodedNode *N;
-
- CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
- : I(i), N(n) {}
- };
+ llvm::OwningPtr<TransferFuncs> TF;
public:
- GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf);
+ ExprEngine(AnalysisManager &mgr, TransferFuncs *tf);
- ~GRExprEngine();
+ ~ExprEngine();
void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
- CoreEngine.ExecuteWorkList(L, Steps, 0);
+ Engine.ExecuteWorkList(L, Steps, 0);
}
/// Execute the work list with an initial state. Nodes that reaches the exit
@@ -139,7 +129,7 @@ public:
void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
const GRState *InitState,
ExplodedNodeSet &Dst) {
- CoreEngine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
+ Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
}
/// getContext - Return the ASTContext associated with this analysis.
@@ -147,16 +137,16 @@ public:
virtual AnalysisManager &getAnalysisManager() { return AMgr; }
- SValuator &getSValuator() { return SVator; }
+ SValBuilder &getSValBuilder() { return svalBuilder; }
- GRTransferFuncs& getTF() { return *TF; }
+ TransferFuncs& getTF() { return *TF; }
BugReporter& getBugReporter() { return BR; }
- GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
+ StmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
- // FIXME: Remove once GRTransferFuncs is no longer referenced.
- void setTransferFunction(GRTransferFuncs* tf);
+ // FIXME: Remove once TransferFuncs is no longer referenced.
+ void setTransferFunction(TransferFuncs* tf);
/// ViewGraph - Visualize the ExplodedGraph created by executing the
/// simulation.
@@ -186,56 +176,64 @@ public:
return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
}
- void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
- void AddCheck(GRSimpleAPICheck* A);
+ /// processCFGElement - Called by CoreEngine. Used to generate new successor
+ /// nodes by processing the 'effects' of a CFG element.
+ void processCFGElement(const CFGElement E, StmtNodeBuilder& builder);
+
+ void ProcessStmt(const CFGStmt S, StmtNodeBuilder &builder);
+
+ void ProcessInitializer(const CFGInitializer I, StmtNodeBuilder &builder);
- /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
- /// nodes by processing the 'effects' of a block-level statement.
- void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder);
+ void ProcessImplicitDtor(const CFGImplicitDtor D, StmtNodeBuilder &builder);
- /// ProcessBlockEntrance - Called by GRCoreEngine when start processing
- /// a CFGBlock. This method returns true if the analysis should continue
- /// exploring the given path, and false otherwise.
- bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
- GRBlockCounter BC);
+ void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
+ StmtNodeBuilder &builder);
+ void ProcessBaseDtor(const CFGBaseDtor D, StmtNodeBuilder &builder);
+ void ProcessMemberDtor(const CFGMemberDtor D, StmtNodeBuilder &builder);
+ void ProcessTemporaryDtor(const CFGTemporaryDtor D,
+ StmtNodeBuilder &builder);
- /// ProcessBranch - Called by GRCoreEngine. Used to generate successor
+ /// Called by CoreEngine when processing the entrance of a CFGBlock.
+ virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
+ GenericNodeBuilder<BlockEntrance> &nodeBuilder);
+
+ /// ProcessBranch - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- void ProcessBranch(const Stmt* Condition, const Stmt* Term,
- GRBranchNodeBuilder& builder);
+ void processBranch(const Stmt* Condition, const Stmt* Term,
+ BranchNodeBuilder& builder);
- /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
+ /// processIndirectGoto - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
- void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder);
+ void processIndirectGoto(IndirectGotoNodeBuilder& builder);
- /// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
+ /// ProcessSwitch - Called by CoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a switch statement.
- void ProcessSwitch(GRSwitchNodeBuilder& builder);
+ void processSwitch(SwitchNodeBuilder& builder);
- /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
+ /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
- void ProcessEndPath(GREndPathNodeBuilder& builder);
+ void processEndOfFunction(EndOfFunctionNodeBuilder& builder);
/// Generate the entry node of the callee.
- void ProcessCallEnter(GRCallEnterNodeBuilder &builder);
+ void processCallEnter(CallEnterNodeBuilder &builder);
/// Generate the first post callsite node.
- void ProcessCallExit(GRCallExitNodeBuilder &builder);
+ void processCallExit(CallExitNodeBuilder &builder);
- /// Called by GRCoreEngine when the analysis worklist has terminated.
- void ProcessEndWorklist(bool hasWorkRemaining);
+ /// Called by CoreEngine when the analysis worklist has terminated.
+ void processEndWorklist(bool hasWorkRemaining);
- /// EvalAssume - Callback function invoked by the ConstraintManager when
+ /// evalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values.
- const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption);
+ const GRState *processAssume(const GRState *state, SVal cond,bool assumption);
- /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
- /// region change should trigger a ProcessRegionChanges update.
- bool WantsRegionChangeUpdate(const GRState* state);
+ /// wantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a processRegionChanges update.
+ bool wantsRegionChangeUpdate(const GRState* state);
- /// ProcessRegionChanges - Called by GRStateManager whenever a change is made
+ /// processRegionChanges - Called by GRStateManager whenever a change is made
/// to the store. Used to update checkers that track region values.
- const GRState* ProcessRegionChanges(const GRState *state,
+ const GRState* processRegionChanges(const GRState *state,
const MemRegion * const *Begin,
const MemRegion * const *End);
@@ -247,7 +245,7 @@ public:
return StateMgr.getConstraintManager();
}
- // FIXME: Remove when we migrate over to just using ValueManager.
+ // FIXME: Remove when we migrate over to just using SValBuilder.
BasicValueFactory& getBasicVals() {
return StateMgr.getBasicVals();
}
@@ -255,20 +253,18 @@ public:
return StateMgr.getBasicVals();
}
- ValueManager &getValueManager() { return ValMgr; }
- const ValueManager &getValueManager() const { return ValMgr; }
-
// FIXME: Remove when we migrate over to just using ValueManager.
SymbolManager& getSymbolManager() { return SymMgr; }
const SymbolManager& getSymbolManager() const { return SymMgr; }
// Functions for external checking of whether we have unfinished work
- bool wasBlockAborted() const { return CoreEngine.wasBlockAborted(); }
+ bool wasBlockAborted() const { return Engine.wasBlockAborted(); }
+ bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
bool hasWorkRemaining() const {
- return wasBlockAborted() || CoreEngine.getWorkList()->hasWork();
+ return wasBlockAborted() || Engine.getWorkList()->hasWork();
}
- const GRCoreEngine &getCoreEngine() const { return CoreEngine; }
+ const CoreEngine &getCoreEngine() const { return Engine; }
protected:
const GRState* GetState(ExplodedNode* N) {
@@ -286,11 +282,14 @@ public:
void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
CallbackKind Kind);
+ void CheckerVisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, bool isPrevisit);
+
bool CheckerEvalCall(const CallExpr *CE,
ExplodedNodeSet &Dst,
ExplodedNode *Pred);
- void CheckerEvalNilReceiver(const ObjCMessageExpr *ME,
+ void CheckerEvalNilReceiver(const ObjCMessage &msg,
ExplodedNodeSet &Dst,
const GRState *state,
ExplodedNode *Pred);
@@ -303,14 +302,10 @@ public:
/// other functions that handle specific kinds of statements.
void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
- /// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is
- /// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
- /// storage location. Note that not all kinds of expressions has lvalue.
- void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
-
/// VisitArraySubscriptExpr - Transfer function for array accesses.
- void VisitArraySubscriptExpr(const ArraySubscriptExpr* Ex, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr* Ex,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitAsmStmt - Transfer function logic for inline asm.
void VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
@@ -331,35 +326,26 @@ public:
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
/// VisitCall - Transfer function for function calls.
void VisitCall(const CallExpr* CE, ExplodedNode* Pred,
CallExpr::const_arg_iterator AI,
CallExpr::const_arg_iterator AE,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
- ExplodedNodeSet &Dst, bool asLValue);
+ ExplodedNodeSet &Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
- ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
-
- /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
- void VisitDeclRefExpr(const DeclRefExpr* DR, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
- /// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
- void VisitBlockDeclRefExpr(const BlockDeclRefExpr* DR, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
-
+ /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D,
- ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(const DeclStmt* DS, ExplodedNode* Pred,
@@ -383,11 +369,18 @@ public:
/// VisitMemberExpr - Transfer function for member expressions.
void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
- /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
- void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ /// Transfer function logic for ObjCAtSynchronizedStmts.
+ void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ /// Transfer function logic for computing the lvalue of an Objective-C ivar.
+ void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
@@ -400,7 +393,9 @@ public:
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
+ void VisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Src,
+ ExplodedNodeSet& Dst);
/// VisitReturnStmt - Transfer function logic for return statements.
void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred,
@@ -416,25 +411,36 @@ public:
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ ExplodedNodeSet& Dst);
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
-
- void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
+
+ void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+ VisitCXXConstructExpr(expr, 0, Pred, Dst);
+ }
+
+ void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ void VisitCXXDestructor(const CXXDestructorDecl *DD,
+ const MemRegion *Dest, const Stmt *S,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
+ void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
- void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
+ void VisitAggExpr(const Expr *E, const MemRegion *Dest, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Create a C++ temporary object for an rvalue.
@@ -442,87 +448,103 @@ public:
ExplodedNodeSet &Dst);
/// Synthesize CXXThisRegion.
- const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD,
+ const CXXThisRegion *getCXXThisRegion(const CXXRecordDecl *RD,
const StackFrameContext *SFC);
+ const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *decl,
+ const StackFrameContext *frameCtx);
+
/// Evaluate arguments with a work list algorithm.
- void EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
+ void evalArguments(ConstExprIterator AI, ConstExprIterator AE,
const FunctionProtoType *FnType,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ ExplodedNode *Pred, ExplodedNodeSet &Dst,
+ bool FstArgAsLValue = false);
- /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
+ /// Evaluate method call itself. Used for CXXMethodCallExpr and
+ /// CXXOperatorCallExpr.
+ void evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
+ const Expr *ThisExpr, ExplodedNode *Pred,
+ ExplodedNodeSet &Src, ExplodedNodeSet &Dst);
+
+ /// evalEagerlyAssume - 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 evalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
const Expr *Ex);
- SVal EvalMinus(SVal X) {
- return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X;
+ SVal evalMinus(SVal X) {
+ return X.isValid() ? svalBuilder.evalMinus(cast<NonLoc>(X)) : X;
}
- SVal EvalComplement(SVal X) {
- return X.isValid() ? SVator.EvalComplement(cast<NonLoc>(X)) : X;
+ SVal evalComplement(SVal X) {
+ return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X;
}
public:
- SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op,
+ SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
NonLoc L, NonLoc R, QualType T) {
- return SVator.EvalBinOpNN(state, op, L, R, T);
+ return svalBuilder.evalBinOpNN(state, op, L, R, T);
}
- SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op,
+ SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
NonLoc L, SVal R, QualType T) {
- return R.isValid() ? SVator.EvalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
+ return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
}
- SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
+ SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
SVal LHS, SVal RHS, QualType T) {
- return SVator.EvalBinOp(ST, Op, LHS, RHS, T);
+ return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
}
protected:
- void EvalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME,
- ExplodedNode* Pred, const GRState *state) {
- assert (Builder && "GRStmtNodeBuilder must be defined.");
- getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
+ void evalObjCMessage(ExplodedNodeSet& Dst, const ObjCMessage &msg,
+ ExplodedNode* Pred, const GRState *state) {
+ assert (Builder && "StmtNodeBuilder must be defined.");
+ getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state);
}
const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,
bool branchTaken);
- /// 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,
+ /// 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,
const GRState* St, SVal location, SVal Val,
bool atDeclInit = false);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
+ // FIXME: Comment on the meaning of the arguments, when 'St' may not
+ // be the same as Pred->state, and when 'location' may not be the
+ // same as state->getLValue(Ex).
+ /// Simulate a read of the result of Ex.
+ void evalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag = 0,
QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
+ void evalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0);
-private:
- void EvalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
+private:
+ void evalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag,
QualType LoadTy);
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
+ void evalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
const void *tag, bool isLoad);
bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
};
+} // end ento namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h
index 5503412f7e45..18e39d999bb4 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h
@@ -1,4 +1,4 @@
-//===-- GRExprEngineBuilders.h - "Builder" classes for GRExprEngine -*- C++ -*-=
+//===-- ExprEngineBuilders.h - "Builder" classes for ExprEngine ---*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -8,52 +8,53 @@
//===----------------------------------------------------------------------===//
//
// This file defines smart builder "references" which are used to marshal
-// builders between GRExprEngine objects and their related components.
+// builders between ExprEngine objects and their related components.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS
-#define LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS
-#include "clang/Checker/PathSensitive/GRExprEngine.h"
+#ifndef LLVM_CLANG_GR_EXPRENGINE_BUILDERS
+#define LLVM_CLANG_GR_EXPRENGINE_BUILDERS
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/Analysis/Support/SaveAndRestore.h"
namespace clang {
-class GRStmtNodeBuilderRef {
+namespace ento {
+
+class StmtNodeBuilderRef {
ExplodedNodeSet &Dst;
- GRStmtNodeBuilder &B;
- GRExprEngine& Eng;
+ StmtNodeBuilder &B;
+ ExprEngine& Eng;
ExplodedNode* Pred;
const GRState* state;
const Stmt* stmt;
const unsigned OldSize;
const bool AutoCreateNode;
SaveAndRestore<bool> OldSink;
- SaveAndRestore<const void*> OldTag;
SaveOr OldHasGen;
private:
- friend class GRExprEngine;
+ friend class ExprEngine;
- GRStmtNodeBuilderRef(); // do not implement
- void operator=(const GRStmtNodeBuilderRef&); // do not implement
+ StmtNodeBuilderRef(); // do not implement
+ void operator=(const StmtNodeBuilderRef&); // do not implement
- GRStmtNodeBuilderRef(ExplodedNodeSet &dst,
- GRStmtNodeBuilder &builder,
- GRExprEngine& eng,
+ StmtNodeBuilderRef(ExplodedNodeSet &dst,
+ StmtNodeBuilder &builder,
+ ExprEngine& eng,
ExplodedNode* pred,
const GRState *st,
const Stmt* s, bool auto_create_node)
: Dst(dst), B(builder), Eng(eng), Pred(pred),
state(st), stmt(s), OldSize(Dst.size()), AutoCreateNode(auto_create_node),
- OldSink(B.BuildSinks), OldTag(B.Tag), OldHasGen(B.HasGeneratedNode) {}
+ OldSink(B.BuildSinks), OldHasGen(B.hasGeneratedNode) {}
public:
- ~GRStmtNodeBuilderRef() {
+ ~StmtNodeBuilderRef() {
// Handle the case where no nodes where generated. Auto-generate that
// contains the updated state if we aren't generating sinks.
- if (!B.BuildSinks && Dst.size() == OldSize && !B.HasGeneratedNode) {
+ if (!B.BuildSinks && Dst.size() == OldSize && !B.hasGeneratedNode) {
if (AutoCreateNode)
B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state);
else
@@ -72,5 +73,8 @@ public:
}
};
+} // end GR namespace
+
} // end clang namespace
+
#endif
diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h
index d72d63ab3c98..37694da6573c 100644
--- a/include/clang/Checker/PathSensitive/GRState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h
@@ -1,4 +1,4 @@
-//== GRState*h - Path-Sens. "State" for tracking valuues -----*- C++ -*--==//
+//== GRState.h - Path-sensitive "State" for tracking values -----*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
@@ -7,17 +7,18 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines SymbolRef, ExprBindKey, and GRState*
+// This file defines SymbolRef, ExprBindKey, and GRState*.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H
-#define LLVM_CLANG_ANALYSIS_VALUESTATE_H
+#ifndef LLVM_CLANG_GR_VALUESTATE_H
+#define LLVM_CLANG_GR_VALUESTATE_H
-#include "clang/Checker/PathSensitive/ConstraintManager.h"
-#include "clang/Checker/PathSensitive/Environment.h"
-#include "clang/Checker/PathSensitive/Store.h"
-#include "clang/Checker/PathSensitive/ValueManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/Support/Casting.h"
@@ -30,11 +31,14 @@ class raw_ostream;
namespace clang {
class ASTContext;
+
+namespace ento {
+
class GRStateManager;
class Checker;
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&,
- GRSubEngine&);
+ SubEngine&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
//===----------------------------------------------------------------------===//
@@ -52,16 +56,19 @@ template <typename T> struct GRStateTrait {
}
};
-//===----------------------------------------------------------------------===//
-// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to SVals.
-//===----------------------------------------------------------------------===//
-
class GRStateManager;
-/// GRState - This class encapsulates the actual data values for
-/// for a "state" in our symbolic value tracking. It is intended to be
-/// used as a functional object; that is once it is created and made
-/// "persistent" in a FoldingSet its values will never change.
+/// GRState - This class encapsulates:
+///
+/// 1. A mapping from expressions to values (Environment)
+/// 2. A mapping from locations to values (Store)
+/// 3. Constraints on symbolic values (GenericDataMap)
+///
+/// Together these represent the "abstract state" of a program.
+///
+/// GRState is intended to be used as a functional object; that is,
+/// once it is created and made "persistent" in a FoldingSet, its
+/// values will never change.
class GRState : public llvm::FoldingSetNode {
public:
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
@@ -71,60 +78,59 @@ private:
void operator=(const GRState& R) const; // Do not implement.
friend class GRStateManager;
+ friend class ExplodedGraph;
+ friend class ExplodedNode;
- GRStateManager *StateMgr;
- Environment Env;
- Store St;
- GenericDataMap GDM;
+ GRStateManager *stateMgr;
+ Environment Env; // Maps a Stmt to its current SVal.
+ Store store; // Maps a location to its current value.
+ GenericDataMap GDM; // Custom data stored by a client of this class.
+ unsigned refCount;
/// makeWithStore - Return a GRState with the same values as the current
/// state with the exception of using the specified Store.
- const GRState *makeWithStore(Store store) const;
+ const GRState *makeWithStore(const StoreRef &store) const;
+
+ void setStore(const StoreRef &storeRef);
public:
/// This ctor is used when creating the first GRState object.
GRState(GRStateManager *mgr, const Environment& env,
- Store st, GenericDataMap gdm)
- : StateMgr(mgr),
- Env(env),
- St(st),
- GDM(gdm) {}
-
+ StoreRef st, GenericDataMap gdm);
+
/// Copy ctor - We must explicitly define this or else the "Next" ptr
/// in FoldingSetNode will also get copied.
- GRState(const GRState& RHS)
- : llvm::FoldingSetNode(),
- StateMgr(RHS.StateMgr),
- Env(RHS.Env),
- St(RHS.St),
- GDM(RHS.GDM) {}
-
- /// getStateManager - Return the GRStateManager associated with this state.
- GRStateManager &getStateManager() const {
- return *StateMgr;
- }
+ GRState(const GRState& RHS);
+
+ ~GRState();
+
+ /// Return the GRStateManager associated with this state.
+ GRStateManager &getStateManager() const { return *stateMgr; }
+
+ /// Return true if this state is referenced by a persistent ExplodedNode.
+ bool referencedByExplodedNode() const { return refCount > 0; }
/// getEnvironment - Return the environment associated with this state.
/// The environment is the mapping from expressions to values.
const Environment& getEnvironment() const { return Env; }
- /// getStore - Return the store associated with this state. The store
+ /// Return the store associated with this state. The store
/// is a mapping from locations to values.
- Store getStore() const { return St; }
-
- void setStore(Store s) { St = s; }
+ Store getStore() const { return store; }
+
/// getGDM - Return the generic data map associated with this state.
GenericDataMap getGDM() const { return GDM; }
void setGDM(GenericDataMap gdm) { GDM = gdm; }
- /// Profile - Profile the contents of a GRState object for use
- /// in a FoldingSet.
+ /// Profile - Profile the contents of a GRState object for use in a
+ /// FoldingSet. Two GRState objects are considered equal if they
+ /// have the same Environment, Store, and GenericDataMap.
static void Profile(llvm::FoldingSetNodeID& ID, const GRState* V) {
V->Env.Profile(ID);
- ID.AddPointer(V->St);
+ ID.AddPointer(V->store);
V->GDM.Profile(ID);
}
@@ -134,10 +140,6 @@ public:
Profile(ID, this);
}
- SVal LookupExpr(Expr* E) const {
- return Env.LookupExpr(E);
- }
-
BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() const;
@@ -150,36 +152,32 @@ public:
// As constraints gradually accrue on symbolic values, added constraints
// may conflict and indicate that a state is infeasible (as no real values
// could satisfy all the constraints). This is the principal mechanism
- // for modeling path-sensitivity in GRExprEngine/GRState.
+ // for modeling path-sensitivity in ExprEngine/GRState.
//
- // Various "Assume" methods form the interface for adding constraints to
- // symbolic values. A call to "Assume" indicates an assumption being placed
- // on one or symbolic values. Assume methods take the following inputs:
+ // Various "assume" methods form the interface for adding constraints to
+ // symbolic values. A call to 'assume' indicates an assumption being placed
+ // on one or symbolic values. 'assume' methods take the following inputs:
//
// (1) A GRState object representing the current state.
//
- // (2) The assumed constraint (which is specific to a given "Assume" method).
+ // (2) The assumed constraint (which is specific to a given "assume" method).
//
// (3) A binary value "Assumption" that indicates whether the constraint is
// assumed to be true or false.
//
- // The output of "Assume" are two values:
- //
- // (a) "isFeasible" is set to true or false to indicate whether or not
- // the assumption is feasible.
- //
- // (b) A new GRState object with the added constraints.
- //
- // FIXME: (a) should probably disappear since it is redundant with (b).
- // (i.e., (b) could just be set to NULL).
+ // The output of "assume*" is a new GRState object with the added constraints.
+ // If no new state is feasible, NULL is returned.
//
- const GRState *Assume(DefinedOrUnknownSVal cond, bool assumption) const;
-
+ const GRState *assume(DefinedOrUnknownSVal cond, bool assumption) const;
+
+ /// This method assumes both "true" and "false" for 'cond', and
+ /// returns both corresponding states. It's shorthand for doing
+ /// 'assume' twice.
std::pair<const GRState*, const GRState*>
- Assume(DefinedOrUnknownSVal cond) const;
+ assume(DefinedOrUnknownSVal cond) const;
- const GRState *AssumeInBound(DefinedOrUnknownSVal idx,
+ const GRState *assumeInBound(DefinedOrUnknownSVal idx,
DefinedOrUnknownSVal upperBound,
bool assumption) const;
@@ -194,9 +192,7 @@ public:
//==---------------------------------------------------------------------==//
/// BindCompoundLiteral - Return the state that has the bindings currently
- /// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
- /// for the compound literal and 'BegInit' and 'EndInit' represent an
- /// array of initializer values.
+ /// in this state plus the bindings for the CompoundLiteral.
const GRState *bindCompoundLiteral(const CompoundLiteralExpr* CL,
const LocationContext *LC,
SVal V) const;
@@ -222,27 +218,27 @@ public:
const GRState *unbindLoc(Loc LV) const;
- /// InvalidateRegion - Returns the state with bindings for the given region
- /// cleared from the store. See InvalidateRegions.
- const GRState *InvalidateRegion(const MemRegion *R,
+ /// invalidateRegion - Returns the state with bindings for the given region
+ /// cleared from the store. See invalidateRegions.
+ const GRState *invalidateRegion(const MemRegion *R,
const Expr *E, unsigned BlockCount,
StoreManager::InvalidatedSymbols *IS = NULL)
const {
- return InvalidateRegions(&R, &R+1, E, BlockCount, IS, false);
+ return invalidateRegions(&R, &R+1, E, BlockCount, IS, false);
}
- /// InvalidateRegions - Returns the state with bindings for the given regions
+ /// invalidateRegions - Returns the state with bindings for the given regions
/// cleared from the store. The regions are provided as a continuous array
/// from Begin to End. Optionally invalidates global regions as well.
- const GRState *InvalidateRegions(const MemRegion * const *Begin,
+ const GRState *invalidateRegions(const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned BlockCount,
StoreManager::InvalidatedSymbols *IS,
bool invalidateGlobals) const;
- /// EnterStackFrame - Returns the state for entry to the given stack frame,
+ /// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
- const GRState *EnterStackFrame(const StackFrameContext *frame) const;
+ const GRState *enterStackFrame(const StackFrameContext *frame) const;
/// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
@@ -270,12 +266,9 @@ public:
SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
SVal getSVal(Loc LV, QualType T = QualType()) const;
-
- /// Returns a "simplified" SVal bound to the location 'LV' in the state's
- /// store. A simplified SVal will include optimizations such as
- /// if the SVal is a symbol whose value is perfectly constrained then that
- /// constant value is returned instead.
- SVal getSimplifiedSVal(Loc LV, QualType T= QualType()) const;
+
+ /// Returns the "raw" SVal bound to LV before any value simplfication.
+ SVal getRawSVal(Loc LV, QualType T= QualType()) const;
SVal getSVal(const MemRegion* R) const;
@@ -368,6 +361,16 @@ public:
void printStdErr(CFG &C) const;
void printDOT(llvm::raw_ostream& Out, CFG &C) const;
+
+private:
+ /// Increments the number of times this state is referenced by ExplodeNodes.
+ void incrementReferenceCount() { ++refCount; }
+
+ /// Decrement the number of times this state is referenced by ExplodeNodes.
+ void decrementReferenceCount() {
+ assert(refCount > 0);
+ --refCount;
+ }
};
class GRStateSet {
@@ -409,10 +412,10 @@ public:
class GRStateManager {
friend class GRState;
- friend class GRExprEngine; // FIXME: Remove.
+ friend class ExprEngine; // FIXME: Remove.
private:
- /// Eng - The GRSubEngine that owns this state manager.
- GRSubEngine &Eng;
+ /// Eng - The SubEngine that owns this state manager.
+ SubEngine *Eng; /* Can be null. */
EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StoreMgr;
@@ -431,65 +434,86 @@ private:
/// a particular function. This is used to unique states.
llvm::FoldingSet<GRState> StateSet;
- /// ValueMgr - Object that manages the data for all created SVals.
- ValueManager ValueMgr;
+ /// Object that manages the data for all created SVals.
+ llvm::OwningPtr<SValBuilder> svalBuilder;
- /// Alloc - A BumpPtrAllocator to allocate states.
+ /// A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator &Alloc;
+ /// A vector of recently allocated GRStates that can potentially be
+ /// reused.
+ std::vector<GRState *> recentlyAllocatedStates;
+
+ /// A vector of GRStates that we can reuse.
+ std::vector<GRState *> freeStates;
+
public:
GRStateManager(ASTContext& Ctx,
StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc,
- GRSubEngine &subeng)
- : Eng(subeng),
+ SubEngine &subeng)
+ : Eng(&subeng),
EnvMgr(alloc),
GDMFactory(alloc),
- ValueMgr(alloc, Ctx, *this),
+ svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
Alloc(alloc) {
StoreMgr.reset((*CreateStoreManager)(*this));
ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng));
}
+ GRStateManager(ASTContext& Ctx,
+ StoreManagerCreator CreateStoreManager,
+ ConstraintManager* ConstraintManagerPtr,
+ llvm::BumpPtrAllocator& alloc)
+ : Eng(0),
+ EnvMgr(alloc),
+ GDMFactory(alloc),
+ svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
+ Alloc(alloc) {
+ StoreMgr.reset((*CreateStoreManager)(*this));
+ ConstraintMgr.reset(ConstraintManagerPtr);
+ }
+
~GRStateManager();
const GRState *getInitialState(const LocationContext *InitLoc);
- ASTContext &getContext() { return ValueMgr.getContext(); }
- const ASTContext &getContext() const { return ValueMgr.getContext(); }
+ ASTContext &getContext() { return svalBuilder->getContext(); }
+ const ASTContext &getContext() const { return svalBuilder->getContext(); }
BasicValueFactory &getBasicVals() {
- return ValueMgr.getBasicValueFactory();
+ return svalBuilder->getBasicValueFactory();
}
const BasicValueFactory& getBasicVals() const {
- return ValueMgr.getBasicValueFactory();
+ return svalBuilder->getBasicValueFactory();
+ }
+
+ SValBuilder &getSValBuilder() {
+ return *svalBuilder;
}
SymbolManager &getSymbolManager() {
- return ValueMgr.getSymbolManager();
+ return svalBuilder->getSymbolManager();
}
const SymbolManager &getSymbolManager() const {
- return ValueMgr.getSymbolManager();
+ return svalBuilder->getSymbolManager();
}
- ValueManager &getValueManager() { return ValueMgr; }
- const ValueManager &getValueManager() const { return ValueMgr; }
-
llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
MemRegionManager& getRegionManager() {
- return ValueMgr.getRegionManager();
+ return svalBuilder->getRegionManager();
}
const MemRegionManager& getRegionManager() const {
- return ValueMgr.getRegionManager();
+ return svalBuilder->getRegionManager();
}
StoreManager& getStoreManager() { return *StoreMgr; }
ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
- GRSubEngine& getOwningEngine() { return Eng; }
+ SubEngine* getOwningEngine() { return Eng; }
- const GRState* RemoveDeadBindings(const GRState* St,
+ const GRState* removeDeadBindings(const GRState* St,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper);
@@ -514,6 +538,10 @@ public:
}
const GRState* getPersistentState(GRState& Impl);
+
+ /// Periodically called by ExprEngine to recycle GRStates that were
+ /// created but never used for creating an ExplodedNode.
+ void recycleUnusedStates();
//==---------------------------------------------------------------------==//
// Generic Data Map methods.
@@ -608,21 +636,21 @@ inline const VarRegion* GRState::getRegion(const VarDecl *D,
return getStateManager().getRegionManager().getVarRegion(D, LC);
}
-inline const GRState *GRState::Assume(DefinedOrUnknownSVal Cond,
+inline const GRState *GRState::assume(DefinedOrUnknownSVal Cond,
bool Assumption) const {
if (Cond.isUnknown())
return this;
- return getStateManager().ConstraintMgr->Assume(this, cast<DefinedSVal>(Cond),
+ return getStateManager().ConstraintMgr->assume(this, cast<DefinedSVal>(Cond),
Assumption);
}
inline std::pair<const GRState*, const GRState*>
-GRState::Assume(DefinedOrUnknownSVal Cond) const {
+GRState::assume(DefinedOrUnknownSVal Cond) const {
if (Cond.isUnknown())
return std::make_pair(this, this);
- return getStateManager().ConstraintMgr->AssumeDual(this,
+ return getStateManager().ConstraintMgr->assumeDual(this,
cast<DefinedSVal>(Cond));
}
@@ -653,7 +681,9 @@ inline SVal GRState::getLValue(const FieldDecl* D, SVal Base) const {
}
inline SVal GRState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
- return getStateManager().StoreMgr->getLValueElement(ElementType, Idx, Base);
+ if (NonLoc *N = dyn_cast<NonLoc>(&Idx))
+ return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
+ return UnknownVal();
}
inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const {
@@ -661,25 +691,25 @@ inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const {
}
inline SVal GRState::getSVal(const Stmt* Ex) const {
- return Env.GetSVal(Ex, getStateManager().ValueMgr);
+ return Env.getSVal(Ex, *getStateManager().svalBuilder);
}
inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const {
if (const Expr *Ex = dyn_cast<Expr>(S)) {
QualType T = Ex->getType();
- if (Loc::IsLocType(T) || T->isIntegerType())
+ if (Loc::isLocType(T) || T->isIntegerType())
return getSVal(S);
}
return UnknownVal();
}
-inline SVal GRState::getSVal(Loc LV, QualType T) const {
- return getStateManager().StoreMgr->Retrieve(St, LV, T);
+inline SVal GRState::getRawSVal(Loc LV, QualType T) const {
+ return getStateManager().StoreMgr->Retrieve(getStore(), LV, T);
}
inline SVal GRState::getSVal(const MemRegion* R) const {
- return getStateManager().StoreMgr->Retrieve(St, loc::MemRegionVal(R));
+ return getStateManager().StoreMgr->Retrieve(getStore(), loc::MemRegionVal(R));
}
inline BasicValueFactory &GRState::getBasicVals() const {
@@ -755,6 +785,9 @@ CB GRState::scanReachableSymbols(const MemRegion * const *beg,
scanReachableSymbols(beg, end, cb);
return cb;
}
+
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/GRStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
index 5189a1f5aa7e..411441f8fe34 100644
--- a/include/clang/Checker/PathSensitive/GRStateTrait.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
@@ -14,8 +14,8 @@
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H
-#define LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H
+#ifndef LLVM_CLANG_GR_GRSTATETRAIT_H
+#define LLVM_CLANG_GR_GRSTATETRAIT_H
namespace llvm {
class BumpPtrAllocator;
@@ -26,6 +26,8 @@ namespace llvm {
}
namespace clang {
+
+namespace ento {
template <typename T> struct GRStatePartialTrait;
// Partial-specialization for ImmutableMap.
@@ -48,11 +50,11 @@ namespace clang {
return B.lookup(K);
}
static data_type Set(data_type B, key_type K, value_type E,context_type F){
- return F.Add(B, K, E);
+ return F.add(B, K, E);
}
static data_type Remove(data_type B, key_type K, context_type F) {
- return F.Remove(B, K);
+ return F.remove(B, K);
}
static inline context_type MakeContext(void* p) {
@@ -86,11 +88,11 @@ namespace clang {
}
static data_type Add(data_type B, key_type K, context_type F) {
- return F.Add(B, K);
+ return F.add(B, K);
}
static data_type Remove(data_type B, key_type K, context_type F) {
- return F.Remove(B, K);
+ return F.remove(B, K);
}
static bool Contains(data_type B, key_type K) {
@@ -119,7 +121,7 @@ namespace clang {
typedef typename data_type::Factory& context_type;
static data_type Add(data_type L, key_type K, context_type F) {
- return F.Add(K, L);
+ return F.add(K, L);
}
static inline data_type MakeData(void* const* p) {
@@ -143,6 +145,21 @@ namespace clang {
delete (typename data_type::Factory*) Ctx;
}
};
+
+ // Partial specialization for bool.
+ template <> struct GRStatePartialTrait<bool> {
+ typedef bool data_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return (bool) (uintptr_t) p;
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return (void*) (uintptr_t) d;
+ }
+ };
+
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 96f906af28e1..8d19b5199274 100644
--- a/include/clang/Checker/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -13,12 +13,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_MEMREGION_H
-#define LLVM_CLANG_ANALYSIS_MEMREGION_H
+#ifndef LLVM_CLANG_GR_MEMREGION_H
+#define LLVM_CLANG_GR_MEMREGION_H
+#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/Checker/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/FoldingSet.h"
@@ -31,11 +32,14 @@ class raw_ostream;
namespace clang {
-class MemRegionManager;
-class MemSpaceRegion;
class LocationContext;
class StackFrameContext;
-class ValueManager;
+
+namespace ento {
+
+class MemRegionManager;
+class MemSpaceRegion;
+class SValBuilder;
class VarRegion;
class CodeTextRegion;
@@ -93,9 +97,10 @@ public:
VarRegionKind = BEG_DECL_REGIONS,
FieldRegionKind,
ObjCIvarRegionKind,
- CXXObjectRegionKind,
- END_DECL_REGIONS = CXXObjectRegionKind,
- END_TYPED_REGIONS = END_DECL_REGIONS
+ END_DECL_REGIONS = ObjCIvarRegionKind,
+ CXXTempObjectRegionKind,
+ CXXBaseObjectRegionKind,
+ END_TYPED_REGIONS = CXXBaseObjectRegionKind
};
private:
@@ -294,7 +299,7 @@ public:
}
/// getExtent - Returns the size of the region in bytes.
- virtual DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const {
+ virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
return UnknownVal();
}
@@ -329,7 +334,7 @@ public:
bool isBoundable() const { return true; }
- DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
@@ -353,16 +358,20 @@ public:
virtual QualType getLocationType() const {
// FIXME: We can possibly optimize this later to cache this value.
- return getContext().getPointerType(getValueType());
+ QualType T = getValueType();
+ ASTContext &ctx = getContext();
+ if (T->getAs<ObjCObjectType>())
+ return ctx.getObjCObjectPointerType(T);
+ return ctx.getPointerType(getValueType());
}
- QualType getDesugaredValueType() const {
+ QualType getDesugaredValueType(ASTContext &Context) const {
QualType T = getValueType();
- return T.getTypePtr() ? T.getDesugaredType() : T;
+ return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
}
- QualType getDesugaredLocationType() const {
- return getLocationType().getDesugaredType();
+ QualType getDesugaredLocationType(ASTContext &Context) const {
+ return getLocationType().getDesugaredType(Context);
}
bool isBoundable() const { return true; }
@@ -542,7 +551,7 @@ public:
bool isBoundable() const { return true; }
- DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
@@ -578,7 +587,7 @@ public:
return Str->getType();
}
- DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
bool isBoundable() const { return false; }
@@ -639,7 +648,7 @@ public:
const Decl* getDecl() const { return D; }
void Profile(llvm::FoldingSetNodeID& ID) const;
- DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
@@ -725,7 +734,7 @@ public:
return getDecl()->getType();
}
- DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl* FD,
const MemRegion* superRegion) {
@@ -770,14 +779,14 @@ private:
friend class ElementRegion;
const MemRegion *Region;
- int64_t Offset;
+ CharUnits Offset;
- RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
+ RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
: Region(reg), Offset(offset) {}
public:
// FIXME: Eventually support symbolic offsets.
- int64_t getByteOffset() const { return Offset; }
+ CharUnits getOffset() const { return Offset; }
const MemRegion *getRegion() const { return Region; }
void dumpToStream(llvm::raw_ostream& os) const;
@@ -788,9 +797,9 @@ class ElementRegion : public TypedRegion {
friend class MemRegionManager;
QualType ElementType;
- SVal Index;
+ NonLoc Index;
- ElementRegion(QualType elementType, SVal Idx, const MemRegion* sReg)
+ ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
: TypedRegion(sReg, ElementRegionKind),
ElementType(elementType), Index(Idx) {
assert((!isa<nonloc::ConcreteInt>(&Idx) ||
@@ -803,7 +812,7 @@ class ElementRegion : public TypedRegion {
public:
- SVal getIndex() const { return Index; }
+ NonLoc getIndex() const { return Index; }
QualType getValueType() const {
return ElementType;
@@ -825,13 +834,13 @@ public:
};
// C++ temporary object associated with an expression.
-class CXXObjectRegion : public TypedRegion {
+class CXXTempObjectRegion : public TypedRegion {
friend class MemRegionManager;
Expr const *Ex;
- CXXObjectRegion(Expr const *E, MemRegion const *sReg)
- : TypedRegion(sReg, CXXObjectRegionKind), Ex(E) {}
+ CXXTempObjectRegion(Expr const *E, MemRegion const *sReg)
+ : TypedRegion(sReg, CXXTempObjectRegionKind), Ex(E) {}
static void ProfileRegion(llvm::FoldingSetNodeID &ID,
Expr const *E, const MemRegion *sReg);
@@ -841,10 +850,39 @@ public:
return Ex->getType();
}
+ void dumpToStream(llvm::raw_ostream& os) const;
+
void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const MemRegion* R) {
- return R->getKind() == CXXObjectRegionKind;
+ return R->getKind() == CXXTempObjectRegionKind;
+ }
+};
+
+// CXXBaseObjectRegion represents a base object within a C++ object. It is
+// identified by the base class declaration and the region of its parent object.
+class CXXBaseObjectRegion : public TypedRegion {
+ friend class MemRegionManager;
+
+ const CXXRecordDecl *decl;
+
+ CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg)
+ : TypedRegion(sReg, CXXBaseObjectRegionKind), decl(d) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const CXXRecordDecl *decl, const MemRegion *sReg);
+
+public:
+ const CXXRecordDecl *getDecl() const { return decl; }
+
+ QualType getValueType() const;
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ static bool classof(const MemRegion *region) {
+ return region->getKind() == CXXBaseObjectRegionKind;
}
};
@@ -942,7 +980,7 @@ public:
/// getElementRegion - Retrieve the memory region associated with the
/// associated element type, index, and super region.
- const ElementRegion *getElementRegion(QualType elementType, SVal Idx,
+ const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
const MemRegion *superRegion,
ASTContext &Ctx);
@@ -971,8 +1009,19 @@ public:
const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
const MemRegion* superRegion);
- const CXXObjectRegion *getCXXObjectRegion(Expr const *Ex,
- LocationContext const *LC);
+ const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
+ LocationContext const *LC);
+
+ const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl,
+ const MemRegion *superRegion);
+
+ /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
+ /// super region.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
+ const MemRegion *superRegion) {
+ return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion);
+ }
const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
@@ -1024,6 +1073,8 @@ inline ASTContext& MemRegion::getContext() const {
return getMemRegionManager()->getContext();
}
+} // end GR namespace
+
} // end clang namespace
//===----------------------------------------------------------------------===//
@@ -1032,7 +1083,7 @@ inline ASTContext& MemRegion::getContext() const {
namespace llvm {
static inline raw_ostream& operator<<(raw_ostream& os,
- const clang::MemRegion* R) {
+ const clang::ento::MemRegion* R) {
R->dumpToStream(os);
return os;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
new file mode 100644
index 000000000000..710fc6b84f9e
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
@@ -0,0 +1,210 @@
+//===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- 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 ObjCMessage which serves as a common wrapper for ObjC
+// message expressions or implicit messages for loading/storing ObjC properties.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
+#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/AST/ExprObjC.h"
+
+namespace clang {
+namespace ento {
+
+/// \brief Represents both explicit ObjC message expressions and implicit
+/// messages that are sent for handling properties in dot syntax.
+class ObjCMessage {
+ const Expr *MsgOrPropE;
+ const Expr *OriginE;
+ bool IsPropSetter;
+ SVal SetterArgV;
+
+protected:
+ ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
+ : MsgOrPropE(E), OriginE(origE),
+ IsPropSetter(isSetter), SetterArgV(setArgV) { }
+
+public:
+ ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
+
+ ObjCMessage(const ObjCMessageExpr *E)
+ : MsgOrPropE(E), OriginE(E) {
+ assert(E && "should not be initialized with null expression");
+ }
+
+ bool isValid() const { return MsgOrPropE != 0; }
+ bool isInvalid() const { return !isValid(); }
+
+ bool isMessageExpr() const {
+ return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
+ }
+
+ bool isPropertyGetter() const {
+ return isValid() &&
+ isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
+ }
+
+ bool isPropertySetter() const {
+ return isValid() &&
+ isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
+ }
+
+ const Expr *getOriginExpr() const { return OriginE; }
+
+ QualType getType(ASTContext &ctx) const;
+
+ QualType getResultType(ASTContext &ctx) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ if (const ObjCMethodDecl *MD = msgE->getMethodDecl())
+ return MD->getResultType();
+ return getType(ctx);
+ }
+
+ Selector getSelector() const;
+
+ const Expr *getInstanceReceiver() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getInstanceReceiver();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ if (propE->isObjectReceiver())
+ return propE->getBase();
+ return 0;
+ }
+
+ bool isInstanceMessage() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->isInstanceMessage();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ // FIXME: 'super' may be super class.
+ return propE->isObjectReceiver() || propE->isSuperReceiver();
+ }
+
+ const ObjCMethodDecl *getMethodDecl() const;
+
+ const ObjCInterfaceDecl *getReceiverInterface() const;
+
+ SourceLocation getSuperLoc() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getSuperLoc();
+ return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation();
+ }
+
+ SourceRange getSourceRange() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ return MsgOrPropE->getSourceRange();
+ }
+
+ unsigned getNumArgs() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getNumArgs();
+ return isPropertySetter() ? 1 : 0;
+ }
+
+ SVal getArgSVal(unsigned i, const GRState *state) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return state->getSVal(msgE->getArg(i));
+ assert(isPropertySetter());
+ return SetterArgV;
+ }
+
+ QualType getArgType(unsigned i) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getArg(i)->getType();
+ assert(isPropertySetter());
+ return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
+ }
+
+ const Expr *getArgExpr(unsigned i) const;
+
+ SourceRange getArgSourceRange(unsigned i) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const Expr *argE = getArgExpr(i))
+ return argE->getSourceRange();
+ return OriginE->getSourceRange();
+ }
+};
+
+class ObjCPropertyGetter : public ObjCMessage {
+public:
+ ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE)
+ : ObjCMessage(propE, originE, false, SVal()) {
+ assert(propE && originE &&
+ "should not be initialized with null expressions");
+ }
+};
+
+class ObjCPropertySetter : public ObjCMessage {
+public:
+ ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
+ SVal argV)
+ : ObjCMessage(propE, storeE, true, argV) {
+ assert(propE && storeE &&"should not be initialized with null expressions");
+ }
+};
+
+/// \brief Common wrapper for a call expression or an ObjC message, mainly to
+/// provide a common interface for handling their arguments.
+class CallOrObjCMessage {
+ const CallExpr *CallE;
+ ObjCMessage Msg;
+ const GRState *State;
+
+public:
+ CallOrObjCMessage(const CallExpr *callE, const GRState *state)
+ : CallE(callE), State(state) { }
+ CallOrObjCMessage(const ObjCMessage &msg, const GRState *state)
+ : CallE(0), Msg(msg), State(state) { }
+
+ QualType getResultType(ASTContext &ctx) const;
+
+ unsigned getNumArgs() const {
+ if (CallE) return CallE->getNumArgs();
+ return Msg.getNumArgs();
+ }
+
+ SVal getArgSVal(unsigned i) const {
+ assert(i < getNumArgs());
+ if (CallE) return State->getSVal(CallE->getArg(i));
+ return Msg.getArgSVal(i, State);
+ }
+
+ SVal getArgSValAsScalarOrLoc(unsigned i) const;
+
+ const Expr *getArg(unsigned i) const {
+ assert(i < getNumArgs());
+ if (CallE) return CallE->getArg(i);
+ return Msg.getArgExpr(i);
+ }
+
+ SourceRange getArgSourceRange(unsigned i) const {
+ assert(i < getNumArgs());
+ if (CallE) return CallE->getArg(i)->getSourceRange();
+ return Msg.getArgSourceRange(i);
+ }
+};
+
+}
+}
+
+#endif
diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index b81e9c150234..fc2b76e04a66 100644
--- a/include/clang/Checker/PathSensitive/ValueManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -1,4 +1,4 @@
-//== ValueManager.h - Aggregate manager of symbols and SVals ----*- C++ -*--==//
+// SValBuilder.h - Construction of SVals from evaluating expressions -*- C++ -*-
//
// The LLVM Compiler Infrastructure
//
@@ -7,65 +7,102 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines ValueManager, a class that manages symbolic values
-// and SVals created for use by GRExprEngine and related classes. It
-// wraps and owns SymbolManager, MemRegionManager, and BasicValueFactory.
+// This file defines SValBuilder, a class that defines the interface for
+// "symbolical evaluators" which construct an SVal from an expression.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H
-#define LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H
+#ifndef LLVM_CLANG_GR_SVALBUILDER
+#define LLVM_CLANG_GR_SVALBUILDER
-#include "llvm/ADT/OwningPtr.h"
-#include "clang/Checker/PathSensitive/MemRegion.h"
-#include "clang/Checker/PathSensitive/SVals.h"
-#include "clang/Checker/PathSensitive/BasicValueFactory.h"
-#include "clang/Checker/PathSensitive/SymbolManager.h"
-#include "clang/Checker/PathSensitive/SValuator.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-
-namespace llvm { class BumpPtrAllocator; }
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
namespace clang {
-class GRStateManager;
+namespace ento {
-class ValueManager {
+class GRState;
+class SValBuilder {
+protected:
ASTContext &Context;
+
+ /// Manager of APSInt values.
BasicValueFactory BasicVals;
- /// SymMgr - Object that manages the symbol information.
+ /// Manages the creation of symbols.
SymbolManager SymMgr;
- /// SVator - SValuator object that creates SVals from expressions.
- llvm::OwningPtr<SValuator> SVator;
-
+ /// Manages the creation of memory regions.
MemRegionManager MemMgr;
GRStateManager &StateMgr;
+ /// The scalar type to use for array indices.
const QualType ArrayIndexTy;
+
+ /// The width of the scalar type used for array indices.
const unsigned ArrayIndexWidth;
public:
- ValueManager(llvm::BumpPtrAllocator &alloc, ASTContext &context,
- GRStateManager &stateMgr)
- : Context(context), BasicVals(context, alloc),
- SymMgr(context, BasicVals, alloc),
- MemMgr(context, alloc), StateMgr(stateMgr),
- ArrayIndexTy(context.IntTy),
- ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {
- // FIXME: Generalize later.
- SVator.reset(clang::CreateSimpleSValuator(*this));
- }
+ // FIXME: Make these protected again one RegionStoreManager correctly
+ // handles loads from differening bound value types.
+ virtual SVal evalCastNL(NonLoc val, QualType castTy) = 0;
+ virtual SVal evalCastL(Loc val, QualType castTy) = 0;
- // Accessors to submanagers.
+public:
+ SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
+ GRStateManager &stateMgr)
+ : Context(context), BasicVals(context, alloc),
+ SymMgr(context, BasicVals, alloc),
+ MemMgr(context, alloc),
+ StateMgr(stateMgr),
+ ArrayIndexTy(context.IntTy),
+ ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
+
+ virtual ~SValBuilder() {}
+
+ SVal evalCast(SVal V, QualType castTy, QualType originalType);
+
+ virtual SVal evalMinus(NonLoc val) = 0;
+
+ virtual SVal evalComplement(NonLoc val) = 0;
+
+ virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode Op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
+
+ virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode Op,
+ Loc lhs, Loc rhs, QualType resultTy) = 0;
+
+ virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode Op,
+ Loc lhs, NonLoc rhs, QualType resultTy) = 0;
+
+ /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
+ /// (integer) value, that value is returned. Otherwise, returns NULL.
+ virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V) = 0;
+
+ SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
+ SVal L, SVal R, QualType T);
+
+ DefinedOrUnknownSVal evalEQ(const GRState *ST, DefinedOrUnknownSVal L,
+ DefinedOrUnknownSVal R);
ASTContext &getContext() { return Context; }
const ASTContext &getContext() const { return Context; }
GRStateManager &getStateManager() { return StateMgr; }
+
+ QualType getConditionType() const {
+ return getContext().IntTy;
+ }
+
+ QualType getArrayIndexType() const {
+ return ArrayIndexTy;
+ }
BasicValueFactory &getBasicValueFactory() { return BasicVals; }
const BasicValueFactory &getBasicValueFactory() const { return BasicVals; }
@@ -73,8 +110,6 @@ public:
SymbolManager &getSymbolManager() { return SymMgr; }
const SymbolManager &getSymbolManager() const { return SymMgr; }
- SValuator &getSValuator() { return *SVator.get(); }
-
MemRegionManager &getRegionManager() { return MemMgr; }
const MemRegionManager &getRegionManager() const { return MemMgr; }
@@ -137,9 +172,8 @@ public:
I->getType()->isUnsignedIntegerType()));
}
- nonloc::ConcreteInt makeIntVal(const CXXBoolLiteralExpr *E) {
- return E->getValue() ? nonloc::ConcreteInt(BasicVals.getValue(1, 1, true))
- : nonloc::ConcreteInt(BasicVals.getValue(0, 1, true));
+ nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *E) {
+ return makeTruthVal(E->getValue());
}
nonloc::ConcreteInt makeIntVal(const llvm::APSInt& V) {
@@ -155,7 +189,7 @@ public:
}
DefinedSVal makeIntVal(uint64_t X, QualType T) {
- if (Loc::IsLocType(T))
+ if (Loc::isLocType(T))
return loc::ConcreteInt(BasicVals.getValue(X, T));
return nonloc::ConcreteInt(BasicVals.getValue(X, T));
@@ -183,11 +217,11 @@ public:
NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType T);
- NonLoc makeTruthVal(bool b, QualType T) {
+ nonloc::ConcreteInt makeTruthVal(bool b, QualType T) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T));
}
- NonLoc makeTruthVal(bool b) {
+ nonloc::ConcreteInt makeTruthVal(bool b) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
}
@@ -203,14 +237,22 @@ public:
return loc::MemRegionVal(R);
}
- Loc makeLoc(const AddrLabelExpr* E) {
+ Loc makeLoc(const AddrLabelExpr *E) {
return loc::GotoLabel(E->getLabel());
}
Loc makeLoc(const llvm::APSInt& V) {
return loc::ConcreteInt(BasicVals.getValue(V));
}
+
};
+
+SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
+ ASTContext &context,
+ GRStateManager &stateMgr);
+
+} // end GR namespace
+
} // end clang namespace
-#endif
+#endif
diff --git a/include/clang/Checker/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index cdb338a3f2cc..0d430794e76c 100644
--- a/include/clang/Checker/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -12,10 +12,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H
-#define LLVM_CLANG_ANALYSIS_RVALUE_H
+#ifndef LLVM_CLANG_GR_RVALUE_H
+#define LLVM_CLANG_GR_RVALUE_H
-#include "clang/Checker/PathSensitive/SymbolManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/ImmutableList.h"
@@ -29,6 +29,8 @@ namespace llvm {
namespace clang {
+namespace ento {
+
class CompoundValData;
class LazyCompoundValData;
class GRState;
@@ -37,26 +39,38 @@ class MemRegion;
class TypedRegion;
class MemRegionManager;
class GRStateManager;
-class ValueManager;
+class SValBuilder;
+/// SVal - This represents a symbolic expression, which can be either
+/// an L-value or an R-value.
+///
class SVal {
public:
- enum BaseKind { UndefinedKind, UnknownKind, LocKind, NonLocKind };
+ enum BaseKind {
+ // The enumerators must be representable using 2 bits.
+ UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value)
+ UnknownKind = 1, // for subclass UnknownVal (a void value)
+ LocKind = 2, // for subclass Loc (an L-value)
+ NonLocKind = 3 // for subclass NonLoc (an R-value that's not
+ // an L-value)
+ };
enum { BaseBits = 2, BaseMask = 0x3 };
protected:
const void* Data;
+
+ /// The lowest 2 bits are a BaseKind (0 -- 3).
+ /// The higher bits are an unsigned "kind" value.
unsigned Kind;
-protected:
- SVal(const void* d, bool isLoc, unsigned ValKind)
+ explicit SVal(const void* d, bool isLoc, unsigned ValKind)
: Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
explicit SVal(BaseKind k, const void* D = NULL)
: Data(D), Kind(k) {}
public:
- SVal() : Data(0), Kind(0) {}
+ explicit SVal() : Data(0), Kind(0) {}
~SVal() {}
/// BufferTy - A temporary buffer to hold a set of SVals.
@@ -66,6 +80,8 @@ public:
inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
+ // This method is required for using SVal in a FoldingSetNode. It
+ // extracts a unique signature for this SVal object.
inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getRawKind());
ID.AddPointer(Data);
@@ -194,13 +210,13 @@ public:
class UnknownVal : public DefinedOrUnknownSVal {
public:
- UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
+ explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
static inline bool classof(const SVal *V) {
return V->getBaseKind() == UnknownKind;
}
};
-
+
class DefinedSVal : public DefinedOrUnknownSVal {
private:
// Do not implement. We want calling these methods to be a compiler
@@ -209,7 +225,7 @@ private:
bool isUnknownOrUndef() const;
bool isValid() const;
protected:
- DefinedSVal(const void* d, bool isLoc, unsigned ValKind)
+ explicit DefinedSVal(const void* d, bool isLoc, unsigned ValKind)
: DefinedOrUnknownSVal(d, isLoc, ValKind) {}
public:
// Implement isa<T> support.
@@ -220,7 +236,8 @@ public:
class NonLoc : public DefinedSVal {
protected:
- NonLoc(unsigned SubKind, const void* d) : DefinedSVal(d, false, SubKind) {}
+ explicit NonLoc(unsigned SubKind, const void* d)
+ : DefinedSVal(d, false, SubKind) {}
public:
void dumpToStream(llvm::raw_ostream& Out) const;
@@ -233,21 +250,20 @@ public:
class Loc : public DefinedSVal {
protected:
- Loc(unsigned SubKind, const void* D)
+ explicit Loc(unsigned SubKind, const void* D)
: DefinedSVal(const_cast<void*>(D), true, SubKind) {}
public:
void dumpToStream(llvm::raw_ostream& Out) const;
Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
- Loc& operator=(const Loc& X) { memcpy(this, &X, sizeof(Loc)); return *this; }
// Implement isa<T> support.
static inline bool classof(const SVal* V) {
return V->getBaseKind() == LocKind;
}
- static inline bool IsLocType(QualType T) {
+ static inline bool isLocType(QualType T) {
return T->isAnyPointerType() || T->isBlockPointerType() ||
T->isReferenceType();
}
@@ -282,7 +298,7 @@ public:
class SymExprVal : public NonLoc {
public:
- SymExprVal(const SymExpr *SE)
+ explicit SymExprVal(const SymExpr *SE)
: NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
const SymExpr *getSymbolicExpression() const {
@@ -301,19 +317,19 @@ public:
class ConcreteInt : public NonLoc {
public:
- ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
+ explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
return *static_cast<const llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
- SVal evalBinOp(ValueManager &ValMgr, BinaryOperator::Opcode Op,
+ SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
const ConcreteInt& R) const;
- ConcreteInt evalComplement(ValueManager &ValMgr) const;
+ ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
- ConcreteInt evalMinus(ValueManager &ValMgr) const;
+ ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
// Implement isa<T> support.
static inline bool classof(const SVal* V) {
@@ -327,9 +343,9 @@ public:
};
class LocAsInteger : public NonLoc {
- friend class clang::ValueManager;
+ friend class ento::SValBuilder;
- LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
+ explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
NonLoc(LocAsIntegerKind, &data) {
assert (isa<Loc>(data.first));
}
@@ -361,9 +377,9 @@ public:
};
class CompoundVal : public NonLoc {
- friend class clang::ValueManager;
+ friend class ento::SValBuilder;
- CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
+ explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
public:
const CompoundValData* getValue() const {
@@ -384,9 +400,9 @@ public:
};
class LazyCompoundVal : public NonLoc {
- friend class clang::ValueManager;
+ friend class ento::SValBuilder;
- LazyCompoundVal(const LazyCompoundValData *D)
+ explicit LazyCompoundVal(const LazyCompoundValData *D)
: NonLoc(LazyCompoundValKind, D) {}
public:
const LazyCompoundValData *getCVData() const {
@@ -404,7 +420,7 @@ public:
}
};
-} // end namespace clang::nonloc
+} // end namespace ento::nonloc
//==------------------------------------------------------------------------==//
// Subclasses of Loc.
@@ -412,19 +428,18 @@ public:
namespace loc {
-enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
+enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
class GotoLabel : public Loc {
public:
- GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {}
+ explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
- const LabelStmt* getLabel() const {
- return static_cast<const LabelStmt*>(Data);
+ const LabelDecl *getLabel() const {
+ return static_cast<const LabelDecl*>(Data);
}
static inline bool classof(const SVal* V) {
- return V->getBaseKind() == LocKind &&
- V->getSubKind() == GotoLabelKind;
+ return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
}
static inline bool classof(const Loc* V) {
@@ -435,13 +450,13 @@ public:
class MemRegionVal : public Loc {
public:
- MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
+ explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
const MemRegion* getRegion() const {
return static_cast<const MemRegion*>(Data);
}
- const MemRegion* StripCasts() const;
+ const MemRegion* stripCasts() const;
template <typename REGION>
const REGION* getRegionAs() const {
@@ -469,14 +484,14 @@ public:
class ConcreteInt : public Loc {
public:
- ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
+ explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
return *static_cast<const llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
- SVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+ SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
const ConcreteInt& R) const;
// Implement isa<T> support.
@@ -490,14 +505,40 @@ public:
}
};
-} // end clang::loc namespace
+/// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
+/// "store" of an ObjC property for the dot syntax.
+class ObjCPropRef : public Loc {
+public:
+ explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
+ : Loc(ObjCPropRefKind, E) {}
+
+ const ObjCPropertyRefExpr *getPropRefExpr() const {
+ return static_cast<const ObjCPropertyRefExpr *>(Data);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind &&
+ V->getSubKind() == ObjCPropRefKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == ObjCPropRefKind;
+ }
+};
+
+} // end ento::loc namespace
+} // end GR namespace
+
} // end clang namespace
namespace llvm {
static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
- clang::SVal V) {
+ clang::ento::SVal V) {
V.dumpToStream(os);
return os;
}
+
} // end llvm namespace
+
#endif
diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index a1a41847a206..0251311c27ae 100644
--- a/include/clang/Checker/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -11,30 +11,56 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_STORE_H
-#define LLVM_CLANG_ANALYSIS_STORE_H
+#ifndef LLVM_CLANG_GR_STORE_H
+#define LLVM_CLANG_GR_STORE_H
-#include "clang/Checker/PathSensitive/MemRegion.h"
-#include "clang/Checker/PathSensitive/SVals.h"
-#include "clang/Checker/PathSensitive/ValueManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
namespace clang {
+class Stmt;
+class Expr;
+class ObjCIvarDecl;
+class StackFrameContext;
+
+namespace ento {
+
+/// Store - This opaque type encapsulates an immutable mapping from
+/// locations to values. At a high-level, it represents the symbolic
+/// memory model. Different subclasses of StoreManager may choose
+/// different types to represent the locations and values.
typedef const void* Store;
class GRState;
class GRStateManager;
-class Stmt;
-class Expr;
-class ObjCIvarDecl;
class SubRegionMap;
-class StackFrameContext;
+class StoreManager;
+
+class StoreRef {
+ Store store;
+ StoreManager &mgr;
+public:
+ StoreRef(Store, StoreManager &);
+ StoreRef(const StoreRef &);
+ StoreRef &operator=(StoreRef const &);
+
+ bool operator==(const StoreRef &x) const {
+ assert(&mgr == &x.mgr);
+ return x.store == store;
+ }
+ bool operator!=(const StoreRef &x) const { return !operator==(x); }
+ ~StoreRef();
+
+ Store getStore() const { return store; }
+};
+
class StoreManager {
protected:
- ValueManager &ValMgr;
+ SValBuilder &svalBuilder;
GRStateManager &StateMgr;
/// MRMgr - Manages region objects associated with this StoreManager.
@@ -62,25 +88,22 @@ public:
/// \return A pointer to a GRState object that contains the same bindings as
/// \c state with the addition of having the value specified by \c val bound
/// to the location given for \c loc.
- virtual Store Bind(Store store, Loc loc, SVal val) = 0;
-
- virtual Store BindDefault(Store store, const MemRegion *R, SVal V) {
- return store;
- }
+ virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
- virtual Store Remove(Store St, Loc L) = 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 Store BindCompoundLiteral(Store store,
- const CompoundLiteralExpr* cl,
- const LocationContext *LC, SVal v) = 0;
+ virtual StoreRef BindCompoundLiteral(Store store,
+ 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.
- virtual Store getInitialStore(const LocationContext *InitLoc) = 0;
+ virtual StoreRef getInitialStore(const LocationContext *InitLoc) = 0;
/// getRegionManager - Returns the internal RegionManager object that is
/// used to query and manipulate MemRegion objects.
@@ -92,11 +115,11 @@ public:
virtual SubRegionMap *getSubRegionMap(Store store) = 0;
virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
- return ValMgr.makeLoc(MRMgr.getVarRegion(VD, LC));
+ return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
}
virtual Loc getLValueString(const StringLiteral* S) {
- return ValMgr.makeLoc(MRMgr.getStringRegion(S));
+ return svalBuilder.makeLoc(MRMgr.getStringRegion(S));
}
Loc getLValueCompoundLiteral(const CompoundLiteralExpr* CL,
@@ -112,7 +135,7 @@ public:
return getLValueFieldOrIvar(D, Base);
}
- virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base);
+ virtual SVal getLValueElement(QualType elementType, NonLoc offset, SVal Base);
// FIXME: This should soon be eliminated altogether; clients should deal with
// region extents directly.
@@ -122,10 +145,15 @@ public:
return UnknownVal();
}
- /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
+ /// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
/// conversions between arrays and pointers.
virtual SVal ArrayToPointer(Loc Array) = 0;
+ /// Evaluates DerivedToBase casts.
+ virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) {
+ return UnknownVal();
+ }
+
class CastResult {
const GRState *state;
const MemRegion *region;
@@ -137,30 +165,32 @@ public:
const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
- /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+ /// castRegion - Used by ExprEngine::VisitCast to handle casts from
/// a MemRegion* to a specific location type. 'R' is the region being
/// casted and 'CastToTy' the result type of the cast.
- const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy);
-
-
- /// EvalBinOp - Perform pointer arithmetic.
- virtual SVal EvalBinOp(BinaryOperator::Opcode Op,
- Loc lhs, NonLoc rhs, QualType resultTy) {
- return UnknownVal();
- }
+ const MemRegion *castRegion(const MemRegion *region, QualType CastToTy);
- virtual Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
- SymbolReaper& SymReaper,
+ virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
- virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
+ virtual StoreRef BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
+
+ virtual StoreRef BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
+
+ /// If the StoreManager supports it, increment the reference count of
+ /// the specified Store object.
+ virtual void incrementReferenceCount(Store store) {}
- virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
+ /// If the StoreManager supports it, decrement the reference count of
+ /// the specified Store object. If the reference count hits 0, the memory
+ /// associated with the object is recycled.
+ virtual void decrementReferenceCount(Store store) {}
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
typedef llvm::SmallVector<const MemRegion *, 8> InvalidatedRegions;
- /// InvalidateRegions - Clears out the specified regions from the store,
+ /// invalidateRegions - Clears out the specified regions from the store,
/// marking their values as unknown. Depending on the store, this may also
/// invalidate additional regions that may have changed based on accessing
/// the given regions. Optionally, invalidates non-static globals as well.
@@ -179,18 +209,18 @@ public:
/// invalidated. This should include any regions explicitly invalidated
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
- virtual Store InvalidateRegions(Store store,
- const MemRegion * const *Begin,
- const MemRegion * const *End,
- const Expr *E, unsigned Count,
- InvalidatedSymbols *IS,
- bool invalidateGlobals,
- InvalidatedRegions *Regions) = 0;
-
- /// EnterStackFrame - Let the StoreManager to do something when execution
+ virtual StoreRef invalidateRegions(Store store,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) = 0;
+
+ /// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
- virtual Store EnterStackFrame(const GRState *state,
- const StackFrameContext *frame);
+ virtual StoreRef enterStackFrame(const GRState *state,
+ const StackFrameContext *frame);
virtual void print(Store store, llvm::raw_ostream& Out,
const char* nl, const char *sep) = 0;
@@ -206,19 +236,48 @@ public:
virtual void iterBindings(Store store, BindingsHandler& f) = 0;
protected:
- const MemRegion *MakeElementRegion(const MemRegion *Base,
+ const MemRegion *MakeElementRegion(const MemRegion *baseRegion,
QualType pointeeTy, uint64_t index = 0);
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
/// as another region.
- SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy,
+ SVal CastRetrievedVal(SVal val, const TypedRegion *region, QualType castTy,
bool performTestOnly = true);
private:
- SVal getLValueFieldOrIvar(const Decl* D, SVal Base);
+ SVal getLValueFieldOrIvar(const Decl* decl, SVal base);
};
+
+inline StoreRef::StoreRef(Store store, StoreManager & smgr)
+ : store(store), mgr(smgr) {
+ if (store)
+ mgr.incrementReferenceCount(store);
+}
+
+inline StoreRef::StoreRef(const StoreRef &sr)
+ : store(sr.store), mgr(sr.mgr)
+{
+ if (store)
+ mgr.incrementReferenceCount(store);
+}
+
+inline StoreRef::~StoreRef() {
+ if (store)
+ mgr.decrementReferenceCount(store);
+}
+
+inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {
+ assert(&newStore.mgr == &mgr);
+ if (store != newStore.store) {
+ mgr.incrementReferenceCount(newStore.store);
+ mgr.decrementReferenceCount(store);
+ store = newStore.getStore();
+ }
+ return *this;
+}
+
// FIXME: Do we still need this?
/// SubRegionMap - An abstract interface that represents a queryable map
/// between MemRegion objects and their subregions.
@@ -240,6 +299,9 @@ StoreManager *CreateBasicStoreManager(GRStateManager& StMgr);
StoreManager *CreateRegionStoreManager(GRStateManager& StMgr);
StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr);
StoreManager *CreateFlatStoreManager(GRStateManager &StMgr);
+
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
new file mode 100644
index 000000000000..3d6f9fa15b73
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -0,0 +1,116 @@
+//== SubEngine.h - Interface of the subengine of CoreEngine --------*- 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 interface of a subengine of the CoreEngine.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_GR_SUBENGINE_H
+#define LLVM_CLANG_GR_SUBENGINE_H
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+
+namespace clang {
+
+class CFGBlock;
+class CFGElement;
+class LocationContext;
+class Stmt;
+
+namespace ento {
+
+template <typename PP> class GenericNodeBuilder;
+class AnalysisManager;
+class ExplodedNodeSet;
+class ExplodedNode;
+class GRState;
+class GRStateManager;
+class BlockCounter;
+class StmtNodeBuilder;
+class BranchNodeBuilder;
+class IndirectGotoNodeBuilder;
+class SwitchNodeBuilder;
+class EndOfFunctionNodeBuilder;
+class CallEnterNodeBuilder;
+class CallExitNodeBuilder;
+class MemRegion;
+
+class SubEngine {
+public:
+ virtual ~SubEngine() {}
+
+ virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0;
+
+ virtual AnalysisManager &getAnalysisManager() = 0;
+
+ virtual GRStateManager &getStateManager() = 0;
+
+ /// Called by CoreEngine. Used to generate new successor
+ /// nodes by processing the 'effects' of a block-level statement.
+ virtual void processCFGElement(const CFGElement E, StmtNodeBuilder& builder)=0;
+
+ /// Called by CoreEngine when it starts processing a CFGBlock. The
+ /// 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(ExplodedNodeSet &dstNodes,
+ GenericNodeBuilder<BlockEntrance> &nodeBuilder) = 0;
+
+ /// Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a branch condition.
+ virtual void processBranch(const Stmt* Condition, const Stmt* Term,
+ BranchNodeBuilder& builder) = 0;
+
+ /// Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a computed goto jump.
+ virtual void processIndirectGoto(IndirectGotoNodeBuilder& builder) = 0;
+
+ /// Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a switch statement.
+ virtual void processSwitch(SwitchNodeBuilder& builder) = 0;
+
+ /// Called by CoreEngine. Used to generate end-of-path
+ /// nodes when the control reaches the end of a function.
+ virtual void processEndOfFunction(EndOfFunctionNodeBuilder& builder) = 0;
+
+ // Generate the entry node of the callee.
+ virtual void processCallEnter(CallEnterNodeBuilder &builder) = 0;
+
+ // Generate the first post callsite node.
+ virtual void processCallExit(CallExitNodeBuilder &builder) = 0;
+
+ /// Called by ConstraintManager. Used to call checker-specific
+ /// logic for handling assumptions on symbolic values.
+ virtual const GRState* processAssume(const GRState *state,
+ SVal cond, bool assumption) = 0;
+
+ /// wantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a processRegionChanges update.
+ virtual bool wantsRegionChangeUpdate(const GRState* state) = 0;
+
+ /// processRegionChanges - Called by GRStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ virtual const GRState* processRegionChanges(const GRState* state,
+ const MemRegion* const *Begin,
+ const MemRegion* const *End) = 0;
+
+ inline const GRState* processRegionChange(const GRState* state,
+ const MemRegion* MR) {
+ return processRegionChanges(state, &MR, &MR+1);
+ }
+
+ /// Called by CoreEngine when the analysis worklist is either empty or the
+ // maximum number of analysis steps have been reached.
+ virtual void processEndWorklist(bool hasWorkRemaining) = 0;
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Checker/PathSensitive/SummaryManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
index fd23189491b3..ed878515988a 100644
--- a/include/clang/Checker/PathSensitive/SummaryManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
@@ -12,14 +12,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CHECKER_SUMMARY
-#define LLVM_CLANG_CHECKER_SUMMARY
+#ifndef LLVM_CLANG_GR_SUMMARY
+#define LLVM_CLANG_GR_SUMMARY
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h"
namespace clang {
+namespace ento {
+
namespace summMgr {
@@ -52,6 +54,8 @@ class SummaryManager : SummaryManagerImpl {
};
+} // end GR namespace
+
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 26ed0c1bc06f..ad173bb43536 100644
--- a/include/clang/Checker/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -8,17 +8,17 @@
//===----------------------------------------------------------------------===//
//
// This file defines SymbolManager, a class that manages symbolic values
-// created for use by GRExprEngine and related classes.
+// created for use by ExprEngine and related classes.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ANALYSIS_SYMMGR_H
-#define LLVM_CLANG_ANALYSIS_SYMMGR_H
+#ifndef LLVM_CLANG_GR_SYMMGR_H
+#define LLVM_CLANG_GR_SYMMGR_H
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Analysis/AnalysisContext.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseSet.h"
@@ -29,12 +29,14 @@ class raw_ostream;
namespace clang {
class ASTContext;
+ class StackFrameContext;
+
+namespace ento {
class BasicValueFactory;
class MemRegion;
class SubRegion;
class TypedRegion;
class VarRegion;
- class StackFrameContext;
class SymExpr : public llvm::FoldingSetNode {
public:
@@ -458,7 +460,7 @@ public:
/// isDead - Returns whether or not a symbol has been confirmed dead. This
/// should only be called once all marking of dead symbols has completed.
- /// (For checkers, this means only in the EvalDeadSymbols callback.)
+ /// (For checkers, this means only in the evalDeadSymbols callback.)
bool isDead(SymbolRef sym) const {
return TheDead.count(sym);
}
@@ -473,11 +475,13 @@ public:
virtual ~SymbolVisitor();
};
+} // end GR namespace
+
} // end clang namespace
namespace llvm {
static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
- const clang::SymExpr *SE) {
+ const clang::ento::SymExpr *SE) {
SE->dumpToStream(os);
return os;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
new file mode 100644
index 000000000000..23ed2be8c7a4
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
@@ -0,0 +1,93 @@
+//== TransferFuncs.h - Path-Sens. Transfer Functions 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 TransferFuncs, which provides a base-class that
+// defines an interface for transfer functions used by ExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_TRANSFERFUNCS
+#define LLVM_CLANG_GR_TRANSFERFUNCS
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include <vector>
+
+namespace clang {
+class ObjCMessageExpr;
+
+namespace ento {
+class ExplodedNode;
+class ExplodedNodeSet;
+class EndOfFunctionNodeBuilder;
+class ExprEngine;
+class StmtNodeBuilder;
+class StmtNodeBuilderRef;
+
+class TransferFuncs {
+public:
+ TransferFuncs() {}
+ virtual ~TransferFuncs() {}
+
+ virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
+ virtual void RegisterChecks(ExprEngine& Eng) {}
+
+
+ // Calls.
+
+ virtual void evalCall(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ const CallExpr* CE, SVal L,
+ ExplodedNode* Pred) {}
+
+ virtual void evalObjCMessage(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ ObjCMessage msg,
+ ExplodedNode* Pred,
+ const GRState *state) {}
+
+ // Stores.
+
+ virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val) {}
+
+ // End-of-path and dead symbol notification.
+
+ virtual void evalEndPath(ExprEngine& Engine,
+ EndOfFunctionNodeBuilder& Builder) {}
+
+
+ virtual void evalDeadSymbols(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ ExplodedNode* Pred,
+ const GRState* state,
+ SymbolReaper& SymReaper) {}
+
+ // Return statements.
+ virtual void evalReturn(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ const ReturnStmt* S,
+ ExplodedNode* Pred) {}
+
+ // Assumptions.
+ virtual const GRState* evalAssume(const GRState *state,
+ SVal Cond, bool Assumption) {
+ return state;
+ }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
new file mode 100644
index 000000000000..6bc9fe56f8d6
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -0,0 +1,101 @@
+//==- WorkList.h - Worklist class used by CoreEngine ---------------*- 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 WorkList, a pure virtual class that represents an opaque
+// worklist used by CoreEngine to explore the reachability state space.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_WORKLIST
+#define LLVM_CLANG_GR_WORKLIST
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include <cstddef>
+
+namespace clang {
+
+class CFGBlock;
+
+namespace ento {
+
+class ExplodedNode;
+class ExplodedNodeImpl;
+
+class WorkListUnit {
+ ExplodedNode* node;
+ BlockCounter counter;
+ const CFGBlock* block;
+ unsigned blockIdx; // This is the index of the next statement.
+
+public:
+ WorkListUnit(ExplodedNode* N, BlockCounter C,
+ const CFGBlock* B, unsigned idx)
+ : node(N),
+ counter(C),
+ block(B),
+ blockIdx(idx) {}
+
+ explicit WorkListUnit(ExplodedNode* N, BlockCounter C)
+ : node(N),
+ counter(C),
+ block(NULL),
+ blockIdx(0) {}
+
+ /// Returns the node associated with the worklist unit.
+ ExplodedNode *getNode() const { return node; }
+
+ /// Returns the block counter map associated with the worklist unit.
+ BlockCounter getBlockCounter() const { return counter; }
+
+ /// Returns the CFGblock associated with the worklist unit.
+ const CFGBlock *getBlock() const { return block; }
+
+ /// Return the index within the CFGBlock for the worklist unit.
+ unsigned getIndex() const { return blockIdx; }
+};
+
+class WorkList {
+ BlockCounter CurrentCounter;
+public:
+ virtual ~WorkList();
+ virtual bool hasWork() const = 0;
+
+ virtual void enqueue(const WorkListUnit& U) = 0;
+
+ void enqueue(ExplodedNode *N, const CFGBlock *B, unsigned idx) {
+ enqueue(WorkListUnit(N, CurrentCounter, B, idx));
+ }
+
+ void enqueue(ExplodedNode *N) {
+ enqueue(WorkListUnit(N, CurrentCounter));
+ }
+
+ virtual WorkListUnit dequeue() = 0;
+
+ void setBlockCounter(BlockCounter C) { CurrentCounter = C; }
+ BlockCounter getBlockCounter() const { return CurrentCounter; }
+
+ class Visitor {
+ public:
+ Visitor() {}
+ virtual ~Visitor();
+ virtual bool visit(const WorkListUnit &U) = 0;
+ };
+ virtual bool visitItemsInWorkList(Visitor &V) = 0;
+
+ static WorkList *makeDFS();
+ static WorkList *makeBFS();
+ static WorkList *makeBFSBlockDFSContents();
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
new file mode 100644
index 000000000000..4c3e379f3345
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -0,0 +1,26 @@
+//===-- CheckerRegistration.h - Checker Registration Function-------*- 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_FRONTEND_CHECKERREGISTRATION_H
+#define LLVM_CLANG_SA_FRONTEND_CHECKERREGISTRATION_H
+
+namespace clang {
+ class AnalyzerOptions;
+ class Diagnostic;
+
+namespace ento {
+ class CheckerManager;
+
+CheckerManager *registerCheckers(const AnalyzerOptions &opts,Diagnostic &diags);
+
+} // end ento namespace
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Checker/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index 1c0bbb78ba8c..e3867a2a2478 100644
--- a/include/clang/Checker/FrontendActions.h
+++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -7,13 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_CHECKER_FRONTENDACTIONS_H
-#define LLVM_CLANG_CHECKER_FRONTENDACTIONS_H
+#ifndef LLVM_CLANG_GR_FRONTENDACTIONS_H
+#define LLVM_CLANG_GR_FRONTENDACTIONS_H
#include "clang/Frontend/FrontendAction.h"
namespace clang {
+namespace ento {
+
//===----------------------------------------------------------------------===//
// AST Consumer Actions
//===----------------------------------------------------------------------===//
@@ -24,6 +26,8 @@ protected:
llvm::StringRef InFile);
};
-} // end namespace clang
+} // end GR namespace
+
+} // end namespace clang
#endif