aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
commitbfef399519ca9b8a4b4c6b563253bad7e0eeffe0 (patch)
treedf8df0b0067b381eab470a3b8f28d14a552a6340 /include/clang
parent6a0372513edbc473b538d2f724efac50405d6fef (diff)
downloadsrc-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.tar.gz
src-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.zip
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):vendor/clang/clang-release_34-r197841
Notes
Notes: svn path=/vendor/clang/dist/; revision=259701 svn path=/vendor/clang/clang-release_34-r197841/; revision=259703; tag=vendor/clang/clang-release_34-r197841
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/ARCMigrate/ARCMT.h2
-rw-r--r--include/clang/ARCMigrate/ARCMTActions.h6
-rw-r--r--include/clang/ARCMigrate/FileRemapper.h1
-rw-r--r--include/clang/AST/APValue.h7
-rw-r--r--include/clang/AST/ASTConsumer.h21
-rw-r--r--include/clang/AST/ASTContext.h310
-rw-r--r--include/clang/AST/ASTDiagnostic.h2
-rw-r--r--include/clang/AST/ASTFwd.h28
-rw-r--r--include/clang/AST/ASTImporter.h8
-rw-r--r--include/clang/AST/ASTLambda.h80
-rw-r--r--include/clang/AST/ASTMutationListener.h17
-rw-r--r--include/clang/AST/ASTTypeTraits.h387
-rw-r--r--include/clang/AST/ASTUnresolvedSet.h42
-rw-r--r--include/clang/AST/ASTVector.h55
-rw-r--r--include/clang/AST/Attr.h3
-rw-r--r--include/clang/AST/CXXInheritance.h4
-rw-r--r--include/clang/AST/CanonicalType.h2
-rw-r--r--include/clang/AST/CharUnits.h21
-rw-r--r--include/clang/AST/Comment.h20
-rw-r--r--include/clang/AST/CommentCommandTraits.h5
-rw-r--r--include/clang/AST/CommentCommands.td11
-rw-r--r--include/clang/AST/CommentDiagnostic.h2
-rw-r--r--include/clang/AST/CommentParser.h6
-rw-r--r--include/clang/AST/CommentSema.h9
-rw-r--r--include/clang/AST/Decl.h367
-rw-r--r--include/clang/AST/DeclAccessPair.h9
-rw-r--r--include/clang/AST/DeclBase.h163
-rw-r--r--include/clang/AST/DeclCXX.h1014
-rw-r--r--include/clang/AST/DeclContextInternals.h48
-rw-r--r--include/clang/AST/DeclFriend.h4
-rw-r--r--include/clang/AST/DeclLookups.h22
-rw-r--r--include/clang/AST/DeclObjC.h47
-rw-r--r--include/clang/AST/DeclOpenMP.h26
-rw-r--r--include/clang/AST/DeclTemplate.h691
-rw-r--r--include/clang/AST/DeclarationName.h12
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h2
-rw-r--r--include/clang/AST/Expr.h245
-rw-r--r--include/clang/AST/ExprCXX.h688
-rw-r--r--include/clang/AST/ExprObjC.h23
-rw-r--r--include/clang/AST/ExternalASTSource.h7
-rw-r--r--include/clang/AST/GlobalDecl.h1
-rw-r--r--include/clang/AST/LambdaMangleContext.h38
-rw-r--r--include/clang/AST/Mangle.h117
-rw-r--r--include/clang/AST/MangleNumberingContext.h59
-rw-r--r--include/clang/AST/NestedNameSpecifier.h6
-rw-r--r--include/clang/AST/ParentMap.h5
-rw-r--r--include/clang/AST/PrettyPrinter.h13
-rw-r--r--include/clang/AST/RawCommentList.h31
-rw-r--r--include/clang/AST/RecordLayout.h55
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h330
-rw-r--r--include/clang/AST/Redeclarable.h52
-rw-r--r--include/clang/AST/Stmt.h104
-rw-r--r--include/clang/AST/StmtCXX.h4
-rw-r--r--include/clang/AST/StmtIterator.h32
-rw-r--r--include/clang/AST/StmtObjC.h9
-rw-r--r--include/clang/AST/StmtOpenMP.h528
-rw-r--r--include/clang/AST/StmtVisitor.h36
-rw-r--r--include/clang/AST/TemplateBase.h108
-rw-r--r--include/clang/AST/Type.h113
-rw-r--r--include/clang/AST/TypeLoc.h142
-rw-r--r--include/clang/AST/TypeNodes.def3
-rw-r--r--include/clang/AST/TypeOrdering.h16
-rw-r--r--include/clang/AST/TypeVisitor.h44
-rw-r--r--include/clang/AST/UnresolvedSet.h15
-rw-r--r--include/clang/AST/VTTBuilder.h49
-rw-r--r--include/clang/AST/VTableBuilder.h301
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h21
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h718
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h786
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h189
-rw-r--r--include/clang/ASTMatchers/Dynamic/Diagnostics.h185
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h151
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h75
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h261
-rw-r--r--include/clang/Analysis/Analyses/Consumed.h264
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h8
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafety.h4
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h22
-rw-r--r--include/clang/Analysis/AnalysisContext.h6
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h2
-rw-r--r--include/clang/Analysis/CFG.h90
-rw-r--r--include/clang/Analysis/CallGraph.h4
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h3
-rw-r--r--include/clang/Analysis/Support/BlkExprDeclBitVector.h307
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h107
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtVisitor.h59
-rw-r--r--include/clang/Analysis/Visitors/CFGStmtVisitor.h175
-rw-r--r--include/clang/Basic/ABI.h142
-rw-r--r--include/clang/Basic/Attr.td274
-rw-r--r--include/clang/Basic/AttrKinds.h2
-rw-r--r--include/clang/Basic/Builtins.def471
-rw-r--r--include/clang/Basic/Builtins.h28
-rw-r--r--include/clang/Basic/BuiltinsAArch64.def9
-rw-r--r--include/clang/Basic/BuiltinsARM.def25
-rw-r--r--include/clang/Basic/BuiltinsMips.def712
-rw-r--r--include/clang/Basic/BuiltinsNVPTX.def744
-rw-r--r--include/clang/Basic/BuiltinsX86.def16
-rw-r--r--include/clang/Basic/BuiltinsXCore.def22
-rw-r--r--include/clang/Basic/CapturedStmt.h3
-rw-r--r--include/clang/Basic/DeclNodes.td4
-rw-r--r--include/clang/Basic/Diagnostic.h16
-rw-r--r--include/clang/Basic/Diagnostic.td43
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td16
-rw-r--r--include/clang/Basic/DiagnosticCommentKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td20
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td24
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td7
-rw-r--r--include/clang/Basic/DiagnosticGroups.td102
-rw-r--r--include/clang/Basic/DiagnosticIDs.h34
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td66
-rw-r--r--include/clang/Basic/DiagnosticOptions.def1
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td81
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td760
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td13
-rw-r--r--include/clang/Basic/FileManager.h36
-rw-r--r--include/clang/Basic/FileSystemStatCache.h47
-rw-r--r--include/clang/Basic/IdentifierTable.h82
-rw-r--r--include/clang/Basic/Lambda.h15
-rw-r--r--include/clang/Basic/LangOptions.def33
-rw-r--r--include/clang/Basic/LangOptions.h7
-rw-r--r--include/clang/Basic/Linkage.h40
-rw-r--r--include/clang/Basic/Module.h57
-rw-r--r--include/clang/Basic/ObjCRuntime.h7
-rw-r--r--include/clang/Basic/OpenMPKinds.def31
-rw-r--r--include/clang/Basic/OpenMPKinds.h28
-rw-r--r--include/clang/Basic/OperatorKinds.h2
-rw-r--r--include/clang/Basic/PartialDiagnostic.h21
-rw-r--r--include/clang/Basic/Sanitizers.def23
-rw-r--r--include/clang/Basic/SourceLocation.h2
-rw-r--r--include/clang/Basic/SourceManager.h58
-rw-r--r--include/clang/Basic/Specifiers.h35
-rw-r--r--include/clang/Basic/StmtNodes.td6
-rw-r--r--include/clang/Basic/TargetBuiltins.h14
-rw-r--r--include/clang/Basic/TargetCXXABI.h24
-rw-r--r--include/clang/Basic/TargetInfo.h47
-rw-r--r--include/clang/Basic/TargetOptions.h3
-rw-r--r--include/clang/Basic/TemplateKinds.h3
-rw-r--r--include/clang/Basic/TokenKinds.def17
-rw-r--r--include/clang/Basic/TypeTraits.h1
-rw-r--r--include/clang/Basic/Visibility.h16
-rw-r--r--include/clang/Basic/arm_neon.td888
-rw-r--r--include/clang/CodeGen/CGFunctionInfo.h361
-rw-r--r--include/clang/CodeGen/CodeGenABITypes.h80
-rw-r--r--include/clang/Driver/Action.h14
-rw-r--r--include/clang/Driver/Arg.h133
-rw-r--r--include/clang/Driver/ArgList.h442
-rw-r--r--include/clang/Driver/CC1AsOptions.h13
-rw-r--r--include/clang/Driver/CC1AsOptions.td11
-rw-r--r--include/clang/Driver/CC1Options.td43
-rw-r--r--include/clang/Driver/CLCompatOptions.td255
-rw-r--r--include/clang/Driver/CMakeLists.txt12
-rw-r--r--include/clang/Driver/Compilation.h55
-rw-r--r--include/clang/Driver/Driver.h77
-rw-r--r--include/clang/Driver/DriverDiagnostic.h2
-rw-r--r--include/clang/Driver/Job.h71
-rw-r--r--include/clang/Driver/Makefile8
-rw-r--r--include/clang/Driver/OptParser.td152
-rw-r--r--include/clang/Driver/OptSpecifier.h41
-rw-r--r--include/clang/Driver/OptTable.h161
-rw-r--r--include/clang/Driver/Option.h204
-rw-r--r--include/clang/Driver/Options.h28
-rw-r--r--include/clang/Driver/Options.td535
-rw-r--r--include/clang/Driver/SanitizerArgs.h147
-rw-r--r--include/clang/Driver/Tool.h13
-rw-r--r--include/clang/Driver/ToolChain.h102
-rw-r--r--include/clang/Driver/Types.def2
-rw-r--r--include/clang/Driver/Types.h4
-rw-r--r--include/clang/Driver/Util.h5
-rw-r--r--include/clang/Edit/Commit.h16
-rw-r--r--include/clang/Edit/EditedSource.h9
-rw-r--r--include/clang/Edit/Rewriters.h8
-rw-r--r--include/clang/Format/Format.h286
-rw-r--r--include/clang/Frontend/ASTConsumers.h9
-rw-r--r--include/clang/Frontend/ASTUnit.h14
-rw-r--r--include/clang/Frontend/CodeGenOptions.def14
-rw-r--r--include/clang/Frontend/CodeGenOptions.h12
-rw-r--r--include/clang/Frontend/CompilerInstance.h36
-rw-r--r--include/clang/Frontend/CompilerInvocation.h15
-rw-r--r--include/clang/Frontend/DependencyOutputOptions.h2
-rw-r--r--include/clang/Frontend/FrontendAction.h10
-rw-r--r--include/clang/Frontend/FrontendActions.h10
-rw-r--r--include/clang/Frontend/FrontendDiagnostic.h2
-rw-r--r--include/clang/Frontend/FrontendOptions.h33
-rw-r--r--include/clang/Frontend/TextDiagnostic.h3
-rw-r--r--include/clang/Frontend/Utils.h23
-rw-r--r--include/clang/Index/CommentToXML.h50
-rw-r--r--include/clang/Index/USRGeneration.h54
-rw-r--r--include/clang/Lex/DirectoryLookup.h10
-rw-r--r--include/clang/Lex/HeaderSearch.h65
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h8
-rw-r--r--include/clang/Lex/LexDiagnostic.h2
-rw-r--r--include/clang/Lex/Lexer.h69
-rw-r--r--include/clang/Lex/LiteralSupport.h20
-rw-r--r--include/clang/Lex/MacroInfo.h4
-rw-r--r--include/clang/Lex/ModuleLoader.h4
-rw-r--r--include/clang/Lex/ModuleMap.h86
-rw-r--r--include/clang/Lex/MultipleIncludeOpt.h56
-rw-r--r--include/clang/Lex/PPCallbacks.h95
-rw-r--r--include/clang/Lex/PPConditionalDirectiveRecord.h5
-rw-r--r--include/clang/Lex/PTHLexer.h2
-rw-r--r--include/clang/Lex/PreprocessingRecord.h3
-rw-r--r--include/clang/Lex/Preprocessor.h79
-rw-r--r--include/clang/Lex/PreprocessorLexer.h6
-rw-r--r--include/clang/Lex/Token.h9
-rw-r--r--include/clang/Lex/TokenLexer.h4
-rw-r--r--include/clang/Parse/CMakeLists.txt9
-rw-r--r--include/clang/Parse/Makefile16
-rw-r--r--include/clang/Parse/ParseDiagnostic.h2
-rw-r--r--include/clang/Parse/Parser.h185
-rw-r--r--include/clang/Rewrite/Core/HTMLRewrite.h2
-rw-r--r--include/clang/Rewrite/Core/Rewriter.h17
-rw-r--r--include/clang/Sema/AnalysisBasedWarnings.h1
-rw-r--r--include/clang/Sema/AttributeList.h233
-rw-r--r--include/clang/Sema/CMakeLists.txt5
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h20
-rw-r--r--include/clang/Sema/DeclSpec.h120
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h24
-rw-r--r--include/clang/Sema/ExternalSemaSource.h44
-rw-r--r--include/clang/Sema/IdentifierResolver.h10
-rw-r--r--include/clang/Sema/Initialization.h117
-rw-r--r--include/clang/Sema/Lookup.h119
-rw-r--r--include/clang/Sema/Makefile7
-rw-r--r--include/clang/Sema/MultiplexExternalSemaSource.h30
-rw-r--r--include/clang/Sema/Overload.h77
-rw-r--r--include/clang/Sema/Ownership.h24
-rw-r--r--include/clang/Sema/Scope.h23
-rw-r--r--include/clang/Sema/ScopeInfo.h269
-rw-r--r--include/clang/Sema/Sema.h970
-rw-r--r--include/clang/Sema/SemaDiagnostic.h2
-rw-r--r--include/clang/Sema/SemaInternal.h39
-rw-r--r--include/clang/Sema/SemaLambda.h39
-rw-r--r--include/clang/Sema/Template.h123
-rw-r--r--include/clang/Sema/TemplateDeduction.h122
-rw-r--r--include/clang/Sema/TypoCorrection.h105
-rw-r--r--include/clang/Serialization/ASTBitCodes.h30
-rw-r--r--include/clang/Serialization/ASTReader.h61
-rw-r--r--include/clang/Serialization/ASTWriter.h23
-rw-r--r--include/clang/Serialization/GlobalModuleIndex.h1
-rw-r--r--include/clang/Serialization/ModuleManager.h6
-rw-r--r--include/clang/Serialization/SerializationDiagnostic.h2
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h223
-rw-r--r--include/clang/StaticAnalyzer/Core/Analyses.def12
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h25
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h19
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h11
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h (renamed from include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h)11
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h56
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h63
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h64
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerRegistry.h7
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h18
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h33
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h48
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h22
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h3
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h19
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h2
-rw-r--r--include/clang/Tooling/ArgumentsAdjusters.h6
-rw-r--r--include/clang/Tooling/CommonOptionsParser.h2
-rw-r--r--include/clang/Tooling/CompilationDatabase.h14
-rw-r--r--include/clang/Tooling/Refactoring.h103
-rw-r--r--include/clang/Tooling/ReplacementsYaml.h88
-rw-r--r--include/clang/Tooling/Tooling.h170
267 files changed, 16426 insertions, 6835 deletions
diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h
index c167d3c3192b..196f6c0b731f 100644
--- a/include/clang/ARCMigrate/ARCMT.h
+++ b/include/clang/ARCMigrate/ARCMT.h
@@ -97,6 +97,8 @@ class MigrationProcess {
FileRemapper Remapper;
public:
+ bool HadARCErrors;
+
MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient,
StringRef outputDir = StringRef());
diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h
index 2daaf73065c2..45c8b4ed1a39 100644
--- a/include/clang/ARCMigrate/ARCMTActions.h
+++ b/include/clang/ARCMigrate/ARCMTActions.h
@@ -57,14 +57,12 @@ public:
/// \brief Migrates to modern ObjC syntax.
class ObjCMigrateAction : public WrapperFrontendAction {
std::string MigrateDir;
- bool MigrateLiterals;
- bool MigrateSubscripting;
+ unsigned ObjCMigAction;
FileRemapper Remapper;
CompilerInstance *CompInst;
public:
ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
- bool migrateLiterals,
- bool migrateSubscripting);
+ unsigned migrateAction);
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,StringRef InFile);
diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h
index 94c9e8f31acb..f7677cc8620a 100644
--- a/include/clang/ARCMigrate/FileRemapper.h
+++ b/include/clang/ARCMigrate/FileRemapper.h
@@ -53,7 +53,6 @@ public:
StringRef outputDir = StringRef());
void remap(StringRef filePath, llvm::MemoryBuffer *memBuf);
- void remap(StringRef filePath, StringRef newPath);
void applyMappings(PreprocessorOptions &PPOpts) const;
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index ec8faa4e3524..b4fd2affa653 100644
--- a/include/clang/AST/APValue.h
+++ b/include/clang/AST/APValue.h
@@ -168,6 +168,13 @@ public:
MakeUninit();
}
+ /// \brief Returns whether the object performed allocations.
+ ///
+ /// If APValues are constructed via placement new, \c needsCleanup()
+ /// indicates whether the destructor must be called in order to correctly
+ /// free all allocated memory.
+ bool needsCleanup() const;
+
/// \brief Swaps the contents of this and the given APValue.
void swap(APValue &RHS);
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index ae779436a9da..7b6fa94b2043 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
#define LLVM_CLANG_AST_ASTCONSUMER_H
+#include "llvm/ADT/StringRef.h"
+
namespace clang {
class ASTContext;
class CXXRecordDecl;
@@ -70,6 +72,10 @@ public:
/// can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {}
+ /// \brief This callback is invoked the first time each TagDecl is required to
+ /// be complete.
+ virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {}
+
/// \brief Invoked when a function is implicitly instantiated.
/// Note that at this point point it does not have a body, its body is
/// instantiated at the end of the translation unit and passed to
@@ -86,6 +92,21 @@ public:
/// The default implementation passes it to HandleTopLevelDecl.
virtual void HandleImplicitImportDecl(ImportDecl *D);
+ /// \brief Handle a pragma that appends to Linker Options. Currently this
+ /// only exists to support Microsoft's #pragma comment(linker, "/foo").
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {}
+
+ /// \brief Handle a pragma that emits a mismatch identifier and value to the
+ /// object file for the linker to work with. Currently, this only exists to
+ /// support Microsoft's #pragma detect_mismatch.
+ virtual void HandleDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) {}
+
+ /// \brief Handle a dependent library created by a pragma in the source.
+ /// Currently this only exists to support Microsoft's
+ /// #pragma comment(lib, "/foo").
+ virtual void HandleDependentLibrary(llvm::StringRef Lib) {}
+
/// CompleteTentativeDefinition - Callback invoked at the end of a translation
/// unit to notify the consumer that the given tentative definition should be
/// completed.
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index c5d3337fd22d..f420e85ee146 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -19,11 +19,9 @@
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/LambdaMangleContext.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RawCommentList.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
@@ -47,6 +45,7 @@ namespace llvm {
namespace clang {
class FileManager;
+ class AtomicExpr;
class ASTRecordLayout;
class BlockExpr;
class CharUnits;
@@ -55,9 +54,11 @@ namespace clang {
class ExternalASTSource;
class ASTMutationListener;
class IdentifierTable;
+ class MaterializeTemporaryExpr;
class SelectorTable;
class TargetInfo;
class CXXABI;
+ class MangleNumberingContext;
// Decls
class MangleContext;
class ObjCIvarDecl;
@@ -81,6 +82,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
mutable llvm::FoldingSet<ComplexType> ComplexTypes;
mutable llvm::FoldingSet<PointerType> PointerTypes;
+ mutable llvm::FoldingSet<DecayedType> DecayedTypes;
mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
@@ -146,7 +148,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable TypeInfoMap MemoizedTypeInfo;
/// \brief A cache mapping from CXXRecordDecls to key functions.
- llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions;
+ llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions;
/// \brief Mapping from ObjCContainers to their ObjCImplementations.
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
@@ -163,6 +165,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
llvm::DenseMap<const FunctionDecl*, FunctionDecl*>
ClassScopeSpecializationPattern;
+ /// \brief Mapping from materialized temporaries with static storage duration
+ /// that appear in constant initializers to their evaluated values.
+ llvm::DenseMap<const MaterializeTemporaryExpr*, APValue>
+ MaterializedTemporaryValues;
+
/// \brief Representation of a "canonical" template template parameter that
/// is used in canonical template names.
class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
@@ -190,6 +197,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// \brief The typedef for the __uint128_t type.
mutable TypedefDecl *UInt128Decl;
+
+ /// \brief The typedef for the __float128 stub type.
+ mutable TypeDecl *Float128StubDecl;
/// \brief The typedef for the target specific predefined
/// __builtin_va_list type.
@@ -261,13 +271,30 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// wasting space in the Decl class.
llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs;
- /// \brief Keeps track of the static data member templates from which
- /// static data members of class template specializations were instantiated.
+ /// \brief A mapping from non-redeclarable declarations in modules that were
+ /// merged with other declarations to the canonical declaration that they were
+ /// merged into.
+ llvm::DenseMap<Decl*, Decl*> MergedDecls;
+
+public:
+ /// \brief A type synonym for the TemplateOrInstantiation mapping.
+ typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
+ TemplateOrSpecializationInfo;
+
+private:
+
+ /// \brief A mapping to contain the template or declaration that
+ /// a variable declaration describes or was instantiated from,
+ /// respectively.
///
- /// This data structure stores the mapping from instantiations of static
- /// data members to the static data member representations within the
- /// class template from which they were instantiated along with the kind
- /// of instantiation or specialization (a TemplateSpecializationKind - 1).
+ /// For non-templates, this value will be NULL. For variable
+ /// declarations that describe a variable template, this will be a
+ /// pointer to a VarTemplateDecl. For static data members
+ /// of class template specializations, this will be the
+ /// MemberSpecializationInfo referring to the member variable that was
+ /// instantiated or specialized. Thus, the mapping will keep track of
+ /// the static data member templates from which static data members of
+ /// class template specializations were instantiated.
///
/// Given the following example:
///
@@ -286,8 +313,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// This mapping will contain an entry that maps from the VarDecl for
/// X<int>::value to the corresponding VarDecl for X<T>::value (within the
/// class template X) and will be marked TSK_ImplicitInstantiation.
- llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>
- InstantiatedFromStaticDataMember;
+ llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>
+ TemplateOrInstantiation;
/// \brief Keeps track of the declaration from which a UsingDecl was
/// created during instantiation.
@@ -328,12 +355,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector;
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
- /// \brief Mapping from each declaration context to its corresponding lambda
- /// mangling context.
- llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts;
+ /// \brief Mapping from each declaration context to its corresponding
+ /// mangling numbering context (used for constructs like lambdas which
+ /// need to be consistently numbered for the mangler).
+ llvm::DenseMap<const DeclContext *, MangleNumberingContext *>
+ MangleNumberingContexts;
- llvm::DenseMap<const DeclContext *, unsigned> UnnamedMangleContexts;
- llvm::DenseMap<const TagDecl *, unsigned> UnnamedMangleNumbers;
+ /// \brief Side-table of mangling numbers for declarations which rarely
+ /// need them (like static local vars).
+ llvm::DenseMap<const NamedDecl *, unsigned> MangleNumbers;
/// \brief Mapping that stores parameterIndex values for ParmVarDecls when
/// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
@@ -368,6 +398,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// \brief The logical -> physical address space map.
const LangAS::Map *AddrSpaceMap;
+ /// \brief Address space map mangling must be used with language specific
+ /// address spaces (e.g. OpenCL/CUDA)
+ bool AddrSpaceMapMangling;
+
friend class ASTDeclReader;
friend class ASTReader;
friend class ASTWriter;
@@ -419,22 +453,7 @@ public:
return getParents(ast_type_traits::DynTypedNode::create(Node));
}
- ParentVector getParents(const ast_type_traits::DynTypedNode &Node) {
- assert(Node.getMemoizationData() &&
- "Invariant broken: only nodes that support memoization may be "
- "used in the parent map.");
- if (!AllParents) {
- // We always need to run over the whole translation unit, as
- // hasAncestor can escape any subtree.
- AllParents.reset(
- ParentMapASTVisitor::buildMap(*getTranslationUnitDecl()));
- }
- ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData());
- if (I == AllParents->end()) {
- return ParentVector();
- }
- return I->second;
- }
+ ParentVector getParents(const ast_type_traits::DynTypedNode &Node);
const clang::PrintingPolicy &getPrintingPolicy() const {
return PrintingPolicy;
@@ -451,7 +470,7 @@ public:
return BumpAlloc;
}
- void *Allocate(unsigned Size, unsigned Align = 8) const {
+ void *Allocate(size_t Size, unsigned Align = 8) const {
return BumpAlloc.Allocate(Size, Align);
}
void Deallocate(void *Ptr) const { }
@@ -470,6 +489,19 @@ public:
const TargetInfo &getTargetInfo() const { return *Target; }
+ /// getIntTypeForBitwidth -
+ /// sets integer QualTy according to specified details:
+ /// bitwidth, signed/unsigned.
+ /// Returns empty type if there is no appropriate target types.
+ QualType getIntTypeForBitwidth(unsigned DestWidth,
+ unsigned Signed) const;
+ /// getRealTypeForBitwidth -
+ /// sets floating point QualTy according to specified bitwidth.
+ /// Returns empty type if there is no appropriate target types.
+ QualType getRealTypeForBitwidth(unsigned DestWidth) const;
+
+ bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const;
+
const LangOptions& getLangOpts() const { return LangOpts; }
DiagnosticsEngine &getDiagnostics() const;
@@ -580,7 +612,12 @@ public:
/// preprocessor is not available.
comments::FullComment *getCommentForDecl(const Decl *D,
const Preprocessor *PP) const;
-
+
+ /// Return parsed documentation comment attached to a given declaration.
+ /// Returns NULL if no comment is attached. Does not look at any
+ /// redeclarations of the declaration.
+ comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const;
+
comments::FullComment *cloneFullComment(comments::FullComment *FC,
const Decl *D) const;
@@ -601,9 +638,13 @@ public:
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
/// from which it was instantiated.
+ // FIXME: Remove ?
MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
const VarDecl *Var);
+ TemplateOrSpecializationInfo
+ getTemplateOrSpecializationInfo(const VarDecl *Var);
+
FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD);
void setClassScopeSpecializationPattern(FunctionDecl *FD,
@@ -615,6 +656,9 @@ public:
TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation = SourceLocation());
+ void setTemplateOrSpecializationInfo(VarDecl *Inst,
+ TemplateOrSpecializationInfo TSI);
+
/// \brief If the given using decl \p Inst is an instantiation of a
/// (possibly unresolved) using decl from a template instantiation,
/// return it.
@@ -632,31 +676,6 @@ public:
void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
- /// \brief Return \c true if \p FD is a zero-length bitfield which follows
- /// the non-bitfield \p LastFD.
- bool ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD,
- const FieldDecl *LastFD) const;
-
- /// \brief Return \c true if \p FD is a zero-length bitfield which follows
- /// the bitfield \p LastFD.
- bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD,
- const FieldDecl *LastFD) const;
-
- /// \brief Return \c true if \p FD is a bitfield which follows the bitfield
- /// \p LastFD.
- bool BitfieldFollowsBitfield(const FieldDecl *FD,
- const FieldDecl *LastFD) const;
-
- /// \brief Return \c true if \p FD is not a bitfield which follows the
- /// bitfield \p LastFD.
- bool NonBitfieldFollowsBitfield(const FieldDecl *FD,
- const FieldDecl *LastFD) const;
-
- /// \brief Return \c true if \p FD is a bitfield which follows the
- /// non-bitfield \p LastFD.
- bool BitfieldFollowsNonBitfield(const FieldDecl *FD,
- const FieldDecl *LastFD) const;
-
// Access to the set of methods overridden by the given C++ method.
typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator;
overridden_cxx_method_iterator
@@ -732,7 +751,15 @@ public:
return import_iterator(FirstLocalImport);
}
import_iterator local_import_end() const { return import_iterator(); }
-
+
+ Decl *getPrimaryMergedDecl(Decl *D) {
+ Decl *Result = MergedDecls.lookup(D);
+ return Result ? Result : D;
+ }
+ void setPrimaryMergedDecl(Decl *D, Decl *Primary) {
+ MergedDecls[D] = Primary;
+ }
+
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
@@ -740,7 +767,8 @@ public:
CanQualType VoidTy;
CanQualType BoolTy;
CanQualType CharTy;
- CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ CanQualType WCharTy; // [C++ 3.9.1p5].
+ CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99.
CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions.
CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
@@ -809,6 +837,9 @@ public:
/// \brief Retrieve the declaration for the 128-bit unsigned integer type.
TypedefDecl *getUInt128Decl() const;
+
+ /// \brief Retrieve the declaration for a 128-bit float stub type.
+ TypeDecl *getFloat128StubType() const;
//===--------------------------------------------------------------------===//
// Type Constructors
@@ -884,6 +915,14 @@ public:
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
}
+ /// \brief Return the uniqued reference to the decayed version of the given
+ /// type. Can only be called on array and function types which decay to
+ /// pointer types.
+ QualType getDecayedType(QualType T) const;
+ CanQualType getDecayedType(CanQualType T) const {
+ return CanQualType::CreateUnsafe(getDecayedType((QualType) T));
+ }
+
/// \brief Return the uniqued reference to the atomic type for the specified
/// type.
QualType getAtomicType(QualType T) const;
@@ -1104,7 +1143,7 @@ public:
/// \brief C++11 deduced auto type.
QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
- bool IsDependent = false) const;
+ bool IsDependent) const;
/// \brief C++11 deduction pattern for 'auto' type.
QualType getAutoDeductType() const;
@@ -1130,11 +1169,15 @@ public:
/// <stdint.h>.
CanQualType getUIntMaxType() const;
- /// \brief In C++, this returns the unique wchar_t type. In C99, this
- /// returns a type compatible with the type defined in <stddef.h> as defined
- /// by the target.
+ /// \brief Return the unique wchar_t type available in C++ (and available as
+ /// __wchar_t as a Microsoft extension).
QualType getWCharType() const { return WCharTy; }
+ /// \brief Return the type of wide characters. In C++, this returns the
+ /// unique wchar_t type. In C99, this returns a type compatible with the type
+ /// defined in <stddef.h> as defined by the target.
+ QualType getWideCharType() const { return WideCharTy; }
+
/// \brief Return the type of "signed wchar_t".
///
/// Used when in C++, as a GCC extension.
@@ -1607,14 +1650,17 @@ public:
/// \pre \p D must not be a bitfield type, as bitfields do not have a valid
/// alignment.
///
- /// If \p RefAsPointee, references are treated like their underlying type
- /// (for alignof), else they're treated like pointers (for CodeGen).
- CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false) const;
+ /// If \p ForAlignof, references are treated like their underlying type
+ /// and large arrays don't get any special treatment. If not \p ForAlignof
+ /// it computes the value expected by CodeGen: references are treated like
+ /// pointers and large arrays get extra alignment.
+ CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const;
/// \brief Get or compute information about the layout of the specified
/// record (struct/union/class) \p D, which indicates its size and field
/// position information.
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
+ const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const;
/// \brief Get or compute information about the layout of the specified
/// Objective-C interface.
@@ -1721,6 +1767,9 @@ public:
getCanonicalType(T2).getTypePtr();
}
+ bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
+ const ObjCMethodDecl *MethodImp);
+
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
/// \brief Retrieves the "canonical" nested name specifier for a
@@ -1749,19 +1798,9 @@ public:
NestedNameSpecifier *
getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
- /// \brief Retrieves the default calling convention to use for
- /// C++ instance methods.
- CallingConv getDefaultCXXMethodCallConv(bool isVariadic);
-
- /// \brief Retrieves the canonical representation of the given
- /// calling convention.
- CallingConv getCanonicalCallConv(CallingConv CC) const;
-
- /// \brief Determines whether two calling conventions name the same
- /// calling convention.
- bool isSameCallConv(CallingConv lcc, CallingConv rcc) {
- return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc));
- }
+ /// \brief Retrieves the default calling convention for the current target.
+ CallingConv getDefaultCallingConvention(bool isVariadic,
+ bool IsCXXMethod) const;
/// \brief Retrieves the "canonical" template name that refers to a
/// given template.
@@ -1899,6 +1938,12 @@ public:
return (*AddrSpaceMap)[AS - LangAS::Offset];
}
+ bool addressSpaceMapManglingFor(unsigned AS) const {
+ return AddrSpaceMapMangling ||
+ AS < LangAS::Offset ||
+ AS >= LangAS::Offset + LangAS::Count;
+ }
+
private:
// Helper for integer ordering
unsigned getIntegerRank(const Type *T) const;
@@ -1925,7 +1970,6 @@ public:
bool isObjCSelType(QualType T) const {
return T == getObjCSelType();
}
- bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS);
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
bool ForCompare);
@@ -2092,12 +2136,15 @@ public:
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
- void addUnnamedTag(const TagDecl *Tag);
- int getUnnamedTagManglingNumber(const TagDecl *Tag) const;
+ void setManglingNumber(const NamedDecl *ND, unsigned Number);
+ unsigned getManglingNumber(const NamedDecl *ND) const;
+
+ /// \brief Retrieve the context for computing mangling numbers in the given
+ /// DeclContext.
+ MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
+
+ MangleNumberingContext *createMangleNumberingContext() const;
- /// \brief Retrieve the lambda mangling number for a lambda expression.
- unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator);
-
/// \brief Used by ParmVarDecl to store on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
void setParameterIndex(const ParmVarDecl *D, unsigned index);
@@ -2105,7 +2152,12 @@ public:
/// \brief Used by ParmVarDecl to retrieve on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
unsigned getParameterIndex(const ParmVarDecl *D) const;
-
+
+ /// \brief Get the storage for the constant value of a materialized temporary
+ /// of static storage duration.
+ APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E,
+ bool MayCreate);
+
//===--------------------------------------------------------------------===//
// Statistics
//===--------------------------------------------------------------------===//
@@ -2197,93 +2249,21 @@ private:
const ObjCImplementationDecl *Impl) const;
private:
- /// \brief A set of deallocations that should be performed when the
+ /// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
- SmallVector<std::pair<void (*)(void*), void *>, 16> Deallocations;
-
+ typedef llvm::SmallDenseMap<void(*)(void*), llvm::SmallVector<void*, 16> >
+ DeallocationMap;
+ DeallocationMap Deallocations;
+
// FIXME: This currently contains the set of StoredDeclMaps used
// by DeclContext objects. This probably should not be in ASTContext,
// but we include it here so that ASTContext can quickly deallocate them.
llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM;
- /// \brief A counter used to uniquely identify "blocks".
- mutable unsigned int UniqueBlockByRefTypeID;
-
friend class DeclContext;
friend class DeclarationNameTable;
void ReleaseDeclContextMaps();
- /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their
- /// parents as defined by the \c RecursiveASTVisitor.
- ///
- /// Note that the relationship described here is purely in terms of AST
- /// traversal - there are other relationships (for example declaration context)
- /// in the AST that are better modeled by special matchers.
- ///
- /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
- class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> {
- public:
- /// \brief Builds and returns the translation unit's parent map.
- ///
- /// The caller takes ownership of the returned \c ParentMap.
- static ParentMap *buildMap(TranslationUnitDecl &TU) {
- ParentMapASTVisitor Visitor(new ParentMap);
- Visitor.TraverseDecl(&TU);
- return Visitor.Parents;
- }
-
- private:
- typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase;
-
- ParentMapASTVisitor(ParentMap *Parents) : Parents(Parents) {
- }
-
- bool shouldVisitTemplateInstantiations() const {
- return true;
- }
- bool shouldVisitImplicitCode() const {
- return true;
- }
- // Disables data recursion. We intercept Traverse* methods in the RAV, which
- // are not triggered during data recursion.
- bool shouldUseDataRecursionFor(clang::Stmt *S) const {
- return false;
- }
-
- template <typename T>
- bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) {
- if (Node == NULL)
- return true;
- if (ParentStack.size() > 0)
- // FIXME: Currently we add the same parent multiple times, for example
- // when we visit all subexpressions of template instantiations; this is
- // suboptimal, bug benign: the only way to visit those is with
- // hasAncestor / hasParent, and those do not create new matches.
- // The plan is to enable DynTypedNode to be storable in a map or hash
- // map. The main problem there is to implement hash functions /
- // comparison operators for all types that DynTypedNode supports that
- // do not have pointer identity.
- (*Parents)[Node].push_back(ParentStack.back());
- ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node));
- bool Result = (this ->* traverse) (Node);
- ParentStack.pop_back();
- return Result;
- }
-
- bool TraverseDecl(Decl *DeclNode) {
- return TraverseNode(DeclNode, &VisitorBase::TraverseDecl);
- }
-
- bool TraverseStmt(Stmt *StmtNode) {
- return TraverseNode(StmtNode, &VisitorBase::TraverseStmt);
- }
-
- ParentMap *Parents;
- llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
-
- friend class RecursiveASTVisitor<ParentMapASTVisitor>;
- };
-
llvm::OwningPtr<ParentMap> AllParents;
};
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 64e955ea1472..1635511984dc 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
#undef DIAG
diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h
new file mode 100644
index 000000000000..4f3279874b16
--- /dev/null
+++ b/include/clang/AST/ASTFwd.h
@@ -0,0 +1,28 @@
+//===--- ASTFwd.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------===//
+///
+/// \file
+/// \brief Forward declaration of all AST node types.
+///
+//===-------------------------------------------------------------===//
+
+namespace clang {
+
+class Decl;
+#define DECL(DERIVED, BASE) class DERIVED##Decl;
+#include "clang/AST/DeclNodes.inc"
+class Stmt;
+#define STMT(DERIVED, BASE) class DERIVED;
+#include "clang/AST/StmtNodes.inc"
+class Type;
+#define TYPE(DERIVED, BASE) class DERIVED##Type;
+#include "clang/AST/TypeNodes.def"
+class CXXCtorInitializer;
+
+} // end namespace clang
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 1672ab22a3de..b74c8ee1bf47 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -271,6 +271,14 @@ namespace clang {
/// 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 Called by StructuralEquivalenceContext. If a RecordDecl is
+ /// being compared to another RecordDecl as part of import, completing the
+ /// other RecordDecl may trigger importation of the first RecordDecl. This
+ /// happens especially for anonymous structs. If the original of the second
+ /// RecordDecl can be found, we can complete it without the need for
+ /// importation, eliminating this loop.
+ virtual Decl *GetOriginalDecl(Decl *To) { return NULL; }
/// \brief Determine whether the given types are structurally
/// equivalent.
diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h
new file mode 100644
index 000000000000..358ac7131e40
--- /dev/null
+++ b/include/clang/AST/ASTLambda.h
@@ -0,0 +1,80 @@
+//===--- ASTLambda.h - Lambda Helper Functions --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides some common utility functions for processing
+/// Lambda related AST Constructs.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_LAMBDA_H
+#define LLVM_CLANG_AST_LAMBDA_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+inline StringRef getLambdaStaticInvokerName() {
+ return "__invoke";
+}
+// This function returns true if M is a specialization, a template,
+// or a non-generic lambda call operator.
+inline bool isLambdaCallOperator(const CXXMethodDecl *MD) {
+ const CXXRecordDecl *LambdaClass = MD->getParent();
+ if (!LambdaClass || !LambdaClass->isLambda()) return false;
+ return MD->getOverloadedOperator() == OO_Call;
+}
+
+inline bool isLambdaCallOperator(const DeclContext *DC) {
+ if (!DC || !isa<CXXMethodDecl>(DC)) return false;
+ return isLambdaCallOperator(cast<CXXMethodDecl>(DC));
+}
+
+inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) {
+ if (!MD) return false;
+ CXXRecordDecl *LambdaClass = MD->getParent();
+ if (LambdaClass && LambdaClass->isGenericLambda())
+ return isLambdaCallOperator(MD) &&
+ MD->isFunctionTemplateSpecialization();
+ return false;
+}
+
+inline bool isLambdaConversionOperator(CXXConversionDecl *C) {
+ return C ? C->getParent()->isLambda() : false;
+}
+
+inline bool isLambdaConversionOperator(Decl *D) {
+ if (!D) return false;
+ if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D))
+ return isLambdaConversionOperator(Conv);
+ if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D))
+ if (CXXConversionDecl *Conv =
+ dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl()))
+ return isLambdaConversionOperator(Conv);
+ return false;
+}
+
+inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
+ return isGenericLambdaCallOperatorSpecialization(
+ dyn_cast<CXXMethodDecl>(DC));
+}
+
+
+// This returns the parent DeclContext ensuring that the correct
+// parent DeclContext is returned for Lambdas
+inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
+ if (isLambdaCallOperator(DC))
+ return DC->getParent()->getParent();
+ else
+ return DC->getParent();
+}
+
+} // clang
+
+#endif // LLVM_CLANG_AST_LAMBDA_H
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index 6b70285e3ad8..6d12a92c61bf 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -27,8 +27,11 @@ namespace clang {
class ObjCContainerDecl;
class ObjCInterfaceDecl;
class ObjCPropertyDecl;
+ class QualType;
class TagDecl;
class VarDecl;
+ class VarTemplateDecl;
+ class VarTemplateSpecializationDecl;
/// \brief An abstract interface that should be implemented by listeners
/// that want to be notified when an AST entity gets modified after its
@@ -53,9 +56,18 @@ public:
/// \brief A template specialization (or partial one) was added to the
/// template declaration.
+ virtual void
+ AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
+ const VarTemplateSpecializationDecl *D) {}
+
+ /// \brief A template specialization (or partial one) was added to the
+ /// template declaration.
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {}
+ /// \brief A function's return type has been deduced.
+ virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
+
/// \brief An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
@@ -78,6 +90,11 @@ public:
const ObjCPropertyDecl *OrigProp,
const ObjCCategoryDecl *ClassExt) {}
+ /// \brief A declaration is marked used which was not previously marked used.
+ ///
+ /// \param D the declaration marked used
+ virtual void DeclarationMarkedUsed(const Decl *D) {}
+
// NOTE: If new methods are added they should also be added to
// MultiplexASTMutationListener.
};
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index 4688b12de701..087ad5609001 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -7,22 +7,132 @@
//
//===----------------------------------------------------------------------===//
//
-// Provides a dynamically typed node container that can be used to store
-// an AST base node at runtime in the same storage in a type safe way.
+// Provides a dynamic type identifier and a dynamically typed node container
+// that can be used to store an AST base node at runtime in the same storage in
+// a type safe way.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H
#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H
+#include "clang/AST/ASTFwd.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/Support/AlignOf.h"
+namespace llvm {
+
+class raw_ostream;
+
+}
+
namespace clang {
+
+struct PrintingPolicy;
+
namespace ast_type_traits {
+/// \brief Kind identifier.
+///
+/// It can be constructed from any node kind and allows for runtime type
+/// hierarchy checks.
+/// Use getFromNodeKind<T>() to construct them.
+class ASTNodeKind {
+public:
+ /// \brief Empty identifier. It matches nothing.
+ ASTNodeKind() : KindId(NKI_None) {}
+
+ /// \brief Construct an identifier for T.
+ template <class T>
+ static ASTNodeKind getFromNodeKind() {
+ return ASTNodeKind(KindToKindId<T>::Id);
+ }
+
+ /// \brief Returns \c true if \c this and \c Other represent the same kind.
+ bool isSame(ASTNodeKind Other) const;
+
+ /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
+ bool isBaseOf(ASTNodeKind Other) const;
+
+ /// \brief String representation of the kind.
+ StringRef asStringRef() const;
+
+private:
+ /// \brief Kind ids.
+ ///
+ /// Includes all possible base and derived kinds.
+ enum NodeKindId {
+ NKI_None,
+ NKI_CXXCtorInitializer,
+ NKI_TemplateArgument,
+ NKI_NestedNameSpecifier,
+ NKI_NestedNameSpecifierLoc,
+ NKI_QualType,
+ NKI_TypeLoc,
+ NKI_Decl,
+#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
+#include "clang/AST/DeclNodes.inc"
+ NKI_Stmt,
+#define STMT(DERIVED, BASE) NKI_##DERIVED,
+#include "clang/AST/StmtNodes.inc"
+ NKI_Type,
+#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
+#include "clang/AST/TypeNodes.def"
+ NKI_NumberOfKinds
+ };
+
+ /// \brief Use getFromNodeKind<T>() to construct the kind.
+ ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
+
+ /// \brief Returns \c true if \c Base is a base kind of (or same as) \c
+ /// Derived.
+ static bool isBaseOf(NodeKindId Base, NodeKindId Derived);
+
+ /// \brief Helper meta-function to convert a kind T to its enum value.
+ ///
+ /// This struct is specialized below for all known kinds.
+ template <class T> struct KindToKindId {
+ static const NodeKindId Id = NKI_None;
+ };
+
+ /// \brief Per kind info.
+ struct KindInfo {
+ /// \brief The id of the parent kind, or None if it has no parent.
+ NodeKindId ParentId;
+ /// \brief Name of the kind.
+ const char *Name;
+ };
+ static const KindInfo AllKindInfo[NKI_NumberOfKinds];
+
+ NodeKindId KindId;
+};
+
+#define KIND_TO_KIND_ID(Class) \
+ template <> struct ASTNodeKind::KindToKindId<Class> { \
+ static const NodeKindId Id = NKI_##Class; \
+ };
+KIND_TO_KIND_ID(CXXCtorInitializer)
+KIND_TO_KIND_ID(TemplateArgument)
+KIND_TO_KIND_ID(NestedNameSpecifier)
+KIND_TO_KIND_ID(NestedNameSpecifierLoc)
+KIND_TO_KIND_ID(QualType)
+KIND_TO_KIND_ID(TypeLoc)
+KIND_TO_KIND_ID(Decl)
+KIND_TO_KIND_ID(Stmt)
+KIND_TO_KIND_ID(Type)
+#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
+#include "clang/AST/DeclNodes.inc"
+#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
+#include "clang/AST/StmtNodes.inc"
+#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
+#include "clang/AST/TypeNodes.def"
+#undef KIND_TO_KIND_ID
+
/// \brief A dynamically typed AST node container.
///
/// Stores an AST node in a type safe way. This allows writing code that
@@ -32,7 +142,7 @@ namespace ast_type_traits {
/// Use \c create(Node) to create a \c DynTypedNode from an AST node,
/// and \c get<T>() to retrieve the node as type T if the types match.
///
-/// See \c NodeTypeTag for which node base types are currently supported;
+/// See \c ASTNodeKind for which node base types are currently supported;
/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
/// the supported base types.
class DynTypedNode {
@@ -49,15 +159,15 @@ public:
/// convertible to \c T.
///
/// For types that have identity via their pointer in the AST
- /// (like \c Stmt and \c Decl) the returned pointer points to the
- /// referenced AST node.
+ /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned
+ /// pointer points to the referenced AST node.
/// For other types (like \c QualType) the value is stored directly
/// in the \c DynTypedNode, and the returned pointer points at
/// the storage inside DynTypedNode. For those nodes, do not
/// use the pointer outside the scope of the DynTypedNode.
template <typename T>
const T *get() const {
- return BaseConverter<T>::get(Tag, Storage.buffer);
+ return BaseConverter<T>::get(NodeKind, Storage.buffer);
}
/// \brief Returns a pointer that identifies the stored AST node.
@@ -67,142 +177,171 @@ public:
/// method returns NULL.
const void *getMemoizationData() const;
+ /// \brief Prints the node to the given output stream.
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
+
+ /// \brief Dumps the node to the given output stream.
+ void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
+
+ /// \brief For nodes which represent textual entities in the source code,
+ /// return their SourceRange. For all other nodes, return SourceRange().
+ SourceRange getSourceRange() const;
+
+ /// @{
+ /// \brief Imposes an order on \c DynTypedNode.
+ ///
+ /// Supports comparison of nodes that support memoization.
+ /// FIXME: Implement comparsion for other node types (currently
+ /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
+ bool operator<(const DynTypedNode &Other) const {
+ assert(getMemoizationData() && Other.getMemoizationData());
+ return getMemoizationData() < Other.getMemoizationData();
+ }
+ bool operator==(const DynTypedNode &Other) const {
+ // Nodes with different types cannot be equal.
+ if (!NodeKind.isSame(Other.NodeKind))
+ return false;
+
+ // FIXME: Implement for other types.
+ if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) {
+ return *get<QualType>() == *Other.get<QualType>();
+ }
+ assert(getMemoizationData() && Other.getMemoizationData());
+ return getMemoizationData() == Other.getMemoizationData();
+ }
+ bool operator!=(const DynTypedNode &Other) const {
+ return !operator==(Other);
+ }
+ /// @}
+
private:
/// \brief Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
- /// \brief Supported base node types.
- enum NodeTypeTag {
- NT_Decl,
- NT_Stmt,
- NT_NestedNameSpecifier,
- NT_NestedNameSpecifierLoc,
- NT_QualType,
- NT_Type,
- NT_TypeLoc
- } Tag;
+ /// \brief Converter that uses dyn_cast<T> from a stored BaseT*.
+ template <typename T, typename BaseT> struct DynCastPtrConverter {
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind))
+ return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ return NULL;
+ }
+ static DynTypedNode create(const BaseT &Node) {
+ DynTypedNode Result;
+ Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ new (Result.Storage.buffer) const BaseT * (&Node);
+ return Result;
+ }
+ };
+
+ /// \brief Converter that stores T* (by pointer).
+ template <typename T> struct PtrConverter {
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
+ return *reinterpret_cast<T *const *>(Storage);
+ return NULL;
+ }
+ static DynTypedNode create(const T &Node) {
+ DynTypedNode Result;
+ Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ new (Result.Storage.buffer) const T * (&Node);
+ return Result;
+ }
+ };
+
+ /// \brief Converter that stores T (by value).
+ template <typename T> struct ValueConverter {
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
+ return reinterpret_cast<const T *>(Storage);
+ return NULL;
+ }
+ static DynTypedNode create(const T &Node) {
+ DynTypedNode Result;
+ Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ new (Result.Storage.buffer) T(Node);
+ return Result;
+ }
+ };
+
+ ASTNodeKind NodeKind;
/// \brief Stores the data of the node.
///
- /// Note that we can store \c Decls and \c Stmts by pointer as they are
- /// guaranteed to be unique pointers pointing to dedicated storage in the
- /// AST. \c QualTypes on the other hand do not have storage or unique
+ /// Note that we can store \c Decls, \c Stmts, \c Types,
+ /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
+ /// guaranteed to be unique pointers pointing to dedicated storage in the AST.
+ /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
+ /// \c TemplateArguments on the other hand do not have storage or unique
/// pointers and thus need to be stored by value.
- llvm::AlignedCharArrayUnion<Decl *, Stmt *, NestedNameSpecifier,
- NestedNameSpecifierLoc, QualType, Type,
- TypeLoc> Storage;
+ typedef llvm::AlignedCharArrayUnion<
+ Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *>
+ KindsByPointer;
+ llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument,
+ NestedNameSpecifierLoc, QualType, TypeLoc>
+ Storage;
};
-// FIXME: Pull out abstraction for the following.
-template<typename T> struct DynTypedNode::BaseConverter<T,
- typename llvm::enable_if<llvm::is_base_of<Decl, T> >::type> {
- static const T *get(NodeTypeTag Tag, const char Storage[]) {
- if (Tag == NT_Decl)
- return dyn_cast<T>(*reinterpret_cast<Decl*const*>(Storage));
- return NULL;
- }
- static DynTypedNode create(const Decl &Node) {
- DynTypedNode Result;
- Result.Tag = NT_Decl;
- new (Result.Storage.buffer) const Decl*(&Node);
- return Result;
- }
-};
-template<typename T> struct DynTypedNode::BaseConverter<T,
- typename llvm::enable_if<llvm::is_base_of<Stmt, T> >::type> {
- static const T *get(NodeTypeTag Tag, const char Storage[]) {
- if (Tag == NT_Stmt)
- return dyn_cast<T>(*reinterpret_cast<Stmt*const*>(Storage));
- return NULL;
- }
- static DynTypedNode create(const Stmt &Node) {
- DynTypedNode Result;
- Result.Tag = NT_Stmt;
- new (Result.Storage.buffer) const Stmt*(&Node);
- return Result;
- }
-};
-template<typename T> struct DynTypedNode::BaseConverter<T,
- typename llvm::enable_if<llvm::is_base_of<Type, T> >::type> {
- static const T *get(NodeTypeTag Tag, const char Storage[]) {
- if (Tag == NT_Type)
- return dyn_cast<T>(*reinterpret_cast<Type*const*>(Storage));
- return NULL;
- }
- static DynTypedNode create(const Type &Node) {
- DynTypedNode Result;
- Result.Tag = NT_Type;
- new (Result.Storage.buffer) const Type*(&Node);
- return Result;
- }
-};
-template<> struct DynTypedNode::BaseConverter<NestedNameSpecifier, void> {
- static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) {
- if (Tag == NT_NestedNameSpecifier)
- return *reinterpret_cast<NestedNameSpecifier*const*>(Storage);
- return NULL;
- }
- static DynTypedNode create(const NestedNameSpecifier &Node) {
- DynTypedNode Result;
- Result.Tag = NT_NestedNameSpecifier;
- new (Result.Storage.buffer) const NestedNameSpecifier*(&Node);
- return Result;
- }
-};
-template<> struct DynTypedNode::BaseConverter<NestedNameSpecifierLoc, void> {
- static const NestedNameSpecifierLoc *get(NodeTypeTag Tag,
- const char Storage[]) {
- if (Tag == NT_NestedNameSpecifierLoc)
- return reinterpret_cast<const NestedNameSpecifierLoc*>(Storage);
- return NULL;
- }
- static DynTypedNode create(const NestedNameSpecifierLoc &Node) {
- DynTypedNode Result;
- Result.Tag = NT_NestedNameSpecifierLoc;
- new (Result.Storage.buffer) NestedNameSpecifierLoc(Node);
- return Result;
- }
-};
-template<> struct DynTypedNode::BaseConverter<QualType, void> {
- static const QualType *get(NodeTypeTag Tag, const char Storage[]) {
- if (Tag == NT_QualType)
- return reinterpret_cast<const QualType*>(Storage);
- return NULL;
- }
- static DynTypedNode create(const QualType &Node) {
- DynTypedNode Result;
- Result.Tag = NT_QualType;
- new (Result.Storage.buffer) QualType(Node);
- return Result;
- }
-};
-template<> struct DynTypedNode::BaseConverter<TypeLoc, void> {
- static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) {
- if (Tag == NT_TypeLoc)
- return reinterpret_cast<const TypeLoc*>(Storage);
- return NULL;
- }
- static DynTypedNode create(const TypeLoc &Node) {
- DynTypedNode Result;
- Result.Tag = NT_TypeLoc;
- new (Result.Storage.buffer) TypeLoc(Node);
- return Result;
- }
-};
+template <typename T>
+struct DynTypedNode::BaseConverter<
+ T, typename llvm::enable_if<llvm::is_base_of<
+ Decl, T> >::type> : public DynCastPtrConverter<T, Decl> {};
+
+template <typename T>
+struct DynTypedNode::BaseConverter<
+ T, typename llvm::enable_if<llvm::is_base_of<
+ Stmt, T> >::type> : public DynCastPtrConverter<T, Stmt> {};
+
+template <typename T>
+struct DynTypedNode::BaseConverter<
+ T, typename llvm::enable_if<llvm::is_base_of<
+ Type, T> >::type> : public DynCastPtrConverter<T, Type> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ NestedNameSpecifierLoc,
+ void> : public ValueConverter<NestedNameSpecifierLoc> {};
+
+template <>
+struct DynTypedNode::BaseConverter<QualType,
+ void> : public ValueConverter<QualType> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ TypeLoc, void> : public ValueConverter<TypeLoc> {};
+
// The only operation we allow on unsupported types is \c get.
// This allows to conveniently use \c DynTypedNode when having an arbitrary
// AST node that is not supported, but prevents misuse - a user cannot create
// a DynTypedNode from arbitrary types.
template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
- static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; }
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ return NULL;
+ }
};
inline const void *DynTypedNode::getMemoizationData() const {
- switch (Tag) {
- case NT_Decl: return BaseConverter<Decl>::get(Tag, Storage.buffer);
- case NT_Stmt: return BaseConverter<Stmt>::get(Tag, Storage.buffer);
- default: return NULL;
- };
+ if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(NodeKind)) {
+ return BaseConverter<Decl>::get(NodeKind, Storage.buffer);
+ } else if (ASTNodeKind::getFromNodeKind<Stmt>().isBaseOf(NodeKind)) {
+ return BaseConverter<Stmt>::get(NodeKind, Storage.buffer);
+ } else if (ASTNodeKind::getFromNodeKind<Type>().isBaseOf(NodeKind)) {
+ return BaseConverter<Type>::get(NodeKind, Storage.buffer);
+ } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) {
+ return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer);
+ }
+ return NULL;
}
} // end namespace ast_type_traits
diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h
index 5a56b4d2b46d..e8be67006c5b 100644
--- a/include/clang/AST/ASTUnresolvedSet.h
+++ b/include/clang/AST/ASTUnresolvedSet.h
@@ -22,12 +22,21 @@ namespace clang {
/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator.
class ASTUnresolvedSet {
- typedef ASTVector<DeclAccessPair> DeclsTy;
+ struct DeclsTy : ASTVector<DeclAccessPair> {
+ DeclsTy() {}
+ DeclsTy(ASTContext &C, unsigned N) : ASTVector<DeclAccessPair>(C, N) {}
+
+ bool isLazy() const { return getTag(); }
+ void setLazy(bool Lazy) { setTag(Lazy); }
+ };
+
DeclsTy Decls;
ASTUnresolvedSet(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION;
void operator=(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION;
+ friend class LazyASTUnresolvedSet;
+
public:
ASTUnresolvedSet() {}
ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {}
@@ -48,7 +57,7 @@ public:
/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
- bool replace(const NamedDecl* Old, NamedDecl *New, AccessSpecifier AS) {
+ bool replace(const NamedDecl *Old, NamedDecl *New, AccessSpecifier AS) {
for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
if (I->getDecl() == Old) {
I->set(New, AS);
@@ -58,10 +67,7 @@ public:
return false;
}
- void erase(unsigned I) {
- Decls[I] = Decls.back();
- Decls.pop_back();
- }
+ void erase(unsigned I) { Decls[I] = Decls.pop_back_val(); }
void clear() { Decls.clear(); }
@@ -79,7 +85,29 @@ public:
DeclAccessPair &operator[](unsigned I) { return Decls[I]; }
const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; }
};
-
+
+/// \brief An UnresolvedSet-like class that might not have been loaded from the
+/// external AST source yet.
+class LazyASTUnresolvedSet {
+ mutable ASTUnresolvedSet Impl;
+
+ void getFromExternalSource(ASTContext &C) const;
+
+public:
+ ASTUnresolvedSet &get(ASTContext &C) const {
+ if (Impl.Decls.isLazy())
+ getFromExternalSource(C);
+ return Impl;
+ }
+
+ void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }
+ void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) {
+ assert(Impl.empty() || Impl.Decls.isLazy());
+ Impl.Decls.setLazy(true);
+ Impl.addDecl(C, reinterpret_cast<NamedDecl*>(ID << 2), AS);
+ }
+};
+
} // namespace clang
#endif
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index 669e50dbeb87..6db918eaa631 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -55,16 +55,24 @@ namespace clang {
template<typename T>
class ASTVector {
- T *Begin, *End, *Capacity;
+private:
+ T *Begin, *End;
+ llvm::PointerIntPair<T*, 1, bool> Capacity;
void setEnd(T *P) { this->End = P; }
+protected:
+ // Make a tag bit available to users of this class.
+ // FIXME: This is a horrible hack.
+ bool getTag() const { return Capacity.getInt(); }
+ void setTag(bool B) { Capacity.setInt(B); }
+
public:
// Default ctor - Initialize to empty.
- ASTVector() : Begin(NULL), End(NULL), Capacity(NULL) { }
+ ASTVector() : Begin(0), End(0), Capacity(0, false) {}
- ASTVector(ASTContext &C, unsigned N)
- : Begin(NULL), End(NULL), Capacity(NULL) {
+ ASTVector(const ASTContext &C, unsigned N)
+ : Begin(0), End(0), Capacity(0, false) {
reserve(C, N);
}
@@ -155,8 +163,8 @@ public:
return const_pointer(Begin);
}
- void push_back(const_reference Elt, ASTContext &C) {
- if (End < Capacity) {
+ void push_back(const_reference Elt, const ASTContext &C) {
+ if (End < this->capacity_ptr()) {
Retry:
new (End) T(Elt);
++End;
@@ -166,19 +174,19 @@ public:
goto Retry;
}
- void reserve(ASTContext &C, unsigned N) {
- if (unsigned(Capacity-Begin) < N)
+ void reserve(const ASTContext &C, unsigned N) {
+ if (unsigned(this->capacity_ptr()-Begin) < N)
grow(C, N);
}
/// capacity - Return the total number of elements in the currently allocated
/// buffer.
- size_t capacity() const { return Capacity - Begin; }
+ size_t capacity() const { return this->capacity_ptr() - Begin; }
/// append - Add the specified range to the end of the SmallVector.
///
template<typename in_iter>
- void append(ASTContext &C, in_iter in_start, in_iter in_end) {
+ void append(const ASTContext &C, in_iter in_start, in_iter in_end) {
size_type NumInputs = std::distance(in_start, in_end);
if (NumInputs == 0)
@@ -197,7 +205,7 @@ public:
/// append - Add the specified range to the end of the SmallVector.
///
- void append(ASTContext &C, size_type NumInputs, const T &Elt) {
+ void append(const ASTContext &C, size_type NumInputs, const T &Elt) {
// Grow allocated space if needed.
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
this->grow(C, this->size()+NumInputs);
@@ -214,13 +222,13 @@ public:
std::uninitialized_copy(I, E, Dest);
}
- iterator insert(ASTContext &C, iterator I, const T &Elt) {
+ iterator insert(const ASTContext &C, iterator I, const T &Elt) {
if (I == this->end()) { // Important special case for empty vector.
- push_back(Elt);
+ push_back(Elt, C);
return this->end()-1;
}
- if (this->EndX < this->CapacityX) {
+ if (this->End < this->capacity_ptr()) {
Retry:
new (this->end()) T(this->back());
this->setEnd(this->end()+1);
@@ -235,7 +243,7 @@ public:
goto Retry;
}
- iterator insert(ASTContext &C, iterator I, size_type NumToInsert,
+ iterator insert(const ASTContext &C, iterator I, size_type NumToInsert,
const T &Elt) {
if (I == this->end()) { // Important special case for empty vector.
append(C, NumToInsert, Elt);
@@ -284,7 +292,7 @@ public:
}
template<typename ItTy>
- iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) {
+ iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) {
if (I == this->end()) { // Important special case for empty vector.
append(C, From, To);
return this->end()-1;
@@ -335,7 +343,7 @@ public:
return I;
}
- void resize(ASTContext &C, unsigned N, const T &NV) {
+ void resize(const ASTContext &C, unsigned N, const T &NV) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
this->setEnd(this->begin()+N);
@@ -350,7 +358,7 @@ public:
private:
/// grow - double the size of the allocated memory, guaranteeing space for at
/// least one more element or MinSize if specified.
- void grow(ASTContext &C, size_type MinSize = 1);
+ void grow(const ASTContext &C, size_type MinSize = 1);
void construct_range(T *S, T *E, const T &Elt) {
for (; S != E; ++S)
@@ -365,13 +373,16 @@ private:
}
protected:
- iterator capacity_ptr() { return (iterator)this->Capacity; }
+ const_iterator capacity_ptr() const {
+ return (iterator) Capacity.getPointer();
+ }
+ iterator capacity_ptr() { return (iterator)Capacity.getPointer(); }
};
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T>
-void ASTVector<T>::grow(ASTContext &C, size_t MinSize) {
- size_t CurCapacity = Capacity-Begin;
+void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
+ size_t CurCapacity = this->capacity();
size_t CurSize = size();
size_t NewCapacity = 2*CurCapacity;
if (NewCapacity < MinSize)
@@ -394,7 +405,7 @@ void ASTVector<T>::grow(ASTContext &C, size_t MinSize) {
// ASTContext never frees any memory.
Begin = NewElts;
End = NewElts+CurSize;
- Capacity = Begin+NewCapacity;
+ Capacity.setPointer(Begin+NewCapacity);
}
} // end: clang namespace
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 27dcef2a1e98..7dbf41350a0f 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_ATTR_H
#include "clang/AST/AttrIterator.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/LLVM.h"
@@ -145,7 +146,7 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
// Relies on relative order of enum emission with respect to param attrs.
- return (A->getKind() <= attr::LAST_MS_INHERITABLE &&
+ return (A->getKind() <= attr::LAST_MS_INHERITANCE &&
A->getKind() > attr::LAST_INHERITABLE_PARAM);
}
};
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 2983e04cda34..dbe4ad0f5a1d 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -287,9 +287,9 @@ public:
// Iterate over the set of overriding virtual methods in a given
// subobject.
- typedef SmallVector<UniqueVirtualMethod, 4>::iterator
+ typedef SmallVectorImpl<UniqueVirtualMethod>::iterator
overriding_iterator;
- typedef SmallVector<UniqueVirtualMethod, 4>::const_iterator
+ typedef SmallVectorImpl<UniqueVirtualMethod>::const_iterator
overriding_const_iterator;
// Add a new overriding method for a particular subobject.
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 946075739d06..9c699b7e0ae2 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -81,7 +81,7 @@ public:
operator QualType() const { return Stored; }
/// \brief Implicit conversion to bool.
- operator bool() const { return !isNull(); }
+ LLVM_EXPLICIT operator bool() const { return !isNull(); }
bool isNull() const {
return Stored.isNull();
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 082c672c2191..09ff6828ef5c 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -19,21 +19,20 @@
#include "llvm/Support/MathExtras.h"
namespace clang {
-
+
/// CharUnits - This is an opaque type for sizes expressed in character units.
- /// Instances of this type represent a quantity as a multiple of the size
+ /// Instances of this type represent a quantity as a multiple of the size
/// of the standard C type, char, on the target architecture. As an opaque
/// type, CharUnits protects you from accidentally combining operations on
- /// quantities in bit units and character units.
+ /// quantities in bit units and character units.
+ ///
+ /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned
+ /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to
+ /// the same quantity of storage. However, we use the term 'character unit'
+ /// rather than 'byte' to avoid an implication that a character unit is
+ /// exactly 8 bits.
///
- /// It should be noted that characters and bytes are distinct concepts. Bytes
- /// refer to addressable units of data storage on the target machine, and
- /// characters are members of a set of elements used for the organization,
- /// control, or representation of data. According to C99, bytes are allowed
- /// to exceed characters in size, although currently, clang only supports
- /// architectures where the two are the same size.
- ///
- /// For portability, never assume that a target character is 8 bits wide. Use
+ /// For portability, never assume that a target character is 8 bits wide. Use
/// CharUnit values wherever you calculate sizes, offsets, or alignments
/// in character units.
class CharUnits {
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index c02a82f0fa55..28849f58a8ec 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -699,7 +699,10 @@ private:
unsigned ParamIndex;
public:
- enum { InvalidParamIndex = ~0U };
+ enum LLVM_ENUM_INT_TYPE(unsigned) {
+ InvalidParamIndex = ~0U,
+ VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
+ };
ParamCommandComment(SourceLocation LocBegin,
SourceLocation LocEnd,
@@ -755,14 +758,25 @@ public:
return ParamIndex != InvalidParamIndex;
}
+ bool isVarArgParam() const LLVM_READONLY {
+ return ParamIndex == VarArgParamIndex;
+ }
+
+ void setIsVarArgParam() {
+ ParamIndex = VarArgParamIndex;
+ assert(isParamIndexValid());
+ }
+
unsigned getParamIndex() const LLVM_READONLY {
assert(isParamIndexValid());
+ assert(!isVarArgParam());
return ParamIndex;
}
void setParamIndex(unsigned Index) {
ParamIndex = Index;
assert(isParamIndexValid());
+ assert(!isVarArgParam());
}
};
@@ -1097,10 +1111,6 @@ public:
return ThisDeclInfo;
}
- DeclInfo *getThisDeclInfo() const LLVM_READONLY {
- return ThisDeclInfo;
- }
-
ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
};
diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h
index d1f5209d1eef..dde7a1442fe1 100644
--- a/include/clang/AST/CommentCommandTraits.h
+++ b/include/clang/AST/CommentCommandTraits.h
@@ -67,6 +67,9 @@ struct CommandInfo {
/// a template parameter (\\tparam or an alias).
unsigned IsTParamCommand : 1;
+ /// True if this command is \\throws or an alias.
+ unsigned IsThrowsCommand : 1;
+
/// True if this command is \\deprecated or an alias.
unsigned IsDeprecatedCommand : 1;
@@ -142,6 +145,8 @@ public:
llvm_unreachable("the command should be known");
}
+ const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const;
+
const CommandInfo *getCommandInfo(unsigned CommandID) const;
const CommandInfo *registerUnknownCommand(StringRef CommandName);
diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td
index 8c88494e9ae4..ed323daa9f8b 100644
--- a/include/clang/AST/CommentCommands.td
+++ b/include/clang/AST/CommentCommands.td
@@ -15,6 +15,7 @@ class Command<string name> {
bit IsReturnsCommand = 0;
bit IsParamCommand = 0;
bit IsTParamCommand = 0;
+ bit IsThrowsCommand = 0;
bit IsDeprecatedCommand = 0;
bit IsHeaderfileCommand = 0;
@@ -109,6 +110,10 @@ def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; }
// HeaderDoc command for template parameter documentation.
def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; }
+def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; }
+def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; }
+def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; }
+
def Deprecated : BlockCommand<"deprecated"> {
let IsEmptyParagraphAllowed = 1;
let IsDeprecatedCommand = 1;
@@ -200,11 +205,17 @@ def Mainpage : VerbatimLineCommand<"mainpage">;
def Subpage : VerbatimLineCommand<"subpage">;
def Ref : VerbatimLineCommand<"ref">;
+def Relates : VerbatimLineCommand<"relates">;
+def Related : VerbatimLineCommand<"related">;
+def RelatesAlso : VerbatimLineCommand<"relatesalso">;
+def RelatedAlso : VerbatimLineCommand<"relatedalso">;
+
//===----------------------------------------------------------------------===//
// DeclarationVerbatimLineCommand
//===----------------------------------------------------------------------===//
// Doxygen commands.
+def Def : DeclarationVerbatimLineCommand<"def">;
def Fn : DeclarationVerbatimLineCommand<"fn">;
def Namespace : DeclarationVerbatimLineCommand<"namespace">;
def Overload : DeclarationVerbatimLineCommand<"overload">;
diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h
index 6e8941057994..312da065ff59 100644
--- a/include/clang/AST/CommentDiagnostic.h
+++ b/include/clang/AST/CommentDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
#define COMMENTSTART
#include "clang/Basic/DiagnosticCommentKinds.inc"
#undef DIAG
diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h
index d6a1072786ed..7e008131d205 100644
--- a/include/clang/AST/CommentParser.h
+++ b/include/clang/AST/CommentParser.h
@@ -61,10 +61,8 @@ class Parser {
void consumeToken() {
if (MoreLATokens.empty())
L.lex(Tok);
- else {
- Tok = MoreLATokens.back();
- MoreLATokens.pop_back();
- }
+ else
+ Tok = MoreLATokens.pop_back_val();
}
void putBack(const Token &OldTok) {
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 15e454dcc389..39109602b148 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -58,9 +58,6 @@ class Sema {
/// AST node for the \\brief command and its aliases.
const BlockCommandComment *BriefCommand;
- /// AST node for the \\returns command and its aliases.
- const BlockCommandComment *ReturnsCommand;
-
/// AST node for the \\headerfile command.
const BlockCommandComment *HeaderfileCommand;
@@ -211,7 +208,11 @@ public:
bool isFunctionDecl();
bool isAnyFunctionDecl();
+
+ /// \returns \c true if declaration that this comment is attached to declares
+ /// a function pointer.
bool isFunctionPointerVarDecl();
+ bool isFunctionOrMethodVariadic();
bool isObjCMethodDecl();
bool isObjCPropertyDecl();
bool isTemplateOrSpecialization();
@@ -220,6 +221,8 @@ public:
bool isUnionDecl();
bool isObjCInterfaceDecl();
bool isObjCProtocolDecl();
+ bool isClassTemplateDecl();
+ bool isFunctionTemplateDecl();
ArrayRef<const ParmVarDecl *> getParamVars();
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index a0c76c069b86..244a7b8d400c 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
struct ASTTemplateArgumentListInfo;
@@ -43,6 +44,7 @@ class TemplateArgumentList;
class TemplateParameterList;
class TypeLoc;
class UnresolvedSetImpl;
+class VarTemplateDecl;
/// \brief A container of type source information.
///
@@ -109,7 +111,6 @@ class NamedDecl : public Decl {
private:
NamedDecl *getUnderlyingDeclImpl();
- void verifyLinkage() const;
protected:
NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
@@ -142,7 +143,7 @@ public:
// FIXME: Deprecated, move clients to getName().
std::string getNameAsString() const { return Name.getAsString(); }
- void printName(raw_ostream &os) const { return Name.printName(os); }
+ void printName(raw_ostream &os) const { os << Name; }
/// getDeclName - Get the actual, stored name of the declaration,
/// which may be a special name.
@@ -189,10 +190,13 @@ public:
using Decl::isModulePrivate;
using Decl::setModulePrivate;
-
+
/// \brief Determine whether this declaration is hidden from name lookup.
bool isHidden() const { return Hidden; }
-
+
+ /// \brief Set whether this declaration is hidden from name lookup.
+ void setHidden(bool Hide) { Hidden = Hide; }
+
/// \brief Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();
@@ -212,11 +216,24 @@ public:
bool isCXXInstanceMember() const;
/// \brief Determine what kind of linkage this entity has.
- Linkage getLinkage() const;
+ /// This is not the linkage as defined by the standard or the codegen notion
+ /// of linkage. It is just an implementation detail that is used to compute
+ /// those.
+ Linkage getLinkageInternal() const;
+
+ /// \brief Get the linkage from a semantic point of view. Entities in
+ /// anonymous namespaces are external (in c++98).
+ Linkage getFormalLinkage() const {
+ return clang::getFormalLinkage(getLinkageInternal());
+ }
/// \brief True if this decl has external linkage.
- bool hasExternalLinkage() const {
- return getLinkage() == ExternalLinkage;
+ bool hasExternalFormalLinkage() const {
+ return isExternalFormalLinkage(getLinkageInternal());
+ }
+
+ bool isExternallyVisible() const {
+ return clang::isExternallyVisible(getLinkageInternal());
}
/// \brief Determines the visibility of this entity.
@@ -256,6 +273,13 @@ public:
return const_cast<NamedDecl*>(this)->getUnderlyingDecl();
}
+ NamedDecl *getMostRecentDecl() {
+ return cast<NamedDecl>(static_cast<Decl *>(this)->getMostRecentDecl());
+ }
+ const NamedDecl *getMostRecentDecl() const {
+ return const_cast<NamedDecl*>(this)->getMostRecentDecl();
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; }
};
@@ -351,6 +375,7 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
/// \brief Returns true if this is an anonymous namespace declaration.
///
@@ -377,7 +402,7 @@ public:
/// \brief Get the original (first) namespace declaration.
NamespaceDecl *getOriginalNamespace() {
- if (isFirstDeclaration())
+ if (isFirstDecl())
return this;
return AnonOrFirstNamespaceAndInline.getPointer();
@@ -385,7 +410,7 @@ public:
/// \brief Get the original (first) namespace declaration.
const NamespaceDecl *getOriginalNamespace() const {
- if (isFirstDeclaration())
+ if (isFirstDecl())
return this;
return AnonOrFirstNamespaceAndInline.getPointer();
@@ -394,9 +419,7 @@ public:
/// \brief Return true if this declaration is an original (first) declaration
/// of the namespace. This is false for non-original (subsequent) namespace
/// declarations and anonymous namespaces.
- bool isOriginalNamespace() const {
- return isFirstDeclaration();
- }
+ bool isOriginalNamespace() const { return isFirstDecl(); }
/// \brief Retrieve the anonymous namespace nested inside this namespace,
/// if any.
@@ -689,11 +712,21 @@ private:
/// \brief Whether this variable is (C++0x) constexpr.
unsigned IsConstexpr : 1;
+
+ /// \brief Whether this variable is the implicit variable for a lambda
+ /// init-capture.
+ unsigned IsInitCapture : 1;
+
+ /// \brief Whether this local extern variable's previous declaration was
+ /// declared in the same block scope. This controls whether we should merge
+ /// the type of this declaration with its previous declaration.
+ unsigned PreviousDeclInSameBlockScope : 1;
};
- enum { NumVarDeclBits = 12 };
+ enum { NumVarDeclBits = 14 };
friend class ASTDeclReader;
friend class StmtIteratorBase;
+ friend class ASTNodeImporter;
protected:
enum { NumParameterIndexBits = 8 };
@@ -732,15 +765,8 @@ protected:
};
VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- QualType T, TypeSourceInfo *TInfo, StorageClass SC)
- : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() {
- assert(sizeof(VarDeclBitfields) <= sizeof(unsigned));
- assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned));
- AllBits = 0;
- VarDeclBits.SClass = SC;
- // Everything else is implicitly initialized to false.
- }
+ SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo, StorageClass SC);
typedef Redeclarable<VarDecl> redeclarable_base;
virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@@ -757,6 +783,7 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
static VarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -797,7 +824,8 @@ public:
/// is a non-static local variable.
bool hasLocalStorage() const {
if (getStorageClass() == SC_None)
- return !isFileVarDecl();
+ // Second check is for C++11 [dcl.stc]p4.
+ return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified;
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal.
@@ -808,7 +836,10 @@ public:
/// isStaticLocal - Returns true if a variable with function scope is a
/// static local variable.
bool isStaticLocal() const {
- return getStorageClass() == SC_Static && !isFileVarDecl();
+ return (getStorageClass() == SC_Static ||
+ // C++11 [dcl.stc]p4
+ (getStorageClass() == SC_None && getTSCSpec() == TSCS_thread_local))
+ && !isFileVarDecl();
}
/// \brief Returns true if a variable has extern or __private_extern__
@@ -818,12 +849,19 @@ public:
getStorageClass() == SC_PrivateExtern;
}
- /// hasGlobalStorage - Returns true for all variables that do not
- /// have local storage. This includs all global variables as well
- /// as static variables declared within a function.
+ /// \brief Returns true for all variables that do not have local storage.
+ ///
+ /// This includes all global variables as well as static variables declared
+ /// within a function.
bool hasGlobalStorage() const { return !hasLocalStorage(); }
- /// Compute the language linkage.
+ /// \brief Get the storage duration of this variable, per C++ [basic.stc].
+ StorageDuration getStorageDuration() const {
+ return hasLocalStorage() ? SD_Automatic :
+ getTSCSpec() ? SD_Thread : SD_Static;
+ }
+
+ /// \brief Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
/// \brief Determines whether this variable is a variable with
@@ -847,7 +885,7 @@ public:
bool isLocalVarDecl() const {
if (getKind() != Decl::Var)
return false;
- if (const DeclContext *DC = getDeclContext())
+ if (const DeclContext *DC = getLexicalDeclContext())
return DC->getRedeclContext()->isFunctionOrMethod();
return false;
}
@@ -857,7 +895,7 @@ public:
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
- const DeclContext *DC = getDeclContext()->getRedeclContext();
+ const DeclContext *DC = getLexicalDeclContext()->getRedeclContext();
return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
}
@@ -908,10 +946,6 @@ public:
return const_cast<VarDecl*>(this)->getActingDefinition();
}
- /// \brief Determine whether this is a tentative definition of a
- /// variable in C.
- bool isTentativeDefinitionNow() const;
-
/// \brief Get the real (not just tentative) definition for this declaration.
VarDecl *getDefinition(ASTContext &);
const VarDecl *getDefinition(ASTContext &C) const {
@@ -933,10 +967,11 @@ public:
/// isFileVarDecl - Returns true for file scoped variable declaration.
bool isFileVarDecl() const {
- if (getKind() != Decl::Var)
+ Kind K = getKind();
+ if (K == ParmVar || K == ImplicitParam)
return false;
- if (getDeclContext()->getRedeclContext()->isFileContext())
+ if (getLexicalDeclContext()->getRedeclContext()->isFileContext())
return true;
if (isStaticDataMember())
@@ -1000,20 +1035,6 @@ public:
void setInit(Expr *I);
- /// \brief Determine whether this variable is a reference that
- /// extends the lifetime of its temporary initializer.
- ///
- /// A reference extends the lifetime of its temporary initializer if
- /// it's initializer is an rvalue that would normally go out of scope
- /// at the end of the initializer (a full expression). In such cases,
- /// the reference itself takes ownership of the temporary, which will
- /// be destroyed when the reference goes out of scope. For example:
- ///
- /// \code
- /// const int &r = 1.0; // creates a temporary of type 'int'
- /// \endcode
- bool extendsLifetimeOfTemporary() const;
-
/// \brief Determine whether this variable's value can be used in a
/// constant expression, according to the relevant language standard.
/// This only checks properties of the declaration, and does not check
@@ -1123,15 +1144,34 @@ public:
bool isConstexpr() const { return VarDeclBits.IsConstexpr; }
void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; }
+ /// Whether this variable is the implicit variable for a lambda init-capture.
+ bool isInitCapture() const { return VarDeclBits.IsInitCapture; }
+ void setInitCapture(bool IC) { VarDeclBits.IsInitCapture = IC; }
+
+ /// Whether this local extern variable declaration's previous declaration
+ /// was declared in the same block scope. Only correct in C++.
+ bool isPreviousDeclInSameBlockScope() const {
+ return VarDeclBits.PreviousDeclInSameBlockScope;
+ }
+ void setPreviousDeclInSameBlockScope(bool Same) {
+ VarDeclBits.PreviousDeclInSameBlockScope = Same;
+ }
+
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
/// from which it was instantiated.
VarDecl *getInstantiatedFromStaticDataMember() const;
- /// \brief If this variable is a static data member, determine what kind of
+ /// \brief If this variable is an instantiation of a variable template or a
+ /// static data member of a class template, determine what kind of
/// template specialization or instantiation this is.
TemplateSpecializationKind getTemplateSpecializationKind() const;
+ /// \brief If this variable is an instantiation of a variable template or a
+ /// static data member of a class template, determine its point of
+ /// instantiation.
+ SourceLocation getPointOfInstantiation() const;
+
/// \brief If this variable is an instantiation of a static data member of a
/// class template specialization, retrieves the member specialization
/// information.
@@ -1142,6 +1182,26 @@ public:
void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation = SourceLocation());
+ /// \brief Specify that this variable is an instantiation of the
+ /// static data member VD.
+ void setInstantiationOfStaticDataMember(VarDecl *VD,
+ TemplateSpecializationKind TSK);
+
+ /// \brief Retrieves the variable template that is described by this
+ /// variable declaration.
+ ///
+ /// Every variable template is represented as a VarTemplateDecl and a
+ /// VarDecl. The former contains template properties (such as
+ /// the template parameter lists) while the latter contains the
+ /// actual description of the template's
+ /// contents. VarTemplateDecl::getTemplatedDecl() retrieves the
+ /// VarDecl that from a VarTemplateDecl, while
+ /// getDescribedVarTemplate() retrieves the VarTemplateDecl from
+ /// a VarDecl.
+ VarTemplateDecl *getDescribedVarTemplate() const;
+
+ void setDescribedVarTemplate(VarTemplateDecl *Template);
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }
@@ -1314,11 +1374,7 @@ public:
ParmVarDeclBits.HasInheritedDefaultArg = I;
}
- QualType getOriginalType() const {
- if (getTypeSourceInfo())
- return getTypeSourceInfo()->getType();
- return getType();
- }
+ QualType getOriginalType() const;
/// \brief Determine whether this parameter is actually a function
/// parameter pack.
@@ -1517,6 +1573,7 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation NLoc,
@@ -1701,6 +1758,10 @@ public:
/// entry point into an executable program.
bool isMain() const;
+ /// \brief Determines whether this function is a MSVCRT user defined entry
+ /// point.
+ bool isMSVCRTEntryPoint() const;
+
/// \brief Determines whether this operator new or delete is one
/// of the reserved global placement operators:
/// void *operator new(size_t, void *);
@@ -1716,6 +1777,28 @@ public:
/// This function must be an allocation or deallocation function.
bool isReservedGlobalPlacementOperator() const;
+ /// \brief Determines whether this function is one of the replaceable
+ /// global allocation functions:
+ /// void *operator new(size_t);
+ /// void *operator new(size_t, const std::nothrow_t &) noexcept;
+ /// void *operator new[](size_t);
+ /// void *operator new[](size_t, const std::nothrow_t &) noexcept;
+ /// void operator delete(void *) noexcept;
+ /// void operator delete(void *, std::size_t) noexcept; [C++1y]
+ /// void operator delete(void *, const std::nothrow_t &) noexcept;
+ /// void operator delete[](void *) noexcept;
+ /// void operator delete[](void *, std::size_t) noexcept; [C++1y]
+ /// void operator delete[](void *, const std::nothrow_t &) noexcept;
+ /// These functions have special behavior under C++1y [expr.new]:
+ /// An implementation is allowed to omit a call to a replaceable global
+ /// allocation function. [...]
+ bool isReplaceableGlobalAllocationFunction() const;
+
+ /// \brief Determine whether this function is a sized global deallocation
+ /// function in C++1y. If so, find and return the corresponding unsized
+ /// deallocation function.
+ FunctionDecl *getCorrespondingUnsizedGlobalDeallocationFunction() const;
+
/// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
@@ -2039,7 +2122,7 @@ public:
/// FieldDecl - An instance of this class is created by Sema::ActOnField to
/// represent a member of a struct/union/class.
-class FieldDecl : public DeclaratorDecl {
+class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
// FIXME: This can be packed into the bitfields in Decl.
bool Mutable : 1;
mutable unsigned CachedFieldIndex : 31;
@@ -2153,6 +2236,10 @@ public:
SourceRange getSourceRange() const LLVM_READONLY;
+ /// Retrieves the canonical declaration of this field.
+ FieldDecl *getCanonicalDecl() { return getFirstDecl(); }
+ const FieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstField && K <= lastField; }
@@ -2165,7 +2252,7 @@ public:
/// that is defined. For example, in "enum X {a,b}", each of a/b are
/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
/// TagType for the X EnumDecl.
-class EnumConstantDecl : public ValueDecl {
+class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> {
Stmt *Init; // an integer constant expression
llvm::APSInt Val; // The value.
protected:
@@ -2191,6 +2278,10 @@ public:
SourceRange getSourceRange() const LLVM_READONLY;
+ /// Retrieves the canonical declaration of this enumerator.
+ EnumConstantDecl *getCanonicalDecl() { return getFirstDecl(); }
+ const EnumConstantDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == EnumConstant; }
@@ -2289,14 +2380,14 @@ public:
/// Base class for declarations which introduce a typedef-name.
class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
virtual void anchor();
- /// UnderlyingType - This is the type the typedef is set to.
- TypeSourceInfo *TInfo;
+ typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo;
+ llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo;
protected:
TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
TypeSourceInfo *TInfo)
- : TypeDecl(DK, DC, IdLoc, Id, StartLoc), TInfo(TInfo) {}
+ : TypeDecl(DK, DC, IdLoc, Id, StartLoc), MaybeModedTInfo(TInfo) {}
typedef Redeclarable<TypedefNameDecl> redeclarable_base;
virtual TypedefNameDecl *getNextRedeclaration() {
@@ -2315,26 +2406,31 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
- TypeSourceInfo *getTypeSourceInfo() const {
- return TInfo;
- }
+ bool isModed() const { return MaybeModedTInfo.is<ModedTInfo*>(); }
- /// Retrieves the canonical declaration of this typedef-name.
- TypedefNameDecl *getCanonicalDecl() {
- return getFirstDeclaration();
- }
- const TypedefNameDecl *getCanonicalDecl() const {
- return getFirstDeclaration();
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return isModed()
+ ? MaybeModedTInfo.get<ModedTInfo*>()->first
+ : MaybeModedTInfo.get<TypeSourceInfo*>();
}
-
QualType getUnderlyingType() const {
- return TInfo->getType();
+ return isModed()
+ ? MaybeModedTInfo.get<ModedTInfo*>()->second
+ : MaybeModedTInfo.get<TypeSourceInfo*>()->getType();
}
void setTypeSourceInfo(TypeSourceInfo *newType) {
- TInfo = newType;
+ MaybeModedTInfo = newType;
+ }
+ void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) {
+ MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy);
}
+ /// Retrieves the canonical declaration of this typedef-name.
+ TypedefNameDecl *getCanonicalDecl() { return getFirstDecl(); }
+ const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
@@ -2436,6 +2532,9 @@ protected:
/// This option is only enabled when modules are enabled.
bool MayHaveOutOfDateDef : 1;
+ /// Has the full definition of this type been required by a use somewhere in
+ /// the TU.
+ bool IsCompleteDefinitionRequired : 1;
private:
SourceLocation RBraceLoc;
@@ -2443,33 +2542,33 @@ private:
// to be used for the (uncommon) case of out-of-line declarations.
typedef QualifierInfo ExtInfo;
- /// TypedefNameDeclOrQualifier - If the (out-of-line) tag declaration name
+ /// \brief If the (out-of-line) tag declaration name
/// is qualified, it points to the qualifier info (nns and range);
/// otherwise, if the tag declaration is anonymous and it is part of
/// a typedef or alias, it points to the TypedefNameDecl (used for mangling);
+ /// otherwise, if the tag declaration is anonymous and it is used as a
+ /// declaration specifier for variables, it points to the first VarDecl (used
+ /// for mangling);
/// otherwise, it is a null (TypedefNameDecl) pointer.
- llvm::PointerUnion<TypedefNameDecl*, ExtInfo*> TypedefNameDeclOrQualifier;
+ llvm::PointerUnion<NamedDecl *, ExtInfo *> NamedDeclOrQualifier;
- bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo*>(); }
- ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo*>(); }
+ bool hasExtInfo() const { return NamedDeclOrQualifier.is<ExtInfo *>(); }
+ ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get<ExtInfo *>(); }
const ExtInfo *getExtInfo() const {
- return TypedefNameDeclOrQualifier.get<ExtInfo*>();
+ return NamedDeclOrQualifier.get<ExtInfo *>();
}
protected:
- TagDecl(Kind DK, TagKind TK, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id,
- TagDecl *PrevDecl, SourceLocation StartL)
- : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK),
- TypedefNameDeclOrQualifier((TypedefNameDecl*) 0) {
+ TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, TagDecl *PrevDecl, SourceLocation StartL)
+ : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), TagDeclKind(TK),
+ IsCompleteDefinition(false), IsBeingDefined(false),
+ IsEmbeddedInDeclarator(false), IsFreeStanding(false),
+ IsCompleteDefinitionRequired(false),
+ NamedDeclOrQualifier((NamedDecl *)0) {
assert((DK != Enum || TK == TTK_Enum) &&
"EnumDecl not matched with TTK_Enum");
- TagDeclKind = TK;
- IsCompleteDefinition = false;
- IsBeingDefined = false;
- IsEmbeddedInDeclarator = false;
- IsFreeStanding = false;
- setPreviousDeclaration(PrevDecl);
+ setPreviousDecl(PrevDecl);
}
typedef Redeclarable<TagDecl> redeclarable_base;
@@ -2492,6 +2591,7 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
@@ -2522,6 +2622,12 @@ public:
return IsCompleteDefinition;
}
+ /// \brief Return true if this complete decl is
+ /// required to be complete for some existing use.
+ bool isCompleteDefinitionRequired() const {
+ return IsCompleteDefinitionRequired;
+ }
+
/// isBeingDefined - Return true if this decl is currently being defined.
bool isBeingDefined() const {
return IsBeingDefined;
@@ -2563,6 +2669,10 @@ public:
void setCompleteDefinition(bool V) { IsCompleteDefinition = V; }
+ void setCompleteDefinitionRequired(bool V = true) {
+ IsCompleteDefinitionRequired = V;
+ }
+
// FIXME: Return StringRef;
const char *getKindName() const {
return TypeWithKeyword::getTagTypeKindName(getTagKind());
@@ -2599,11 +2709,22 @@ public:
return (getDeclName() || getTypedefNameForAnonDecl());
}
+ bool hasDeclaratorForAnonDecl() const {
+ return dyn_cast_or_null<DeclaratorDecl>(
+ NamedDeclOrQualifier.get<NamedDecl *>());
+ }
+ DeclaratorDecl *getDeclaratorForAnonDecl() const {
+ return hasExtInfo() ? 0 : dyn_cast_or_null<DeclaratorDecl>(
+ NamedDeclOrQualifier.get<NamedDecl *>());
+ }
+
TypedefNameDecl *getTypedefNameForAnonDecl() const {
- return hasExtInfo() ? 0 :
- TypedefNameDeclOrQualifier.get<TypedefNameDecl*>();
+ return hasExtInfo() ? 0 : dyn_cast_or_null<TypedefNameDecl>(
+ NamedDeclOrQualifier.get<NamedDecl *>());
}
+ void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; }
+
void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);
/// \brief Retrieve the nested-name-specifier that qualifies the name of this
@@ -2702,21 +2823,22 @@ public:
return cast<EnumDecl>(TagDecl::getCanonicalDecl());
}
const EnumDecl *getCanonicalDecl() const {
- return cast<EnumDecl>(TagDecl::getCanonicalDecl());
+ return const_cast<EnumDecl*>(this)->getCanonicalDecl();
}
- const EnumDecl *getPreviousDecl() const {
- return cast_or_null<EnumDecl>(TagDecl::getPreviousDecl());
- }
EnumDecl *getPreviousDecl() {
- return cast_or_null<EnumDecl>(TagDecl::getPreviousDecl());
+ return cast_or_null<EnumDecl>(
+ static_cast<TagDecl *>(this)->getPreviousDecl());
}
-
- const EnumDecl *getMostRecentDecl() const {
- return cast<EnumDecl>(TagDecl::getMostRecentDecl());
+ const EnumDecl *getPreviousDecl() const {
+ return const_cast<EnumDecl*>(this)->getPreviousDecl();
}
+
EnumDecl *getMostRecentDecl() {
- return cast<EnumDecl>(TagDecl::getMostRecentDecl());
+ return cast<EnumDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl());
+ }
+ const EnumDecl *getMostRecentDecl() const {
+ return const_cast<EnumDecl*>(this)->getMostRecentDecl();
}
EnumDecl *getDefinition() const {
@@ -2912,18 +3034,19 @@ public:
IdentifierInfo *Id, RecordDecl* PrevDecl = 0);
static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
- const RecordDecl *getPreviousDecl() const {
- return cast_or_null<RecordDecl>(TagDecl::getPreviousDecl());
- }
RecordDecl *getPreviousDecl() {
- return cast_or_null<RecordDecl>(TagDecl::getPreviousDecl());
+ return cast_or_null<RecordDecl>(
+ static_cast<TagDecl *>(this)->getPreviousDecl());
}
-
- const RecordDecl *getMostRecentDecl() const {
- return cast<RecordDecl>(TagDecl::getMostRecentDecl());
+ const RecordDecl *getPreviousDecl() const {
+ return const_cast<RecordDecl*>(this)->getPreviousDecl();
}
+
RecordDecl *getMostRecentDecl() {
- return cast<RecordDecl>(TagDecl::getMostRecentDecl());
+ return cast<RecordDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl());
+ }
+ const RecordDecl *getMostRecentDecl() const {
+ return const_cast<RecordDecl*>(this)->getMostRecentDecl();
}
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
@@ -3106,13 +3229,17 @@ private:
Capture *Captures;
unsigned NumCaptures;
+ unsigned ManglingNumber;
+ Decl *ManglingContextDecl;
+
protected:
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
: Decl(Block, DC, CaretLoc), DeclContext(Block),
IsVariadic(false), CapturesCXXThis(false),
BlockMissingReturnType(true), IsConversionFromLambda(false),
ParamInfo(0), NumParams(0), Body(0),
- SignatureAsWritten(0), Captures(0), NumCaptures(0) {}
+ SignatureAsWritten(0), Captures(0), NumCaptures(0),
+ ManglingNumber(0), ManglingContextDecl(0) {}
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
@@ -3182,6 +3309,18 @@ public:
const Capture *end,
bool capturesCXXThis);
+ unsigned getBlockManglingNumber() const {
+ return ManglingNumber;
+ }
+ Decl *getBlockManglingContextDecl() const {
+ return ManglingContextDecl;
+ }
+
+ void setBlockMangling(unsigned Number, Decl *Ctx) {
+ ManglingNumber = Number;
+ ManglingContextDecl = Ctx;
+ }
+
virtual SourceRange getSourceRange() const LLVM_READONLY;
// Implement isa/cast/dyncast/etc.
@@ -3354,7 +3493,7 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
}
template<typename decl_type>
-void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) {
+void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
// Note: This routine is implemented here because we need both NamedDecl
// and Redeclarable to be defined.
@@ -3364,10 +3503,16 @@ void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *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.
- First = PrevDecl->getFirstDeclaration();
+ First = PrevDecl->getFirstDecl();
assert(First->RedeclLink.NextIsLatest() && "Expected first");
decl_type *MostRecent = First->RedeclLink.getNext();
RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent));
+
+ // If the declaration was previously visible, a redeclaration of it remains
+ // visible even if it wouldn't be visible by itself.
+ static_cast<decl_type*>(this)->IdentifierNamespace |=
+ MostRecent->getIdentifierNamespace() &
+ (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
} else {
// Make this first.
First = static_cast<decl_type*>(this);
diff --git a/include/clang/AST/DeclAccessPair.h b/include/clang/AST/DeclAccessPair.h
index 5731308f55e6..3c5056c6e55b 100644
--- a/include/clang/AST/DeclAccessPair.h
+++ b/include/clang/AST/DeclAccessPair.h
@@ -28,7 +28,7 @@ class NamedDecl;
/// A POD class for pairing a NamedDecl* with an access specifier.
/// Can be put into unions.
class DeclAccessPair {
- NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
+ uintptr_t Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
enum { Mask = 0x3 };
@@ -40,10 +40,10 @@ public:
}
NamedDecl *getDecl() const {
- return (NamedDecl*) (~Mask & (uintptr_t) Ptr);
+ return reinterpret_cast<NamedDecl*>(~Mask & Ptr);
}
AccessSpecifier getAccess() const {
- return AccessSpecifier(Mask & (uintptr_t) Ptr);
+ return AccessSpecifier(Mask & Ptr);
}
void setDecl(NamedDecl *D) {
@@ -53,8 +53,7 @@ public:
set(getDecl(), AS);
}
void set(NamedDecl *D, AccessSpecifier AS) {
- Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) |
- reinterpret_cast<uintptr_t>(D));
+ Ptr = uintptr_t(AS) | reinterpret_cast<uintptr_t>(D);
}
operator NamedDecl*() const { return getDecl(); }
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 754facfb591d..26eea64f9d34 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -16,6 +16,7 @@
#include "clang/AST/AttrIterator.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/Linkage.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
@@ -31,6 +32,7 @@ class DeclarationName;
class DependentDiagnostic;
class EnumDecl;
class FunctionDecl;
+class LinkageComputer;
class LinkageSpecDecl;
class Module;
class NamedDecl;
@@ -157,7 +159,12 @@ public:
/// This declaration is a C++ operator declared in a non-class
/// context. All such operators are also in IDNS_Ordinary.
/// C++ lexical operator lookup looks for these.
- IDNS_NonMemberOperator = 0x0400
+ IDNS_NonMemberOperator = 0x0400,
+
+ /// This declaration is a function-local extern declaration of a
+ /// variable or function. This may also be IDNS_Ordinary if it
+ /// has been declared outside any function.
+ IDNS_LocalExtern = 0x0800
};
/// ObjCDeclQualifier - 'Qualifiers' written next to the return and
@@ -284,19 +291,16 @@ protected:
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
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;
+ /// \brief If 0, we have not computed the linkage of this declaration.
+ /// Otherwise, it is the linkage + 1.
+ mutable unsigned CacheValidAndLinkage : 3;
friend class ASTDeclWriter;
friend class ASTDeclReader;
friend class ASTReader;
+ friend class LinkageComputer;
+
+ template<typename decl_type> friend class Redeclarable;
private:
void CheckAccessDeclContext() const;
@@ -309,7 +313,7 @@ protected:
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
- HasCachedLinkage(0)
+ CacheValidAndLinkage(0)
{
if (StatisticsEnabled) add(DK);
}
@@ -319,7 +323,7 @@ protected:
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
Access(AS_none), FromASTFile(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
- HasCachedLinkage(0)
+ CacheValidAndLinkage(0)
{
if (StatisticsEnabled) add(DK);
}
@@ -341,6 +345,18 @@ protected:
/// \brief Update a potentially out-of-date declaration.
void updateOutOfDate(IdentifierInfo &II) const;
+ Linkage getCachedLinkage() const {
+ return Linkage(CacheValidAndLinkage - 1);
+ }
+
+ void setCachedLinkage(Linkage L) const {
+ CacheValidAndLinkage = L + 1;
+ }
+
+ bool hasCachedLinkage() const {
+ return CacheValidAndLinkage;
+ }
+
public:
/// \brief Source range that this declaration covers.
@@ -419,7 +435,6 @@ public:
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
const AttrVec &getAttrs() const;
- void swapAttrs(Decl *D);
void dropAttrs();
void addAttr(Attr *A) {
@@ -490,7 +505,16 @@ public:
/// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const;
- void setUsed(bool U = true) { Used = U; }
+ /// \brief Set whether the declaration is used, in the sense of odr-use.
+ ///
+ /// This should only be used immediately after creating a declaration.
+ void setIsUsed() { Used = true; }
+
+ /// \brief Mark the declaration used, in the sense of odr-use.
+ ///
+ /// This notifies any mutation listeners in addition to setting a bit
+ /// indicating the declaration is used.
+ void markUsed(ASTContext &C);
/// \brief Whether this declaration was referenced.
bool isReferenced() const;
@@ -513,13 +537,13 @@ public:
NextInContextAndBits.setInt(Bits);
}
-protected:
/// \brief Whether this declaration was marked as being private to the
/// module in which it was defined.
- bool isModulePrivate() const {
+ bool isModulePrivate() const {
return NextInContextAndBits.getInt() & ModulePrivateFlag;
}
-
+
+protected:
/// \brief Specify whether this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate(bool MP = true) {
@@ -761,7 +785,12 @@ public:
const Decl *getPreviousDecl() const {
return const_cast<Decl *>(this)->getPreviousDeclImpl();
}
-
+
+ /// \brief True if this is the first declaration in its redeclaration chain.
+ bool isFirstDecl() const {
+ return getPreviousDecl() == 0;
+ }
+
/// \brief Retrieve the most recent declaration that declares the same entity
/// as this declaration (which may be this declaration).
Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); }
@@ -777,8 +806,10 @@ public:
/// top-level Stmt* of that body. Otherwise this method returns null.
virtual Stmt* getBody() const { return 0; }
- /// \brief Returns true if this Decl represents a declaration for a body of
+ /// \brief Returns true if this \c Decl represents a declaration for a body of
/// code, such as a function or method definition.
+ /// Note that \c hasBody can also return true if any redeclaration of this
+ /// \c Decl represents a declaration for a body of code.
virtual bool hasBody() const { return getBody() != 0; }
/// getBodyRBrace - Gets the right brace of the body, if a body exists.
@@ -808,37 +839,71 @@ public:
bool isFunctionOrFunctionTemplate() const;
/// \brief Changes the namespace of this declaration to reflect that it's
+ /// a function-local extern declaration.
+ ///
+ /// These declarations appear in the lexical context of the extern
+ /// declaration, but in the semantic context of the enclosing namespace
+ /// scope.
+ void setLocalExternDecl() {
+ assert((IdentifierNamespace == IDNS_Ordinary ||
+ IdentifierNamespace == IDNS_OrdinaryFriend) &&
+ "namespace is not ordinary");
+
+ Decl *Prev = getPreviousDecl();
+ IdentifierNamespace &= ~IDNS_Ordinary;
+
+ IdentifierNamespace |= IDNS_LocalExtern;
+ if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)
+ IdentifierNamespace |= IDNS_Ordinary;
+ }
+
+ /// \brief Determine whether this is a block-scope declaration with linkage.
+ /// This will either be a local variable declaration declared 'extern', or a
+ /// local function declaration.
+ bool isLocalExternDecl() {
+ return IdentifierNamespace & IDNS_LocalExtern;
+ }
+
+ /// \brief Changes the namespace of this declaration to reflect that it's
/// the object of a friend declaration.
///
/// These declarations appear in the lexical context of the friending
/// class, but in the semantic context of the actual entity. This property
/// applies only to a specific decl object; other redeclarations of the
/// same entity may not (and probably don't) share this property.
- void setObjectOfFriendDecl(bool PreviouslyDeclared) {
+ void setObjectOfFriendDecl(bool PerformFriendInjection = false) {
unsigned OldNS = IdentifierNamespace;
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
- IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
+ IDNS_TagFriend | IDNS_OrdinaryFriend |
+ IDNS_LocalExtern)) &&
"namespace includes neither ordinary nor tag");
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
- IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
+ IDNS_TagFriend | IDNS_OrdinaryFriend |
+ IDNS_LocalExtern)) &&
"namespace includes other than ordinary or tag");
- IdentifierNamespace = 0;
+ Decl *Prev = getPreviousDecl();
+ IdentifierNamespace &= ~(IDNS_Ordinary | IDNS_Tag | IDNS_Type);
+
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
IdentifierNamespace |= IDNS_TagFriend;
- if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
+ if (PerformFriendInjection ||
+ (Prev && Prev->getIdentifierNamespace() & IDNS_Tag))
+ IdentifierNamespace |= IDNS_Tag | IDNS_Type;
}
- if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
+ if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend | IDNS_LocalExtern)) {
IdentifierNamespace |= IDNS_OrdinaryFriend;
- if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
+ if (PerformFriendInjection ||
+ (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary))
+ IdentifierNamespace |= IDNS_Ordinary;
}
}
enum FriendObjectKind {
- FOK_None, // not a friend object
- FOK_Declared, // a friend of a previously-declared entity
- FOK_Undeclared // a friend of a previously-undeclared entity
+ FOK_None, ///< Not a friend object.
+ FOK_Declared, ///< A friend of a previously-declared entity.
+ FOK_Undeclared ///< A friend of a previously-undeclared entity.
};
/// \brief Determines whether this declaration is the object of a
@@ -846,11 +911,11 @@ public:
///
/// There is currently no direct way to find the associated FriendDecl.
FriendObjectKind getFriendObjectKind() const {
- unsigned mask
- = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend));
+ unsigned mask =
+ (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend));
if (!mask) return FOK_None;
- return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ?
- FOK_Declared : FOK_Undeclared);
+ return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared
+ : FOK_Undeclared);
}
/// Specifies that this declaration is a C++ overloaded non-member.
@@ -877,9 +942,6 @@ public:
// Same as dump(), but forces color printing.
LLVM_ATTRIBUTE_USED void dumpColor() const;
void dump(raw_ostream &Out) const;
- // Debuggers don't usually respect default arguments.
- LLVM_ATTRIBUTE_USED void dumpXML() const;
- void dumpXML(raw_ostream &OS) const;
private:
void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx);
@@ -974,6 +1036,7 @@ protected:
mutable Decl *LastDecl;
friend class ExternalASTSource;
+ friend class ASTDeclReader;
friend class ASTWriter;
/// \brief Build up a chain of declarations.
@@ -1096,6 +1159,14 @@ public:
/// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
+ /// \brief Determines whether this context or some of its ancestors is a
+ /// linkage specification context that specifies C linkage.
+ bool isExternCContext() const;
+
+ /// \brief Determines whether this context or some of its ancestors is a
+ /// linkage specification context that specifies C++ linkage.
+ bool isExternCXXContext() const;
+
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(const DeclContext *DC) const {
@@ -1429,12 +1500,20 @@ public:
return const_cast<DeclContext*>(this)->lookup(Name);
}
+ /// \brief Find the declarations with the given name that are visible
+ /// within this context; don't attempt to retrieve anything from an
+ /// external source.
+ lookup_result noload_lookup(DeclarationName Name);
+
/// \brief A simplistic name lookup mechanism that performs name lookup
/// into this declaration context without consulting the external source.
///
/// This function should almost never be used, because it subverts the
/// usual relationship between a DeclContext and the external source.
/// See the ASTImporter for the (few, but important) use cases.
+ ///
+ /// FIXME: This is very inefficient; replace uses of it with uses of
+ /// noload_lookup.
void localUncachedLookup(DeclarationName Name,
SmallVectorImpl<NamedDecl *> &Results);
@@ -1458,10 +1537,16 @@ public:
/// of looking up every possible name.
class all_lookups_iterator;
+ /// \brief Iterators over all possible lookups within this context.
all_lookups_iterator lookups_begin() const;
-
all_lookups_iterator lookups_end() const;
+ /// \brief Iterators over all possible lookups within this context that are
+ /// currently loaded; don't attempt to retrieve anything from an external
+ /// source.
+ all_lookups_iterator noload_lookups_begin() const;
+ all_lookups_iterator noload_lookups_end() const;
+
/// udir_iterator - Iterates through the using-directives stored
/// within this context.
typedef UsingDirectiveDecl * const * udir_iterator;
@@ -1532,6 +1617,8 @@ public:
static bool classof(const DeclContext *D) { return true; }
LLVM_ATTRIBUTE_USED void dumpDeclContext() const;
+ LLVM_ATTRIBUTE_USED void dumpLookups() const;
+ LLVM_ATTRIBUTE_USED void dumpLookups(llvm::raw_ostream &OS) const;
private:
void reconcileExternalVisibleStorage();
@@ -1548,6 +1635,8 @@ private:
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
+ template<decl_iterator (DeclContext::*Begin)() const,
+ decl_iterator (DeclContext::*End)() const>
void buildLookupImpl(DeclContext *DCtx);
void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
bool Rediscoverable);
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index c483dde1f518..dbc41320bd72 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -6,10 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the C++ Decl subclasses, other than those for
-// templates (in DeclTemplate.h) and friends (in DeclFriend.h).
-//
+///
+/// \file
+/// \brief Defines the C++ Decl subclasses, other than those for templates
+/// (found in DeclTemplate.h) and friends (in DeclFriend.h).
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLCXX_H
@@ -88,7 +89,7 @@ namespace llvm {
namespace clang {
-/// @brief Represents an access specifier followed by colon ':'.
+/// \brief Represents an access specifier followed by colon ':'.
///
/// An objects of this class represents sugar for the syntactic occurrence
/// of an access specifier followed by a colon in the list of member
@@ -146,16 +147,16 @@ public:
/// level of access (public, protected, private) is used for the
/// derivation. For example:
///
-/// @code
+/// \code
/// class A { };
/// class B { };
/// class C : public virtual A, protected B { };
-/// @endcode
+/// \endcode
///
/// In this code, C will have two CXXBaseSpecifiers, one for "public
/// virtual A" and the other for "protected B".
class CXXBaseSpecifier {
- /// Range - The source code range that covers the full base
+ /// \brief The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access
/// specifier (if present).
SourceRange Range;
@@ -167,25 +168,26 @@ class CXXBaseSpecifier {
/// \brief Whether this is a virtual base class or not.
bool Virtual : 1;
- /// BaseOfClass - Whether this is the base of a class (true) or of a
- /// struct (false). This determines the mapping from the access
- /// specifier as written in the source code to the access specifier
- /// used for semantic analysis.
+ /// \brief Whether this is the base of a class (true) or of a struct (false).
+ ///
+ /// This determines the mapping from the access specifier as written in the
+ /// source code to the access specifier used for semantic analysis.
bool BaseOfClass : 1;
- /// Access - Access specifier as written in the source code (which
- /// may be AS_none). The actual type of data stored here is an
- /// AccessSpecifier, but we use "unsigned" here to work around a
- /// VC++ bug.
+ /// \brief Access specifier as written in the source code (may be AS_none).
+ ///
+ /// The actual type of data stored here is an AccessSpecifier, but we use
+ /// "unsigned" here to work around a VC++ bug.
unsigned Access : 2;
- /// InheritConstructors - Whether the class contains a using declaration
+ /// \brief 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.
+ /// \brief 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 \c virtual or the access specifier.
TypeSourceInfo *BaseTypeInfo;
public:
@@ -196,14 +198,12 @@ public:
: 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.
+ /// \brief Retrieves the source range that contains the entire base specifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
- /// isVirtual - Determines whether the base class is a virtual base
- /// class (or not).
+ /// \brief Determines whether the base class is a virtual base class (or not).
bool isVirtual() const { return Virtual; }
/// \brief Determine whether this base class is a base of a class declared
@@ -226,11 +226,11 @@ public:
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
- /// retrieve the access specifier as written in the source code, use
- /// getAccessSpecifierAsWritten().
+ /// \brief 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 retrieve the access specifier as
+ /// written in the source code, use getAccessSpecifierAsWritten().
AccessSpecifier getAccessSpecifier() const {
if ((AccessSpecifier)Access == AS_none)
return BaseOfClass? AS_private : AS_public;
@@ -238,19 +238,23 @@ public:
return (AccessSpecifier)Access;
}
- /// getAccessSpecifierAsWritten - Retrieves the access specifier as
- /// written in the source code (which may mean that no access
- /// specifier was explicitly written). Use getAccessSpecifier() to
- /// retrieve the access specifier for use in semantic analysis.
+ /// \brief Retrieves the access specifier as written in the source code
+ /// (which may mean that no access specifier was explicitly written).
+ ///
+ /// Use getAccessSpecifier() to retrieve the access specifier for use in
+ /// semantic analysis.
AccessSpecifier getAccessSpecifierAsWritten() const {
return (AccessSpecifier)Access;
}
- /// getType - Retrieves the type of the base class. This type will
- /// always be an unqualified class type.
- QualType getType() const { return BaseTypeInfo->getType(); }
+ /// \brief Retrieves the type of the base class.
+ ///
+ /// This type will always be an unqualified class type.
+ QualType getType() const {
+ return BaseTypeInfo->getType().getUnqualifiedType();
+ }
- /// getTypeLoc - Retrieves the type and source location of the base class.
+ /// \brief Retrieves the type and source location of the base class.
TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
};
@@ -264,7 +268,8 @@ enum MSInheritanceModel {
MSIM_Unspecified
};
-/// CXXRecordDecl - Represents a C++ struct/union/class.
+/// \brief Represents a C++ struct/union/class.
+///
/// FIXME: This class will disappear once we've properly taught RecordDecl
/// to deal with C++-specific things.
class CXXRecordDecl : public RecordDecl {
@@ -288,32 +293,32 @@ class CXXRecordDecl : public RecordDecl {
/// \brief True if this class has any user-declared constructors.
bool UserDeclaredConstructor : 1;
- /// The user-declared special members which this class has.
+ /// \brief The user-declared special members which this class has.
unsigned UserDeclaredSpecialMembers : 6;
- /// Aggregate - True when this class is an aggregate.
+ /// \brief True when this class is an aggregate.
bool Aggregate : 1;
- /// PlainOldData - True when this class is a POD-type.
+ /// \brief True when this class is a POD-type.
bool PlainOldData : 1;
- /// Empty - true when this class is empty for traits purposes,
+ /// true when this class is empty for traits purposes,
/// i.e. has no data members other than 0-width bit-fields, has no
/// virtual function/base, and doesn't inherit from a non-empty
/// class. Doesn't take union-ness into account.
bool Empty : 1;
- /// Polymorphic - True when this class is polymorphic, i.e. has at
+ /// \brief True when this class is polymorphic, i.e., has at
/// least one virtual member or derives from a polymorphic class.
bool Polymorphic : 1;
- /// Abstract - True when this class is abstract, i.e. has at least
+ /// \brief True when this class is abstract, i.e., has at least
/// one pure virtual function, (that can come from a base class).
bool Abstract : 1;
- /// IsStandardLayout - True when this class has standard layout.
+ /// \brief True when this class has standard layout.
///
- /// C++0x [class]p7. A standard-layout class is a class that:
+ /// C++11 [class]p7. A standard-layout class is a class that:
/// * has no non-static data members of type non-standard-layout class (or
/// array of such types) or reference,
/// * has no virtual functions (10.3) and no virtual base classes (10.1),
@@ -327,20 +332,19 @@ class CXXRecordDecl : public RecordDecl {
/// member.
bool IsStandardLayout : 1;
- /// HasNoNonEmptyBases - True when there are no non-empty base classes.
+ /// \brief True when there are no non-empty base classes.
///
/// This is a helper bit of state used to implement IsStandardLayout more
/// efficiently.
bool HasNoNonEmptyBases : 1;
- /// HasPrivateFields - True when there are private non-static data members.
+ /// \brief True when there are private non-static data members.
bool HasPrivateFields : 1;
- /// HasProtectedFields - True when there are protected non-static data
- /// members.
+ /// \brief True when there are protected non-static data members.
bool HasProtectedFields : 1;
- /// HasPublicFields - True when there are private non-static data members.
+ /// \brief True when there are private non-static data members.
bool HasPublicFields : 1;
/// \brief True if this class (or any subobject) has mutable fields.
@@ -353,8 +357,10 @@ class CXXRecordDecl : public RecordDecl {
bool HasInClassInitializer : 1;
/// \brief True if any field is of reference type, and does not have an
- /// in-class initializer. In this case, value-initialization of this class
- /// is illegal in C++98 even if the class has a trivial default constructor.
+ /// in-class initializer.
+ ///
+ /// In this case, value-initialization of this class is illegal in C++98
+ /// even if the class has a trivial default constructor.
bool HasUninitializedReferenceMember : 1;
/// \brief These flags are \c true if a defaulted corresponding special
@@ -389,30 +395,29 @@ class CXXRecordDecl : public RecordDecl {
/// members which have not yet been declared.
unsigned DeclaredNonTrivialSpecialMembers : 6;
- /// HasIrrelevantDestructor - True when this class has a destructor with no
- /// semantic effect.
+ /// \brief True when this class has a destructor with no semantic effect.
bool HasIrrelevantDestructor : 1;
- /// HasConstexprNonCopyMoveConstructor - True when this class has at least
- /// one user-declared constexpr constructor which is neither the copy nor
- /// move constructor.
+ /// \brief True when this class has at least one user-declared constexpr
+ /// constructor which is neither the copy nor move constructor.
bool HasConstexprNonCopyMoveConstructor : 1;
- /// DefaultedDefaultConstructorIsConstexpr - True if a defaulted default
- /// constructor for this class would be constexpr.
+ /// \brief True if a defaulted default constructor for this class would
+ /// be constexpr.
bool DefaultedDefaultConstructorIsConstexpr : 1;
- /// HasConstexprDefaultConstructor - True if this class has a constexpr
- /// default constructor (either user-declared or implicitly declared).
+ /// \brief True if this class has a constexpr default constructor.
+ ///
+ /// This is true for either a user-declared constexpr default constructor
+ /// or an implicitly declared constexpr default constructor..
bool HasConstexprDefaultConstructor : 1;
- /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least
- /// one non-static data member or base class of non-literal or volatile
- /// type.
+ /// \brief True when this class contains at least one non-static data
+ /// member or base class of non-literal or volatile type.
bool HasNonLiteralTypeFieldsOrBases : 1;
- /// ComputedVisibleConversions - True when visible conversion functions are
- /// already computed and are available.
+ /// \brief True when visible conversion functions are already computed
+ /// and are available.
bool ComputedVisibleConversions : 1;
/// \brief Whether we have a C++11 user-provided default constructor (not
@@ -439,50 +444,44 @@ class CXXRecordDecl : public RecordDecl {
/// const-qualified reference parameter or a non-reference parameter.
bool HasDeclaredCopyAssignmentWithConstParam : 1;
- /// \brief Whether an implicit move constructor was attempted to be declared
- /// but would have been deleted.
- bool FailedImplicitMoveConstructor : 1;
-
- /// \brief Whether an implicit move assignment operator was attempted to be
- /// declared but would have been deleted.
- bool FailedImplicitMoveAssignment : 1;
-
/// \brief Whether this class describes a C++ lambda.
bool IsLambda : 1;
- /// NumBases - The number of base class specifiers in Bases.
+ /// \brief The number of base class specifiers in Bases.
unsigned NumBases;
- /// NumVBases - The number of virtual base class specifiers in VBases.
+ /// \brief The number of virtual base class specifiers in VBases.
unsigned NumVBases;
- /// Bases - Base classes of this class.
+ /// \brief 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.
+ /// \brief 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
- /// CXXConversionDecl.
- ASTUnresolvedSet Conversions;
+ /// \brief The conversion functions of this C++ class (but not its
+ /// inherited conversion functions).
+ ///
+ /// Each of the entries in this overload set is a CXXConversionDecl.
+ LazyASTUnresolvedSet Conversions;
- /// VisibleConversions - Overload set containing the conversion
- /// functions of this C++ class and all those inherited conversion
- /// functions that are visible in this class. Each of the entries
- /// in this overload set is a CXXConversionDecl or a
+ /// \brief The conversion functions of this C++ class and all those
+ /// inherited conversion functions that are visible in this class.
+ ///
+ /// Each of the entries in this overload set is a CXXConversionDecl or a
/// FunctionTemplateDecl.
- ASTUnresolvedSet VisibleConversions;
+ LazyASTUnresolvedSet VisibleConversions;
- /// Definition - The declaration which defines this record.
+ /// \brief The declaration which defines this record.
CXXRecordDecl *Definition;
- /// FirstFriend - The first friend declaration in this class, or
- /// null if there aren't any. This is actually currently stored
- /// in reverse order.
- FriendDecl *FirstFriend;
+ /// \brief The first friend declaration in this class, or null if there
+ /// aren't any.
+ ///
+ /// This is actually currently stored in reverse order.
+ LazyDeclPtr FirstFriend;
/// \brief Retrieve the set of direct base classes.
CXXBaseSpecifier *getBases() const {
@@ -507,10 +506,12 @@ class CXXRecordDecl : public RecordDecl {
struct LambdaDefinitionData : public DefinitionData {
typedef LambdaExpr::Capture Capture;
- LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent)
- : DefinitionData(D), Dependent(Dependent), NumCaptures(0),
- NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0),
- MethodTyInfo(Info)
+ LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
+ bool Dependent, bool IsGeneric,
+ LambdaCaptureDefault CaptureDefault)
+ : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
+ CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
+ ManglingNumber(0), ContextDecl(0), Captures(0), MethodTyInfo(Info)
{
IsLambda = true;
}
@@ -522,14 +523,20 @@ class CXXRecordDecl : public RecordDecl {
/// within the default argument of a function template, because the
/// lambda will have been created with the enclosing context as its
/// declaration context, rather than function. This is an unfortunate
- /// artifact of having to parse the default arguments before
+ /// artifact of having to parse the default arguments before.
unsigned Dependent : 1;
- /// \brief The number of captures in this lambda.
- unsigned NumCaptures : 16;
+ /// \brief Whether this lambda is a generic lambda.
+ unsigned IsGenericLambda : 1;
+
+ /// \brief The Default Capture.
+ unsigned CaptureDefault : 2;
+
+ /// \brief The number of captures in this lambda is limited 2^NumCaptures.
+ unsigned NumCaptures : 15;
/// \brief The number of explicit captures in this lambda.
- unsigned NumExplicitCaptures : 15;
+ unsigned NumExplicitCaptures : 13;
/// \brief The number used to indicate this lambda expression for name
/// mangling in the Itanium C++ ABI.
@@ -547,6 +554,7 @@ class CXXRecordDecl : public RecordDecl {
/// \brief The type of the call method.
TypeSourceInfo *MethodTyInfo;
+
};
struct DefinitionData &data() {
@@ -569,7 +577,7 @@ class CXXRecordDecl : public RecordDecl {
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
- /// For non-templates, this value will be NULL. For record
+ /// For non-templates, this value will be null. For record
/// declarations that describe a class template, this will be a
/// pointer to a ClassTemplateDecl. For member
/// classes of class template specializations, this will be the
@@ -597,27 +605,29 @@ class CXXRecordDecl : public RecordDecl {
friend class ASTNodeImporter;
+ /// \brief Get the head of our list of friend declarations, possibly
+ /// deserializing the friends from an external AST source.
+ FriendDecl *getFirstFriend() const;
+
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, CXXRecordDecl *PrevDecl);
public:
- /// base_class_iterator - Iterator that traverses the base classes
- /// of a class.
+ /// \brief Iterator that traverses the base classes of a class.
typedef CXXBaseSpecifier* base_class_iterator;
- /// base_class_const_iterator - Iterator that traverses the base
- /// classes of a class.
+ /// \brief Iterator that traverses the base classes of a class.
typedef const CXXBaseSpecifier* base_class_const_iterator;
- /// reverse_base_class_iterator = Iterator that traverses the base classes
- /// of a class in reverse order.
+ /// \brief Iterator that traverses the base classes of a class in reverse
+ /// order.
typedef std::reverse_iterator<base_class_iterator>
reverse_base_class_iterator;
- /// reverse_base_class_iterator = Iterator that traverses the base classes
- /// of a class in reverse order.
+ /// \brief Iterator that traverses the base classes of a class in reverse
+ /// order.
typedef std::reverse_iterator<base_class_const_iterator>
reverse_base_class_const_iterator;
@@ -628,18 +638,21 @@ public:
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
}
+ CXXRecordDecl *getPreviousDecl() {
+ return cast_or_null<CXXRecordDecl>(
+ static_cast<RecordDecl *>(this)->getPreviousDecl());
+ }
const CXXRecordDecl *getPreviousDecl() const {
- return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDecl());
+ return const_cast<CXXRecordDecl*>(this)->getPreviousDecl();
}
- CXXRecordDecl *getPreviousDecl() {
- return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDecl());
+
+ CXXRecordDecl *getMostRecentDecl() {
+ return cast<CXXRecordDecl>(
+ static_cast<RecordDecl *>(this)->getMostRecentDecl());
}
const CXXRecordDecl *getMostRecentDecl() const {
- return cast_or_null<CXXRecordDecl>(RecordDecl::getMostRecentDecl());
- }
- CXXRecordDecl *getMostRecentDecl() {
- return cast_or_null<CXXRecordDecl>(RecordDecl::getMostRecentDecl());
+ return const_cast<CXXRecordDecl*>(this)->getMostRecentDecl();
}
CXXRecordDecl *getDefinition() const {
@@ -655,18 +668,18 @@ public:
bool DelayTypeCreation = false);
static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC,
TypeSourceInfo *Info, SourceLocation Loc,
- bool DependentLambda);
+ bool DependentLambda, bool IsGeneric,
+ LambdaCaptureDefault CaptureDefault);
static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0;
}
- /// setBases - Sets the base classes of this struct or class.
+ /// \brief Sets the base classes of this struct or class.
void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
- /// getNumBases - Retrieves the number of base classes of this
- /// class.
+ /// \brief Retrieves the number of base classes of this class.
unsigned getNumBases() const { return data().NumBases; }
base_class_iterator bases_begin() { return data().getBases(); }
@@ -688,8 +701,7 @@ public:
return reverse_base_class_const_iterator(bases_begin());
}
- /// getNumVBases - Retrieves the number of virtual base classes of this
- /// class.
+ /// \brief Retrieves the number of virtual base classes of this class.
unsigned getNumVBases() const { return data().NumVBases; }
base_class_iterator vbases_begin() { return data().getVBases(); }
@@ -720,12 +732,12 @@ public:
/// special methods, etc.
typedef specific_decl_iterator<CXXMethodDecl> method_iterator;
- /// method_begin - Method begin iterator. Iterates in the order the methods
+ /// \brief Method begin iterator. Iterates in the order the methods
/// were declared.
method_iterator method_begin() const {
return method_iterator(decls_begin());
}
- /// method_end - Method end iterator.
+ /// \brief Method past-the-end iterator.
method_iterator method_end() const {
return method_iterator(decls_end());
}
@@ -749,18 +761,20 @@ public:
/// Determines whether this record has any friends.
bool hasFriends() const {
- return data().FirstFriend != 0;
+ return data().FirstFriend.isValid();
}
/// \brief \c true if we know for sure that this class has a single,
/// accessible, unambiguous move constructor that is not deleted.
bool hasSimpleMoveConstructor() const {
- return !hasUserDeclaredMoveConstructor() && hasMoveConstructor();
+ return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() &&
+ !data().DefaultedMoveConstructorIsDeleted;
}
/// \brief \c true if we know for sure that this class has a single,
/// accessible, unambiguous move assignment operator that is not deleted.
bool hasSimpleMoveAssignment() const {
- return !hasUserDeclaredMoveAssignment() && hasMoveAssignment();
+ return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() &&
+ !data().DefaultedMoveAssignmentIsDeleted;
}
/// \brief \c true if we know for sure that this class has an accessible
/// destructor that is not deleted.
@@ -784,22 +798,22 @@ public:
!(data().DeclaredSpecialMembers & SMF_DefaultConstructor);
}
- /// hasUserDeclaredConstructor - Whether this class has any
- /// user-declared constructors. When true, a default constructor
- /// will not be implicitly declared.
+ /// \brief Determine whether this class has any user-declared constructors.
+ ///
+ /// When true, a default constructor will not be implicitly declared.
bool hasUserDeclaredConstructor() const {
return data().UserDeclaredConstructor;
}
- /// hasUserProvidedDefaultconstructor - Whether this class has a
- /// user-provided default constructor per C++0x.
+ /// \brief Whether this class has a user-provided default constructor
+ /// per C++11.
bool hasUserProvidedDefaultConstructor() const {
return data().UserProvidedDefaultConstructor;
}
- /// hasUserDeclaredCopyConstructor - Whether this class has a
- /// user-declared copy constructor. When false, a copy constructor
- /// will be implicitly declared.
+ /// \brief Determine whether this class has a user-declared copy constructor.
+ ///
+ /// When false, a copy constructor will be implicitly declared.
bool hasUserDeclaredCopyConstructor() const {
return data().UserDeclaredSpecialMembers & SMF_CopyConstructor;
}
@@ -830,9 +844,11 @@ public:
implicitCopyConstructorHasConstParam());
}
- /// hasUserDeclaredMoveOperation - Whether this class has a user-
- /// declared move constructor or assignment operator. When false, a
- /// move constructor and assignment operator may be implicitly declared.
+ /// \brief Whether this class has a user-declared move constructor or
+ /// assignment operator.
+ ///
+ /// When false, a move constructor and assignment operator may be
+ /// implicitly declared.
bool hasUserDeclaredMoveOperation() const {
return data().UserDeclaredSpecialMembers &
(SMF_MoveConstructor | SMF_MoveAssignment);
@@ -850,28 +866,23 @@ public:
needsImplicitMoveConstructor();
}
- /// \brief Determine whether implicit move constructor generation for this
- /// class has failed before.
- bool hasFailedImplicitMoveConstructor() const {
- return data().FailedImplicitMoveConstructor;
- }
-
- /// \brief Set whether implicit move constructor generation for this class
- /// has failed before.
- void setFailedImplicitMoveConstructor(bool Failed = true) {
- data().FailedImplicitMoveConstructor = Failed;
+ /// \brief Set that we attempted to declare an implicitly move
+ /// constructor, but overload resolution failed so we deleted it.
+ void setImplicitMoveConstructorIsDeleted() {
+ assert((data().DefaultedMoveConstructorIsDeleted ||
+ needsOverloadResolutionForMoveConstructor()) &&
+ "move constructor should not be deleted");
+ data().DefaultedMoveConstructorIsDeleted = true;
}
/// \brief Determine whether this class should get an implicit move
/// constructor or if any existing special member function inhibits this.
bool needsImplicitMoveConstructor() const {
- return !hasFailedImplicitMoveConstructor() &&
- !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&
+ return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&
!hasUserDeclaredCopyConstructor() &&
!hasUserDeclaredCopyAssignment() &&
!hasUserDeclaredMoveAssignment() &&
- !hasUserDeclaredDestructor() &&
- !data().DefaultedMoveConstructorIsDeleted;
+ !hasUserDeclaredDestructor();
}
/// \brief Determine whether we need to eagerly declare a defaulted move
@@ -880,9 +891,10 @@ public:
return data().NeedOverloadResolutionForMoveConstructor;
}
- /// hasUserDeclaredCopyAssignment - Whether this class has a
- /// user-declared copy assignment operator. When false, a copy
- /// assigment operator will be implicitly declared.
+ /// \brief Determine whether this class has a user-declared copy assignment
+ /// operator.
+ ///
+ /// When false, a copy assigment operator will be implicitly declared.
bool hasUserDeclaredCopyAssignment() const {
return data().UserDeclaredSpecialMembers & SMF_CopyAssignment;
}
@@ -907,7 +919,7 @@ public:
/// \brief Determine whether this class has a copy assignment operator with
/// a parameter type which is a reference to a const-qualified type or is not
- /// a reference..
+ /// a reference.
bool hasCopyAssignmentWithConstParam() const {
return data().HasDeclaredCopyAssignmentWithConstParam ||
(needsImplicitCopyAssignment() &&
@@ -926,29 +938,24 @@ public:
needsImplicitMoveAssignment();
}
- /// \brief Determine whether implicit move assignment generation for this
- /// class has failed before.
- bool hasFailedImplicitMoveAssignment() const {
- return data().FailedImplicitMoveAssignment;
- }
-
- /// \brief Set whether implicit move assignment generation for this class
- /// has failed before.
- void setFailedImplicitMoveAssignment(bool Failed = true) {
- data().FailedImplicitMoveAssignment = Failed;
+ /// \brief Set that we attempted to declare an implicit move assignment
+ /// operator, but overload resolution failed so we deleted it.
+ void setImplicitMoveAssignmentIsDeleted() {
+ assert((data().DefaultedMoveAssignmentIsDeleted ||
+ needsOverloadResolutionForMoveAssignment()) &&
+ "move assignment should not be deleted");
+ data().DefaultedMoveAssignmentIsDeleted = true;
}
/// \brief Determine whether this class should get an implicit move
/// assignment operator or if any existing special member function inhibits
/// this.
bool needsImplicitMoveAssignment() const {
- return !hasFailedImplicitMoveAssignment() &&
- !(data().DeclaredSpecialMembers & SMF_MoveAssignment) &&
+ return !(data().DeclaredSpecialMembers & SMF_MoveAssignment) &&
!hasUserDeclaredCopyConstructor() &&
!hasUserDeclaredCopyAssignment() &&
!hasUserDeclaredMoveConstructor() &&
- !hasUserDeclaredDestructor() &&
- !data().DefaultedMoveAssignmentIsDeleted;
+ !hasUserDeclaredDestructor();
}
/// \brief Determine whether we need to eagerly declare a move assignment
@@ -957,9 +964,9 @@ public:
return data().NeedOverloadResolutionForMoveAssignment;
}
- /// hasUserDeclaredDestructor - Whether this class has a
- /// user-declared destructor. When false, a destructor will be
- /// implicitly declared.
+ /// \brief Determine whether this class has a user-declared destructor.
+ ///
+ /// When false, a destructor will be implicitly declared.
bool hasUserDeclaredDestructor() const {
return data().UserDeclaredSpecialMembers & SMF_Destructor;
}
@@ -979,15 +986,42 @@ public:
/// \brief Determine whether this class describes a lambda function object.
bool isLambda() const { return hasDefinition() && data().IsLambda; }
+ /// \brief Determine whether this class describes a generic
+ /// lambda function object (i.e. function call operator is
+ /// a template).
+ bool isGenericLambda() const;
+
+ /// \brief Retrieve the lambda call operator of the closure type
+ /// if this is a closure type.
+ CXXMethodDecl *getLambdaCallOperator() const;
+
+ /// \brief Retrieve the lambda static invoker, the address of which
+ /// is returned by the conversion operator, and the body of which
+ /// is forwarded to the lambda call operator.
+ CXXMethodDecl *getLambdaStaticInvoker() const;
+
+ /// \brief Retrieve the generic lambda's template parameter list.
+ /// Returns null if the class does not represent a lambda or a generic
+ /// lambda.
+ TemplateParameterList *getGenericLambdaTemplateParameterList() const;
+
+ LambdaCaptureDefault getLambdaCaptureDefault() const {
+ assert(isLambda());
+ return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault);
+ }
+
/// \brief For a closure type, retrieve the mapping from captured
- /// variables and this to the non-static data members that store the
+ /// variables and \c this to the non-static data members that store the
/// values or references of the captures.
///
/// \param Captures Will be populated with the mapping from captured
/// variables to the corresponding fields.
///
/// \param ThisCapture Will be set to the field declaration for the
- /// 'this' capture.
+ /// \c this capture.
+ ///
+ /// \note No entries will be added for init-captures, as they do not capture
+ /// variables.
void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
FieldDecl *&ThisCapture) const;
@@ -1001,10 +1035,10 @@ public:
typedef UnresolvedSetIterator conversion_iterator;
conversion_iterator conversion_begin() const {
- return data().Conversions.begin();
+ return data().Conversions.get(getASTContext()).begin();
}
conversion_iterator conversion_end() const {
- return data().Conversions.end();
+ return data().Conversions.get(getASTContext()).end();
}
/// Removes a conversion function from this class. The conversion
@@ -1012,38 +1046,39 @@ public:
/// this class must currently be in the process of being defined.
void removeConversion(const NamedDecl *Old);
- /// getVisibleConversionFunctions - get all conversion functions visible
- /// in current class; including conversion function templates.
+ /// \brief Get all conversion functions visible in current class,
+ /// including conversion function templates.
std::pair<conversion_iterator, conversion_iterator>
getVisibleConversionFunctions();
- /// 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).
+ /// Determine 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; }
- /// hasInClassInitializer - Whether this class has any in-class initializers
+ /// \brief Whether this class has any in-class initializers
/// for non-static data members.
bool hasInClassInitializer() const { return data().HasInClassInitializer; }
/// \brief Whether this class or any of its subobjects has any members of
- /// reference type which would make value-initialization ill-formed, per
- /// C++03 [dcl.init]p5:
- /// -- if T is a non-union class type without a user-declared constructor,
- /// then every non-static data member and base-class component of T is
- /// value-initialized
- /// [...]
- /// A program that calls for [...] value-initialization of an entity of
- /// reference type is ill-formed.
+ /// reference type which would make value-initialization ill-formed.
+ ///
+ /// Per C++03 [dcl.init]p5:
+ /// - if T is a non-union class type without a user-declared constructor,
+ /// then every non-static data member and base-class component of T is
+ /// value-initialized [...] A program that calls for [...]
+ /// value-initialization of an entity of reference type is ill-formed.
bool hasUninitializedReferenceMember() const {
return !isUnion() && !hasUserDeclaredConstructor() &&
data().HasUninitializedReferenceMember;
}
- /// 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
+ /// \brief Whether this class is a POD-type (C++ [class]p4)
+ ///
+ /// For purposes of this function a class is POD if it 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.
///
/// Note that this is the C++ TR1 definition of POD.
@@ -1053,26 +1088,33 @@ public:
/// it contains only public fields, no bases, tag kind is not 'class', etc.
bool isCLike() const;
- /// 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.
+ /// \brief Determine whether this is an empty class in the sense of
+ /// (C++11 [meta.unary.prop]).
+ ///
+ /// A non-union class is empty iff it has a virtual function, virtual base,
+ /// data member (other than 0-width bit-field) or inherits from a non-empty
+ /// class.
+ ///
+ /// \note This does NOT include a check for union-ness.
bool isEmpty() const { return data().Empty; }
- /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
+ /// 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; }
- /// isAbstract - Whether this class is abstract (C++ [class.abstract]),
- /// which means that the class contains or inherits a pure virtual function.
+ /// \brief Determine whether this class has a pure virtual function.
+ ///
+ /// The class is is abstract per (C++ [class.abstract]p2) if it declares
+ /// a pure virtual function or inherits a pure virtual function that is
+ /// not overridden.
bool isAbstract() const { return data().Abstract; }
- /// isStandardLayout - Whether this class has standard layout
+ /// \brief Determine whether this class has standard layout per
/// (C++ [class]p7)
bool isStandardLayout() const { return data().IsStandardLayout; }
- /// \brief Whether this class, or any of its class subobjects, contains a
- /// mutable field.
+ /// \brief Determine whether this class, or any of its class subobjects,
+ /// contains a mutable field.
bool hasMutableFields() const { return data().HasMutableFields; }
/// \brief Determine whether this class has a trivial default constructor
@@ -1180,47 +1222,49 @@ public:
return !(data().HasTrivialSpecialMembers & SMF_Destructor);
}
- // hasIrrelevantDestructor - Whether this class has a destructor which has no
- // semantic effect. Any such destructor will be trivial, public, defaulted
- // and not deleted, and will call only irrelevant destructors.
+ /// \brief Determine whether this class has a destructor which has no
+ /// semantic effect.
+ ///
+ /// Any such destructor will be trivial, public, defaulted and not deleted,
+ /// and will call only irrelevant destructors.
bool hasIrrelevantDestructor() const {
return data().HasIrrelevantDestructor;
}
- // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal or
- // volatile type non-static data member or base class.
+ /// \brief Determine whether this class has a non-literal or/ volatile type
+ /// non-static data member or base class.
bool hasNonLiteralTypeFieldsOrBases() const {
return data().HasNonLiteralTypeFieldsOrBases;
}
- // isTriviallyCopyable - Whether this class is considered trivially copyable
- // (C++0x [class]p6).
+ /// \brief Determine whether this class is considered trivially copyable per
+ /// (C++11 [class]p6).
bool isTriviallyCopyable() const;
- // isTrivial - Whether this class is considered trivial
- //
- // C++0x [class]p6
- // A trivial class is a class that has a trivial default constructor and
- // is trivially copiable.
+ /// \brief Determine whether this class is considered trivial.
+ ///
+ /// C++11 [class]p6:
+ /// "A trivial class is a class that has a trivial default constructor and
+ /// is trivially copiable."
bool isTrivial() const {
return isTriviallyCopyable() && hasTrivialDefaultConstructor();
}
- // isLiteral - Whether this class is a literal type.
- //
- // C++11 [basic.types]p10
- // A class type that has all the following properties:
- // -- it has a trivial destructor
- // -- every constructor call and full-expression in the
- // brace-or-equal-intializers for non-static data members (if any) is
- // a constant expression.
- // -- it is an aggregate type or has at least one constexpr constructor or
- // constructor template that is not a copy or move constructor, and
- // -- all of its non-static data members and base classes are of literal
- // types
- //
- // We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
- // treating types with trivial default constructors as literal types.
+ /// \brief Determine whether this class is a literal type.
+ ///
+ /// C++11 [basic.types]p10:
+ /// A class type that has all the following properties:
+ /// - it has a trivial destructor
+ /// - every constructor call and full-expression in the
+ /// brace-or-equal-intializers for non-static data members (if any) is
+ /// a constant expression.
+ /// - it is an aggregate type or has at least one constexpr constructor
+ /// or constructor template that is not a copy or move constructor, and
+ /// - all of its non-static data members and base classes are of literal
+ /// types
+ ///
+ /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
+ /// treating types with trivial default constructors as literal types.
bool isLiteral() const {
return hasTrivialDestructor() &&
(isAggregate() || hasConstexprNonCopyMoveConstructor() ||
@@ -1231,15 +1275,15 @@ public:
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
- /// This routine will return non-NULL for (non-templated) member
+ /// This routine will return non-null for (non-templated) member
/// classes of class templates. For example, given:
///
- /// @code
+ /// \code
/// template<typename T>
/// struct X {
/// struct A { };
/// };
- /// @endcode
+ /// \endcode
///
/// The declaration for X<int>::A is a (non-templated) CXXRecordDecl
/// whose parent is the class template specialization X<int>. For
@@ -1257,7 +1301,7 @@ public:
}
/// \brief Specify that this record is an instantiation of the
- /// member class RD.
+ /// member class \p RD.
void setInstantiationOfMemberClass(CXXRecordDecl *RD,
TemplateSpecializationKind TSK);
@@ -1288,10 +1332,10 @@ public:
/// \brief Set the kind of specialization or template instantiation this is.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
- /// getDestructor - Returns the destructor decl for this class.
+ /// \brief Returns the destructor decl for this class.
CXXDestructorDecl *getDestructor() const;
- /// isLocalClass - If the class is a local class [class.local], returns
+ /// \brief If the class is a local class [class.local], returns
/// the enclosing function declaration.
const FunctionDecl *isLocalClass() const {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext()))
@@ -1300,6 +1344,11 @@ public:
return dyn_cast<FunctionDecl>(getDeclContext());
}
+ FunctionDecl *isLocalClass() {
+ return const_cast<FunctionDecl*>(
+ const_cast<const CXXRecordDecl*>(this)->isLocalClass());
+ }
+
/// \brief Determine whether this dependent class is a current instantiation,
/// when viewed from within the given context.
bool isCurrentInstantiation(const DeclContext *CurContext) const;
@@ -1328,7 +1377,7 @@ public:
/// \param Paths will contain the paths taken from the current class to the
/// given \p Base class.
///
- /// \returns true if this class is derived from Base, false otherwise.
+ /// \returns true if this class is derived from \p Base, false otherwise.
///
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
/// tangling input and output in \p Paths
@@ -1367,6 +1416,13 @@ public:
/// The class itself does not count as a base class. This routine
/// returns false if the class has non-computable base classes.
///
+ /// \param BaseMatches Callback invoked for each (direct or indirect) base
+ /// class of this type, or if \p AllowShortCircuit is true then until a call
+ /// returns false.
+ ///
+ /// \param UserData Passed as the second argument of every call to
+ /// \p BaseMatches.
+ ///
/// \param AllowShortCircuit if false, forces the callback to be called
/// for every base class, even if a dependent or non-matching base was
/// found.
@@ -1471,12 +1527,12 @@ public:
/// \brief Get the indirect primary bases for this class.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const;
- /// viewInheritance - Renders and displays an inheritance diagram
+ /// Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
void viewInheritance(ASTContext& Context) const;
- /// MergeAccess - Calculates the access of a decl that is reached
+ /// \brief Calculates the access of a decl that is reached
/// along a path.
static AccessSpecifier MergeAccess(AccessSpecifier PathAccess,
AccessSpecifier DeclAccess) {
@@ -1575,8 +1631,10 @@ public:
friend class ASTWriter;
};
-/// CXXMethodDecl - Represents a static or instance method of a
-/// struct/union/class.
+/// \brief Represents a static or instance method of a struct/union/class.
+///
+/// In the terminology of the C++ Standard, these are the (static and
+/// non-static) member functions, whether virtual or not.
class CXXMethodDecl : public FunctionDecl {
virtual void anchor();
protected:
@@ -1606,6 +1664,18 @@ public:
bool isStatic() const;
bool isInstance() const { return !isStatic(); }
+ /// Returns true if the given operator is implicitly static in a record
+ /// context.
+ static bool isStaticOverloadedOperator(OverloadedOperatorKind OOK) {
+ // [class.free]p1:
+ // Any allocation function for a class T is a static member
+ // (even if not explicitly declared static).
+ // [class.free]p6 Any deallocation function for a class X is a static member
+ // (even if not explicitly declared static).
+ return OOK == OO_New || OOK == OO_Array_New || OOK == OO_Delete ||
+ OOK == OO_Array_Delete;
+ }
+
bool isConst() const { return getType()->castAs<FunctionType>()->isConst(); }
bool isVolatile() const { return getType()->castAs<FunctionType>()->isVolatile(); }
@@ -1633,14 +1703,22 @@ public:
/// \brief Determine whether this is a move assignment operator.
bool isMoveAssignmentOperator() const;
- const CXXMethodDecl *getCanonicalDecl() const {
- return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
- }
CXXMethodDecl *getCanonicalDecl() {
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
}
+ const CXXMethodDecl *getCanonicalDecl() const {
+ return const_cast<CXXMethodDecl*>(this)->getCanonicalDecl();
+ }
+
+ CXXMethodDecl *getMostRecentDecl() {
+ return cast<CXXMethodDecl>(
+ static_cast<FunctionDecl *>(this)->getMostRecentDecl());
+ }
+ const CXXMethodDecl *getMostRecentDecl() const {
+ return const_cast<CXXMethodDecl*>(this)->getMostRecentDecl();
+ }
- /// isUserProvided - True if this method is user-declared and was not
+ /// True if this method is user-declared and was not
/// deleted or defaulted on its first declaration.
bool isUserProvided() const {
return !(isDeleted() || getCanonicalDecl()->isDefaulted());
@@ -1655,21 +1733,22 @@ public:
method_iterator end_overridden_methods() const;
unsigned size_overridden_methods() const;
- /// getParent - Returns the parent of this method declaration, which
+ /// Returns the parent of this method declaration, which
/// is the class in which this method is defined.
const CXXRecordDecl *getParent() const {
return cast<CXXRecordDecl>(FunctionDecl::getParent());
}
- /// getParent - Returns the parent of this method declaration, which
+ /// Returns the parent of this method declaration, which
/// is the class in which this method is defined.
CXXRecordDecl *getParent() {
return const_cast<CXXRecordDecl *>(
cast<CXXRecordDecl>(FunctionDecl::getParent()));
}
- /// getThisType - Returns the type of 'this' pointer.
- /// Should only be called for instance methods.
+ /// \brief Returns the type of the \c this pointer.
+ ///
+ /// Should only be called for instance (i.e., non-static) methods.
QualType getThisType(ASTContext &C) const;
unsigned getTypeQualifiers() const {
@@ -1702,11 +1781,11 @@ public:
/// or clone the function call operator.
bool isLambdaStaticInvoker() const;
- /// \brief Find the method in RD that corresponds to this one.
+ /// \brief Find the method in \p RD that corresponds to this one.
///
- /// Find if RD or one of the classes it inherits from override this method.
- /// If so, return it. RD is assumed to be a subclass of the class defining
- /// this method (or be the class itself), unless MayBeBase is set to true.
+ /// Find if \p RD or one of the classes it inherits from override this method.
+ /// If so, return it. \p RD is assumed to be a subclass of the class defining
+ /// this method (or be the class itself), unless \p MayBeBase is set to true.
CXXMethodDecl *
getCorrespondingMethodInClass(const CXXRecordDecl *RD,
bool MayBeBase = false);
@@ -1725,20 +1804,21 @@ public:
}
};
-/// CXXCtorInitializer - Represents a C++ base or member
-/// initializer, which is part of a constructor initializer that
+/// \brief Represents a C++ base or member initializer.
+///
+/// This 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
/// initializers:
///
-/// @code
+/// \code
/// class A { };
/// class B : public A {
/// float f;
/// public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
-/// @endcode
+/// \endcode
class CXXCtorInitializer {
/// \brief Either the base class name/delegating constructor type (stored as
/// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field
@@ -1747,7 +1827,9 @@ class CXXCtorInitializer {
Initializee;
/// \brief The source location for the field name or, for a base initializer
- /// pack expansion, the location of the ellipsis. In the case of a delegating
+ /// pack expansion, the location of the ellipsis.
+ ///
+ /// In the case of a delegating
/// constructor, it will still include the type's source location as the
/// Initializee points to the CXXConstructorDecl (to allow loop detection).
SourceLocation MemberOrEllipsisLocation;
@@ -1756,29 +1838,28 @@ class CXXCtorInitializer {
/// end up constructing an object (when multiple arguments are involved).
Stmt *Init;
- /// LParenLoc - Location of the left paren of the ctor-initializer.
+ /// \brief Location of the left paren of the ctor-initializer.
SourceLocation LParenLoc;
- /// RParenLoc - Location of the right paren of the ctor-initializer.
+ /// \brief Location of the right paren of the ctor-initializer.
SourceLocation RParenLoc;
/// \brief If the initializee is a type, whether that type makes this
/// a delegating initialization.
bool IsDelegating : 1;
- /// IsVirtual - If the initializer is a base initializer, this keeps track
+ /// \brief If the initializer is a base initializer, this keeps track
/// of whether the base is virtual or not.
bool IsVirtual : 1;
- /// IsWritten - Whether or not the initializer is explicitly written
+ /// \brief 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,
- /// it stores the number of array index variables stored after this
- /// object in memory.
+ /// If IsWritten is true, then this number keeps track of the textual order
+ /// of this initializer in the original sources, counting from 0; otherwise,
+ /// it stores the number of array index variables stored after this object
+ /// in memory.
unsigned SourceOrderOrNumArrayIndices : 13;
CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
@@ -1786,25 +1867,25 @@ class CXXCtorInitializer {
SourceLocation R, VarDecl **Indices, unsigned NumIndices);
public:
- /// CXXCtorInitializer - Creates a new base-class initializer.
+ /// \brief Creates a new base-class initializer.
explicit
CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual,
SourceLocation L, Expr *Init, SourceLocation R,
SourceLocation EllipsisLoc);
- /// CXXCtorInitializer - Creates a new member initializer.
+ /// \brief Creates a new member initializer.
explicit
CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
SourceLocation MemberLoc, SourceLocation L, Expr *Init,
SourceLocation R);
- /// CXXCtorInitializer - Creates a new anonymous field initializer.
+ /// \brief Creates a new anonymous field initializer.
explicit
CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
SourceLocation MemberLoc, SourceLocation L, Expr *Init,
SourceLocation R);
- /// CXXCtorInitializer - Creates a new delegating Initializer.
+ /// \brief Creates a new delegating initializer.
explicit
CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo,
SourceLocation L, Expr *Init, SourceLocation R);
@@ -1816,14 +1897,13 @@ public:
Expr *Init, SourceLocation R,
VarDecl **Indices, unsigned NumIndices);
- /// isBaseInitializer - Returns true when this initializer is
- /// initializing a base class.
+ /// \brief Determine whether this initializer is initializing a base class.
bool isBaseInitializer() const {
return Initializee.is<TypeSourceInfo*>() && !IsDelegating;
}
- /// isMemberInitializer - Returns true when this initializer is
- /// initializing a non-static data member.
+ /// \brief Determine whether this initializer is initializing a non-static
+ /// data member.
bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); }
bool isAnyMemberInitializer() const {
@@ -1834,15 +1914,18 @@ public:
return Initializee.is<IndirectFieldDecl*>();
}
- /// isInClassMemberInitializer - Returns true when this initializer is an
- /// implicit ctor initializer generated for a field with an initializer
- /// defined on the member declaration.
+ /// \brief Determine whether this initializer is an implicit initializer
+ /// generated for a field with an initializer defined on the member
+ /// declaration.
+ ///
+ /// In-class member initializers (also known as "non-static data member
+ /// initializations", NSDMIs) were introduced in C++11.
bool isInClassMemberInitializer() const {
return isa<CXXDefaultInitExpr>(Init);
}
- /// isDelegatingInitializer - Returns true when this initializer is creating
- /// a delegating constructor.
+ /// \brief Determine whether this initializer is creating a delegating
+ /// constructor.
bool isDelegatingInitializer() const {
return Initializee.is<TypeSourceInfo*>() && IsDelegating;
}
@@ -1864,7 +1947,7 @@ public:
TypeLoc getBaseClassLoc() const;
/// If this is a base class initializer, returns the type of the base class.
- /// Otherwise, returns NULL.
+ /// Otherwise, returns null.
const Type *getBaseClass() const;
/// Returns whether the base is virtual or not.
@@ -1880,9 +1963,8 @@ public:
return Initializee.dyn_cast<TypeSourceInfo *>();
}
- /// getMember - If this is a member initializer, returns the
- /// declaration of the non-static data member being
- /// initialized. Otherwise, returns NULL.
+ /// \brief If this is a member initializer, returns the declaration of the
+ /// non-static data member being initialized. Otherwise, returns null.
FieldDecl *getMember() const {
if (isMemberInitializer())
return Initializee.get<FieldDecl*>();
@@ -1912,7 +1994,7 @@ public:
/// \brief Determine the source range covering the entire initializer.
SourceRange getSourceRange() const LLVM_READONLY;
- /// isWritten - Returns true if this initializer is explicitly written
+ /// \brief Determine whether this initializer is explicitly written
/// in the source code.
bool isWritten() const { return IsWritten; }
@@ -1922,9 +2004,13 @@ public:
return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1;
}
- /// \brief Set the source order of this initializer. This method can only
- /// be called once for each initializer; it cannot be called on an
- /// initializer having a positive number of (implicit) array indices.
+ /// \brief Set the source order of this initializer.
+ ///
+ /// This can only be called once for each initializer; it cannot be called
+ /// on an initializer having a positive number of (implicit) array indices.
+ ///
+ /// This assumes that the initialzier was written in the source code, and
+ /// ensures that isWritten() returns true.
void setSourceOrder(int pos) {
assert(!IsWritten &&
"calling twice setSourceOrder() on the same initializer");
@@ -1969,34 +2055,28 @@ public:
Expr *getInit() const { return static_cast<Expr*>(Init); }
};
-/// CXXConstructorDecl - Represents a C++ constructor within a
-/// class. For example:
+/// \brief Represents a C++ constructor within a class.
///
-/// @code
+/// For example:
+///
+/// \code
/// class X {
/// public:
/// explicit X(int); // represented by a CXXConstructorDecl.
/// };
-/// @endcode
+/// \endcode
class CXXConstructorDecl : public CXXMethodDecl {
virtual void anchor();
- /// IsExplicitSpecified - Whether this constructor declaration has the
- /// 'explicit' keyword specified.
+ /// \brief Whether this constructor declaration has the \c explicit keyword
+ /// specified.
bool IsExplicitSpecified : 1;
- /// ImplicitlyDefined - Whether this constructor was implicitly
- /// defined by the compiler. When false, the constructor was defined
- /// by the user. In C++03, this flag will have the same value as
- /// Implicit. In C++0x, however, a constructor that is
- /// explicitly defaulted (i.e., defined with " = default") will have
- /// @c !Implicit && ImplicitlyDefined.
- bool ImplicitlyDefined : 1;
-
- /// Support for base and member initializers.
- /// CtorInitializers - The arguments used to initialize the base
- /// or member.
+ /// \name Support for base and member initializers.
+ /// \{
+ /// \brief The arguments used to initialize the base or member.
CXXCtorInitializer **CtorInitializers;
unsigned NumCtorInitializers;
+ /// \}
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
@@ -2005,8 +2085,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
bool isImplicitlyDeclared, bool isConstexpr)
: CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, isConstexpr, SourceLocation()),
- IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
- CtorInitializers(0), NumCtorInitializers(0) {
+ IsExplicitSpecified(isExplicitSpecified), CtorInitializers(0),
+ NumCtorInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -2020,52 +2100,31 @@ public:
bool isInline, bool isImplicitlyDeclared,
bool isConstexpr);
- /// isExplicitSpecified - Whether this constructor declaration has the
- /// 'explicit' keyword specified.
+ /// \brief Determine whether this constructor declaration has the
+ /// \c explicit keyword specified.
bool isExplicitSpecified() const { return IsExplicitSpecified; }
- /// isExplicit - Whether this constructor was marked "explicit" or not.
+ /// \brief Determine whether this constructor was marked "explicit" or not.
bool isExplicit() const {
- return cast<CXXConstructorDecl>(getFirstDeclaration())
- ->isExplicitSpecified();
- }
-
- /// isImplicitlyDefined - Whether this constructor was implicitly
- /// defined. If false, then this constructor was defined by the
- /// user. This operation can only be invoked if the constructor has
- /// already been defined.
- bool isImplicitlyDefined() const {
- assert(isThisDeclarationADefinition() &&
- "Can only get the implicit-definition flag once the "
- "constructor has been defined");
- return ImplicitlyDefined;
- }
-
- /// setImplicitlyDefined - Set whether this constructor was
- /// implicitly defined or not.
- void setImplicitlyDefined(bool ID) {
- assert(isThisDeclarationADefinition() &&
- "Can only set the implicit-definition flag once the constructor "
- "has been defined");
- ImplicitlyDefined = ID;
+ return cast<CXXConstructorDecl>(getFirstDecl())->isExplicitSpecified();
}
- /// init_iterator - Iterates through the member/base initializer list.
+ /// \brief Iterates through the member/base initializer list.
typedef CXXCtorInitializer **init_iterator;
- /// init_const_iterator - Iterates through the memberbase initializer list.
+ /// \brief Iterates through the member/base initializer list.
typedef CXXCtorInitializer * const * init_const_iterator;
- /// init_begin() - Retrieve an iterator to the first initializer.
+ /// \brief Retrieve an iterator to the first initializer.
init_iterator init_begin() { return CtorInitializers; }
- /// begin() - Retrieve an iterator to the first initializer.
+ /// \brief Retrieve an iterator to the first initializer.
init_const_iterator init_begin() const { return CtorInitializers; }
- /// init_end() - Retrieve an iterator past the last initializer.
+ /// \brief Retrieve an iterator past the last initializer.
init_iterator init_end() {
return CtorInitializers + NumCtorInitializers;
}
- /// end() - Retrieve an iterator past the last initializer.
+ /// \brief Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
return CtorInitializers + NumCtorInitializers;
}
@@ -2088,8 +2147,8 @@ public:
return init_const_reverse_iterator(init_begin());
}
- /// getNumArgs - Determine the number of arguments used to
- /// initialize the member or base.
+ /// \brief Determine the number of arguments used to initialize the member
+ /// or base.
unsigned getNumCtorInitializers() const {
return NumCtorInitializers;
}
@@ -2102,37 +2161,36 @@ public:
CtorInitializers = initializers;
}
- /// isDelegatingConstructor - Whether this constructor is a
- /// delegating constructor
+ /// \brief Determine whether this constructor is a delegating constructor.
bool isDelegatingConstructor() const {
return (getNumCtorInitializers() == 1) &&
CtorInitializers[0]->isDelegatingInitializer();
}
- /// getTargetConstructor - When this constructor delegates to
- /// another, retrieve the target
+ /// \brief When this constructor delegates to another, retrieve the target.
CXXConstructorDecl *getTargetConstructor() const;
- /// isDefaultConstructor - Whether this constructor is a default
+ /// Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
/// default-initialize a class of this type.
bool isDefaultConstructor() const;
- /// isCopyConstructor - Whether this constructor is a copy
- /// constructor (C++ [class.copy]p2, which can be used to copy the
- /// class. @p TypeQuals will be set to the qualifiers on the
- /// argument type. For example, @p TypeQuals would be set to @c
+ /// \brief Whether this constructor is a copy constructor (C++ [class.copy]p2,
+ /// which can be used to copy the class.
+ ///
+ /// \p TypeQuals will be set to the qualifiers on the
+ /// argument type. For example, \p TypeQuals would be set to \c
/// Qualifiers::Const for the following copy constructor:
///
- /// @code
+ /// \code
/// class X {
/// public:
/// X(const X&);
/// };
- /// @endcode
+ /// \endcode
bool isCopyConstructor(unsigned &TypeQuals) const;
- /// isCopyConstructor - Whether this constructor is a copy
+ /// Whether this constructor is a copy
/// constructor (C++ [class.copy]p2, which can be used to copy the
/// class.
bool isCopyConstructor() const {
@@ -2166,7 +2224,7 @@ public:
return isCopyOrMoveConstructor(Quals);
}
- /// isConvertingConstructor - Whether this constructor is a
+ /// Whether this constructor is a
/// converting constructor (C++ [class.conv.ctor]), which can be
/// used for user-defined conversions.
bool isConvertingConstructor(bool AllowExplicit) const;
@@ -2197,24 +2255,18 @@ public:
friend class ASTDeclWriter;
};
-/// CXXDestructorDecl - Represents a C++ destructor within a
-/// class. For example:
+/// \brief Represents a C++ destructor within a class.
///
-/// @code
+/// For example:
+///
+/// \code
/// class X {
/// public:
/// ~X(); // represented by a CXXDestructorDecl.
/// };
-/// @endcode
+/// \endcode
class CXXDestructorDecl : public CXXMethodDecl {
virtual void anchor();
- /// ImplicitlyDefined - Whether this destructor was implicitly
- /// defined by the compiler. When false, the destructor was defined
- /// by the user. In C++03, this flag will have the same value as
- /// Implicit. In C++0x, however, a destructor that is
- /// explicitly defaulted (i.e., defined with " = default") will have
- /// @c !Implicit && ImplicitlyDefined.
- bool ImplicitlyDefined : 1;
FunctionDecl *OperatorDelete;
@@ -2224,7 +2276,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, /*isConstexpr=*/false, SourceLocation()),
- ImplicitlyDefined(false), OperatorDelete(0) {
+ OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -2237,26 +2289,6 @@ public:
bool isImplicitlyDeclared);
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
- /// isImplicitlyDefined - Whether this destructor was implicitly
- /// defined. If false, then this destructor was defined by the
- /// user. This operation can only be invoked if the destructor has
- /// already been defined.
- bool isImplicitlyDefined() const {
- assert(isThisDeclarationADefinition() &&
- "Can only get the implicit-definition flag once the destructor has "
- "been defined");
- return ImplicitlyDefined;
- }
-
- /// setImplicitlyDefined - Set whether this destructor was
- /// implicitly defined or not.
- void setImplicitlyDefined(bool ID) {
- assert(isThisDeclarationADefinition() &&
- "Can only set the implicit-definition flag once the destructor has "
- "been defined");
- ImplicitlyDefined = ID;
- }
-
void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
@@ -2268,19 +2300,20 @@ public:
friend class ASTDeclWriter;
};
-/// CXXConversionDecl - Represents a C++ conversion function within a
-/// class. For example:
+/// \brief Represents a C++ conversion function within a class.
+///
+/// For example:
///
-/// @code
+/// \code
/// class X {
/// public:
/// operator bool();
/// };
-/// @endcode
+/// \endcode
class CXXConversionDecl : public CXXMethodDecl {
virtual void anchor();
- /// IsExplicitSpecified - Whether this conversion function declaration is
- /// marked "explicit", meaning that it can only be applied when the user
+ /// Whether this conversion function declaration is marked
+ /// "explicit", meaning that it can only be applied when the user
/// explicitly wrote a cast. This is a C++0x feature.
bool IsExplicitSpecified : 1;
@@ -2303,21 +2336,20 @@ public:
SourceLocation EndLocation);
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// IsExplicitSpecified - Whether this conversion function declaration is
- /// marked "explicit", meaning that it can only be applied when the user
- /// explicitly wrote a cast. This is a C++0x feature.
+ /// Whether this conversion function declaration is marked
+ /// "explicit", meaning that it can only be used for direct initialization
+ /// (including explitly written casts). This is a C++11 feature.
bool isExplicitSpecified() const { return IsExplicitSpecified; }
- /// isExplicit - Whether this is an explicit conversion operator
- /// (C++0x only). Explicit conversion operators are only considered
- /// when the user has explicitly written a cast.
+ /// \brief Whether this is an explicit conversion operator (C++11 and later).
+ ///
+ /// Explicit conversion operators are only considered for direct
+ /// initialization, e.g., when the user has explicitly written a cast.
bool isExplicit() const {
- return cast<CXXConversionDecl>(getFirstDeclaration())
- ->isExplicitSpecified();
+ return cast<CXXConversionDecl>(getFirstDecl())->isExplicitSpecified();
}
- /// getConversionType - Returns the type that this conversion
- /// function is converting to.
+ /// \brief Returns the type that this conversion function is converting to.
QualType getConversionType() const {
return getType()->getAs<FunctionType>()->getResultType();
}
@@ -2334,32 +2366,37 @@ public:
friend class ASTDeclWriter;
};
-/// LinkageSpecDecl - This represents a linkage specification. For example:
-/// extern "C" void foo();
+/// \brief Represents a linkage specification.
///
+/// For example:
+/// \code
+/// extern "C" void foo();
+/// \endcode
class LinkageSpecDecl : public Decl, public DeclContext {
virtual void anchor();
public:
- /// LanguageIDs - Used to represent the language in a linkage
- /// specification. The values are part of the serialization abi for
- /// ASTs and cannot be changed without altering that abi. To help
- /// ensure a stable abi for this, we choose the DW_LANG_ encodings
+ /// \brief Represents the language in a linkage specification.
+ ///
+ /// The values are part of the serialization ABI for
+ /// ASTs and cannot be changed without altering that ABI. To help
+ /// ensure a stable ABI for this, we choose the DW_LANG_ encodings
/// from the dwarf standard.
enum LanguageIDs {
lang_c = /* DW_LANG_C */ 0x0002,
lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004
};
private:
- /// Language - The language for this linkage specification.
+ /// \brief The language for this linkage specification.
unsigned Language : 3;
- /// True if this linkage spec has brances. This is needed so that hasBraces()
- /// returns the correct result while the linkage spec body is being parsed.
- /// Once RBraceLoc has been set this is not used, so it doesn't need to be
- /// serialized.
+ /// \brief True if this linkage spec has braces.
+ ///
+ /// This is needed so that hasBraces() returns the correct result while the
+ /// linkage spec body is being parsed. Once RBraceLoc has been set this is
+ /// not used, so it doesn't need to be serialized.
unsigned HasBraces : 1;
- /// ExternLoc - The source location for the extern keyword.
+ /// \brief The source location for the extern keyword.
SourceLocation ExternLoc;
- /// RBraceLoc - The source location for the right brace (if valid).
+ /// \brief The source location for the right brace (if valid).
SourceLocation RBraceLoc;
LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
@@ -2417,34 +2454,38 @@ public:
}
};
-/// UsingDirectiveDecl - Represents C++ using-directive. For example:
+/// \brief Represents C++ using-directive.
///
+/// For example:
+/// \code
/// using namespace std;
+/// \endcode
///
-// NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide
-// artificial names for all using-directives in order to store
-// them in DeclContext effectively.
+/// \note UsingDirectiveDecl should be Decl not NamedDecl, but we provide
+/// artificial names for all using-directives in order to store
+/// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
virtual void anchor();
- /// \brief The location of the "using" keyword.
+ /// \brief The location of the \c using keyword.
SourceLocation UsingLoc;
- /// SourceLocation - Location of 'namespace' token.
+ /// \brief The location of the \c namespace keyword.
SourceLocation NamespaceLoc;
/// \brief The nested-name-specifier that precedes the namespace.
NestedNameSpecifierLoc QualifierLoc;
- /// NominatedNamespace - Namespace nominated by using-directive.
+ /// \brief The namespace nominated by this using-directive.
NamedDecl *NominatedNamespace;
/// Enclosing context containing both using-directive and nominated
/// namespace.
DeclContext *CommonAncestor;
- /// getUsingDirectiveName - Returns special DeclarationName used by
- /// using-directives. This is only used by DeclContext for storing
- /// UsingDirectiveDecls in its lookup structure.
+ /// \brief Returns special DeclarationName used by using-directives.
+ ///
+ /// This is only used by DeclContext for storing UsingDirectiveDecls in
+ /// its lookup structure.
static DeclarationName getName() {
return DeclarationName::getUsingDirectiveName();
}
@@ -2475,7 +2516,7 @@ public:
return NominatedNamespace;
}
- /// getNominatedNamespace - Returns namespace nominated by using-directive.
+ /// \brief Returns the namespace nominated by this using-directive.
NamespaceDecl *getNominatedNamespace();
const NamespaceDecl *getNominatedNamespace() const {
@@ -2487,14 +2528,14 @@ public:
DeclContext *getCommonAncestor() { return CommonAncestor; }
const DeclContext *getCommonAncestor() const { return CommonAncestor; }
- /// \brief Return the location of the "using" keyword.
+ /// \brief Return the location of the \c using keyword.
SourceLocation getUsingLoc() const { return UsingLoc; }
// FIXME: Could omit 'Key' in name.
- /// getNamespaceKeyLocation - Returns location of namespace keyword.
+ /// \brief Returns the location of the \c namespace keyword.
SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
- /// getIdentLocation - Returns location of identifier.
+ /// \brief Returns the location of this using declaration's identifier.
SourceLocation getIdentLocation() const { return getLocation(); }
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2523,23 +2564,25 @@ public:
///
/// For example:
///
-/// @code
+/// \code
/// namespace Foo = Bar;
-/// @endcode
+/// \endcode
class NamespaceAliasDecl : public NamedDecl {
virtual void anchor();
- /// \brief The location of the "namespace" keyword.
+ /// \brief The location of the \c namespace keyword.
SourceLocation NamespaceLoc;
- /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc.
+ /// \brief The location of the namespace's identifier.
+ ///
+ /// This is accessed by TargetNameLoc.
SourceLocation IdentLoc;
/// \brief The nested-name-specifier that precedes the namespace.
NestedNameSpecifierLoc QualifierLoc;
- /// Namespace - The Decl that this alias points to. Can either be a
- /// NamespaceDecl or a NamespaceAliasDecl.
+ /// \brief The Decl that this alias points to, either a NamespaceDecl or
+ /// a NamespaceAliasDecl.
NamedDecl *Namespace;
NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
@@ -2579,7 +2622,7 @@ public:
/// "namespace foo = ns::bar;".
SourceLocation getAliasLoc() const { return getLocation(); }
- /// Returns the location of the 'namespace' keyword.
+ /// Returns the location of the \c namespace keyword.
SourceLocation getNamespaceLoc() const { return NamespaceLoc; }
/// Returns the location of the identifier in the named namespace.
@@ -2611,7 +2654,7 @@ public:
/// (resolved) using declaration.
///
/// For example,
-/// @code
+/// \code
/// namespace A {
/// void foo();
/// }
@@ -2619,8 +2662,8 @@ public:
/// using A::foo; // <- a UsingDecl
/// // Also creates a UsingShadowDecl for A::foo() in B
/// }
-/// @endcode
-class UsingShadowDecl : public NamedDecl {
+/// \endcode
+class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
virtual void anchor();
/// The referenced declaration.
@@ -2643,6 +2686,17 @@ class UsingShadowDecl : public NamedDecl {
setImplicit();
}
+ typedef Redeclarable<UsingShadowDecl> redeclarable_base;
+ virtual UsingShadowDecl *getNextRedeclaration() {
+ return RedeclLink.getNext();
+ }
+ virtual UsingShadowDecl *getPreviousDeclImpl() {
+ return getPreviousDecl();
+ }
+ virtual UsingShadowDecl *getMostRecentDeclImpl() {
+ return getMostRecentDecl();
+ }
+
public:
static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
@@ -2651,7 +2705,20 @@ public:
}
static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
+
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+
+ virtual UsingShadowDecl *getCanonicalDecl() {
+ return getFirstDecl();
+ }
+ virtual const UsingShadowDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
/// \brief Gets the underlying declaration which has been brought into the
/// local scope.
NamedDecl *getTargetDecl() const { return Underlying; }
@@ -2683,20 +2750,20 @@ public:
/// \brief Represents a C++ using-declaration.
///
/// For example:
-/// @code
+/// \code
/// using someNameSpace::someIdentifier;
-/// @endcode
+/// \endcode
class UsingDecl : public NamedDecl {
virtual void anchor();
- /// \brief The source location of the "using" location itself.
+ /// \brief The source location of the 'using' keyword itself.
SourceLocation UsingLocation;
/// \brief The nested-name-specifier that precedes the name.
NestedNameSpecifierLoc QualifierLoc;
- /// DNLoc - Provides source/type location info for the
- /// declaration name embedded in the ValueDecl base class.
+ /// \brief Provides source/type location info for the declaration name
+ /// embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
/// \brief The first shadow declaration of the shadow decl chain associated
@@ -2708,18 +2775,18 @@ class UsingDecl : public NamedDecl {
UsingDecl(DeclContext *DC, SourceLocation UL,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
+ const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
UsingLocation(UL), QualifierLoc(QualifierLoc),
- DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, IsTypeNameArg) {
+ DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, HasTypenameKeyword) {
}
public:
- /// \brief Returns the source location of the "using" keyword.
- SourceLocation getUsingLocation() const { return UsingLocation; }
+ /// \brief Return the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
- void setUsingLocation(SourceLocation L) { UsingLocation = L; }
+ void setUsingLoc(SourceLocation L) { UsingLocation = L; }
/// \brief Retrieve the nested-name-specifier that qualifies the name,
/// with source-location information.
@@ -2734,13 +2801,16 @@ public:
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
+ /// \brief Return true if it is a C++03 access declaration (no 'using').
+ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
+
/// \brief Return true if the using declaration has 'typename'.
- bool isTypeName() const { return FirstUsingShadow.getInt(); }
+ bool hasTypename() const { return FirstUsingShadow.getInt(); }
/// \brief Sets whether the using declaration has 'typename'.
- void setTypeName(bool TN) { FirstUsingShadow.setInt(TN); }
+ void setTypename(bool TN) { FirstUsingShadow.setInt(TN); }
- /// \brief Iterates through the using shadow declarations assosiated with
+ /// \brief Iterates through the using shadow declarations associated with
/// this using declaration.
class shadow_iterator {
/// \brief The current using shadow declaration.
@@ -2796,13 +2866,11 @@ public:
SourceLocation UsingL,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
- bool IsTypeNameArg);
+ bool HasTypenameKeyword);
static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(UsingLocation, getNameInfo().getEndLoc());
- }
+
+ SourceRange getSourceRange() const LLVM_READONLY;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Using; }
@@ -2817,11 +2885,11 @@ public:
/// Unlike non-dependent using declarations, these *only* bring through
/// non-types; otherwise they would break two-phase lookup.
///
-/// @code
+/// \code
/// template \<class T> class A : public Base<T> {
/// using Base<T>::foo;
/// };
-/// @endcode
+/// \endcode
class UnresolvedUsingValueDecl : public ValueDecl {
virtual void anchor();
@@ -2831,8 +2899,8 @@ class UnresolvedUsingValueDecl : public ValueDecl {
/// \brief The nested-name-specifier that precedes the name.
NestedNameSpecifierLoc QualifierLoc;
- /// DNLoc - Provides source/type location info for the
- /// declaration name embedded in the ValueDecl base class.
+ /// \brief Provides source/type location info for the declaration name
+ /// embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
@@ -2852,6 +2920,9 @@ public:
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+ /// \brief Return true if it is a C++03 access declaration (no 'using').
+ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
+
/// \brief Retrieve the nested-name-specifier that qualifies the name,
/// with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
@@ -2873,9 +2944,7 @@ public:
static UnresolvedUsingValueDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
- SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(UsingLocation, getNameInfo().getEndLoc());
- }
+ SourceRange getSourceRange() const LLVM_READONLY;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
@@ -2884,23 +2953,20 @@ public:
friend class ASTDeclWriter;
};
-/// @brief Represents a dependent using declaration which was marked with
+/// \brief Represents a dependent using declaration which was marked with
/// \c typename.
///
-/// @code
+/// \code
/// template \<class T> class A : public Base<T> {
/// using typename Base<T>::foo;
/// };
-/// @endcode
+/// \endcode
///
/// The type associated with an unresolved using typename decl is
/// currently always a typename type.
class UnresolvedUsingTypenameDecl : public TypeDecl {
virtual void anchor();
- /// \brief The source location of the 'using' keyword
- SourceLocation UsingLocation;
-
/// \brief The source location of the 'typename' keyword
SourceLocation TypenameLocation;
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 84f3698d6b58..9c626c80aaee 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -18,6 +18,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
@@ -26,23 +27,29 @@ namespace clang {
class DependentDiagnostic;
-/// StoredDeclsList - This is an array of decls optimized a common case of only
-/// containing one entry.
+/// \brief An array of decls optimized for the common case of only containing
+/// one entry.
struct StoredDeclsList {
- /// DeclsTy - When in vector form, this is what the Data pointer points to.
+ /// \brief When in vector form, this is what the Data pointer points to.
typedef SmallVector<NamedDecl *, 4> DeclsTy;
+ /// \brief A collection of declarations, with a flag to indicate if we have
+ /// further external declarations.
+ typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy;
+
/// \brief The stored data, which will be either a pointer to a NamedDecl,
- /// or a pointer to a vector.
- llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
+ /// or a pointer to a vector with a flag to indicate if there are further
+ /// external declarations.
+ llvm::PointerUnion<NamedDecl*, DeclsAndHasExternalTy> Data;
public:
StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
if (DeclsTy *RHSVec = RHS.getAsVector())
- Data = new DeclsTy(*RHSVec);
+ Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec),
+ RHS.hasExternalDecls());
}
~StoredDeclsList() {
@@ -56,7 +63,7 @@ public:
delete Vector;
Data = RHS.Data;
if (DeclsTy *RHSVec = RHS.getAsVector())
- Data = new DeclsTy(*RHSVec);
+ Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), hasExternalDecls());
return *this;
}
@@ -66,8 +73,27 @@ public:
return Data.dyn_cast<NamedDecl *>();
}
+ DeclsAndHasExternalTy getAsVectorAndHasExternal() const {
+ return Data.dyn_cast<DeclsAndHasExternalTy>();
+ }
+
DeclsTy *getAsVector() const {
- return Data.dyn_cast<DeclsTy *>();
+ return getAsVectorAndHasExternal().getPointer();
+ }
+
+ bool hasExternalDecls() const {
+ return getAsVectorAndHasExternal().getInt();
+ }
+
+ void setHasExternalDecls() {
+ if (DeclsTy *Vec = getAsVector())
+ Data = DeclsAndHasExternalTy(Vec, true);
+ else {
+ DeclsTy *VT = new DeclsTy();
+ if (NamedDecl *OldD = getAsDecl())
+ VT->push_back(OldD);
+ Data = DeclsAndHasExternalTy(VT, true);
+ }
}
void setOnlyValue(NamedDecl *ND) {
@@ -110,6 +136,8 @@ public:
Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
std::mem_fun(&Decl::isFromASTFile)),
Vec.end());
+ // Don't have any external decls any more.
+ Data = DeclsAndHasExternalTy(&Vec, false);
}
}
@@ -165,12 +193,14 @@ public:
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
+ assert(!isNull() && "don't AddSubsequentDecl when we have no decls");
+
// If this is the second decl added to the list, convert this to vector
// form.
if (NamedDecl *OldD = getAsDecl()) {
DeclsTy *VT = new DeclsTy();
VT->push_back(OldD);
- Data = VT;
+ Data = DeclsAndHasExternalTy(VT, false);
}
DeclsTy &Vec = *getAsVector();
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 3a12878e7414..be6f2eb3e3ad 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -220,7 +220,7 @@ public:
};
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
- return friend_iterator(data().FirstFriend);
+ return friend_iterator(getFirstFriend());
}
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
@@ -228,7 +228,7 @@ inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
}
inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
- assert(FD->NextFriend == 0 && "friend already has next friend?");
+ assert(!FD->NextFriend && "friend already has next friend?");
FD->NextFriend = data().FirstFriend;
data().FirstFriend = FD;
}
diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h
index 4477c25a9135..c16975a3307f 100644
--- a/include/clang/AST/DeclLookups.h
+++ b/include/clang/AST/DeclLookups.h
@@ -37,6 +37,8 @@ public:
StoredDeclsMap::iterator End)
: It(It), End(End) {}
+ DeclarationName getLookupName() const { return It->first; }
+
reference operator*() const { return It->second.getLookupResult(); }
pointer operator->() const { return It->second.getLookupResult(); }
@@ -66,7 +68,7 @@ public:
}
};
-DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
+inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (Primary->hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
@@ -75,7 +77,7 @@ DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
return all_lookups_iterator();
}
-DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
+inline DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (Primary->hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
@@ -84,6 +86,22 @@ DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
return all_lookups_iterator();
}
+inline
+DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const {
+ DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
+ if (StoredDeclsMap *Map = Primary->getLookupPtr())
+ return all_lookups_iterator(Map->begin(), Map->end());
+ return all_lookups_iterator();
+}
+
+inline
+DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const {
+ DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
+ if (StoredDeclsMap *Map = Primary->getLookupPtr())
+ return all_lookups_iterator(Map->end(), Map->end());
+ return all_lookups_iterator();
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 40de0135a74f..2e760d658e43 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -452,7 +452,7 @@ public:
}
/// \brief Determine whether this method has a body.
- virtual bool hasBody() const { return Body; }
+ virtual bool hasBody() const { return Body.isValid(); }
/// \brief Retrieve the body of this method, if it has one.
virtual Stmt *getBody() const;
@@ -463,7 +463,7 @@ public:
void setBody(Stmt *B) { Body = B; }
/// \brief Returns whether this specific method is a definition.
- bool isThisDeclarationADefinition() const { return Body; }
+ bool isThisDeclarationADefinition() const { return hasBody(); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -553,6 +553,9 @@ public:
typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap;
+ typedef llvm::DenseMap<const ObjCProtocolDecl *, ObjCPropertyDecl*>
+ ProtocolPropertyMap;
+
typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder;
/// This routine collects list of properties to be implemented in the class.
@@ -1133,6 +1136,8 @@ public:
return lookupInstanceVariable(IVarName, ClassDeclared);
}
+ ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
+
// Lookup a method. First, we search locally. If a method isn't
// found, we search referenced protocols and class categories.
ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
@@ -1196,14 +1201,11 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
/// Retrieves the canonical declaration of this Objective-C class.
- ObjCInterfaceDecl *getCanonicalDecl() {
- return getFirstDeclaration();
- }
- const ObjCInterfaceDecl *getCanonicalDecl() const {
- return getFirstDeclaration();
- }
+ ObjCInterfaceDecl *getCanonicalDecl() { return getFirstDecl(); }
+ const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
// Low-level accessor
const Type *getTypeForDecl() const { return TypeForDecl; }
@@ -1244,10 +1246,12 @@ private:
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
- bool synthesized)
+ bool synthesized,
+ bool backingIvarReferencedInAccessor)
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
/*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
- NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
+ NextIvar(0), DeclAccess(ac), Synthesized(synthesized),
+ BackingIvarReferencedInAccessor(backingIvarReferencedInAccessor) {}
public:
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
@@ -1255,7 +1259,8 @@ public:
IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo,
AccessControl ac, Expr *BW = NULL,
- bool synthesized=false);
+ bool synthesized=false,
+ bool backingIvarReferencedInAccessor=false);
static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -1277,6 +1282,13 @@ public:
return DeclAccess == None ? Protected : AccessControl(DeclAccess);
}
+ void setBackingIvarReferencedInAccessor(bool val) {
+ BackingIvarReferencedInAccessor = val;
+ }
+ bool getBackingIvarReferencedInAccessor() const {
+ return BackingIvarReferencedInAccessor;
+ }
+
void setSynthesize(bool synth) { Synthesized = synth; }
bool getSynthesize() const { return Synthesized; }
@@ -1291,6 +1303,7 @@ private:
// NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
unsigned DeclAccess : 3;
unsigned Synthesized : 1;
+ unsigned BackingIvarReferencedInAccessor : 1;
};
@@ -1502,17 +1515,17 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
/// Retrieves the canonical declaration of this Objective-C protocol.
- ObjCProtocolDecl *getCanonicalDecl() {
- return getFirstDeclaration();
- }
- const ObjCProtocolDecl *getCanonicalDecl() const {
- return getFirstDeclaration();
- }
+ ObjCProtocolDecl *getCanonicalDecl() { return getFirstDecl(); }
+ const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
virtual void collectPropertiesToImplement(PropertyMap &PM,
PropertyDeclOrder &PO) const;
+
+void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
+ ProtocolPropertyMap &PM) const;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCProtocol; }
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index ca92040c3286..42fe907aa174 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -1,4 +1,4 @@
-//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===//
+//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines OpenMP nodes.
+/// \brief This file defines OpenMP nodes for declarative directives.
///
//===----------------------------------------------------------------------===//
@@ -20,8 +20,6 @@
namespace clang {
-class DeclRefExpr;
-
/// \brief This represents '#pragma omp threadprivate ...' directive.
/// For example, in the following, both 'a' and 'A::b' are threadprivate:
///
@@ -43,29 +41,29 @@ class OMPThreadPrivateDecl : public Decl {
OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
Decl(DK, DC, L), NumVars(0) { }
- ArrayRef<const DeclRefExpr *> getVars() const {
- return ArrayRef<const DeclRefExpr *>(
- reinterpret_cast<const DeclRefExpr * const *>(this + 1),
+ ArrayRef<const Expr *> getVars() const {
+ return ArrayRef<const Expr *>(
+ reinterpret_cast<const Expr * const *>(this + 1),
NumVars);
}
- llvm::MutableArrayRef<DeclRefExpr *> getVars() {
- return llvm::MutableArrayRef<DeclRefExpr *>(
- reinterpret_cast<DeclRefExpr **>(this + 1),
+ llvm::MutableArrayRef<Expr *> getVars() {
+ return llvm::MutableArrayRef<Expr *>(
+ reinterpret_cast<Expr **>(this + 1),
NumVars);
}
- void setVars(ArrayRef<DeclRefExpr *> VL);
+ void setVars(ArrayRef<Expr *> VL);
public:
static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
- ArrayRef<DeclRefExpr *> VL);
+ ArrayRef<Expr *> VL);
static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
unsigned ID, unsigned N);
- typedef llvm::MutableArrayRef<DeclRefExpr *>::iterator varlist_iterator;
- typedef ArrayRef<const DeclRefExpr *>::iterator varlist_const_iterator;
+ typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator;
+ typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
unsigned varlist_size() const { return NumVars; }
bool varlist_empty() const { return NumVars == 0; }
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 425a617738b0..24bd28a75aaa 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -34,6 +34,8 @@ class TemplateTypeParmDecl;
class NonTypeTemplateParmDecl;
class TemplateTemplateParmDecl;
class TypeAliasTemplateDecl;
+class VarTemplateDecl;
+class VarTemplatePartialSpecializationDecl;
/// \brief Stores a template parameter of any kind.
typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
@@ -629,9 +631,9 @@ public:
template <class decl_type> friend class RedeclarableTemplate;
/// \brief Retrieves the canonical declaration of this template.
- RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); }
- const RedeclarableTemplateDecl *getCanonicalDecl() const {
- return getFirstDeclaration();
+ RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDecl(); }
+ const RedeclarableTemplateDecl *getCanonicalDecl() const {
+ return getFirstDecl();
}
/// \brief Determines whether this template was a specialization of a
@@ -713,6 +715,7 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -743,7 +746,7 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common : CommonBase {
- Common() : InjectedArgs(0) { }
+ Common() : InjectedArgs(), LazySpecializations() { }
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
@@ -757,6 +760,13 @@ protected:
/// template, and is allocated lazily, since most function templates do not
/// require the use of this information.
TemplateArgument *InjectedArgs;
+
+ /// \brief If non-null, points to an array of specializations known only
+ /// by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations
+ /// that follow.
+ uint32_t *LazySpecializations;
};
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
@@ -771,12 +781,13 @@ protected:
friend class FunctionDecl;
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
- getSpecializations() const {
- return getCommonPtr()->Specializations;
- }
+ getSpecializations() const;
/// \brief Add a specialization of this function template.
///
@@ -815,14 +826,14 @@ public:
/// NULL if no such declaration exists.
FunctionTemplateDecl *getPreviousDecl() {
return cast_or_null<FunctionTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDecl() const {
return cast_or_null<FunctionTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
@@ -847,7 +858,7 @@ public:
/// arguments for a function template, the notion is convenient when
/// we need to perform substitutions inside the definition of a function
/// template.
- std::pair<const TemplateArgument *, unsigned> getInjectedTemplateArgs();
+ ArrayRef<TemplateArgument> getInjectedTemplateArgs();
/// \brief Create a function template node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1377,7 +1388,7 @@ class ClassTemplateSpecializationDecl
/// \brief The template argument list deduced for the class template
/// partial specialization itself.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
};
/// \brief The template that this specialization specializes
@@ -1402,7 +1413,7 @@ class ClassTemplateSpecializationDecl
ExplicitSpecializationInfo *ExplicitInfo;
/// \brief The template arguments used to describe this specialization.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
/// \brief The point where this template was instantiated (if any)
SourceLocation PointOfInstantiation;
@@ -1438,9 +1449,9 @@ public:
bool Qualified) const;
ClassTemplateSpecializationDecl *getMostRecentDecl() {
- CXXRecordDecl *Recent
- = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDecl());
- if (!isa<ClassTemplateSpecializationDecl>(Recent)) {
+ CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>(
+ this)->getMostRecentDecl();
+ while (!isa<ClassTemplateSpecializationDecl>(Recent)) {
// FIXME: Does injected class name need to be in the redeclarations chain?
assert(Recent->isInjectedClassName() && Recent->getPreviousDecl());
Recent = Recent->getPreviousDecl();
@@ -1553,7 +1564,7 @@ public:
/// instantiation of the given class template partial specialization whose
/// template arguments have been deduced.
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
- TemplateArgumentList *TemplateArgs) {
+ const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Already set to a class template partial specialization!");
SpecializedPartialSpecialization *PS
@@ -1639,13 +1650,7 @@ class ClassTemplatePartialSpecializationDecl
/// \brief The source info for the template arguments as written.
/// FIXME: redundant with TypeAsWritten?
- TemplateArgumentLoc *ArgsAsWritten;
- unsigned NumArgsAsWritten;
-
- /// \brief Sequence number indicating when this class template partial
- /// specialization was added to the set of partial specializations for
- /// its owning class template.
- unsigned SequenceNumber;
+ const ASTTemplateArgumentListInfo *ArgsAsWritten;
/// \brief The class template partial specialization from which this
/// class template partial specialization was instantiated.
@@ -1663,16 +1668,12 @@ class ClassTemplatePartialSpecializationDecl
ClassTemplateDecl *SpecializedTemplate,
const TemplateArgument *Args,
unsigned NumArgs,
- TemplateArgumentLoc *ArgInfos,
- unsigned NumArgInfos,
- ClassTemplatePartialSpecializationDecl *PrevDecl,
- unsigned SequenceNumber);
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ClassTemplatePartialSpecializationDecl *PrevDecl);
ClassTemplatePartialSpecializationDecl()
: ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization),
- TemplateParams(0), ArgsAsWritten(0),
- NumArgsAsWritten(0), SequenceNumber(0),
- InstantiatedFromMember(0, false) { }
+ TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) { }
public:
static ClassTemplatePartialSpecializationDecl *
@@ -1684,15 +1685,15 @@ public:
unsigned NumArgs,
const TemplateArgumentListInfo &ArgInfos,
QualType CanonInjectedType,
- ClassTemplatePartialSpecializationDecl *PrevDecl,
- unsigned SequenceNumber);
+ ClassTemplatePartialSpecializationDecl *PrevDecl);
static ClassTemplatePartialSpecializationDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
ClassTemplatePartialSpecializationDecl *getMostRecentDecl() {
return cast<ClassTemplatePartialSpecializationDecl>(
- ClassTemplateSpecializationDecl::getMostRecentDecl());
+ static_cast<ClassTemplateSpecializationDecl *>(
+ this)->getMostRecentDecl());
}
/// Get the list of template parameters
@@ -1701,19 +1702,10 @@ public:
}
/// Get the template arguments as written.
- TemplateArgumentLoc *getTemplateArgsAsWritten() const {
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
}
- /// Get the number of template arguments as written.
- unsigned getNumTemplateArgsAsWritten() const {
- return NumArgsAsWritten;
- }
-
- /// \brief Get the sequence number for this class template partial
- /// specialization.
- unsigned getSequenceNumber() const { return SequenceNumber; }
-
/// \brief Retrieve the member class template partial specialization from
/// which this particular class template partial specialization was
/// instantiated.
@@ -1735,15 +1727,15 @@ public:
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
void setInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *PartialSpec) {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
First->InstantiatedFromMember.setPointer(PartialSpec);
}
@@ -1764,15 +1756,15 @@ public:
/// struct X<int>::Inner<T*> { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}
/// \brief Note that this member template is a specialization.
void setMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
@@ -1821,7 +1813,7 @@ protected:
QualType InjectedClassNameType;
/// \brief If non-null, points to an array of specializations (including
- /// partial specializations) known ownly by their external declaration IDs.
+ /// partial specializations) known only by their external declaration IDs.
///
/// The first value in the array is the number of of specializations/
/// partial specializations that follow.
@@ -1900,14 +1892,23 @@ public:
/// NULL if no such declaration exists.
ClassTemplateDecl *getPreviousDecl() {
return cast_or_null<ClassTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
/// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists.
const ClassTemplateDecl *getPreviousDecl() const {
return cast_or_null<ClassTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
+ }
+
+ ClassTemplateDecl *getMostRecentDecl() {
+ return cast<ClassTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
+ }
+ const ClassTemplateDecl *getMostRecentDecl() const {
+ return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl();
}
ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
@@ -1926,11 +1927,6 @@ public:
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
void *InsertPos);
- /// \brief Return the next partial specialization sequence number.
- unsigned getNextPartialSpecSequenceNumber() {
- return getPartialSpecializations().size();
- }
-
/// \brief Retrieve the partial specializations as an ordered list.
void getPartialSpecializations(
SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
@@ -2139,14 +2135,15 @@ public:
/// NULL if no such declaration exists.
TypeAliasTemplateDecl *getPreviousDecl() {
return cast_or_null<TypeAliasTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const TypeAliasTemplateDecl *getPreviousDecl() const {
return cast_or_null<TypeAliasTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
}
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
@@ -2239,6 +2236,578 @@ public:
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
: Function(FTD) { }
+/// \brief Represents a variable template specialization, which refers to
+/// a variable template with a given set of template arguments.
+///
+/// Variable template specializations represent both explicit
+/// specializations of variable templates, as in the example below, and
+/// implicit instantiations of variable templates.
+///
+/// \code
+/// template<typename T> constexpr T pi = T(3.1415926535897932385);
+///
+/// template<>
+/// constexpr float pi<float>; // variable template specialization pi<float>
+/// \endcode
+class VarTemplateSpecializationDecl : public VarDecl,
+ public llvm::FoldingSetNode {
+
+ /// \brief Structure that stores information about a variable template
+ /// specialization that was instantiated from a variable template partial
+ /// specialization.
+ struct SpecializedPartialSpecialization {
+ /// \brief The variable template partial specialization from which this
+ /// variable template specialization was instantiated.
+ VarTemplatePartialSpecializationDecl *PartialSpecialization;
+
+ /// \brief The template argument list deduced for the variable template
+ /// partial specialization itself.
+ const TemplateArgumentList *TemplateArgs;
+ };
+
+ /// \brief The template that this specialization specializes.
+ llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *>
+ SpecializedTemplate;
+
+ /// \brief Further info for explicit template specialization/instantiation.
+ struct ExplicitSpecializationInfo {
+ /// \brief The type-as-written.
+ TypeSourceInfo *TypeAsWritten;
+ /// \brief The location of the extern keyword.
+ SourceLocation ExternLoc;
+ /// \brief The location of the template keyword.
+ SourceLocation TemplateKeywordLoc;
+
+ ExplicitSpecializationInfo()
+ : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {}
+ };
+
+ /// \brief Further info for explicit template specialization/instantiation.
+ /// Does not apply to implicit specializations.
+ ExplicitSpecializationInfo *ExplicitInfo;
+
+ /// \brief The template arguments used to describe this specialization.
+ const TemplateArgumentList *TemplateArgs;
+ TemplateArgumentListInfo TemplateArgsInfo;
+
+ /// \brief The point where this template was instantiated (if any).
+ SourceLocation PointOfInstantiation;
+
+ /// \brief The kind of specialization this declaration refers to.
+ /// Really a value of type TemplateSpecializationKind.
+ unsigned SpecializationKind : 3;
+
+protected:
+ VarTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ VarTemplateDecl *SpecializedTemplate,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ explicit VarTemplateSpecializationDecl(Kind DK);
+
+public:
+ static VarTemplateSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs);
+ static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ virtual void getNameForDiagnostic(raw_ostream &OS,
+ const PrintingPolicy &Policy,
+ bool Qualified) const;
+
+ VarTemplateSpecializationDecl *getMostRecentDecl() {
+ VarDecl *Recent = static_cast<VarDecl *>(this)->getMostRecentDecl();
+ return cast<VarTemplateSpecializationDecl>(Recent);
+ }
+
+ /// \brief Retrieve the template that this specialization specializes.
+ VarTemplateDecl *getSpecializedTemplate() const;
+
+ /// \brief Retrieve the template arguments of the variable template
+ /// specialization.
+ const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
+
+ // TODO: Always set this when creating the new specialization?
+ void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
+
+ const TemplateArgumentListInfo &getTemplateArgsInfo() const {
+ return TemplateArgsInfo;
+ }
+
+ /// \brief Determine the kind of specialization that this
+ /// declaration represents.
+ TemplateSpecializationKind getSpecializationKind() const {
+ return static_cast<TemplateSpecializationKind>(SpecializationKind);
+ }
+
+ bool isExplicitSpecialization() const {
+ return getSpecializationKind() == TSK_ExplicitSpecialization;
+ }
+
+ /// \brief True if this declaration is an explicit specialization,
+ /// explicit instantiation declaration, or explicit instantiation
+ /// definition.
+ bool isExplicitInstantiationOrSpecialization() const {
+ switch (getTemplateSpecializationKind()) {
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ return false;
+ }
+ llvm_unreachable("bad template specialization kind");
+ }
+
+ void setSpecializationKind(TemplateSpecializationKind TSK) {
+ SpecializationKind = TSK;
+ }
+
+ /// \brief Get the point of instantiation (if any), or null if none.
+ SourceLocation getPointOfInstantiation() const {
+ return PointOfInstantiation;
+ }
+
+ void setPointOfInstantiation(SourceLocation Loc) {
+ assert(Loc.isValid() && "point of instantiation must be valid!");
+ PointOfInstantiation = Loc;
+ }
+
+ /// \brief If this variable template specialization is an instantiation of
+ /// a template (rather than an explicit specialization), return the
+ /// variable template or variable template partial specialization from which
+ /// it was instantiated.
+ llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ getInstantiatedFrom() const {
+ if (getSpecializationKind() != TSK_ImplicitInstantiation &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
+ return llvm::PointerUnion<VarTemplateDecl *,
+ VarTemplatePartialSpecializationDecl *>();
+
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<VarTemplateDecl *>();
+ }
+
+ /// \brief Retrieve the variable template or variable template partial
+ /// specialization which was specialized by this.
+ llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ getSpecializedTemplateOrPartial() const {
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<VarTemplateDecl *>();
+ }
+
+ /// \brief Retrieve the set of template arguments that should be used
+ /// to instantiate the initializer of the variable template or variable
+ /// template partial specialization from which this variable template
+ /// specialization was instantiated.
+ ///
+ /// \returns For a variable template specialization instantiated from the
+ /// primary template, this function will return the same template arguments
+ /// as getTemplateArgs(). For a variable template specialization instantiated
+ /// from a variable template partial specialization, this function will the
+ /// return deduced template arguments for the variable template partial
+ /// specialization itself.
+ const TemplateArgumentList &getTemplateInstantiationArgs() const {
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return *PartialSpec->TemplateArgs;
+
+ return getTemplateArgs();
+ }
+
+ /// \brief Note that this variable template specialization is actually an
+ /// instantiation of the given variable template partial specialization whose
+ /// template arguments have been deduced.
+ void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
+ const TemplateArgumentList *TemplateArgs) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+ "Already set to a variable template partial specialization!");
+ SpecializedPartialSpecialization *PS =
+ new (getASTContext()) SpecializedPartialSpecialization();
+ PS->PartialSpecialization = PartialSpec;
+ PS->TemplateArgs = TemplateArgs;
+ SpecializedTemplate = PS;
+ }
+
+ /// \brief Note that this variable template specialization is an instantiation
+ /// of the given variable template.
+ void setInstantiationOf(VarTemplateDecl *TemplDecl) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+ "Previously set to a variable template partial specialization!");
+ SpecializedTemplate = TemplDecl;
+ }
+
+ /// \brief Sets the type of this specialization as it was written by
+ /// the user.
+ void setTypeAsWritten(TypeSourceInfo *T) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->TypeAsWritten = T;
+ }
+ /// \brief Gets the type of this specialization as it was written by
+ /// the user, if it was so written.
+ TypeSourceInfo *getTypeAsWritten() const {
+ return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0;
+ }
+
+ /// \brief Gets the location of the extern keyword, if present.
+ SourceLocation getExternLoc() const {
+ return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+ }
+ /// \brief Sets the location of the extern keyword.
+ void setExternLoc(SourceLocation Loc) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->ExternLoc = Loc;
+ }
+
+ /// \brief Sets the location of the template keyword.
+ void setTemplateKeywordLoc(SourceLocation Loc) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->TemplateKeywordLoc = Loc;
+ }
+ /// \brief Gets the location of the template keyword, if present.
+ SourceLocation getTemplateKeywordLoc() const {
+ return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs, ASTContext &Context) {
+ ID.AddInteger(NumTemplateArgs);
+ for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+ TemplateArgs[Arg].Profile(ID, Context);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstVarTemplateSpecialization &&
+ K <= lastVarTemplateSpecialization;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+class VarTemplatePartialSpecializationDecl
+ : public VarTemplateSpecializationDecl {
+ virtual void anchor();
+
+ /// \brief The list of template parameters
+ TemplateParameterList *TemplateParams;
+
+ /// \brief The source info for the template arguments as written.
+ /// FIXME: redundant with TypeAsWritten?
+ const ASTTemplateArgumentListInfo *ArgsAsWritten;
+
+ /// \brief The variable template partial specialization from which this
+ /// variable template partial specialization was instantiated.
+ ///
+ /// The boolean value will be true to indicate that this variable template
+ /// partial specialization was specialized at this level.
+ llvm::PointerIntPair<VarTemplatePartialSpecializationDecl *, 1, bool>
+ InstantiatedFromMember;
+
+ VarTemplatePartialSpecializationDecl(
+ ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, TemplateParameterList *Params,
+ VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
+ const ASTTemplateArgumentListInfo *ArgInfos);
+
+ VarTemplatePartialSpecializationDecl()
+ : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization),
+ TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) {}
+
+public:
+ static VarTemplatePartialSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, TemplateParameterList *Params,
+ VarTemplateDecl *SpecializedTemplate, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos);
+
+ static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ VarTemplatePartialSpecializationDecl *getMostRecentDecl() {
+ return cast<VarTemplatePartialSpecializationDecl>(
+ static_cast<VarTemplateSpecializationDecl *>(
+ this)->getMostRecentDecl());
+ }
+
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ /// Get the template arguments as written.
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// \brief Retrieve the member variable template partial specialization from
+ /// which this particular variable template partial specialization was
+ /// instantiated.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct Outer {
+ /// template<typename U> U Inner;
+ /// template<typename U> U* Inner<U*> = (U*)(0); // #1
+ /// };
+ ///
+ /// template int* Outer<float>::Inner<int*>;
+ /// \endcode
+ ///
+ /// In this example, the instantiation of \c Outer<float>::Inner<int*> will
+ /// end up instantiating the partial specialization
+ /// \c Outer<float>::Inner<U*>, which itself was instantiated from the
+ /// variable template partial specialization \c Outer<T>::Inner<U*>. Given
+ /// \c Outer<float>::Inner<U*>, this function would return
+ /// \c Outer<T>::Inner<U*>.
+ VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ return First->InstantiatedFromMember.getPointer();
+ }
+
+ void
+ setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ First->InstantiatedFromMember.setPointer(PartialSpec);
+ }
+
+ /// \brief Determines whether this variable template partial specialization
+ /// was a specialization of a member partial specialization.
+ ///
+ /// In the following example, the member template partial specialization
+ /// \c X<int>::Inner<T*> is a member specialization.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> U Inner;
+ /// template<typename U> U* Inner<U*> = (U*)(0);
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// U* X<int>::Inner<T*> = (T*)(0) + 1;
+ /// \endcode
+ bool isMemberSpecialization() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ return First->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ assert(First->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ return First->InstantiatedFromMember.setInt(true);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K == VarTemplatePartialSpecialization;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Declaration of a variable template.
+class VarTemplateDecl : public RedeclarableTemplateDecl {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ /// \brief Data that is common to all of the declarations of a given
+ /// variable template.
+ struct Common : CommonBase {
+ Common() : LazySpecializations() {}
+
+ /// \brief The variable template specializations for this variable
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations;
+
+ /// \brief The variable template partial specializations for this variable
+ /// template.
+ llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
+ PartialSpecializations;
+
+ /// \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() const;
+
+ /// \brief Retrieve the set of specializations of this variable template.
+ llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
+ getSpecializations() const;
+
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
+ getPartialSpecializations();
+
+ VarTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : RedeclarableTemplateDecl(VarTemplate, DC, L, Name, Params, Decl) {}
+
+ VarTemplateDecl(EmptyShell Empty)
+ : RedeclarableTemplateDecl(VarTemplate, 0, SourceLocation(),
+ DeclarationName(), 0, 0) {}
+
+ CommonBase *newCommon(ASTContext &C) const;
+
+ Common *getCommonPtr() const {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+public:
+ /// \brief Get the underlying variable declarations of the template.
+ VarDecl *getTemplatedDecl() const {
+ return static_cast<VarDecl *>(TemplatedDecl);
+ }
+
+ /// \brief Returns whether this template declaration defines the primary
+ /// variable pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ VarTemplateDecl *getDefinition();
+
+ /// \brief Create a variable template node.
+ static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl,
+ VarTemplateDecl *PrevDecl);
+
+ /// \brief Create an empty variable template node.
+ static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ VarTemplateSpecializationDecl *
+ findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified specialization knowing that it is not already
+ /// in. InsertPos must be obtained from findSpecialization.
+ void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos);
+
+ VarTemplateDecl *getCanonicalDecl() {
+ return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+ const VarTemplateDecl *getCanonicalDecl() const {
+ return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this variable template, or
+ /// NULL if no such declaration exists.
+ VarTemplateDecl *getPreviousDecl() {
+ return cast_or_null<VarTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this variable template, or
+ /// NULL if no such declaration exists.
+ const VarTemplateDecl *getPreviousDecl() const {
+ return cast_or_null<VarTemplateDecl>(
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
+ }
+
+ VarTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return cast_or_null<VarTemplateDecl>(
+ RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
+ }
+
+ /// \brief Return the partial specialization with the provided arguments if it
+ /// exists, otherwise return the insertion point.
+ VarTemplatePartialSpecializationDecl *
+ findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified partial specialization knowing that it is not
+ /// already in. InsertPos must be obtained from findPartialSpecialization.
+ void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D,
+ void *InsertPos);
+
+ /// \brief Retrieve the partial specializations as an ordered list.
+ void getPartialSpecializations(
+ SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS);
+
+ /// \brief Find a variable template partial specialization which was
+ /// instantiated
+ /// from the given member partial specialization.
+ ///
+ /// \param D a member variable template partial specialization.
+ ///
+ /// \returns the variable template partial specialization which was
+ /// instantiated
+ /// from the given member partial specialization, or NULL if no such partial
+ /// specialization exists.
+ VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember(
+ VarTemplatePartialSpecializationDecl *D);
+
+ typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator;
+
+ spec_iterator spec_begin() const {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() const {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
+ typedef SpecIterator<VarTemplatePartialSpecializationDecl>
+ partial_spec_iterator;
+
+ partial_spec_iterator partial_spec_begin() {
+ return makeSpecIterator(getPartialSpecializations(), false);
+ }
+
+ partial_spec_iterator partial_spec_end() {
+ return makeSpecIterator(getPartialSpecializations(), true);
+ }
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == VarTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
} /* end of namespace clang */
#endif
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index f28882b3bf94..00766c27c136 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -182,11 +182,16 @@ public:
// operator bool() - Evaluates true when this declaration name is
// non-empty.
- operator bool() const {
+ LLVM_EXPLICIT operator bool() const {
return ((Ptr & PtrMask) != 0) ||
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
}
+ /// \brief Evaluates true when this declaration name is empty.
+ bool isEmpty() const {
+ return !*this;
+ }
+
/// Predicate functions for querying what type of name this is.
bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
bool isObjCZeroArgSelector() const {
@@ -210,9 +215,6 @@ public:
/// getNameAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
- /// printName - Print the human-readable name to a stream.
- void printName(raw_ostream &OS) const;
-
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
/// simple identifier.
@@ -302,6 +304,8 @@ public:
void dump() const;
};
+raw_ostream &operator<<(raw_ostream &OS, DeclarationName N);
+
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator<(DeclarationName LHS, DeclarationName RHS) {
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index 2e3cbfad919d..12c4fcc49b01 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -53,7 +53,7 @@ public:
if (E->getCond()->isValueDependent())
return;
// Only the selected subexpression matters; the other one is not evaluated.
- return this->Visit(E->getChosenSubExpr(Context));
+ return this->Visit(E->getChosenSubExpr());
}
void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 4ff1257b7dc8..f2648b9a4a04 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -277,7 +277,6 @@ public:
MLV_IncompleteType,
MLV_ConstQualified,
MLV_ArrayType,
- MLV_ReadonlyProperty,
MLV_NoSetterProperty,
MLV_MemberFunction,
MLV_SubObjCPropertySetting,
@@ -483,21 +482,22 @@ public:
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
- bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
+ bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx,
SourceLocation *Loc = 0,
bool isEvaluated = true) const;
- bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const;
+ bool isIntegerConstantExpr(const ASTContext &Ctx,
+ SourceLocation *Loc = 0) const;
/// isCXX98IntegralConstantExpr - Return true if this expression is an
/// integral constant expression in C++98. Can only be used in C++.
- bool isCXX98IntegralConstantExpr(ASTContext &Ctx) const;
+ bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const;
/// isCXX11ConstantExpr - Return true if this expression is a constant
/// expression in C++11. Can only be used in C++.
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
- bool isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result = 0,
+ bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = 0,
SourceLocation *Loc = 0) const;
/// isPotentialConstantExpr - Return true if this function's definition
@@ -579,15 +579,14 @@ public:
/// \brief Determine whether this expression involves a call to any function
/// that is not trivial.
bool hasNonTrivialCall(ASTContext &Ctx);
-
+
/// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
/// integer. This must be called on an expression that constant folds to an
/// integer.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
SmallVectorImpl<PartialDiagnosticAt> *Diag=0) const;
-
- void EvaluateForOverflow(const ASTContext &Ctx,
- SmallVectorImpl<PartialDiagnosticAt> *Diag) const;
+
+ void EvaluateForOverflow(const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an
/// lvalue with link time known address, with no side-effects.
@@ -760,10 +759,10 @@ public:
/// Walk outwards from an expression we want to bind a reference to and
/// find the expression whose lifetime needs to be extended. Record
- /// the adjustments needed along the path.
- const Expr *
- skipRValueSubobjectAdjustments(
- SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
+ /// the LHSs of comma expressions and adjustments needed along the path.
+ const Expr *skipRValueSubobjectAdjustments(
+ SmallVectorImpl<const Expr *> &CommaLHS,
+ SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
/// Skip irrelevant expressions to find what should be materialize for
/// binding with a reference.
@@ -893,7 +892,7 @@ class DeclRefExpr : public Expr {
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
/// \brief Helper to retrieve the optional NamedDecl through which this
- /// reference occured.
+ /// reference occurred.
NamedDecl *&getInternalFoundDecl() {
assert(hasFoundDecl());
if (hasQualifier())
@@ -902,12 +901,12 @@ class DeclRefExpr : public Expr {
}
/// \brief Helper to retrieve the optional NamedDecl through which this
- /// reference occured.
+ /// reference occurred.
NamedDecl *getInternalFoundDecl() const {
return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl();
}
- DeclRefExpr(ASTContext &Ctx,
+ DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D, bool refersToEnclosingLocal,
@@ -922,7 +921,7 @@ class DeclRefExpr : public Expr {
/// \brief Computes the type- and value-dependence flags for this
/// declaration reference expression.
- void computeDependence(ASTContext &C);
+ void computeDependence(const ASTContext &C);
public:
DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T,
@@ -938,7 +937,7 @@ public:
computeDependence(D->getASTContext());
}
- static DeclRefExpr *Create(ASTContext &Context,
+ static DeclRefExpr *Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D,
@@ -948,7 +947,7 @@ public:
NamedDecl *FoundD = 0,
const TemplateArgumentListInfo *TemplateArgs = 0);
- static DeclRefExpr *Create(ASTContext &Context,
+ static DeclRefExpr *Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D,
@@ -959,7 +958,7 @@ public:
const TemplateArgumentListInfo *TemplateArgs = 0);
/// \brief Construct an empty declaration reference expression.
- static DeclRefExpr *CreateEmpty(ASTContext &Context,
+ static DeclRefExpr *CreateEmpty(const ASTContext &Context,
bool HasQualifier,
bool HasFoundDecl,
bool HasTemplateKWAndArgsInfo,
@@ -1000,7 +999,7 @@ public:
return getInternalQualifierLoc();
}
- /// \brief Get the NamedDecl through which this reference occured.
+ /// \brief Get the NamedDecl through which this reference occurred.
///
/// This Decl may be different from the ValueDecl actually referred to in the
/// presence of using declarations, etc. It always returns non-NULL, and may
@@ -1151,6 +1150,7 @@ public:
Func,
Function,
LFunction, // Same as Function, but as wide string.
+ FuncDName,
PrettyFunction,
/// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
@@ -1221,13 +1221,15 @@ protected:
else
return llvm::APInt(BitWidth, VAL);
}
- void setIntValue(ASTContext &C, const llvm::APInt &Val);
+ void setIntValue(const ASTContext &C, const llvm::APInt &Val);
};
class APIntStorage : private APNumericStorage {
public:
llvm::APInt getValue() const { return getIntValue(); }
- void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); }
+ void setValue(const ASTContext &C, const llvm::APInt &Val) {
+ setIntValue(C, Val);
+ }
};
class APFloatStorage : private APNumericStorage {
@@ -1235,7 +1237,7 @@ public:
llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
return llvm::APFloat(Semantics, getIntValue());
}
- void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ void setValue(const ASTContext &C, const llvm::APFloat &Val) {
setIntValue(C, Val.bitcastToAPInt());
}
};
@@ -1250,17 +1252,17 @@ class IntegerLiteral : public Expr, public APIntStorage {
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
- IntegerLiteral(ASTContext &C, const llvm::APInt &V, QualType type,
+ IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
SourceLocation l);
/// \brief Returns a new integer literal with value 'V' and type 'type'.
/// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
/// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
/// \param V - the value that the returned integer literal contains.
- static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
+ static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l);
/// \brief Returns a new empty integer literal.
- static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
+ static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty);
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
@@ -1328,21 +1330,21 @@ public:
class FloatingLiteral : public Expr, private APFloatStorage {
SourceLocation Loc;
- FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
+ FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L);
/// \brief Construct an empty floating-point literal.
- explicit FloatingLiteral(ASTContext &C, EmptyShell Empty);
+ explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty);
public:
- static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V,
+ static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L);
- static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
+ static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty);
llvm::APFloat getValue() const {
return APFloatStorage::getValue(getSemantics());
}
- void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ void setValue(const ASTContext &C, const llvm::APFloat &Val) {
assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics");
APFloatStorage::setValue(C, Val);
}
@@ -1420,7 +1422,7 @@ public:
};
/// StringLiteral - This represents a string literal expression, e.g. "foo"
-/// or L"bar" (wide strings). The actual string is returned by getStrData()
+/// or L"bar" (wide strings). The actual string is returned by getBytes()
/// is NOT null-terminated, and the length of the string is determined by
/// calling getByteLength(). The C type for a string is always a
/// ConstantArrayType. In C++, the char type is const qualified, in C it is
@@ -1469,19 +1471,19 @@ private:
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
- static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind,
- bool Pascal, QualType Ty,
+ static StringLiteral *Create(const ASTContext &C, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc, unsigned NumStrs);
/// Simple constructor for string literals made from one token.
- static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind,
- bool Pascal, QualType Ty,
+ static StringLiteral *Create(const ASTContext &C, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
SourceLocation Loc) {
return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
}
/// \brief Construct an empty string literal.
- static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs);
+ static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs);
StringRef getString() const {
assert(CharByteWidth==1
@@ -1520,7 +1522,7 @@ public:
unsigned getCharByteWidth() const { return CharByteWidth; }
/// \brief Sets the string data to the given string data.
- void setString(ASTContext &C, StringRef Str,
+ void setString(const ASTContext &C, StringRef Str,
StringKind Kind, bool IsPascal);
StringKind getKind() const { return static_cast<StringKind>(Kind); }
@@ -1853,7 +1855,7 @@ private:
// Number of sub-expressions (i.e. array subscript expressions).
unsigned NumExprs;
- OffsetOfExpr(ASTContext &C, QualType type,
+ OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
SourceLocation RParenLoc);
@@ -1864,12 +1866,12 @@ private:
public:
- static OffsetOfExpr *Create(ASTContext &C, QualType type,
+ static OffsetOfExpr *Create(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps,
ArrayRef<Expr*> exprs, SourceLocation RParenLoc);
- static OffsetOfExpr *CreateEmpty(ASTContext &C,
+ static OffsetOfExpr *CreateEmpty(const ASTContext &C,
unsigned NumComps, unsigned NumExprs);
/// getOperatorLoc - Return the location of the operator.
@@ -2133,10 +2135,11 @@ class CallExpr : public Expr {
protected:
// These versions of the constructor are for derived classes.
- CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
+ CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
SourceLocation rparenloc);
- CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty);
+ CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
+ EmptyShell Empty);
Stmt *getPreArg(unsigned i) {
assert(i < getNumPreArgs() && "Prearg access out of range!");
@@ -2154,11 +2157,11 @@ protected:
unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
public:
- CallExpr(ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
+ CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
ExprValueKind VK, SourceLocation rparenloc);
/// \brief Build an empty call expression.
- CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
+ CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty);
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
@@ -2206,7 +2209,7 @@ public:
/// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set
/// to null.
- void setNumArgs(ASTContext& C, unsigned NumArgs);
+ void setNumArgs(const ASTContext& C, unsigned NumArgs);
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
@@ -2360,7 +2363,7 @@ public:
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
HadMultipleCandidates(false) {}
- static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
+ static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *memberdecl, DeclAccessPair founddecl,
@@ -2747,12 +2750,13 @@ public:
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
}
- static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
+ static ImplicitCastExpr *Create(const ASTContext &Context, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
ExprValueKind Cat);
- static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
+ static ImplicitCastExpr *CreateEmpty(const ASTContext &Context,
+ unsigned PathSize);
SourceLocation getLocStart() const LLVM_READONLY {
return getSubExpr()->getLocStart();
@@ -2838,13 +2842,14 @@ class CStyleCastExpr : public ExplicitCastExpr {
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
public:
- static CStyleCastExpr *Create(ASTContext &Context, QualType T,
+ static CStyleCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K,
Expr *Op, const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation R);
- static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
+ static CStyleCastExpr *CreateEmpty(const ASTContext &Context,
+ unsigned PathSize);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
@@ -3412,7 +3417,7 @@ class ShuffleVectorExpr : public Expr {
unsigned NumExprs;
public:
- ShuffleVectorExpr(ASTContext &C, ArrayRef<Expr*> args, QualType Type,
+ ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type,
SourceLocation BLoc, SourceLocation RP);
/// \brief Build an empty vector-shuffle expression.
@@ -3450,11 +3455,11 @@ public:
return cast<Expr>(SubExprs[Index]);
}
- void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs);
+ void setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs);
- unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) const {
+ llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const {
assert((N < NumExprs - 2) && "Shuffle idx out of range!");
- return getExpr(N+2)->EvaluateKnownConstInt(Ctx).getZExtValue();
+ return getExpr(N+2)->EvaluateKnownConstInt(Ctx);
}
// Iterators
@@ -3463,6 +3468,60 @@ public:
}
};
+/// ConvertVectorExpr - Clang builtin function __builtin_convertvector
+/// This AST node provides support for converting a vector type to another
+/// vector type of the same arity.
+class ConvertVectorExpr : public Expr {
+private:
+ Stmt *SrcExpr;
+ TypeSourceInfo *TInfo;
+ SourceLocation BuiltinLoc, RParenLoc;
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {}
+
+public:
+ ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation BuiltinLoc, SourceLocation RParenLoc)
+ : Expr(ConvertVectorExprClass, DstType, VK, OK,
+ DstType->isDependentType(),
+ DstType->isDependentType() || SrcExpr->isValueDependent(),
+ (DstType->isInstantiationDependentType() ||
+ SrcExpr->isInstantiationDependent()),
+ (DstType->containsUnexpandedParameterPack() ||
+ SrcExpr->containsUnexpandedParameterPack())),
+ SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
+
+ /// getSrcExpr - Return the Expr to be converted.
+ Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }
+
+ /// getTypeSourceInfo - Return the destination type.
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TInfo;
+ }
+ void setTypeSourceInfo(TypeSourceInfo *ti) {
+ TInfo = ti;
+ }
+
+ /// getBuiltinLoc - Return the location of the __builtin_convertvector token.
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+
+ /// getRParenLoc - Return the location of final right parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConvertVectorExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
+};
+
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
/// This AST node is similar to the conditional operator (?:) in C, with
/// the following exceptions:
@@ -3476,10 +3535,12 @@ class ChooseExpr : public Expr {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
SourceLocation BuiltinLoc, RParenLoc;
+ bool CondIsTrue;
public:
ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
QualType t, ExprValueKind VK, ExprObjectKind OK,
- SourceLocation RP, bool TypeDependent, bool ValueDependent)
+ SourceLocation RP, bool condIsTrue,
+ bool TypeDependent, bool ValueDependent)
: Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
(cond->isInstantiationDependent() ||
lhs->isInstantiationDependent() ||
@@ -3487,7 +3548,7 @@ public:
(cond->containsUnexpandedParameterPack() ||
lhs->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack())),
- BuiltinLoc(BLoc), RParenLoc(RP) {
+ BuiltinLoc(BLoc), RParenLoc(RP), CondIsTrue(condIsTrue) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
@@ -3498,12 +3559,21 @@ public:
/// isConditionTrue - Return whether the condition is true (i.e. not
/// equal to zero).
- bool isConditionTrue(const ASTContext &C) const;
+ bool isConditionTrue() const {
+ assert(!isConditionDependent() &&
+ "Dependent condition isn't true or false");
+ return CondIsTrue;
+ }
+ void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; }
+
+ bool isConditionDependent() const {
+ return getCond()->isTypeDependent() || getCond()->isValueDependent();
+ }
/// getChosenSubExpr - Return the subexpression chosen according to the
/// condition.
- Expr *getChosenSubExpr(const ASTContext &C) const {
- return isConditionTrue(C) ? getLHS() : getRHS();
+ Expr *getChosenSubExpr() const {
+ return isConditionTrue() ? getLHS() : getRHS();
}
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
@@ -3663,7 +3733,7 @@ class InitListExpr : public Expr {
SourceLocation LBraceLoc, RBraceLoc;
/// The alternative form of the initializer list (if it exists).
- /// The int part of the pair stores whether this initalizer list is
+ /// The int part of the pair stores whether this initializer list is
/// in semantic form. If not null, the pointer points to:
/// - the syntactic form, if this is in semantic form;
/// - the semantic form, if this is in syntactic form.
@@ -3679,7 +3749,7 @@ class InitListExpr : public Expr {
llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit;
public:
- InitListExpr(ASTContext &C, SourceLocation lbraceloc,
+ InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc);
/// \brief Build an empty initializer list.
@@ -3707,7 +3777,7 @@ public:
}
/// \brief Reserve space for some number of initializers.
- void reserveInits(ASTContext &C, unsigned NumInits);
+ void reserveInits(const ASTContext &C, unsigned NumInits);
/// @brief Specify the number of initializers
///
@@ -3715,7 +3785,7 @@ public:
/// initializers will be destroyed. If there are fewer than @p
/// NumInits initializers, NULL expressions will be added for the
/// unknown initializers.
- void resizeInits(ASTContext &Context, unsigned NumInits);
+ void resizeInits(const ASTContext &Context, unsigned NumInits);
/// @brief Updates the initializer at index @p Init with the new
/// expression @p expr, and returns the old expression at that
@@ -3724,7 +3794,7 @@ public:
/// When @p Init is out of range for this initializer list, the
/// initializer list will be extended with NULL expressions to
/// accommodate the new entry.
- Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr);
+ Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr);
/// \brief If this initializer list initializes an array with more elements
/// than there are initializers in the list, specifies an expression to be
@@ -3754,6 +3824,10 @@ public:
return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
}
void setInitializedFieldInUnion(FieldDecl *FD) {
+ assert((FD == 0
+ || getInitializedFieldInUnion() == 0
+ || getInitializedFieldInUnion() == FD)
+ && "Only one field of a union may be initialized at a time!");
ArrayFillerOrUnionFieldInit = FD;
}
@@ -3794,13 +3868,6 @@ public:
InitListExprBits.HadArrayRangeDesignator = ARD;
}
- bool initializesStdInitializerList() const {
- return InitListExprBits.InitializesStdInitializerList != 0;
- }
- void setInitializesStdInitializerList(bool ISIL = true) {
- InitListExprBits.InitializesStdInitializerList = ISIL;
- }
-
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
@@ -3851,7 +3918,7 @@ public:
/// The InitListExpr contains three DesignatedInitExprs, the first of
/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two
/// designators, one array designator for @c [2] followed by one field
-/// designator for @c .y. The initalization expression will be 1.0.
+/// designator for @c .y. The initialization expression will be 1.0.
class DesignatedInitExpr : public Expr {
public:
/// \brief Forward declaration of the Designator class.
@@ -3879,7 +3946,7 @@ private:
Designator *Designators;
- DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators,
+ DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned NumDesignators,
const Designator *Designators,
SourceLocation EqualOrColonLoc, bool GNUSyntax,
ArrayRef<Expr*> IndexExprs, Expr *Init);
@@ -4041,13 +4108,15 @@ public:
}
};
- static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators,
+ static DesignatedInitExpr *Create(const ASTContext &C,
+ Designator *Designators,
unsigned NumDesignators,
ArrayRef<Expr*> IndexExprs,
SourceLocation EqualOrColonLoc,
bool GNUSyntax, Expr *Init);
- static DesignatedInitExpr *CreateEmpty(ASTContext &C, unsigned NumIndexExprs);
+ static DesignatedInitExpr *CreateEmpty(const ASTContext &C,
+ unsigned NumIndexExprs);
/// @brief Returns the number of designators in this initializer.
unsigned size() const { return NumDesignators; }
@@ -4085,7 +4154,7 @@ public:
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
- void setDesignators(ASTContext &C, const Designator *Desigs,
+ void setDesignators(const ASTContext &C, const Designator *Desigs,
unsigned NumDesigs);
Expr *getArrayIndex(const Designator &D) const;
@@ -4133,8 +4202,8 @@ public:
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
- void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First,
- const Designator *Last);
+ void ExpandDesignator(const ASTContext &C, unsigned Idx,
+ const Designator *First, const Designator *Last);
SourceRange getDesignatorsSourceRange() const;
@@ -4188,8 +4257,8 @@ class ParenListExpr : public Expr {
SourceLocation LParenLoc, RParenLoc;
public:
- ParenListExpr(ASTContext& C, SourceLocation lparenloc, ArrayRef<Expr*> exprs,
- SourceLocation rparenloc);
+ ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
+ ArrayRef<Expr*> exprs, SourceLocation rparenloc);
/// \brief Build an empty paren list.
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
@@ -4262,7 +4331,7 @@ class GenericSelectionExpr : public Expr {
SourceLocation GenericLoc, DefaultLoc, RParenLoc;
public:
- GenericSelectionExpr(ASTContext &Context,
+ GenericSelectionExpr(const ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
ArrayRef<TypeSourceInfo*> AssocTypes,
ArrayRef<Expr*> AssocExprs,
@@ -4271,7 +4340,7 @@ public:
unsigned ResultIndex);
/// This constructor is used in the result-dependent case.
- GenericSelectionExpr(ASTContext &Context,
+ GenericSelectionExpr(const ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
ArrayRef<TypeSourceInfo*> AssocTypes,
ArrayRef<Expr*> AssocExprs,
@@ -4450,7 +4519,7 @@ public:
/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
/// This AST node provides support for reinterpreting a type to another
/// type of the same size.
-class AsTypeExpr : public Expr { // Should this be an ExplicitCastExpr?
+class AsTypeExpr : public Expr {
private:
Stmt *SrcExpr;
SourceLocation BuiltinLoc, RParenLoc;
@@ -4552,13 +4621,13 @@ class PseudoObjectExpr : public Expr {
public:
/// NoResult - A value for the result index indicating that there is
/// no semantic result.
- enum { NoResult = ~0U };
+ enum LLVM_ENUM_INT_TYPE(unsigned) { NoResult = ~0U };
- static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic,
+ static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic,
ArrayRef<Expr*> semantic,
unsigned resultIndex);
- static PseudoObjectExpr *Create(ASTContext &Context, EmptyShell shell,
+ static PseudoObjectExpr *Create(const ASTContext &Context, EmptyShell shell,
unsigned numSemanticExprs);
/// Return the syntactic form of this expression, i.e. the
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 91e5b21eacff..6356ee7aee63 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Expr interface and subclasses for C++ expressions.
-//
+///
+/// \file
+/// \brief Defines the clang::Expr interface and subclasses for C++ expressions.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXPRCXX_H
@@ -74,15 +75,15 @@ public:
CallExpr(C, CXXOperatorCallExprClass, Empty) { }
- /// getOperator - Returns the kind of overloaded operator that this
+ /// \brief Returns the kind of overloaded operator that this
/// expression refers to.
OverloadedOperatorKind getOperator() const { return Operator; }
- /// getOperatorLoc - Returns the location of the operator symbol in
- /// the expression. When @c getOperator()==OO_Call, this is the
- /// location of the right parentheses; when @c
- /// getOperator()==OO_Subscript, this is the location of the right
- /// bracket.
+ /// \brief Returns the location of the operator symbol in the expression.
+ ///
+ /// When \c getOperator()==OO_Call, this is the location of the right
+ /// parentheses; when \c getOperator()==OO_Subscript, this is the location
+ /// of the right bracket.
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
@@ -105,7 +106,7 @@ public:
friend class ASTStmtWriter;
};
-/// CXXMemberCallExpr - Represents a call to a member function that
+/// Represents a call to a member function that
/// may be written either with member call syntax (e.g., "obj.func()"
/// or "objptr->func()") or with normal function-call syntax
/// ("func()") within a member function that ends up calling a member
@@ -122,18 +123,19 @@ public:
CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
: CallExpr(C, CXXMemberCallExprClass, Empty) { }
- /// getImplicitObjectArgument - Retrieves the implicit object
- /// argument for the member call. For example, in "x.f(5)", this
- /// operation would return "x".
+ /// \brief Retrieves the implicit object argument for the member call.
+ ///
+ /// For example, in "x.f(5)", this returns the sub-expression "x".
Expr *getImplicitObjectArgument() const;
- /// Retrieves the declaration of the called method.
+ /// \brief Retrieves the declaration of the called method.
CXXMethodDecl *getMethodDecl() 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.
+ /// \brief 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() const;
@@ -142,7 +144,7 @@ public:
}
};
-/// CUDAKernelCallExpr - Represents a call to a CUDA kernel function.
+/// \brief Represents a call to a CUDA kernel function.
class CUDAKernelCallExpr : public CallExpr {
private:
enum { CONFIG, END_PREARG };
@@ -169,13 +171,12 @@ public:
}
};
-/// CXXNamedCastExpr - Abstract class common to all of the C++ "named"
-/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
-/// const_cast.
+/// \brief Abstract class common to all of the C++ "named"/"keyword" casts.
///
/// This abstract class is inherited by all of the classes
-/// representing "named" casts, e.g., CXXStaticCastExpr,
-/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr.
+/// representing "named" casts: CXXStaticCastExpr for \c static_cast,
+/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for
+/// reinterpret_cast, and CXXConstCastExpr for \c const_cast.
class CXXNamedCastExpr : public ExplicitCastExpr {
private:
SourceLocation Loc; // the location of the casting op
@@ -200,7 +201,7 @@ public:
const char *getCastName() const;
/// \brief Retrieve the location of the cast operator keyword, e.g.,
- /// "static_cast".
+ /// \c static_cast.
SourceLocation getOperatorLoc() const { return Loc; }
/// \brief Retrieve the location of the closing parenthesis.
@@ -223,11 +224,10 @@ public:
}
};
-/// CXXStaticCastExpr - A C++ @c static_cast expression
-/// (C++ [expr.static.cast]).
+/// \brief A C++ \c static_cast expression (C++ [expr.static.cast]).
///
/// This expression node represents a C++ static cast, e.g.,
-/// @c static_cast<int>(1.0).
+/// \c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
unsigned pathSize, TypeSourceInfo *writtenTy,
@@ -240,13 +240,13 @@ class CXXStaticCastExpr : public CXXNamedCastExpr {
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
public:
- static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
+ static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K, Expr *Op,
const CXXCastPath *Path,
TypeSourceInfo *Written, SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets);
- static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
+ static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context,
unsigned PathSize);
static bool classof(const Stmt *T) {
@@ -254,12 +254,11 @@ public:
}
};
-/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression
-/// (C++ [expr.dynamic.cast]), which may perform a run-time check to
-/// determine how to perform the type cast.
+/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
///
/// This expression node represents a dynamic cast, e.g.,
-/// @c dynamic_cast<Derived*>(BasePtr).
+/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time
+/// check to determine how to perform the type conversion.
class CXXDynamicCastExpr : public CXXNamedCastExpr {
CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
@@ -272,14 +271,14 @@ class CXXDynamicCastExpr : public CXXNamedCastExpr {
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
public:
- static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
+ static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind Kind, Expr *Op,
const CXXCastPath *Path,
TypeSourceInfo *Written, SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets);
- static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
+ static CXXDynamicCastExpr *CreateEmpty(const ASTContext &Context,
unsigned pathSize);
bool isAlwaysNull() const;
@@ -289,12 +288,14 @@ public:
}
};
-/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++
-/// [expr.reinterpret.cast]), which provides a differently-typed view
-/// of a value but performs no actual work at run time.
+/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
///
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
+///
+/// A reinterpret_cast provides a differently-typed view of a value but
+/// (in Clang, as in most C++ implementations) performs no actual work at
+/// run time.
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
Expr *op, unsigned pathSize,
@@ -308,13 +309,13 @@ class CXXReinterpretCastExpr : public CXXNamedCastExpr {
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
public:
- static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
+ static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind Kind,
Expr *Op, const CXXCastPath *Path,
TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets);
- static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
+ static CXXReinterpretCastExpr *CreateEmpty(const ASTContext &Context,
unsigned pathSize);
static bool classof(const Stmt *T) {
@@ -322,11 +323,13 @@ public:
}
};
-/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]),
-/// which can remove type qualifiers but does not change the underlying value.
+/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]).
///
/// This expression node represents a const cast, e.g.,
-/// @c const_cast<char*>(PtrToConstChar).
+/// \c const_cast<char*>(PtrToConstChar).
+///
+/// A const_cast can remove type qualifiers but does not change the underlying
+/// value.
class CXXConstCastExpr : public CXXNamedCastExpr {
CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l,
@@ -338,19 +341,19 @@ class CXXConstCastExpr : public CXXNamedCastExpr {
: CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
public:
- static CXXConstCastExpr *Create(ASTContext &Context, QualType T,
+ static CXXConstCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, Expr *Op,
TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation RParenLoc,
SourceRange AngleBrackets);
- static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
+ static CXXConstCastExpr *CreateEmpty(const ASTContext &Context);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
}
};
-/// UserDefinedLiteral - A call to a literal operator (C++11 [over.literal])
+/// \brief A call to a literal operator (C++11 [over.literal])
/// written as a user-defined literal (C++11 [lit.ext]).
///
/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this
@@ -364,12 +367,12 @@ class UserDefinedLiteral : public CallExpr {
SourceLocation UDSuffixLoc;
public:
- UserDefinedLiteral(ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args,
+ UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args,
QualType T, ExprValueKind VK, SourceLocation LitEndLoc,
SourceLocation SuffixLoc)
: CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, T, VK, LitEndLoc),
UDSuffixLoc(SuffixLoc) {}
- explicit UserDefinedLiteral(ASTContext &C, EmptyShell Empty)
+ explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty)
: CallExpr(C, UserDefinedLiteralClass, Empty) {}
/// The kind of literal operator which is invoked.
@@ -382,11 +385,11 @@ public:
LOK_Character ///< operator "" X (CharT)
};
- /// getLiteralOperatorKind - Returns the kind of literal operator invocation
+ /// \brief Returns the kind of literal operator invocation
/// which this expression represents.
LiteralOperatorKind getLiteralOperatorKind() const;
- /// getCookedLiteral - If this is not a raw user-defined literal, get the
+ /// \brief If this is not a raw user-defined literal, get the
/// underlying cooked literal (representing the literal with the suffix
/// removed).
Expr *getCookedLiteral();
@@ -402,12 +405,13 @@ public:
SourceLocation getLocEnd() const { return getRParenLoc(); }
- /// getUDSuffixLoc - Returns the location of a ud-suffix in the expression.
+ /// \brief Returns the location of a ud-suffix in the expression.
+ ///
/// For a string literal, there may be multiple identical suffixes. This
/// returns the first.
SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; }
- /// getUDSuffix - Returns the ud-suffix specified for this literal.
+ /// \brief Returns the ud-suffix specified for this literal.
const IdentifierInfo *getUDSuffix() const;
static bool classof(const Stmt *S) {
@@ -418,7 +422,7 @@ public:
friend class ASTStmtWriter;
};
-/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal.
+/// \brief A boolean literal, per ([C++ lex.bool] Boolean literals).
///
class CXXBoolLiteralExpr : public Expr {
bool Value;
@@ -449,7 +453,9 @@ public:
child_range children() { return child_range(); }
};
-/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal
+/// \brief The null pointer literal (C++11 [lex.nullptr])
+///
+/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
class CXXNullPtrLiteralExpr : public Expr {
SourceLocation Loc;
public:
@@ -474,11 +480,50 @@ public:
child_range children() { return child_range(); }
};
-/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
-/// the type_info that corresponds to the supplied type, or the (possibly
+/// \brief Implicit construction of a std::initializer_list<T> object from an
+/// array temporary within list-initialization (C++11 [dcl.init.list]p5).
+class CXXStdInitializerListExpr : public Expr {
+ Stmt *SubExpr;
+
+ CXXStdInitializerListExpr(EmptyShell Empty)
+ : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(0) {}
+
+public:
+ CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr)
+ : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary,
+ Ty->isDependentType(), SubExpr->isValueDependent(),
+ SubExpr->isInstantiationDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ SubExpr(SubExpr) {}
+
+ Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); }
+ const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return SubExpr->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SubExpr->getLocEnd();
+ }
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SubExpr->getSourceRange();
+ }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == CXXStdInitializerListExprClass;
+ }
+
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+};
+
+/// A C++ \c typeid expression (C++ [expr.typeid]), which gets
+/// the \c type_info that corresponds to the supplied type, or the (possibly
/// dynamic) type of the supplied expression.
///
-/// This represents code like @c typeid(int) or @c typeid(*objPtr)
+/// This represents code like \c typeid(int) or \c typeid(*objPtr)
class CXXTypeidExpr : public Expr {
private:
llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
@@ -521,7 +566,7 @@ public:
/// \brief Retrieves the type operand of this typeid() expression after
/// various required adjustments (removing reference types, cv-qualifiers).
- QualType getTypeOperand() const;
+ QualType getTypeOperand(ASTContext &Context) const;
/// \brief Retrieve source information for the type operand.
TypeSourceInfo *getTypeOperandSourceInfo() const {
@@ -561,10 +606,11 @@ public:
}
};
-/// A member reference to an MSPropertyDecl. This expression always
-/// has pseudo-object type, and therefore it is typically not
-/// encountered in a fully-typechecked expression except within the
-/// syntactic form of a PseudoObjectExpr.
+/// \brief A member reference to an MSPropertyDecl.
+///
+/// This expression always has pseudo-object type, and therefore it is
+/// typically not encountered in a fully-typechecked expression except
+/// within the syntactic form of a PseudoObjectExpr.
class MSPropertyRefExpr : public Expr {
Expr *BaseExpr;
MSPropertyDecl *TheDecl;
@@ -619,7 +665,7 @@ public:
friend class ASTStmtReader;
};
-/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
+/// 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)
@@ -655,7 +701,7 @@ public:
/// \brief Retrieves the type operand of this __uuidof() expression after
/// various required adjustments (removing reference types, cv-qualifiers).
- QualType getTypeOperand() const;
+ QualType getTypeOperand(ASTContext &Context) const;
/// \brief Retrieve source information for the type operand.
TypeSourceInfo *getTypeOperandSourceInfo() const {
@@ -678,6 +724,8 @@ public:
Operand = E;
}
+ StringRef getUuidAsStringRef(ASTContext &Context) const;
+
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
@@ -687,8 +735,10 @@ public:
return T->getStmtClass() == CXXUuidofExprClass;
}
- /// Grabs __declspec(uuid()) off a type, or returns 0 if there is none.
- static UuidAttr *GetUuidAttrOfType(QualType QT);
+ /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to
+ /// a single GUID.
+ static UuidAttr *GetUuidAttrOfType(QualType QT,
+ bool *HasMultipleGUIDsPtr = 0);
// Iterators
child_range children() {
@@ -698,17 +748,18 @@ public:
}
};
-/// CXXThisExpr - Represents the "this" expression in C++, which is a
-/// pointer to the object on which the current member function is
+/// \brief Represents the \c this expression in C++.
+///
+/// This is a pointer to the object on which the current member function is
/// executing (C++ [expr.prim]p3). Example:
///
-/// @code
+/// \code
/// class Foo {
/// public:
/// void bar();
/// void test() { this->bar(); }
/// };
-/// @endcode
+/// \endcode
class CXXThisExpr : public Expr {
SourceLocation Loc;
bool Implicit : 1;
@@ -742,10 +793,11 @@ public:
child_range children() { return child_range(); }
};
-/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles
-/// 'throw' and 'throw' assignment-expression. When
-/// assignment-expression isn't present, Op will be null.
+/// \brief A C++ throw-expression (C++ [except.throw]).
///
+/// This handles 'throw' (for re-throwing the current exception) and
+/// 'throw' assignment-expression. When assignment-expression isn't
+/// present, Op will be null.
class CXXThrowExpr : public Expr {
Stmt *Op;
SourceLocation ThrowLoc;
@@ -755,8 +807,8 @@ class CXXThrowExpr : public Expr {
friend class ASTStmtReader;
public:
- // Ty is the void type which is used as the result type of the
- // exepression. The l is the location of the throw keyword. expr
+ // \p Ty is the void type which is used as the result type of the
+ // expression. The \p l is the location of the throw keyword. \p expr
// can by null, if the optional expression to throw isn't present.
CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l,
bool IsThrownVariableInScope) :
@@ -795,10 +847,11 @@ public:
}
};
-/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a
-/// function call argument that was created from the corresponding
-/// parameter's default argument, when the call did not explicitly
-/// supply arguments for all of the parameters.
+/// \brief A default argument (C++ [dcl.fct.default]).
+///
+/// This wraps up a function call argument that was created from the
+/// corresponding parameter's default argument, when the call did not
+/// explicitly supply arguments for all of the parameters.
class CXXDefaultArgExpr : public Expr {
/// \brief The parameter whose default is being used.
///
@@ -831,20 +884,17 @@ class CXXDefaultArgExpr : public Expr {
public:
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
-
- // Param is the parameter whose default argument is used by this
+ // \p Param is the parameter whose default argument is used by this
// expression.
- static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc,
+ static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
ParmVarDecl *Param) {
return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param);
}
- // Param is the parameter whose default argument is used by this
- // expression, and SubExpr is the expression that will actually be used.
- static CXXDefaultArgExpr *Create(ASTContext &C,
- SourceLocation Loc,
- ParmVarDecl *Param,
- Expr *SubExpr);
+ // \p Param is the parameter whose default argument is used by this
+ // expression, and \p SubExpr is the expression that will actually be used.
+ static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
+ ParmVarDecl *Param, Expr *SubExpr);
// Retrieve the parameter that the argument was created from.
const ParmVarDecl *getParam() const { return Param.getPointer(); }
@@ -866,8 +916,8 @@ public:
/// used.
SourceLocation getUsedLocation() const { return Loc; }
- // Default argument expressions have no representation in the
- // source, so they have an empty source range.
+ /// Default argument expressions have no representation in the
+ /// source, so they have an empty source range.
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
@@ -884,7 +934,10 @@ public:
friend class ASTStmtWriter;
};
-/// \brief This wraps a use of a C++ default initializer (technically,
+/// \brief A use of a default initializer in a constructor or in aggregate
+/// initialization.
+///
+/// This wraps a use of a C++ default initializer (technically,
/// a brace-or-equal-initializer for a non-static data member) when it
/// is implicitly used in a mem-initializer-list in a constructor
/// (C++11 [class.base.init]p8) or in aggregate initialization
@@ -896,24 +949,24 @@ class CXXDefaultInitExpr : public Expr {
/// \brief The location where the default initializer expression was used.
SourceLocation Loc;
- CXXDefaultInitExpr(ASTContext &C, SourceLocation Loc, FieldDecl *Field,
+ CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field,
QualType T);
CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}
public:
- // Field is the non-static data member whose default initializer is used
- // by this expression.
- static CXXDefaultInitExpr *Create(ASTContext &C, SourceLocation Loc,
+ /// \p Field is the non-static data member whose default initializer is used
+ /// by this expression.
+ static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc,
FieldDecl *Field) {
return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType());
}
- // Get the field whose initializer will be used.
+ /// \brief Get the field whose initializer will be used.
FieldDecl *getField() { return Field; }
const FieldDecl *getField() const { return Field; }
- // Get the initialization expression that will be used.
+ /// \brief Get the initialization expression that will be used.
const Expr *getExpr() const { return Field->getInClassInitializer(); }
Expr *getExpr() { return Field->getInClassInitializer(); }
@@ -931,16 +984,16 @@ public:
friend class ASTStmtReader;
};
-/// CXXTemporary - Represents a C++ temporary.
+/// \brief Represents a C++ temporary.
class CXXTemporary {
- /// Destructor - The destructor that needs to be called.
+ /// \brief The destructor that needs to be called.
const CXXDestructorDecl *Destructor;
- CXXTemporary(const CXXDestructorDecl *destructor)
+ explicit CXXTemporary(const CXXDestructorDecl *destructor)
: Destructor(destructor) { }
public:
- static CXXTemporary *Create(ASTContext &C,
+ static CXXTemporary *Create(const ASTContext &C,
const CXXDestructorDecl *Destructor);
const CXXDestructorDecl *getDestructor() const { return Destructor; }
@@ -980,7 +1033,7 @@ public:
CXXBindTemporaryExpr(EmptyShell Empty)
: Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {}
- static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp,
+ static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp,
Expr* SubExpr);
CXXTemporary *getTemporary() { return Temp; }
@@ -1019,7 +1072,7 @@ private:
CXXConstructorDecl *Constructor;
SourceLocation Loc;
- SourceRange ParenRange;
+ SourceRange ParenOrBraceRange;
unsigned NumArgs : 16;
bool Elidable : 1;
bool HadMultipleCandidates : 1;
@@ -1029,7 +1082,7 @@ private:
Stmt **Args;
protected:
- CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+ CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *d, bool elidable,
ArrayRef<Expr *> Args,
@@ -1037,7 +1090,7 @@ protected:
bool ListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
- SourceRange ParenRange);
+ SourceRange ParenOrBraceRange);
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
@@ -1055,7 +1108,7 @@ public:
ConstructKind(0), Args(0)
{ }
- static CXXConstructExpr *Create(ASTContext &C, QualType T,
+ static CXXConstructExpr *Create(const ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
ArrayRef<Expr *> Args,
@@ -1063,7 +1116,7 @@ public:
bool ListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
- SourceRange ParenRange);
+ SourceRange ParenOrBraceRange);
CXXConstructorDecl* getConstructor() const { return Constructor; }
void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
@@ -1091,7 +1144,7 @@ public:
ZeroInitialization = ZeroInit;
}
- /// \brief Determines whether this constructor is actually constructing
+ /// \brief Determine whether this constructor is actually constructing
/// a base class (rather than a complete object).
ConstructionKind getConstructionKind() const {
return (ConstructionKind)ConstructKind;
@@ -1111,7 +1164,7 @@ public:
Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); }
unsigned getNumArgs() const { return NumArgs; }
- /// getArg - Return the specified argument.
+ /// \brief Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
return cast<Expr>(Args[Arg]);
@@ -1121,7 +1174,7 @@ public:
return cast<Expr>(Args[Arg]);
}
- /// setArg - Set the specified argument.
+ /// \brief Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
Args[Arg] = ArgExpr;
@@ -1129,8 +1182,8 @@ public:
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
- SourceRange getParenRange() const { return ParenRange; }
- void setParenRange(SourceRange Range) { ParenRange = Range; }
+ SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; }
+ void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstructExprClass ||
@@ -1149,43 +1202,42 @@ public:
/// notation (C++ [expr.type.conv]).
///
/// Example:
-/// @code
+/// \code
/// x = int(0.5);
-/// @endcode
+/// \endcode
class CXXFunctionalCastExpr : public ExplicitCastExpr {
- SourceLocation TyBeginLoc;
+ SourceLocation LParenLoc;
SourceLocation RParenLoc;
CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
TypeSourceInfo *writtenTy,
- SourceLocation tyBeginLoc, CastKind kind,
- Expr *castExpr, unsigned pathSize,
- SourceLocation rParenLoc)
+ CastKind kind, Expr *castExpr, unsigned pathSize,
+ SourceLocation lParenLoc, SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
castExpr, pathSize, writtenTy),
- TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+ LParenLoc(lParenLoc), RParenLoc(rParenLoc) {}
explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
public:
- static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
+ static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK,
TypeSourceInfo *Written,
- SourceLocation TyBeginLoc,
CastKind Kind, Expr *Op,
const CXXCastPath *Path,
+ SourceLocation LPLoc,
SourceLocation RPLoc);
- static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context,
+ static CXXFunctionalCastExpr *CreateEmpty(const ASTContext &Context,
unsigned PathSize);
- SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
- void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return TyBeginLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXFunctionalCastExprClass;
@@ -1200,21 +1252,21 @@ public:
/// constructor to build a temporary object. With N == 1 arguments the
/// functional cast expression will be represented by CXXFunctionalCastExpr.
/// Example:
-/// @code
+/// \code
/// struct X { X(int, float); }
///
/// X create_X() {
/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr
/// };
-/// @endcode
+/// \endcode
class CXXTemporaryObjectExpr : public CXXConstructExpr {
TypeSourceInfo *Type;
public:
- CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons,
+ CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons,
TypeSourceInfo *Type,
ArrayRef<Expr *> Args,
- SourceRange parenRange,
+ SourceRange ParenOrBraceRange,
bool HadMultipleCandidates,
bool ListInitialization,
bool ZeroInitialization);
@@ -1244,26 +1296,35 @@ public:
/// }
/// \endcode
///
-/// Lambda expressions can capture local variables, either by copying
+/// C++11 lambda expressions can capture local variables, either by copying
/// the values of those local variables at the time the function
/// object is constructed (not when it is called!) or by holding a
/// reference to the local variable. These captures can occur either
/// implicitly or can be written explicitly between the square
/// brackets ([...]) that start the lambda expression.
+///
+/// C++1y introduces a new form of "capture" called an init-capture that
+/// includes an initializing expression (rather than capturing a variable),
+/// and which can never occur implicitly.
class LambdaExpr : public Expr {
enum {
/// \brief Flag used by the Capture class to indicate that the given
/// capture was implicit.
Capture_Implicit = 0x01,
- /// \brief Flag used by the Capture class to indciate that the
+ /// \brief Flag used by the Capture class to indicate that the
/// given capture was by-copy.
+ ///
+ /// This includes the case of a non-reference init-capture.
Capture_ByCopy = 0x02
};
/// \brief The source range that covers the lambda introducer ([...]).
SourceRange IntroducerRange;
+ /// \brief The source location of this lambda's capture-default ('=' or '&').
+ SourceLocation CaptureDefaultLoc;
+
/// \brief The number of captures.
unsigned NumCaptures : 16;
@@ -1297,9 +1358,10 @@ class LambdaExpr : public Expr {
// array captures.
public:
- /// \brief Describes the capture of either a variable or 'this'.
+ /// \brief Describes the capture of a variable or of \c this, or of a
+ /// C++1y init-capture.
class Capture {
- llvm::PointerIntPair<VarDecl *, 2> VarAndBits;
+ llvm::PointerIntPair<Decl *, 2> DeclAndBits;
SourceLocation Loc;
SourceLocation EllipsisLoc;
@@ -1307,15 +1369,17 @@ public:
friend class ASTStmtWriter;
public:
- /// \brief Create a new capture.
+ /// \brief Create a new capture of a variable or of \c this.
///
/// \param Loc The source location associated with this capture.
///
- /// \param Kind The kind of capture (this, byref, bycopy).
+ /// \param Kind The kind of capture (this, byref, bycopy), which must
+ /// not be init-capture.
///
/// \param Implicit Whether the capture was implicit or explicit.
///
- /// \param Var The local variable being captured, or null if capturing this.
+ /// \param Var The local variable being captured, or null if capturing
+ /// \c this.
///
/// \param EllipsisLoc The location of the ellipsis (...) for a
/// capture that is a pack expansion, or an invalid source
@@ -1327,36 +1391,43 @@ public:
/// \brief Determine the kind of capture.
LambdaCaptureKind getCaptureKind() const;
- /// \brief Determine whether this capture handles the C++ 'this'
+ /// \brief Determine whether this capture handles the C++ \c this
/// pointer.
- bool capturesThis() const { return VarAndBits.getPointer() == 0; }
+ bool capturesThis() const { return DeclAndBits.getPointer() == 0; }
/// \brief Determine whether this capture handles a variable.
- bool capturesVariable() const { return VarAndBits.getPointer() != 0; }
+ bool capturesVariable() const {
+ return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer());
+ }
+
+ /// \brief Determine whether this is an init-capture.
+ bool isInitCapture() const {
+ return capturesVariable() && getCapturedVar()->isInitCapture();
+ }
/// \brief Retrieve the declaration of the local variable being
/// captured.
///
- /// This operation is only valid if this capture does not capture
- /// 'this'.
- VarDecl *getCapturedVar() const {
- assert(!capturesThis() && "No variable available for 'this' capture");
- return VarAndBits.getPointer();
+ /// This operation is only valid if this capture is a variable capture
+ /// (other than a capture of \c this).
+ VarDecl *getCapturedVar() const {
+ assert(capturesVariable() && "No variable available for 'this' capture");
+ return cast<VarDecl>(DeclAndBits.getPointer());
}
/// \brief Determine whether this was an implicit capture (not
/// written between the square brackets introducing the lambda).
- bool isImplicit() const { return VarAndBits.getInt() & Capture_Implicit; }
+ bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; }
- /// \brief Determine whether this was an explicit capture, written
- /// between the square brackets introducing the lambda.
+ /// \brief Determine whether this was an explicit capture (written
+ /// between the square brackets introducing the lambda).
bool isExplicit() const { return !isImplicit(); }
/// \brief Retrieve the source location of the capture.
///
/// For an explicit capture, this returns the location of the
/// explicit capture in the source. For an implicit capture, this
- /// returns the location at which the variable or 'this' was first
+ /// returns the location at which the variable or \c this was first
/// used.
SourceLocation getLocation() const { return Loc; }
@@ -1376,6 +1447,7 @@ private:
/// \brief Construct a lambda expression.
LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
ArrayRef<Capture> Captures,
bool ExplicitParams,
bool ExplicitResultType,
@@ -1414,10 +1486,11 @@ private:
public:
/// \brief Construct a new lambda expression.
- static LambdaExpr *Create(ASTContext &C,
+ static LambdaExpr *Create(const ASTContext &C,
CXXRecordDecl *Class,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
ArrayRef<Capture> Captures,
bool ExplicitParams,
bool ExplicitResultType,
@@ -1429,14 +1502,20 @@ public:
/// \brief Construct a new lambda expression that will be deserialized from
/// an external source.
- static LambdaExpr *CreateDeserialized(ASTContext &C, unsigned NumCaptures,
+ static LambdaExpr *CreateDeserialized(const ASTContext &C,
+ unsigned NumCaptures,
unsigned NumArrayIndexVars);
-
+
/// \brief Determine the default capture kind for this lambda.
LambdaCaptureDefault getCaptureDefault() const {
return static_cast<LambdaCaptureDefault>(CaptureDefault);
}
+ /// \brief Retrieve the location of this lambda's capture-default, if any.
+ SourceLocation getCaptureDefaultLoc() const {
+ return CaptureDefaultLoc;
+ }
+
/// \brief An iterator that walks over the captures of the lambda,
/// both implicit and explicit.
typedef const Capture *capture_iterator;
@@ -1495,15 +1574,24 @@ public:
/// brackets ([...]).
SourceRange getIntroducerRange() const { return IntroducerRange; }
- /// \brief Retrieve the class that corresponds to the lambda, which
- /// stores the captures in its fields and provides the various
- /// operations permitted on a lambda (copying, calling).
+ /// \brief Retrieve the class that corresponds to the lambda.
+ ///
+ /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the
+ /// captures in its fields and provides the various operations permitted
+ /// on a lambda (copying, calling).
CXXRecordDecl *getLambdaClass() const;
/// \brief Retrieve the function call operator associated with this
/// lambda expression.
CXXMethodDecl *getCallOperator() const;
+ /// \brief If this is a generic lambda expression, retrieve the template
+ /// parameter list associated with it, or else return null.
+ TemplateParameterList *getTemplateParameterList() const;
+
+ /// \brief Whether this is a generic lambda.
+ bool isGenericLambda() const { return getTemplateParameterList(); }
+
/// \brief Retrieve the body of the lambda.
CompoundStmt *getBody() const;
@@ -1535,10 +1623,8 @@ public:
friend class ASTStmtWriter;
};
-/// CXXScalarValueInitExpr - [C++ 5.2.3p2]
-/// Expression "T()" which creates a value-initialized rvalue of type
-/// T, which is a non-class type.
-///
+/// An expression "T()" which creates a value-initialized rvalue of type
+/// T, which is a non-class type. See (C++98 [5.2.3p2]).
class CXXScalarValueInitExpr : public Expr {
SourceLocation RParenLoc;
TypeSourceInfo *TypeInfo;
@@ -1575,11 +1661,11 @@ public:
child_range children() { return child_range(); }
};
-/// @brief Represents a new-expression for memory allocation and constructor
-// calls, e.g: "new CXXNewExpr(foo)".
+/// \brief Represents a new-expression for memory allocation and constructor
+/// calls, e.g: "new CXXNewExpr(foo)".
class CXXNewExpr : public Expr {
- // Contains an optional array size expression, an optional initialization
- // expression, and any number of optional placement arguments, in that order.
+ /// Contains an optional array size expression, an optional initialization
+ /// expression, and any number of optional placement arguments, in that order.
Stmt **SubExprs;
/// \brief Points to the allocation function used.
FunctionDecl *OperatorNew;
@@ -1600,18 +1686,18 @@ class CXXNewExpr : public Expr {
/// \brief Source-range of a paren-delimited initializer.
SourceRange DirectInitRange;
- // Was the usage ::new, i.e. is the global new to be used?
+ /// Was the usage ::new, i.e. is the global new to be used?
bool GlobalNew : 1;
- // Do we allocate an array? If so, the first SubExpr is the size expression.
+ /// 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?
+ /// 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.
+ /// The number of placement new arguments.
unsigned NumPlacementArgs : 13;
- // What kind of initializer do we have? Could be none, parens, or braces.
- // In storage, we distinguish between "none, and no initializer expr", and
- // "none, but an implicit initializer expr".
+ /// What kind of initializer do we have? Could be none, parens, or braces.
+ /// In storage, we distinguish between "none, and no initializer expr", and
+ /// "none, but an implicit initializer expr".
unsigned StoredInitializationStyle : 2;
friend class ASTStmtReader;
@@ -1623,7 +1709,7 @@ public:
ListInit ///< New-expression has a C++11 list-initializer.
};
- CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
+ CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,
ArrayRef<Expr*> placementArgs,
SourceRange typeIdParens, Expr *arraySize,
@@ -1633,8 +1719,8 @@ public:
explicit CXXNewExpr(EmptyShell Shell)
: Expr(CXXNewExprClass, Shell), SubExprs(0) { }
- void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs,
- bool hasInitializer);
+ void AllocateArgsArray(const ASTContext &C, bool isArray,
+ unsigned numPlaceArgs, bool hasInitializer);
QualType getAllocatedType() const {
assert(getType()->isPointerType());
@@ -1646,15 +1732,17 @@ public:
}
/// \brief True if the allocation result needs to be null-checked.
- /// C++0x [expr.new]p13:
+ ///
+ /// C++11 [expr.new]p13:
/// If the allocation function returns null, initialization shall
/// not be done, the deallocation function shall not be called,
/// and the value of the new-expression shall be null.
+ ///
/// An allocation function is not allowed to return null unless it
/// has a non-throwing exception-specification. The '03 rule is
/// identical except that the definition of a non-throwing
/// exception specification is just "is it throw()?".
- bool shouldNullCheckAllocation(ASTContext &Ctx) const;
+ bool shouldNullCheckAllocation(const ASTContext &Ctx) const;
FunctionDecl *getOperatorNew() const { return OperatorNew; }
void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }
@@ -1706,7 +1794,7 @@ public:
return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0;
}
- /// \brief Returns the CXXConstructExpr from this new-expression, or NULL.
+ /// \brief Returns the CXXConstructExpr from this new-expression, or null.
const CXXConstructExpr* getConstructExpr() const {
return dyn_cast_or_null<CXXConstructExpr>(getInitializer());
}
@@ -1768,22 +1856,22 @@ public:
/// \brief Represents a \c delete expression for memory deallocation and
/// destructor calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {
- // Points to the operator delete overload that is used. Could be a member.
+ /// Points to the operator delete overload that is used. Could be a member.
FunctionDecl *OperatorDelete;
- // The pointer expression to be deleted.
+ /// The pointer expression to be deleted.
Stmt *Argument;
- // Location of the expression.
+ /// Location of the expression.
SourceLocation Loc;
- // Is this a forced global delete, i.e. "::delete"?
+ /// Is this a forced global delete, i.e. "::delete"?
bool GlobalDelete : 1;
- // Is this the array form of delete, i.e. "delete[]"?
+ /// 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).
+ /// 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?
+ /// Does the usual deallocation function for the element type require
+ /// a size_t argument?
bool UsualArrayDeleteWantsSize : 1;
public:
CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
@@ -1816,9 +1904,10 @@ public:
Expr *getArgument() { return cast<Expr>(Argument); }
const Expr *getArgument() const { return cast<Expr>(Argument); }
- /// \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.
+ /// \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;
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
@@ -1918,7 +2007,7 @@ class CXXPseudoDestructorExpr : public Expr {
friend class ASTStmtReader;
public:
- CXXPseudoDestructorExpr(ASTContext &Context,
+ CXXPseudoDestructorExpr(const ASTContext &Context,
Expr *Base, bool isArrow, SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
TypeSourceInfo *ScopeType,
@@ -1935,7 +2024,7 @@ public:
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
- bool hasQualifier() const { return QualifierLoc; }
+ bool hasQualifier() const { return QualifierLoc.hasQualifier(); }
/// \brief Retrieves the nested-name-specifier that qualifies the type name,
/// with source-location information.
@@ -1943,7 +2032,7 @@ public:
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
- /// NULL.
+ /// null.
NestedNameSpecifier *getQualifier() const {
return QualifierLoc.getNestedNameSpecifier();
}
@@ -1978,7 +2067,7 @@ public:
///
/// This type-source information is available for non-dependent
/// pseudo-destructor expressions and some dependent pseudo-destructor
- /// expressions. Returns NULL if we only have the identifier for a
+ /// expressions. Returns null if we only have the identifier for a
/// dependent pseudo-destructor expression.
TypeSourceInfo *getDestroyedTypeInfo() const {
return DestroyedType.getTypeSourceInfo();
@@ -2025,23 +2114,23 @@ public:
/// implementation of TR1/C++11 type trait templates.
///
/// Example:
-/// @code
+/// \code
/// __is_pod(int) == true
/// __is_enum(std::string) == false
-/// @endcode
+/// \endcode
class UnaryTypeTraitExpr : public Expr {
- /// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned.
+ /// \brief The trait. A UnaryTypeTrait enum in MSVC compatible unsigned.
unsigned UTT : 31;
/// The value of the type trait. Unspecified if dependent.
bool Value : 1;
- /// Loc - The location of the type trait keyword.
+ /// \brief The location of the type trait keyword.
SourceLocation Loc;
- /// RParen - The location of the closing paren.
+ /// \brief The location of the closing paren.
SourceLocation RParen;
- /// The type being queried.
+ /// \brief The type being queried.
TypeSourceInfo *QueriedType;
public:
@@ -2083,26 +2172,26 @@ public:
/// implementation of TR1/C++11 type trait templates.
///
/// Example:
-/// @code
+/// \code
/// __is_base_of(Base, Derived) == true
-/// @endcode
+/// \endcode
class BinaryTypeTraitExpr : public Expr {
- /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned.
+ /// \brief The trait. A BinaryTypeTrait enum in MSVC compatible unsigned.
unsigned BTT : 8;
/// The value of the type trait. Unspecified if dependent.
bool Value : 1;
- /// Loc - The location of the type trait keyword.
+ /// \brief The location of the type trait keyword.
SourceLocation Loc;
- /// RParen - The location of the closing paren.
+ /// \brief The location of the closing paren.
SourceLocation RParen;
- /// The lhs type being queried.
+ /// \brief The lhs type being queried.
TypeSourceInfo *LhsType;
- /// The rhs type being queried.
+ /// \brief The rhs type being queried.
TypeSourceInfo *RhsType;
public:
@@ -2184,13 +2273,14 @@ class TypeTraitExpr : public Expr {
public:
/// \brief Create a new type trait expression.
- static TypeTraitExpr *Create(ASTContext &C, QualType T, SourceLocation Loc,
- TypeTrait Kind,
+ static TypeTraitExpr *Create(const ASTContext &C, QualType T,
+ SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc,
bool Value);
- static TypeTraitExpr *CreateDeserialized(ASTContext &C, unsigned NumArgs);
+ static TypeTraitExpr *CreateDeserialized(const ASTContext &C,
+ unsigned NumArgs);
/// \brief Determine which type trait this expression uses.
TypeTrait getTrait() const {
@@ -2249,10 +2339,10 @@ public:
/// __array_rank and __array_extent.
///
/// Example:
-/// @code
+/// \code
/// __array_rank(int[10][20]) == 2
/// __array_extent(int, 1) == 20
-/// @endcode
+/// \endcode
class ArrayTypeTraitExpr : public Expr {
virtual void anchor();
@@ -2319,12 +2409,12 @@ public:
/// \brief An expression trait intrinsic.
///
/// Example:
-/// @code
+/// \code
/// __is_lvalue_expr(std::cout) == true
/// __is_lvalue_expr(1) == false
-/// @endcode
+/// \endcode
class ExpressionTraitExpr : public Expr {
- /// \brief The trait. A ExpressionTrait enum in MSVC compat unsigned.
+ /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned.
unsigned ET : 31;
/// \brief The value of the type trait. Unspecified if dependent.
bool Value : 1;
@@ -2403,7 +2493,7 @@ protected:
return const_cast<OverloadExpr*>(this)->getTemplateKWAndArgsInfo();
}
- OverloadExpr(StmtClass K, ASTContext &C,
+ OverloadExpr(StmtClass K, const ASTContext &C,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
@@ -2417,7 +2507,7 @@ protected:
: Expr(K, Empty), QualifierLoc(), Results(0), NumResults(0),
HasTemplateKWAndArgsInfo(false) { }
- void initializeResults(ASTContext &C,
+ void initializeResults(const ASTContext &C,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End);
@@ -2428,7 +2518,7 @@ public:
bool HasFormOfMemberPointer;
};
- /// Finds the overloaded expression in the given expression of
+ /// \brief Finds the overloaded expression in the given expression \p E of
/// OverloadTy.
///
/// \return the expression (which must be there) and true if it has
@@ -2561,10 +2651,11 @@ public:
/// parsing but could not resolve to a specific declaration.
///
/// This arises in several ways:
-/// * we might be waiting for argument-dependent lookup
-/// * the name might resolve to an overloaded function
+/// * we might be waiting for argument-dependent lookup;
+/// * the name might resolve to an overloaded function;
/// and eventually:
-/// * the lookup might have included a function template
+/// * the lookup might have included a function template.
+///
/// These never include UnresolvedUsingValueDecls, which are always class
/// members and therefore appear only in UnresolvedMemberLookupExprs.
class UnresolvedLookupExpr : public OverloadExpr {
@@ -2584,7 +2675,7 @@ class UnresolvedLookupExpr : public OverloadExpr {
/// against the qualified-lookup bits.
CXXRecordDecl *NamingClass;
- UnresolvedLookupExpr(ASTContext &C,
+ UnresolvedLookupExpr(const ASTContext &C,
CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
@@ -2606,7 +2697,7 @@ class UnresolvedLookupExpr : public OverloadExpr {
friend class ASTStmtReader;
public:
- static UnresolvedLookupExpr *Create(ASTContext &C,
+ static UnresolvedLookupExpr *Create(const ASTContext &C,
CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
@@ -2618,7 +2709,7 @@ public:
ADL, Overloaded, 0, Begin, End);
}
- static UnresolvedLookupExpr *Create(ASTContext &C,
+ static UnresolvedLookupExpr *Create(const ASTContext &C,
CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
@@ -2628,7 +2719,7 @@ public:
UnresolvedSetIterator Begin,
UnresolvedSetIterator End);
- static UnresolvedLookupExpr *CreateEmpty(ASTContext &C,
+ static UnresolvedLookupExpr *CreateEmpty(const ASTContext &C,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
@@ -2671,7 +2762,7 @@ public:
/// DependentScopeDeclRefExpr node is used only within C++ templates when
/// the qualification (e.g., X<T>::) refers to a dependent type. In
/// this case, X<T>::value cannot resolve to a declaration because the
-/// declaration will differ from on instantiation of X<T> to the
+/// declaration will differ from one instantiation of X<T> to the
/// next. Therefore, DependentScopeDeclRefExpr keeps track of the
/// qualifier (X<T>::) and the name of the entity being referenced
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
@@ -2681,7 +2772,7 @@ class DependentScopeDeclRefExpr : public Expr {
/// declaration name.
NestedNameSpecifierLoc QualifierLoc;
- /// The name of the entity we will be referencing.
+ /// \brief The name of the entity we will be referencing.
DeclarationNameInfo NameInfo;
/// \brief Whether the name includes info for explicit template
@@ -2706,13 +2797,13 @@ class DependentScopeDeclRefExpr : public Expr {
const TemplateArgumentListInfo *Args);
public:
- static DependentScopeDeclRefExpr *Create(ASTContext &C,
+ static DependentScopeDeclRefExpr *Create(const ASTContext &C,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
- static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
+ static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
@@ -2723,13 +2814,14 @@ public:
DeclarationName getDeclName() const { return NameInfo.getName(); }
/// \brief Retrieve the location of the name within the expression.
+ ///
+ /// For example, in "X<T>::value" this is the location of "value".
SourceLocation getLocation() const { return NameInfo.getLoc(); }
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name, with source location information.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
-
/// \brief Retrieve the nested-name-specifier that qualifies this
/// declaration.
NestedNameSpecifier *getQualifier() const {
@@ -2779,6 +2871,7 @@ public:
}
/// \brief Retrieves the optional explicit template arguments.
+ ///
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
@@ -2800,6 +2893,8 @@ public:
return getExplicitTemplateArgs().NumTemplateArgs;
}
+ /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr,
+ /// and differs from getLocation().getStart().
SourceLocation getLocStart() const LLVM_READONLY {
return QualifierLoc.getBeginLoc();
}
@@ -2819,7 +2914,7 @@ public:
friend class ASTStmtWriter;
};
-/// Represents an expression --- generally a full-expression --- which
+/// Represents an expression -- generally a full-expression -- that
/// 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 kinds of
@@ -2852,10 +2947,10 @@ private:
friend class ASTStmtReader;
public:
- static ExprWithCleanups *Create(ASTContext &C, EmptyShell empty,
+ static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty,
unsigned numObjects);
- static ExprWithCleanups *Create(ASTContext &C, Expr *subexpr,
+ static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr,
ArrayRef<CleanupObject> objects);
ArrayRef<CleanupObject> getObjects() const {
@@ -2872,7 +2967,7 @@ public:
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
- /// setSubExpr - As with any mutator of the AST, be very careful
+ /// As with any mutator of the AST, be very careful
/// when modifying an existing AST to preserve its invariants.
void setSubExpr(Expr *E) { SubExpr = E; }
@@ -2935,13 +3030,13 @@ class CXXUnresolvedConstructExpr : public Expr {
friend class ASTStmtReader;
public:
- static CXXUnresolvedConstructExpr *Create(ASTContext &C,
+ static CXXUnresolvedConstructExpr *Create(const ASTContext &C,
TypeSourceInfo *Type,
SourceLocation LParenLoc,
ArrayRef<Expr*> Args,
SourceLocation RParenLoc);
- static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C,
+ static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C,
unsigned NumArgs);
/// \brief Retrieve the type that is being constructed, as specified
@@ -2993,7 +3088,10 @@ public:
}
SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ assert(RParenLoc.isValid() || NumArgs == 1);
+ return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd();
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXUnresolvedConstructExprClass;
@@ -3047,6 +3145,7 @@ class CXXDependentScopeMemberExpr : public Expr {
/// \brief The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
+ ///
/// FIXME: could also be a template-id
DeclarationNameInfo MemberNameInfo;
@@ -3061,36 +3160,32 @@ class CXXDependentScopeMemberExpr : public Expr {
->getTemplateKWAndArgsInfo();
}
- CXXDependentScopeMemberExpr(ASTContext &C,
- Expr *Base, QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierFoundInScope,
- DeclarationNameInfo MemberNameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
+ CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
+ QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
public:
- CXXDependentScopeMemberExpr(ASTContext &C,
- Expr *Base, QualType BaseType,
- bool IsArrow,
+ CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
+ QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo);
static CXXDependentScopeMemberExpr *
- Create(ASTContext &C,
- Expr *Base, QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierFoundInScope,
+ Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
- CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo,
+ CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
/// \brief True if this is an implicit access, i.e. one in which the
@@ -3197,6 +3292,7 @@ public:
}
/// \brief Retrieves the optional explicit template arguments.
+ ///
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
@@ -3259,11 +3355,13 @@ public:
/// produced a set of overloaded functions.
///
/// The member access may be explicit or implicit:
+/// \code
/// struct A {
/// int a, b;
/// int explicitAccess() { return this->a + this->A::b; }
/// int implicitAccess() { return a + A::b; }
/// };
+/// \endcode
///
/// In the final AST, an explicit access always becomes a MemberExpr.
/// An implicit access may become either a MemberExpr or a
@@ -3278,17 +3376,18 @@ class UnresolvedMemberExpr : public OverloadExpr {
bool HasUnresolvedUsing : 1;
/// \brief The expression for the base pointer or class reference,
- /// e.g., the \c x in x.f. This can be null if this is an 'unbased'
- /// member expression
+ /// e.g., the \c x in x.f.
+ ///
+ /// This can be null if this is an 'unbased' member expression.
Stmt *Base;
- /// \brief The type of the base expression; never null.
+ /// \brief The type of the base expression; never null.
QualType BaseType;
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
- UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing,
+ UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
@@ -3305,7 +3404,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
public:
static UnresolvedMemberExpr *
- Create(ASTContext &C, bool HasUnresolvedUsing,
+ Create(const ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
@@ -3315,12 +3414,13 @@ public:
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
static UnresolvedMemberExpr *
- CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo,
+ CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
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
- /// location of the operator is invalid in this case.
+ /// \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 location of the operator is invalid in this case.
bool isImplicitAccess() const;
/// \brief Retrieve the base object of this member expressions,
@@ -3347,7 +3447,7 @@ public:
/// \brief Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
- /// \brief Retrieves the naming class of this lookup.
+ /// \brief Retrieve the naming class of this lookup.
CXXRecordDecl *getNamingClass() const;
/// \brief Retrieve the full name info for the member that this expression
@@ -3362,6 +3462,10 @@ public:
// expression refers to.
SourceLocation getMemberLoc() const { return getNameLoc(); }
+ // \brief Return the preferred location (the member name) for the arrow when
+ // diagnosing a problem with this expression.
+ SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); }
+
SourceLocation getLocStart() const LLVM_READONLY {
if (!isImplicitAccess())
return Base->getLocStart();
@@ -3386,7 +3490,7 @@ public:
}
};
-/// \brief Represents a C++0x noexcept expression (C++ [expr.unary.noexcept]).
+/// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
///
/// The noexcept expression tests whether a given expression might throw. Its
/// result is a boolean constant.
@@ -3428,7 +3532,7 @@ public:
child_range children() { return child_range(&Operand, &Operand + 1); }
};
-/// \brief Represents a C++0x pack expansion that produces a sequence of
+/// \brief Represents a C++11 pack expansion that produces a sequence of
/// expressions.
///
/// A pack expansion expression contains a pattern (which itself is an
@@ -3527,7 +3631,7 @@ inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() {
/// };
/// \endcode
class SizeOfPackExpr : public Expr {
- /// \brief The location of the 'sizeof' keyword.
+ /// \brief The location of the \c sizeof keyword.
SourceLocation OperatorLoc;
/// \brief The location of the name of the parameter pack.
@@ -3550,7 +3654,7 @@ class SizeOfPackExpr : public Expr {
friend class ASTStmtWriter;
public:
- /// \brief Creates a value-dependent expression that computes the length of
+ /// \brief Create a value-dependent expression that computes the length of
/// the given parameter pack.
SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
SourceLocation PackLoc, SourceLocation RParenLoc)
@@ -3561,7 +3665,7 @@ public:
OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
Length(0), Pack(Pack) { }
- /// \brief Creates an expression that computes the length of
+ /// \brief Create 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,
@@ -3744,11 +3848,11 @@ class FunctionParmPackExpr : public Expr {
friend class ASTStmtReader;
public:
- static FunctionParmPackExpr *Create(ASTContext &Context, QualType T,
+ static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T,
ParmVarDecl *ParamPack,
SourceLocation NameLoc,
ArrayRef<Decl *> Params);
- static FunctionParmPackExpr *CreateEmpty(ASTContext &Context,
+ static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context,
unsigned NumParams);
/// \brief Get the parameter pack which this expression refers to.
@@ -3779,7 +3883,7 @@ public:
child_range children() { return child_range(); }
};
-/// \brief Represents a prvalue temporary that written into memory so that
+/// \brief Represents a prvalue temporary that is written into memory so that
/// a reference can bind to it.
///
/// Prvalue expressions are materialized when they need to have an address
@@ -3795,30 +3899,60 @@ public:
/// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues
/// (either an lvalue or an xvalue, depending on the kind of reference binding
/// to it), maintaining the invariant that references always bind to glvalues.
+///
+/// Reference binding and copy-elision can both extend the lifetime of a
+/// temporary. When either happens, the expression will also track the
+/// declaration which is responsible for the lifetime extension.
class MaterializeTemporaryExpr : public Expr {
+public:
/// \brief The temporary-generating expression whose value will be
/// materialized.
Stmt *Temporary;
+ /// \brief The declaration which lifetime-extended this reference, if any.
+ /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
+ const ValueDecl *ExtendingDecl;
+
friend class ASTStmtReader;
friend class ASTStmtWriter;
public:
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
- bool BoundToLvalueReference)
+ bool BoundToLvalueReference,
+ const ValueDecl *ExtendedBy)
: Expr(MaterializeTemporaryExprClass, T,
BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
Temporary->isTypeDependent(), Temporary->isValueDependent(),
Temporary->isInstantiationDependent(),
Temporary->containsUnexpandedParameterPack()),
- Temporary(Temporary) { }
+ Temporary(Temporary), ExtendingDecl(ExtendedBy) {
+ }
MaterializeTemporaryExpr(EmptyShell Empty)
: Expr(MaterializeTemporaryExprClass, Empty) { }
/// \brief Retrieve the temporary-generating subexpression whose value will
/// be materialized into a glvalue.
- Expr *GetTemporaryExpr() const { return reinterpret_cast<Expr *>(Temporary); }
+ Expr *GetTemporaryExpr() const { return static_cast<Expr *>(Temporary); }
+
+ /// \brief Retrieve the storage duration for the materialized temporary.
+ StorageDuration getStorageDuration() const {
+ if (!ExtendingDecl)
+ return SD_FullExpression;
+ // FIXME: This is not necessarily correct for a temporary materialized
+ // within a default initializer.
+ if (isa<FieldDecl>(ExtendingDecl))
+ return SD_Automatic;
+ return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
+ }
+
+ /// \brief Get the declaration which triggered the lifetime-extension of this
+ /// temporary, if any.
+ const ValueDecl *getExtendingDecl() const { return ExtendingDecl; }
+
+ void setExtendingDecl(const ValueDecl *ExtendedBy) {
+ ExtendingDecl = ExtendedBy;
+ }
/// \brief Determine whether this materialized temporary is bound to an
/// lvalue reference; otherwise, it's bound to an rvalue reference.
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index a94c69a115d6..aeb55da1fb91 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -143,12 +143,13 @@ class ObjCArrayLiteral : public Expr {
: Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
public:
- static ObjCArrayLiteral *Create(ASTContext &C,
+ static ObjCArrayLiteral *Create(const ASTContext &C,
ArrayRef<Expr *> Elements,
QualType T, ObjCMethodDecl * Method,
SourceRange SR);
- static ObjCArrayLiteral *CreateEmpty(ASTContext &C, unsigned NumElements);
+ static ObjCArrayLiteral *CreateEmpty(const ASTContext &C,
+ unsigned NumElements);
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
@@ -289,13 +290,13 @@ class ObjCDictionaryLiteral : public Expr {
}
public:
- static ObjCDictionaryLiteral *Create(ASTContext &C,
+ static ObjCDictionaryLiteral *Create(const ASTContext &C,
ArrayRef<ObjCDictionaryElement> VK,
bool HasPackExpansions,
QualType T, ObjCMethodDecl *method,
SourceRange SR);
- static ObjCDictionaryLiteral *CreateEmpty(ASTContext &C,
+ static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C,
unsigned NumElements,
bool HasPackExpansions);
@@ -807,7 +808,7 @@ public:
explicit ObjCSubscriptRefExpr(EmptyShell Empty)
: Expr(ObjCSubscriptRefExprClass, Empty) {}
- static ObjCSubscriptRefExpr *Create(ASTContext &C,
+ static ObjCSubscriptRefExpr *Create(const ASTContext &C,
Expr *base,
Expr *key, QualType T,
ObjCMethodDecl *getMethod,
@@ -1003,13 +1004,13 @@ class ObjCMessageExpr : public Expr {
return getNumSelectorLocs();
}
- static ObjCMessageExpr *alloc(ASTContext &C,
+ static ObjCMessageExpr *alloc(const ASTContext &C,
ArrayRef<Expr *> Args,
SourceLocation RBraceLoc,
ArrayRef<SourceLocation> SelLocs,
Selector Sel,
SelectorLocationsKind &SelLocsK);
- static ObjCMessageExpr *alloc(ASTContext &C,
+ static ObjCMessageExpr *alloc(const ASTContext &C,
unsigned NumArgs,
unsigned NumStoredSelLocs);
@@ -1051,7 +1052,7 @@ public:
/// \param Args The message send arguments.
///
/// \param RBracLoc The location of the closing square bracket ']'.
- static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK,
SourceLocation LBracLoc,
SourceLocation SuperLoc,
@@ -1087,7 +1088,7 @@ public:
/// \param Args The message send arguments.
///
/// \param RBracLoc The location of the closing square bracket ']'.
- static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK,
SourceLocation LBracLoc,
TypeSourceInfo *Receiver,
@@ -1121,7 +1122,7 @@ public:
/// \param Args The message send arguments.
///
/// \param RBracLoc The location of the closing square bracket ']'.
- static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK,
SourceLocation LBracLoc,
Expr *Receiver,
@@ -1139,7 +1140,7 @@ public:
///
/// \param NumArgs The number of message arguments, not including
/// the receiver.
- static ObjCMessageExpr *CreateEmpty(ASTContext &Context,
+ static ObjCMessageExpr *CreateEmpty(const ASTContext &Context,
unsigned NumArgs,
unsigned NumStoredSelLocs);
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index 81fcf242b65e..b077426e6a47 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -329,7 +329,12 @@ public:
/// \brief Whether this pointer is non-NULL.
///
/// This operation does not require the AST node to be deserialized.
- operator bool() const { return Ptr != 0; }
+ LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
+
+ /// \brief Whether this pointer is non-NULL.
+ ///
+ /// This operation does not require the AST node to be deserialized.
+ bool isValid() const { return Ptr != 0; }
/// \brief Whether this pointer is currently stored as an offset.
bool isOffset() const { return Ptr & 0x01; }
diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h
index c43e44c26f31..54c9d88c9b2e 100644
--- a/include/clang/AST/GlobalDecl.h
+++ b/include/clang/AST/GlobalDecl.h
@@ -41,6 +41,7 @@ public:
GlobalDecl(const VarDecl *D) { Init(D);}
GlobalDecl(const FunctionDecl *D) { Init(D); }
GlobalDecl(const BlockDecl *D) { Init(D); }
+ GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
diff --git a/include/clang/AST/LambdaMangleContext.h b/include/clang/AST/LambdaMangleContext.h
deleted file mode 100644
index bbaee26494a9..000000000000
--- a/include/clang/AST/LambdaMangleContext.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the LambdaMangleContext interface, which keeps track of
-// the Itanium C++ ABI mangling numbers for lambda expressions.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H
-#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-
-namespace clang {
-
-class CXXMethodDecl;
-class FunctionProtoType;
-
-/// \brief Keeps track of the mangled names of lambda expressions within a
-/// particular context.
-class LambdaMangleContext : public RefCountedBase<LambdaMangleContext> {
- llvm::DenseMap<const FunctionProtoType *, unsigned> ManglingNumbers;
-
-public:
- /// \brief Retrieve the mangling number of a new lambda expression with the
- /// given call operator within this lambda context.
- unsigned getManglingNumber(CXXMethodDecl *CallOperator);
-};
-
-} // end namespace clang
-#endif
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index b6d22cfb5fd7..c4d0d22cdf0a 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -64,18 +65,29 @@ private:
/// MangleContext - Context for tracking state which persists across multiple
/// calls to the C++ name mangler.
class MangleContext {
+public:
+ enum ManglerKind {
+ MK_Itanium,
+ MK_Microsoft
+ };
+
+private:
virtual void anchor();
ASTContext &Context;
DiagnosticsEngine &Diags;
+ const ManglerKind Kind;
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
-
+
public:
+ ManglerKind getKind() const { return Kind; }
+
explicit MangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags)
- : Context(Context), Diags(Diags) { }
+ DiagnosticsEngine &Diags,
+ ManglerKind Kind)
+ : Context(Context), Diags(Diags), Kind(Kind) {}
virtual ~MangleContext() { }
@@ -96,8 +108,12 @@ public:
/// @name Mangler Entry Points
/// @{
- virtual bool shouldMangleDeclName(const NamedDecl *D) = 0;
- virtual void mangleName(const NamedDecl *D, raw_ostream &)=0;
+ bool shouldMangleDeclName(const NamedDecl *D);
+ virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
+
+ // FIXME: consider replacing raw_ostream & with something like SmallString &.
+ void mangleName(const NamedDecl *D, raw_ostream &);
+ virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0;
virtual void mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &) = 0;
@@ -106,13 +122,6 @@ public:
raw_ostream &) = 0;
virtual void mangleReferenceTemporary(const VarDecl *D,
raw_ostream &) = 0;
- virtual void mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &) = 0;
- virtual void mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &) = 0;
- virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &) = 0;
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
@@ -129,36 +138,78 @@ public:
const BlockDecl *BD, raw_ostream &Out);
void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
raw_ostream &Out);
- // Do the right thing.
- void mangleBlock(const BlockDecl *BD, raw_ostream &Out,
- const NamedDecl *ID=0);
- void mangleObjCMethodName(const ObjCMethodDecl *MD,
- raw_ostream &);
+ void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &);
- // This is pretty lame.
- virtual void mangleItaniumGuardVariable(const VarDecl *D,
- raw_ostream &) {
- llvm_unreachable("Target does not support mangling guard variables");
- }
- // FIXME: Revisit this once we know what we need to do for MSVC compatibility.
+ virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
+
+ virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;
+
+ virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
+ raw_ostream &) = 0;
+
+ /// Generates a unique string for an externally visible type for use with TBAA
+ /// or type uniquing.
+ /// TODO: Extend this to internal types by generating names that are unique
+ /// across translation units so it can be used with LTO.
+ virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
+
+ /// @}
+};
+
+class ItaniumMangleContext : public MangleContext {
+public:
+ explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
+ : MangleContext(C, D, MK_Itanium) {}
+
+ virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
+ virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
+ virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ raw_ostream &) = 0;
virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
- raw_ostream &) {
- llvm_unreachable("Target does not support mangling thread_local variables");
- }
+ raw_ostream &) = 0;
virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
- raw_ostream &) {
- llvm_unreachable("Target does not support mangling thread_local variables");
+ raw_ostream &) = 0;
+
+ static bool classof(const MangleContext *C) {
+ return C->getKind() == MK_Itanium;
}
- /// @}
+ static ItaniumMangleContext *create(ASTContext &Context,
+ DiagnosticsEngine &Diags);
};
-MangleContext *createItaniumMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags);
-MangleContext *createMicrosoftMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags);
+class MicrosoftMangleContext : public MangleContext {
+public:
+ explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
+ : MangleContext(C, D, MK_Microsoft) {}
+
+ /// \brief Mangle vftable symbols. Only a subset of the bases along the path
+ /// to the vftable are included in the name. It's up to the caller to pick
+ /// them correctly.
+ virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
+ ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) = 0;
+
+ /// \brief Mangle vbtable symbols. Only a subset of the bases along the path
+ /// to the vbtable are included in the name. It's up to the caller to pick
+ /// them correctly.
+ virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
+ ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) = 0;
+
+ virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ uint64_t OffsetInVFTable,
+ raw_ostream &) = 0;
+ static bool classof(const MangleContext *C) {
+ return C->getKind() == MK_Microsoft;
+ }
+
+ static MicrosoftMangleContext *create(ASTContext &Context,
+ DiagnosticsEngine &Diags);
+};
}
#endif
diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h
new file mode 100644
index 000000000000..5a227f201fbb
--- /dev/null
+++ b/include/clang/AST/MangleNumberingContext.h
@@ -0,0 +1,59 @@
+//=== MangleNumberingContext.h - Context for mangling numbers ---*- 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 LambdaBlockMangleContext interface, which keeps track
+// of the Itanium C++ ABI mangling numbers for lambda expressions and block
+// literals.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
+#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+namespace clang {
+
+class BlockDecl;
+class CXXMethodDecl;
+class IdentifierInfo;
+class TagDecl;
+class Type;
+class VarDecl;
+
+/// \brief Keeps track of the mangled names of lambda expressions and block
+/// literals within a particular context.
+class MangleNumberingContext
+ : public RefCountedBase<MangleNumberingContext> {
+ llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
+ llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers;
+
+public:
+ virtual ~MangleNumberingContext() {}
+
+ /// \brief Retrieve the mangling number of a new lambda expression with the
+ /// given call operator within this context.
+ unsigned getManglingNumber(const CXXMethodDecl *CallOperator);
+
+ /// \brief Retrieve the mangling number of a new block literal within this
+ /// context.
+ unsigned getManglingNumber(const BlockDecl *BD);
+
+ /// \brief Retrieve the mangling number of a static local variable within
+ /// this context.
+ virtual unsigned getManglingNumber(const VarDecl *VD) = 0;
+
+ /// \brief Retrieve the mangling number of a static local variable within
+ /// this context.
+ unsigned getManglingNumber(const TagDecl *TD);
+};
+
+} // end namespace clang
+#endif
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 58f39862b102..b332b153fe8d 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -231,7 +231,11 @@ public:
/// \brief Evalutes true when this nested-name-specifier location is
/// non-empty.
- operator bool() const { return Qualifier; }
+ LLVM_EXPLICIT operator bool() const { return Qualifier; }
+
+ /// \brief Evalutes true when this nested-name-specifier location is
+ /// empty.
+ bool hasQualifier() const { return Qualifier; }
/// \brief Retrieve the nested-name-specifier to which this instance
/// refers.
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index 62eae02c1525..bd2ebf5dbedb 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -29,6 +29,11 @@ public:
/// visited and updated or inserted but not the parents of S.
void addStmt(Stmt* S);
+ /// Manually sets the parent of \p S to \p Parent.
+ ///
+ /// If \p S is already in the map, this method will update the mapping.
+ void setParent(const Stmt *S, const Stmt *Parent);
+
Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const;
Stmt *getParentIgnoreParenCasts(Stmt *) const;
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index e3c09e7b418f..76426991cf47 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -39,8 +39,9 @@ struct PrintingPolicy {
SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false),
SuppressUnwrittenScope(false), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
- SuppressStrongLifetime(false), Bool(LO.Bool),
- TerseOutput(false), PolishForDeclaration(false) { }
+ SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
+ Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
+ MSWChar(LO.MicrosoftExt && !LO.WChar) { }
/// \brief What language we're printing.
LangOptions LangOpts;
@@ -131,6 +132,10 @@ struct PrintingPolicy {
/// ARC.
unsigned SuppressStrongLifetime : 1;
+ /// \brief When true, suppress printing of lifetime qualifier in
+ /// ARC.
+ unsigned SuppressLifetimeQualifiers : 1;
+
/// \brief Whether we can use 'bool' rather than '_Bool', even if the language
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
unsigned Bool : 1;
@@ -146,6 +151,10 @@ struct PrintingPolicy {
/// declaration tag; such as, do not print attributes attached to the declaration.
///
unsigned PolishForDeclaration : 1;
+
+ /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in
+ /// Microsoft mode when wchar_t is not available.
+ unsigned MSWChar : 1;
};
} // end namespace clang
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index 84a6e96fa01a..a4fcc108eb5d 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/include/clang/AST/RawCommentList.h
@@ -107,12 +107,9 @@ public:
return RawText;
}
- SourceRange getSourceRange() const LLVM_READONLY {
- return Range;
- }
-
- unsigned getBeginLine(const SourceManager &SM) const;
- unsigned getEndLine(const SourceManager &SM) const;
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
const char *getBriefText(const ASTContext &Context) const {
if (BriefTextValid)
@@ -146,11 +143,6 @@ private:
/// considered as documentation comments.
bool ParseAllComments : 1;
- mutable bool BeginLineValid : 1; ///< True if BeginLine is valid
- mutable bool EndLineValid : 1; ///< True if EndLine is valid
- mutable unsigned BeginLine; ///< Cached line number
- mutable unsigned EndLine; ///< Cached line number
-
/// \brief Constructor for AST deserialization.
RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
bool IsAlmostTrailingComment,
@@ -158,8 +150,7 @@ private:
Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
IsAttached(false), IsTrailingComment(IsTrailingComment),
IsAlmostTrailingComment(IsAlmostTrailingComment),
- ParseAllComments(ParseAllComments),
- BeginLineValid(false), EndLineValid(false)
+ ParseAllComments(ParseAllComments)
{ }
StringRef getRawTextSlow(const SourceManager &SourceMgr) const;
@@ -178,8 +169,7 @@ public:
explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { }
bool operator()(const RawComment &LHS, const RawComment &RHS) {
- return SM.isBeforeInTranslationUnit(LHS.getSourceRange().getBegin(),
- RHS.getSourceRange().getBegin());
+ return SM.isBeforeInTranslationUnit(LHS.getLocStart(), RHS.getLocStart());
}
bool operator()(const RawComment *LHS, const RawComment *RHS) {
@@ -191,8 +181,7 @@ public:
/// sorted in order of appearance in the translation unit.
class RawCommentList {
public:
- RawCommentList(SourceManager &SourceMgr) :
- SourceMgr(SourceMgr), OnlyWhitespaceSeen(true) { }
+ RawCommentList(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator);
@@ -203,15 +192,9 @@ public:
private:
SourceManager &SourceMgr;
std::vector<RawComment *> Comments;
- SourceLocation PrevCommentEndLoc;
- bool OnlyWhitespaceSeen;
void addCommentsToFront(const std::vector<RawComment *> &C) {
- size_t OldSize = Comments.size();
- Comments.resize(C.size() + OldSize);
- std::copy_backward(Comments.begin(), Comments.begin() + OldSize,
- Comments.end());
- std::copy(C.begin(), C.end(), Comments.begin());
+ Comments.insert(Comments.begin(), C.begin(), C.end());
}
friend class ASTReader;
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 36556469eaf8..7268b3a8240c 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -93,10 +93,22 @@ private:
/// HasOwnVFPtr - Does this class provide a virtual function table
/// (vtable in Itanium, vftbl in Microsoft) that is independent from
/// its base classes?
- bool HasOwnVFPtr; // TODO: stash this somewhere more efficient
+ bool HasOwnVFPtr : 1;
+
+ /// HasVFPtr - Does this class have a vftable that could be extended by
+ /// a derived class. The class may have inherited this pointer from
+ /// a primary base class.
+ bool HasExtendableVFPtr : 1;
+
+ /// AlignAfterVBases - Force appropriate alignment after virtual bases are
+ /// laid out in MS-C++-ABI.
+ bool AlignAfterVBases : 1;
/// PrimaryBase - The primary base info for this record.
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
+
+ /// BaseSharingVBPtr - The base we share vbptr with.
+ const CXXRecordDecl *BaseSharingVBPtr;
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
@@ -122,13 +134,16 @@ private:
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
- bool hasOwnVFPtr, CharUnits vbptroffset,
+ bool hasOwnVFPtr, bool hasExtendableVFPtr,
+ CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
CharUnits nonvirtualsize, CharUnits nonvirtualalign,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
+ const CXXRecordDecl *BaseSharingVBPtr,
+ bool ForceAlign,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets);
@@ -226,6 +241,37 @@ public:
return CXXInfo->HasOwnVFPtr;
}
+ /// hasVFPtr - Does this class have a virtual function table pointer
+ /// that can be extended by a derived class? This is synonymous with
+ /// this class having a VFPtr at offset zero.
+ bool hasExtendableVFPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->HasExtendableVFPtr;
+ }
+
+ /// hasOwnVBPtr - Does this class provide its own virtual-base
+ /// table pointer, rather than inheriting one from a primary base
+ /// class?
+ ///
+ /// This implies that the ABI has no primary base class, meaning
+ /// that it has no base classes that are suitable under the conditions
+ /// of the ABI.
+ bool hasOwnVBPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return hasVBPtr() && !CXXInfo->BaseSharingVBPtr;
+ }
+
+ /// hasVBPtr - Does this class have a virtual function table pointer.
+ bool hasVBPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return !CXXInfo->VBPtrOffset.isNegative();
+ }
+
+ bool getAlignAfterVBases() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->AlignAfterVBases;
+ }
+
/// getVBPtrOffset - Get the offset for virtual base table pointer.
/// This is only meaningful with the Microsoft ABI.
CharUnits getVBPtrOffset() const {
@@ -233,6 +279,11 @@ public:
return CXXInfo->VBPtrOffset;
}
+ const CXXRecordDecl *getBaseSharingVBPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->BaseSharingVBPtr;
+ }
+
const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->VBaseOffsets;
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index b5a4b5e36d7d..d09550f0e2c2 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -27,6 +27,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -108,7 +109,7 @@ namespace clang {
/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar
/// is Foo's super class) before calling VisitFoo(), the result is
/// that the Visit*() methods for a given node are called in the
-/// top-down order (e.g. for a node of type NamedDecl, the order will
+/// top-down order (e.g. for a node of type NamespaceDecl, the order will
/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()).
///
/// This scheme guarantees that all Visit*() calls for the same AST
@@ -243,8 +244,16 @@ public:
/// \brief Recursively visit a lambda capture.
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaCapture(LambdaExpr::Capture C);
-
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaExpr::Capture *C);
+
+ /// \brief Recursively visit the body of a lambda expression.
+ ///
+ /// This provides a hook for visitors that need more context when visiting
+ /// \c LE->getBody().
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseLambdaBody(LambdaExpr *LE);
+
// ---- Methods on Stmts ----
// Declare Traverse*() for all concrete Stmt classes.
@@ -342,7 +351,7 @@ public:
// ---- Methods on TypeLocs ----
// FIXME: this currently just calls the matching Type methods
- // Declare Traverse*() for all concrete Type classes.
+ // Declare Traverse*() for all concrete TypeLoc classes.
#define ABSTRACT_TYPELOC(CLASS, BASE)
#define TYPELOC(CLASS, BASE) \
bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
@@ -398,8 +407,12 @@ public:
private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
- bool TraverseClassInstantiations(ClassTemplateDecl *D);
- bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ;
+#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \
+ bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
+ DEF_TRAVERSE_TMPL_INST(Class)
+ DEF_TRAVERSE_TMPL_INST(Var)
+ DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count);
bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
@@ -409,6 +422,13 @@ private:
bool TraverseDeclContextHelper(DeclContext *DC);
bool TraverseFunctionHelper(FunctionDecl *D);
bool TraverseVarHelper(VarDecl *D);
+ bool TraverseOMPClause(OMPClause *C);
+#define OPENMP_CLAUSE(Name, Class) \
+ bool Visit##Class(Class *C);
+#include "clang/Basic/OpenMPKinds.def"
+ /// \brief Process clauses with list of variables.
+ template <typename T>
+ void VisitOMPClauseList(T *Node);
struct EnqueueJob {
Stmt *S;
@@ -802,10 +822,20 @@ bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
}
template<typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr::Capture C){
+bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture(
+ LambdaExpr *LE, const LambdaExpr::Capture *C) {
+ if (C->isInitCapture())
+ TRY_TO(TraverseDecl(C->getCapturedVar()));
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
+ TRY_TO(TraverseStmt(LE->getBody()));
return true;
}
+
// ----------------- Type traversal -----------------
// This macro makes available a variable T, the passed-in type.
@@ -844,6 +874,10 @@ DEF_TRAVERSE_TYPE(MemberPointerType, {
TRY_TO(TraverseType(T->getPointeeType()));
})
+DEF_TRAVERSE_TYPE(DecayedType, {
+ TRY_TO(TraverseType(T->getOriginalType()));
+ })
+
DEF_TRAVERSE_TYPE(ConstantArrayType, {
TRY_TO(TraverseType(T->getElementType()));
})
@@ -1050,6 +1084,10 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
+DEF_TRAVERSE_TYPELOC(DecayedType, {
+ TRY_TO(TraverseTypeLoc(TL.getOriginalLoc()));
+ })
+
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
// This isn't available for ArrayType, but is for the ArrayTypeLoc.
@@ -1420,59 +1458,44 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
return true;
}
-// A helper method for traversing the implicit instantiations of a
-// class template.
-template<typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
- ClassTemplateDecl *D) {
- ClassTemplateDecl::spec_iterator end = D->spec_end();
- for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
- ClassTemplateSpecializationDecl* SD = *it;
-
- switch (SD->getSpecializationKind()) {
- // Visit the implicit instantiations with the requested pattern.
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- TRY_TO(TraverseDecl(SD));
- break;
-
- // We don't need to do anything on an explicit instantiation
- // or explicit specialization because there will be an explicit
- // node for it elsewhere.
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ExplicitSpecialization:
- break;
- }
- }
-
- return true;
+#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \
+/* A helper method for traversing the implicit instantiations of a
+ class or variable template. */ \
+template<typename Derived> \
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( \
+ TMPLDECLKIND##TemplateDecl *D) { \
+ TMPLDECLKIND##TemplateDecl::spec_iterator end = D->spec_end(); \
+ for (TMPLDECLKIND##TemplateDecl::spec_iterator it = D->spec_begin(); \
+ it != end; ++it) { \
+ TMPLDECLKIND##TemplateSpecializationDecl* SD = *it; \
+ \
+ switch (SD->getSpecializationKind()) { \
+ /* Visit the implicit instantiations with the requested pattern. */ \
+ case TSK_Undeclared: \
+ case TSK_ImplicitInstantiation: \
+ TRY_TO(TraverseDecl(SD)); \
+ break; \
+ \
+ /* We don't need to do anything on an explicit instantiation
+ or explicit specialization because there will be an explicit
+ node for it elsewhere. */ \
+ case TSK_ExplicitInstantiationDeclaration: \
+ case TSK_ExplicitInstantiationDefinition: \
+ case TSK_ExplicitSpecialization: \
+ break; \
+ } \
+ } \
+ \
+ return true; \
}
-
-DEF_TRAVERSE_DECL(ClassTemplateDecl, {
- CXXRecordDecl* TempDecl = D->getTemplatedDecl();
- TRY_TO(TraverseDecl(TempDecl));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // class templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the class instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseClassInstantiations(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.
- })
+
+DEF_TRAVERSE_TMPL_INST(Class)
+DEF_TRAVERSE_TMPL_INST(Var)
// A helper method for traversing the instantiations of a
// function while skipping its specializations.
template<typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
FunctionTemplateDecl *D) {
FunctionTemplateDecl::spec_iterator end = D->spec_end();
for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end;
@@ -1500,20 +1523,31 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
return true;
}
-DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // function templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the function instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseFunctionInstantiations(D));
- })
+// This macro unifies the traversal of class, variable and function
+// template declarations.
+#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \
+DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \
+ TRY_TO(TraverseDecl(D->getTemplatedDecl())); \
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \
+ \
+ /* By default, we do not traverse the instantiations of
+ class templates since they do not appear in the user code. The
+ following code optionally traverses them.
+
+ We only traverse the class instantiations when we see the canonical
+ declaration of the template, to ensure we only visit them once. */ \
+ if (getDerived().shouldVisitTemplateInstantiations() && \
+ D == D->getCanonicalDecl()) \
+ TRY_TO(TraverseTemplateInstantiations(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. */ \
+ })
+
+DEF_TRAVERSE_TMPL_DECL(Class)
+DEF_TRAVERSE_TMPL_DECL(Var)
+DEF_TRAVERSE_TMPL_DECL(Function)
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
// D is the "T" in something like
@@ -1607,26 +1641,30 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, {
TRY_TO(TraverseCXXRecordHelper(D));
})
-DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
- // For implicit instantiations ("set<int> x;"), we don't want to
- // recurse at all, since the instatiated class isn't written in
- // the source code anywhere. (Note the instatiated *type* --
- // set<int> -- is written, and will still get a callback of
- // TemplateSpecializationType). For explicit instantiations
- // ("template set<int>;"), we do need a callback, since this
- // is the only callback that's made for this instantiation.
- // We use getTypeAsWritten() to distinguish.
- if (TypeSourceInfo *TSI = D->getTypeAsWritten())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-
- if (!getDerived().shouldVisitTemplateInstantiations() &&
- D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- // Returning from here skips traversing the
- // declaration context of the ClassTemplateSpecializationDecl
- // (embedded in the DEF_TRAVERSE_DECL() macro)
- // which contains the instantiated members of the class.
- return true;
- })
+#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \
+DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \
+ /* For implicit instantiations ("set<int> x;"), we don't want to
+ recurse at all, since the instatiated template isn't written in
+ the source code anywhere. (Note the instatiated *type* --
+ set<int> -- is written, and will still get a callback of
+ TemplateSpecializationType). For explicit instantiations
+ ("template set<int>;"), we do need a callback, since this
+ is the only callback that's made for this instantiation.
+ We use getTypeAsWritten() to distinguish. */ \
+ if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \
+ \
+ if (!getDerived().shouldVisitTemplateInstantiations() && \
+ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \
+ /* Returning from here skips traversing the
+ declaration context of the *TemplateSpecializationDecl
+ (embedded in the DEF_TRAVERSE_DECL() macro)
+ which contains the instantiated members of the template. */ \
+ return true; \
+ })
+
+DEF_TRAVERSE_TMPL_SPEC_DECL(Class)
+DEF_TRAVERSE_TMPL_SPEC_DECL(Var)
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
@@ -1637,25 +1675,30 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
return true;
}
-DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
- // The partial specialization.
- if (TemplateParameterList *TPL = D->getTemplateParameters()) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- }
- // The args that remains unspecialized.
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- D->getTemplateArgsAsWritten(), D->getNumTemplateArgsAsWritten()));
-
- // Don't need the ClassTemplatePartialSpecializationHelper, even
- // though that's our parent class -- we already visit all the
- // template args here.
- TRY_TO(TraverseCXXRecordHelper(D));
-
- // Instantiations will have been visited with the primary template.
- })
+#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
+DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \
+ /* The partial specialization. */ \
+ if (TemplateParameterList *TPL = D->getTemplateParameters()) { \
+ for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \
+ I != E; ++I) { \
+ TRY_TO(TraverseDecl(*I)); \
+ } \
+ } \
+ /* The args that remains unspecialized. */ \
+ TRY_TO(TraverseTemplateArgumentLocsHelper( \
+ D->getTemplateArgsAsWritten()->getTemplateArgs(), \
+ D->getTemplateArgsAsWritten()->NumTemplateArgs)); \
+ \
+ /* Don't need the *TemplatePartialSpecializationHelper, even
+ though that's our parent class -- we already visit all the
+ template args here. */ \
+ TRY_TO(Traverse##DECLKIND##Helper(D)); \
+ \
+ /* Instantiations will have been visited with the primary template. */ \
+ })
+
+DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord)
+DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var)
DEF_TRAVERSE_DECL(EnumConstantDecl, {
TRY_TO(TraverseStmt(D->getInitExpr()));
@@ -1736,6 +1779,14 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
// including exception specifications.
if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) {
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ } else if (getDerived().shouldVisitImplicitCode()) {
+ // Visit parameter variable declarations of the implicit function
+ // if the traverser is visiting implicit code. Parameter variable
+ // declarations do not have valid TypeSourceInfo, so to visit them
+ // we need to traverse the declarations explicitly.
+ for (FunctionDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end(); I != E; ++I)
+ TRY_TO(TraverseDecl(*I));
}
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
@@ -2117,10 +2168,12 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
// Walk only the visible parts of lambda expressions.
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
+ TRY_TO(WalkUpFromLambdaExpr(S));
+
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
- TRY_TO(TraverseLambdaCapture(*C));
+ TRY_TO(TraverseLambdaCapture(S, C));
}
if (S->hasExplicitParameters() || S->hasExplicitResultType()) {
@@ -2140,7 +2193,7 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
}
}
- TRY_TO(TraverseStmt(S->getBody()));
+ TRY_TO(TraverseLambdaBody(S));
return true;
}
@@ -2174,6 +2227,7 @@ DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { })
DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, { })
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
@@ -2211,6 +2265,7 @@ DEF_TRAVERSE_STMT(ParenExpr, { })
DEF_TRAVERSE_STMT(ParenListExpr, { })
DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
+DEF_TRAVERSE_STMT(ConvertVectorExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { })
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
@@ -2269,6 +2324,61 @@ DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { })
// Traverse OpenCL: AsType, Convert.
DEF_TRAVERSE_STMT(AsTypeExpr, { })
+// OpenMP directives.
+DEF_TRAVERSE_STMT(OMPParallelDirective, {
+ ArrayRef<OMPClause *> Clauses = S->clauses();
+ for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
+ I != E; ++I)
+ if (!TraverseOMPClause(*I)) return false;
+})
+
+// OpenMP clauses.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
+ if (!C) return true;
+ switch (C->getClauseKind()) {
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_##Name: \
+ return getDerived().Visit##Class(static_cast<Class*>(C));
+#include "clang/Basic/OpenMPKinds.def"
+ default: break;
+ }
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
+ return true;
+}
+
+template<typename Derived>
+template<typename T>
+void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
+ for (typename T::varlist_iterator I = Node->varlist_begin(),
+ E = Node->varlist_end();
+ I != E; ++I)
+ TraverseStmt(*I);
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
+ VisitOMPClauseList(C);
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
+ OMPFirstprivateClause *C) {
+ VisitOMPClauseList(C);
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
+ VisitOMPClauseList(C);
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index e3b340a5a1fe..cfe5a90be0d5 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -75,7 +75,7 @@ public:
/// \brief Return the first declaration of this declaration or itself if this
/// is the only declaration.
- decl_type *getFirstDeclaration() {
+ decl_type *getFirstDecl() {
decl_type *D = static_cast<decl_type*>(this);
while (D->getPreviousDecl())
D = D->getPreviousDecl();
@@ -84,31 +84,29 @@ public:
/// \brief Return the first declaration of this declaration or itself if this
/// is the only declaration.
- const decl_type *getFirstDeclaration() const {
+ const decl_type *getFirstDecl() const {
const decl_type *D = static_cast<const decl_type*>(this);
while (D->getPreviousDecl())
D = D->getPreviousDecl();
return D;
}
- /// \brief Returns true if this is the first declaration.
- bool isFirstDeclaration() const {
- return RedeclLink.NextIsLatest();
- }
+ /// \brief True if this is the first declaration in its redeclaration chain.
+ bool isFirstDecl() const { return RedeclLink.NextIsLatest(); }
/// \brief Returns the most recent (re)declaration of this declaration.
decl_type *getMostRecentDecl() {
- return getFirstDeclaration()->RedeclLink.getNext();
+ return getFirstDecl()->RedeclLink.getNext();
}
/// \brief Returns the most recent (re)declaration of this declaration.
const decl_type *getMostRecentDecl() const {
- return getFirstDeclaration()->RedeclLink.getNext();
+ return getFirstDecl()->RedeclLink.getNext();
}
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
/// first and only declaration.
- void setPreviousDeclaration(decl_type *PrevDecl);
+ void setPreviousDecl(decl_type *PrevDecl);
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
@@ -134,7 +132,7 @@ public:
redecl_iterator& operator++() {
assert(Current && "Advancing while iterator has reached end");
// Sanity check to avoid infinite loop on invalid redecl chain.
- if (Current->isFirstDeclaration()) {
+ if (Current->isFirstDecl()) {
if (PassedFirst) {
assert(0 && "Passed first decl twice, invalid redecl chain!");
Current = 0;
@@ -175,6 +173,40 @@ public:
friend class ASTDeclWriter;
};
+/// \brief Get the primary declaration for a declaration from an AST file. That
+/// will be the first-loaded declaration.
+Decl *getPrimaryMergedDecl(Decl *D);
+
+/// \brief Provides common interface for the Decls that cannot be redeclared,
+/// but can be merged if the same declaration is brought in from multiple
+/// modules.
+template<typename decl_type>
+class Mergeable {
+public:
+ Mergeable() {}
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ decl_type *getFirstDecl() {
+ decl_type *D = static_cast<decl_type*>(this);
+ if (!D->isFromASTFile())
+ return D;
+ return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
+ }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ const decl_type *getFirstDecl() const {
+ const decl_type *D = static_cast<const decl_type*>(this);
+ if (!D->isFromASTFile())
+ return D;
+ return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
+ }
+
+ /// \brief Returns true if this is the first declaration.
+ bool isFirstDecl() const { return getFirstDecl() == this; }
+};
+
}
#endif
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 74c9ec205363..ace53d83b3cf 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -266,10 +266,6 @@ protected:
/// Whether this initializer list originally had a GNU array-range
/// designator in it. This is a temporary marker used by CodeGen.
unsigned HadArrayRangeDesignator : 1;
-
- /// Whether this initializer list initializes a std::initializer_list
- /// object.
- unsigned InitializesStdInitializerList : 1;
};
class TypeTraitExprBitfields {
@@ -289,7 +285,7 @@ protected:
/// \brief The number of arguments to this type trait.
unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
};
-
+
union {
// FIXME: this is wasteful on 64-bit platforms.
void *Aligner;
@@ -316,19 +312,21 @@ protected:
public:
// Only allow allocation of Stmts using the allocator in ASTContext
// or by doing a placement new.
- void* operator new(size_t bytes, ASTContext& C,
- unsigned alignment = 8) throw();
+ void* operator new(size_t bytes, const ASTContext& C,
+ unsigned alignment = 8);
- void* operator new(size_t bytes, ASTContext* C,
- unsigned alignment = 8) throw();
+ void* operator new(size_t bytes, const ASTContext* C,
+ unsigned alignment = 8) {
+ return operator new(bytes, *C, alignment);
+ }
void* operator new(size_t bytes, void* mem) throw() {
return mem;
}
- void operator delete(void*, ASTContext&, unsigned) throw() { }
- void operator delete(void*, ASTContext*, unsigned) throw() { }
- void operator delete(void*, std::size_t) throw() { }
+ void operator delete(void*, const ASTContext&, unsigned) throw() { }
+ void operator delete(void*, const ASTContext*, unsigned) throw() { }
+ void operator delete(void*, size_t) throw() { }
void operator delete(void*, void*) throw() { }
public:
@@ -382,7 +380,7 @@ public:
/// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
/// back to its original source language syntax.
- void dumpPretty(ASTContext &Context) const;
+ void dumpPretty(const ASTContext &Context) const;
void printPretty(raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
@@ -401,13 +399,6 @@ public:
const_cast<const Stmt*>(this)->stripLabelLikeStatements());
}
- /// hasImplicitControlFlow - Some statements (e.g. short circuited operations)
- /// contain implicit control-flow in the order their subexpressions
- /// are evaluated. This predicate returns true if this statement has
- /// such implicit control-flow. Such statements are also specially handled
- /// within CFGs.
- bool hasImplicitControlFlow() const;
-
/// 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.
@@ -553,10 +544,10 @@ class CompoundStmt : public Stmt {
Stmt** Body;
SourceLocation LBracLoc, RBracLoc;
public:
- CompoundStmt(ASTContext &C, ArrayRef<Stmt*> Stmts,
+ CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
SourceLocation LB, SourceLocation RB);
- // \brief Build an empty compound statment with a location.
+ // \brief Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
: Stmt(CompoundStmtClass), Body(0), LBracLoc(Loc), RBracLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
@@ -568,7 +559,7 @@ public:
CompoundStmtBits.NumStmts = 0;
}
- void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
+ void setStmts(const ASTContext &C, Stmt **Stmts, unsigned NumStmts);
bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
unsigned size() const { return CompoundStmtBits.NumStmts; }
@@ -827,10 +818,10 @@ class AttributedStmt : public Stmt {
}
public:
- static AttributedStmt *Create(ASTContext &C, SourceLocation Loc,
+ static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
// \brief Build an empty attributed statement.
- static AttributedStmt *CreateEmpty(ASTContext &C, unsigned NumAttrs);
+ static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs);
SourceLocation getAttrLoc() const { return AttrLoc; }
ArrayRef<const Attr*> getAttrs() const {
@@ -860,7 +851,7 @@ class IfStmt : public Stmt {
SourceLocation ElseLoc;
public:
- IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
+ IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0);
/// \brief Build an empty if/then/else statement
@@ -875,7 +866,7 @@ public:
/// }
/// \endcode
VarDecl *getConditionVariable() const;
- void setConditionVariable(ASTContext &C, VarDecl *V);
+ void setConditionVariable(const ASTContext &C, VarDecl *V);
/// If this IfStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
@@ -933,7 +924,7 @@ class SwitchStmt : public Stmt {
unsigned AllEnumCasesCovered : 1;
public:
- SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
+ SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond);
/// \brief Build a empty switch statement.
explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
@@ -948,7 +939,7 @@ public:
/// }
/// \endcode
VarDecl *getConditionVariable() const;
- void setConditionVariable(ASTContext &C, VarDecl *V);
+ void setConditionVariable(const ASTContext &C, VarDecl *V);
/// If this SwitchStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
@@ -967,9 +958,6 @@ public:
SwitchCase *getSwitchCaseList() { return FirstCase; }
/// \brief Set the case list for this switch statement.
- ///
- /// The caller is responsible for incrementing the retain counts on
- /// all of the SwitchCase statements in this list.
void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
SourceLocation getSwitchLoc() const { return SwitchLoc; }
@@ -1021,7 +1009,7 @@ class WhileStmt : public Stmt {
Stmt* SubExprs[END_EXPR];
SourceLocation WhileLoc;
public:
- WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
+ WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
SourceLocation WL);
/// \brief Build an empty while statement.
@@ -1036,7 +1024,7 @@ public:
/// }
/// \endcode
VarDecl *getConditionVariable() const;
- void setConditionVariable(ASTContext &C, VarDecl *V);
+ void setConditionVariable(const ASTContext &C, VarDecl *V);
/// If this WhileStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
@@ -1129,8 +1117,9 @@ class ForStmt : public Stmt {
SourceLocation LParenLoc, RParenLoc;
public:
- ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc,
- Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP);
+ ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
+ Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
+ SourceLocation RP);
/// \brief Build an empty for statement.
explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
@@ -1146,7 +1135,7 @@ public:
/// }
/// \endcode
VarDecl *getConditionVariable() const;
- void setConditionVariable(ASTContext &C, VarDecl *V);
+ void setConditionVariable(const ASTContext &C, VarDecl *V);
/// If this ForStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
@@ -1417,7 +1406,7 @@ public:
//===--- Asm String Analysis ---===//
/// Assemble final IR asm string.
- std::string generateAsmString(ASTContext &C) const;
+ std::string generateAsmString(const ASTContext &C) const;
//===--- Output operands ---===//
@@ -1520,7 +1509,7 @@ class GCCAsmStmt : public AsmStmt {
friend class ASTStmtReader;
public:
- GCCAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
+ GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple,
bool isvolatile, unsigned numoutputs, unsigned numinputs,
IdentifierInfo **names, StringLiteral **constraints, Expr **exprs,
StringLiteral *asmstr, unsigned numclobbers,
@@ -1586,10 +1575,10 @@ public:
/// translation of strings from GCC syntax to LLVM IR syntax, and handles
//// flattening of named references like %[foo] to Operand AsmStringPiece's.
unsigned AnalyzeAsmString(SmallVectorImpl<AsmStringPiece> &Pieces,
- ASTContext &C, unsigned &DiagOffs) const;
+ const ASTContext &C, unsigned &DiagOffs) const;
/// Assemble final IR asm string.
- std::string generateAsmString(ASTContext &C) const;
+ std::string generateAsmString(const ASTContext &C) const;
//===--- Output operands ---===//
@@ -1649,7 +1638,7 @@ public:
}
private:
- void setOutputsAndInputsAndClobbers(ASTContext &C,
+ void setOutputsAndInputsAndClobbers(const ASTContext &C,
IdentifierInfo **Names,
StringLiteral **Constraints,
Stmt **Exprs,
@@ -1695,9 +1684,9 @@ class MSAsmStmt : public AsmStmt {
friend class ASTStmtReader;
public:
- MSAsmStmt(ASTContext &C, SourceLocation asmloc, SourceLocation lbraceloc,
- bool issimple, bool isvolatile, ArrayRef<Token> asmtoks,
- unsigned numoutputs, unsigned numinputs,
+ MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
+ SourceLocation lbraceloc, bool issimple, bool isvolatile,
+ ArrayRef<Token> asmtoks, unsigned numoutputs, unsigned numinputs,
ArrayRef<StringRef> constraints,
ArrayRef<Expr*> exprs, StringRef asmstr,
ArrayRef<StringRef> clobbers, SourceLocation endloc);
@@ -1720,7 +1709,7 @@ public:
StringRef getAsmString() const { return AsmStr; }
/// Assemble final IR asm string.
- std::string generateAsmString(ASTContext &C) const;
+ std::string generateAsmString(const ASTContext &C) const;
//===--- Output operands ---===//
@@ -1765,12 +1754,9 @@ public:
StringRef getClobber(unsigned i) const { return getClobbers()[i]; }
private:
- void initialize(ASTContext &C,
- StringRef AsmString,
- ArrayRef<Token> AsmToks,
- ArrayRef<StringRef> Constraints,
- ArrayRef<Expr*> Exprs,
- ArrayRef<StringRef> Clobbers);
+ void initialize(const ASTContext &C, StringRef AsmString,
+ ArrayRef<Token> AsmToks, ArrayRef<StringRef> Constraints,
+ ArrayRef<Expr*> Exprs, ArrayRef<StringRef> Clobbers);
public:
SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
@@ -1800,7 +1786,7 @@ class SEHExceptStmt : public Stmt {
explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { }
public:
- static SEHExceptStmt* Create(ASTContext &C,
+ static SEHExceptStmt* Create(const ASTContext &C,
SourceLocation ExceptLoc,
Expr *FilterExpr,
Stmt *Block);
@@ -1841,7 +1827,7 @@ class SEHFinallyStmt : public Stmt {
explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { }
public:
- static SEHFinallyStmt* Create(ASTContext &C,
+ static SEHFinallyStmt* Create(const ASTContext &C,
SourceLocation FinallyLoc,
Stmt *Block);
@@ -1880,10 +1866,8 @@ class SEHTryStmt : public Stmt {
explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { }
public:
- static SEHTryStmt* Create(ASTContext &C,
- bool isCXXTry,
- SourceLocation TryLoc,
- Stmt *TryBlock,
+ static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry,
+ SourceLocation TryLoc, Stmt *TryBlock,
Stmt *Handler);
SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
@@ -2006,13 +1990,13 @@ private:
void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; }
public:
- static CapturedStmt *Create(ASTContext &Context, Stmt *S,
+ static CapturedStmt *Create(const ASTContext &Context, Stmt *S,
CapturedRegionKind Kind,
ArrayRef<Capture> Captures,
ArrayRef<Expr *> CaptureInits,
CapturedDecl *CD, RecordDecl *RD);
- static CapturedStmt *CreateDeserialized(ASTContext &Context,
+ static CapturedStmt *CreateDeserialized(const ASTContext &Context,
unsigned NumCaptures);
/// \brief Retrieve the statement being captured.
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 0112befb293f..df98d41ad5fb 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -79,10 +79,10 @@ class CXXTryStmt : public Stmt {
}
public:
- static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
+ static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc,
Stmt *tryBlock, ArrayRef<Stmt*> handlers);
- static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
+ static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty,
unsigned numHandlers);
SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index b933ed076260..fbc8e5d4ea71 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_STMT_ITR_H
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
#include <iterator>
@@ -28,18 +29,14 @@ class VariableArrayType;
class StmtIteratorBase {
protected:
- enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
+ enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2,
Flags = 0x3 };
Stmt **stmt;
- union { Decl *decl; Decl **DGI; };
+ Decl **DGI;
uintptr_t RawVAPtr;
Decl **DGE;
- bool inDecl() const {
- return (RawVAPtr & Flags) == DeclMode;
- }
-
bool inDeclGroup() const {
return (RawVAPtr & Flags) == DeclGroupMode;
}
@@ -49,7 +46,7 @@ protected:
}
bool inStmt() const {
- return (RawVAPtr & Flags) == 0;
+ return (RawVAPtr & Flags) == StmtMode;
}
const VariableArrayType *getVAPtr() const {
@@ -57,7 +54,7 @@ protected:
}
void setVAPtr(const VariableArrayType *P) {
- assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
+ assert (inDeclGroup() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
@@ -67,11 +64,10 @@ protected:
Stmt*& GetDeclExpr() const;
- StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
- StmtIteratorBase(Decl *d, Stmt **s);
+ StmtIteratorBase(Stmt **s) : stmt(s), DGI(0), RawVAPtr(0) {}
StmtIteratorBase(const VariableArrayType *t);
StmtIteratorBase(Decl **dgi, Decl **dge);
- StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
+ StmtIteratorBase() : stmt(0), DGI(0), RawVAPtr(0) {}
};
@@ -86,7 +82,6 @@ public:
StmtIteratorImpl() {}
StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
- StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
DERIVED& operator++() {
@@ -107,15 +102,15 @@ public:
}
bool operator==(const DERIVED& RHS) const {
- return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr;
+ return stmt == RHS.stmt && DGI == RHS.DGI && RawVAPtr == RHS.RawVAPtr;
}
bool operator!=(const DERIVED& RHS) const {
- return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr;
+ return stmt != RHS.stmt || DGI != RHS.DGI || RawVAPtr != RHS.RawVAPtr;
}
REFERENCE operator*() const {
- return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr());
+ return inStmt() ? *stmt : GetDeclExpr();
}
REFERENCE operator->() const { return operator*(); }
@@ -131,9 +126,6 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
StmtIterator(const VariableArrayType *t)
: StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
-
- StmtIterator(Decl* D, Stmt **s = 0)
- : StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {}
};
struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
@@ -156,7 +148,7 @@ struct StmtRange : std::pair<StmtIterator,StmtIterator> {
: std::pair<StmtIterator,StmtIterator>(begin, end) {}
bool empty() const { return first == second; }
- operator bool() const { return !empty(); }
+ LLVM_EXPLICIT operator bool() const { return !empty(); }
Stmt *operator->() const { return first.operator->(); }
Stmt *&operator*() const { return first.operator*(); }
@@ -199,7 +191,7 @@ struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
: std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
bool empty() const { return first == second; }
- operator bool() const { return !empty(); }
+ LLVM_EXPLICIT operator bool() const { return !empty(); }
const Stmt *operator->() const { return first.operator->(); }
const Stmt *operator*() const { return first.operator*(); }
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index e97c1a5a319f..bfb4a9b0bb7a 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/include/clang/AST/StmtObjC.h
@@ -181,13 +181,12 @@ private:
HasFinally(HasFinally) { }
public:
- static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc,
- Stmt *atTryStmt,
+ static ObjCAtTryStmt *Create(const ASTContext &Context,
+ SourceLocation atTryLoc, Stmt *atTryStmt,
Stmt **CatchStmts, unsigned NumCatchStmts,
Stmt *atFinallyStmt);
- static ObjCAtTryStmt *CreateEmpty(ASTContext &Context,
- unsigned NumCatchStmts,
- bool HasFinally);
+ static ObjCAtTryStmt *CreateEmpty(const ASTContext &Context,
+ unsigned NumCatchStmts, bool HasFinally);
/// \brief Retrieve the location of the @ in the \@try.
SourceLocation getAtTryLoc() const { return AtTryLoc; }
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
new file mode 100644
index 000000000000..8570d8850a2f
--- /dev/null
+++ b/include/clang/AST/StmtOpenMP.h
@@ -0,0 +1,528 @@
+//===- StmtOpenMP.h - Classes for OpenMP directives and clauses --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file defines OpenMP AST classes for executable directives and
+/// clauses.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTOPENMP_H
+#define LLVM_CLANG_AST_STMTOPENMP_H
+
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// AST classes for clauses.
+//===----------------------------------------------------------------------===//
+
+/// \brief This is a basic class for representing single OpenMP clause.
+///
+class OMPClause {
+ /// \brief Starting location of the clause (the clause keyword).
+ SourceLocation StartLoc;
+ /// \brief Ending location of the clause.
+ SourceLocation EndLoc;
+ /// \brief Kind of the clause.
+ OpenMPClauseKind Kind;
+protected:
+ OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc)
+ : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {}
+
+public:
+
+ /// \brief Returns the starting location of the clause.
+ SourceLocation getLocStart() const { return StartLoc; }
+ /// \brief Returns the ending location of the clause.
+ SourceLocation getLocEnd() const { return EndLoc; }
+
+ /// \brief Sets the starting location of the clause.
+ void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
+ /// \brief Sets the ending location of the clause.
+ void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
+
+ /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.).
+ OpenMPClauseKind getClauseKind() const { return Kind; }
+
+ bool isImplicit() const { return StartLoc.isInvalid();}
+
+ StmtRange children();
+ ConstStmtRange children() const {
+ return const_cast<OMPClause *>(this)->children();
+ }
+ static bool classof(const OMPClause *T) {
+ return true;
+ }
+};
+
+/// \brief This represents clauses with the list of variables like 'private',
+/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the
+/// '#pragma omp ...' directives.
+template <class T>
+class OMPVarList {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Number of variables in the list.
+ unsigned NumVars;
+protected:
+ /// \brief Fetches list of variables associated with this clause.
+ llvm::MutableArrayRef<Expr *> getVarRefs() {
+ return llvm::MutableArrayRef<Expr *>(
+ reinterpret_cast<Expr **>(static_cast<T *>(this) + 1),
+ NumVars);
+ }
+
+ /// \brief Sets the list of variables for this clause.
+ void setVarRefs(ArrayRef<Expr *> VL) {
+ assert(VL.size() == NumVars &&
+ "Number of variables is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(),
+ reinterpret_cast<Expr **>(static_cast<T *>(this) + 1));
+ }
+
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPVarList(SourceLocation LParenLoc, unsigned N)
+ : LParenLoc(LParenLoc), NumVars(N) { }
+public:
+ typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator;
+ typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
+
+ unsigned varlist_size() const { return NumVars; }
+ bool varlist_empty() const { return NumVars == 0; }
+ varlist_iterator varlist_begin() { return getVarRefs().begin(); }
+ varlist_iterator varlist_end() { return getVarRefs().end(); }
+ varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); }
+ varlist_const_iterator varlist_end() const { return getVarRefs().end(); }
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Fetches list of all variables in the clause.
+ ArrayRef<const Expr *> getVarRefs() const {
+ return ArrayRef<const Expr *>(
+ reinterpret_cast<const Expr *const *>(static_cast<const T *>(this) + 1),
+ NumVars);
+ }
+};
+
+/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp parallel default(shared)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has simple 'default'
+/// clause with kind 'shared'.
+///
+class OMPDefaultClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief A kind of the 'default' clause.
+ OpenMPDefaultClauseKind Kind;
+ /// \brief Start location of the kind in source code.
+ SourceLocation KindKwLoc;
+
+ /// \brief Set kind of the clauses.
+ ///
+ /// \param K Argument of clause.
+ ///
+ void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; }
+
+ /// \brief Set argument location.
+ ///
+ /// \param KLoc Argument location.
+ ///
+ void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
+public:
+ /// \brief Build 'default' clause with argument \a A ('none' or 'shared').
+ ///
+ /// \param A Argument of the clause ('none' or 'shared').
+ /// \param ALoc Starting location of the argument.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Kind(A), KindKwLoc(ALoc) { }
+
+ /// \brief Build an empty clause.
+ ///
+ OMPDefaultClause()
+ : OMPClause(OMPC_default, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown),
+ KindKwLoc(SourceLocation()) { }
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns kind of the clause.
+ OpenMPDefaultClauseKind getDefaultKind() const { return Kind; }
+
+ /// \brief Returns location of clause kind.
+ SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_default;
+ }
+
+ StmtRange children() {
+ return StmtRange();
+ }
+};
+
+/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
+///
+/// \code
+/// #pragma omp parallel private(a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'private'
+/// with the variables 'a' and 'b'.
+///
+class OMPPrivateClause : public OMPClause, public OMPVarList<OMPPrivateClause> {
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPClause(OMPC_private, StartLoc, EndLoc),
+ OMPVarList<OMPPrivateClause>(LParenLoc, N) { }
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPPrivateClause(unsigned N)
+ : OMPClause(OMPC_private, SourceLocation(), SourceLocation()),
+ OMPVarList<OMPPrivateClause>(SourceLocation(), N) { }
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_private;
+ }
+};
+
+/// \brief This represents clause 'firstprivate' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp parallel firstprivate(a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'firstprivate'
+/// with the variables 'a' and 'b'.
+///
+class OMPFirstprivateClause : public OMPClause,
+ public OMPVarList<OMPFirstprivateClause> {
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPClause(OMPC_firstprivate, StartLoc, EndLoc),
+ OMPVarList<OMPFirstprivateClause>(LParenLoc, N) { }
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPFirstprivateClause(unsigned N)
+ : OMPClause(OMPC_firstprivate, SourceLocation(), SourceLocation()),
+ OMPVarList<OMPFirstprivateClause>(SourceLocation(), N) { }
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPFirstprivateClause *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_firstprivate;
+ }
+};
+
+/// \brief This represents clause 'shared' in the '#pragma omp ...' directives.
+///
+/// \code
+/// #pragma omp parallel shared(a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'shared'
+/// with the variables 'a' and 'b'.
+///
+class OMPSharedClause : public OMPClause, public OMPVarList<OMPSharedClause> {
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPClause(OMPC_shared, StartLoc, EndLoc),
+ OMPVarList<OMPSharedClause>(LParenLoc, N) { }
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPSharedClause(unsigned N)
+ : OMPClause(OMPC_shared, SourceLocation(), SourceLocation()),
+ OMPVarList<OMPSharedClause>(SourceLocation(), N) { }
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_shared;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// AST classes for directives.
+//===----------------------------------------------------------------------===//
+
+/// \brief This is a basic class for representing single OpenMP executable
+/// directive.
+///
+class OMPExecutableDirective : public Stmt {
+ friend class ASTStmtReader;
+ /// \brief Kind of the directive.
+ OpenMPDirectiveKind Kind;
+ /// \brief Starting location of the directive (directive keyword).
+ SourceLocation StartLoc;
+ /// \brief Ending location of the directive.
+ SourceLocation EndLoc;
+ /// \brief Pointer to the list of clauses.
+ llvm::MutableArrayRef<OMPClause *> Clauses;
+ /// \brief Associated statement (if any) and expressions.
+ llvm::MutableArrayRef<Stmt *> StmtAndExpressions;
+protected:
+ /// \brief Build instance of directive of class \a K.
+ ///
+ /// \param SC Statement class.
+ /// \param K Kind of OpenMP directive.
+ /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \param EndLoc Ending location of the directive.
+ ///
+ template <typename T>
+ OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses, unsigned NumberOfExpressions)
+ : Stmt(SC), Kind(K), StartLoc(StartLoc), EndLoc(EndLoc),
+ Clauses(reinterpret_cast<OMPClause **>(static_cast<T *>(this) + 1),
+ NumClauses),
+ StmtAndExpressions(reinterpret_cast<Stmt **>(Clauses.end()),
+ NumberOfExpressions) { }
+
+ /// \brief Sets the list of variables for this clause.
+ ///
+ /// \param Clauses The list of clauses for the directive.
+ ///
+ void setClauses(ArrayRef<OMPClause *> Clauses);
+
+ /// \brief Set the associated statement for the directive.
+ ///
+ /// /param S Associated statement.
+ ///
+ void setAssociatedStmt(Stmt *S) {
+ StmtAndExpressions[0] = S;
+ }
+
+public:
+ /// \brief Returns starting location of directive kind.
+ SourceLocation getLocStart() const { return StartLoc; }
+ /// \brief Returns ending location of directive.
+ SourceLocation getLocEnd() const { return EndLoc; }
+
+ /// \brief Set starting location of directive kind.
+ ///
+ /// \param Loc New starting location of directive.
+ ///
+ void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
+ /// \brief Set ending location of directive.
+ ///
+ /// \param Loc New ending location of directive.
+ ///
+ void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
+
+ /// \brief Get number of clauses.
+ unsigned getNumClauses() const { return Clauses.size(); }
+
+ /// \brief Returns specified clause.
+ ///
+ /// \param i Number of clause.
+ ///
+ OMPClause *getClause(unsigned i) const {
+ assert(i < Clauses.size() && "index out of bound!");
+ return Clauses[i];
+ }
+
+ /// \brief Returns statement associated with the directive.
+ Stmt *getAssociatedStmt() const {
+ return StmtAndExpressions[0];
+ }
+
+ OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
+ S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
+ }
+
+ child_range children() {
+ return child_range(StmtAndExpressions.begin(), StmtAndExpressions.end());
+ }
+
+ ArrayRef<OMPClause *> clauses() { return Clauses; }
+
+ ArrayRef<OMPClause *> clauses() const { return Clauses; }
+};
+
+/// \brief This represents '#pragma omp parallel' directive.
+///
+/// \code
+/// #pragma omp parallel private(a,b) reduction(+: c,d)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clauses 'private'
+/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
+/// variables 'c' and 'd'.
+///
+class OMPParallelDirective : public OMPExecutableDirective {
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \param EndLoc Ending Location of the directive.
+ ///
+ OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned N)
+ : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
+ StartLoc, EndLoc, N, 1) { }
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param N Number of clauses.
+ ///
+ explicit OMPParallelDirective(unsigned N)
+ : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
+ SourceLocation(), SourceLocation(), N, 1) { }
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement associated with the directive.
+ ///
+ static OMPParallelDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a N clauses.
+ ///
+ /// \param C AST context.
+ /// \param N The number of clauses.
+ ///
+ static OMPParallelDirective *CreateEmpty(const ASTContext &C, unsigned N,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelDirectiveClass;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index 38c4c0220e11..c71af38b61b6 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/include/clang/AST/StmtVisitor.h
@@ -18,6 +18,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.h"
namespace clang {
@@ -184,6 +185,41 @@ template<typename ImplClass, typename RetTy=void>
class ConstStmtVisitor
: public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {};
+/// \brief This class implements a simple visitor for OMPClause
+/// subclasses.
+template<class ImplClass, template <typename> class Ptr, typename RetTy>
+class OMPClauseVisitorBase {
+public:
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(CLASS) \
+ return static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<PTR(CLASS)>(S))
+
+#define OPENMP_CLAUSE(Name, Class) \
+ RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); }
+#include "clang/Basic/OpenMPKinds.def"
+
+ RetTy Visit(PTR(OMPClause) S) {
+ // Top switch clause: visit each OMPClause.
+ switch (S->getClauseKind()) {
+ default: llvm_unreachable("Unknown clause kind!");
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_ ## Name : return Visit ## Class(static_cast<PTR(Class)>(S));
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ }
+ // Base case, ignore it. :)
+ RetTy VisitOMPClause(PTR(OMPClause) Node) { return RetTy(); }
+#undef PTR
+#undef DISPATCH
+};
+
+template<class ImplClass, typename RetTy = void>
+class OMPClauseVisitor :
+ public OMPClauseVisitorBase <ImplClass, make_ptr, RetTy> {};
+template<class ImplClass, typename RetTy = void>
+class ConstOMPClauseVisitor :
+ public OMPClauseVisitorBase <ImplClass, make_const_ptr, RetTy> {};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 70b934f36c2c..6c40eb1168ce 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -60,8 +60,8 @@ public:
/// 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*.
+ /// The template argument is a value- or type-dependent expression or a
+ /// non-dependent __uuidof expression stored in an Expr*.
Expression,
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
@@ -70,57 +70,68 @@ public:
private:
/// \brief The kind of template argument we're storing.
- unsigned Kind;
struct DA {
- ValueDecl *D;
+ unsigned Kind;
bool ForRefParam;
+ ValueDecl *D;
};
struct I {
+ unsigned Kind;
// We store a decomposed APSInt with the data allocated by ASTContext if
// BitWidth > 64. The memory may be shared between multiple
// TemplateArgument instances.
+ unsigned BitWidth : 31;
+ unsigned IsUnsigned : 1;
union {
uint64_t VAL; ///< Used to store the <= 64 bits integer value.
const uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
- unsigned BitWidth : 31;
- unsigned IsUnsigned : 1;
void *Type;
};
struct A {
- const TemplateArgument *Args;
+ unsigned Kind;
unsigned NumArgs;
+ const TemplateArgument *Args;
};
struct TA {
- void *Name;
+ unsigned Kind;
unsigned NumExpansions;
+ void *Name;
+ };
+ struct TV {
+ unsigned Kind;
+ uintptr_t V;
};
union {
struct DA DeclArg;
struct I Integer;
struct A Args;
struct TA TemplateArg;
- uintptr_t TypeOrValue;
+ struct TV TypeOrValue;
};
TemplateArgument(TemplateName, bool) LLVM_DELETED_FUNCTION;
public:
/// \brief Construct an empty, invalid template argument.
- TemplateArgument() : Kind(Null), TypeOrValue(0) { }
+ TemplateArgument() {
+ TypeOrValue.Kind = Null;
+ TypeOrValue.V = 0;
+ }
/// \brief Construct a template type argument.
- TemplateArgument(QualType T, bool isNullPtr = false)
- : Kind(isNullPtr ? NullPtr : Type) {
- TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ TemplateArgument(QualType T, bool isNullPtr = false) {
+ TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
+ TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
}
/// \brief Construct a template argument that refers to a
/// declaration, which is either an external declaration or a
/// template declaration.
- TemplateArgument(ValueDecl *D, bool ForRefParam) : Kind(Declaration) {
+ TemplateArgument(ValueDecl *D, bool ForRefParam) {
assert(D && "Expected decl");
+ DeclArg.Kind = Declaration;
DeclArg.D = D;
DeclArg.ForRefParam = ForRefParam;
}
@@ -131,8 +142,7 @@ public:
/// \brief Construct an integral constant template argument with the same
/// value as Other but a different type.
- TemplateArgument(const TemplateArgument &Other, QualType Type)
- : Kind(Integral) {
+ TemplateArgument(const TemplateArgument &Other, QualType Type) {
Integer = Other.Integer;
Integer.Type = Type.getAsOpaquePtr();
}
@@ -145,8 +155,8 @@ public:
/// is taken.
///
/// \param Name The template name.
- TemplateArgument(TemplateName Name) : Kind(Template)
- {
+ TemplateArgument(TemplateName Name) {
+ TemplateArg.Kind = Template;
TemplateArg.Name = Name.getAsVoidPointer();
TemplateArg.NumExpansions = 0;
}
@@ -162,9 +172,8 @@ public:
///
/// \param NumExpansions The number of expansions that will be generated by
/// instantiating
- TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions)
- : Kind(TemplateExpansion)
- {
+ TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) {
+ TemplateArg.Kind = TemplateExpansion;
TemplateArg.Name = Name.getAsVoidPointer();
if (NumExpansions)
TemplateArg.NumExpansions = *NumExpansions + 1;
@@ -177,15 +186,17 @@ public:
/// This form of template argument only occurs in template argument
/// lists used for dependent types and for expression; it will not
/// occur in a non-dependent, canonical template argument list.
- TemplateArgument(Expr *E) : Kind(Expression) {
- TypeOrValue = reinterpret_cast<uintptr_t>(E);
+ TemplateArgument(Expr *E) {
+ TypeOrValue.Kind = Expression;
+ TypeOrValue.V = 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){
+ TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) {
+ this->Args.Kind = Pack;
this->Args.Args = Args;
this->Args.NumArgs = NumArgs;
}
@@ -201,10 +212,10 @@ public:
unsigned NumArgs);
/// \brief Return the kind of stored template argument.
- ArgKind getKind() const { return (ArgKind)Kind; }
+ ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
/// \brief Determine whether this template argument has no value.
- bool isNull() const { return Kind == Null; }
+ bool isNull() const { return getKind() == Null; }
/// \brief Whether this template argument is dependent on a template
/// parameter such that its result can change from one instantiation to
@@ -224,40 +235,40 @@ public:
/// \brief Retrieve the type for a type template argument.
QualType getAsType() const {
- assert(Kind == Type && "Unexpected kind");
- return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
+ assert(getKind() == Type && "Unexpected kind");
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
}
/// \brief Retrieve the declaration for a declaration non-type
/// template argument.
ValueDecl *getAsDecl() const {
- assert(Kind == Declaration && "Unexpected kind");
+ assert(getKind() == Declaration && "Unexpected kind");
return DeclArg.D;
}
/// \brief Retrieve whether a declaration is binding to a
/// reference parameter in a declaration non-type template argument.
bool isDeclForReferenceParam() const {
- assert(Kind == Declaration && "Unexpected kind");
+ assert(getKind() == Declaration && "Unexpected kind");
return DeclArg.ForRefParam;
}
/// \brief Retrieve the type for null non-type template argument.
QualType getNullPtrType() const {
- assert(Kind == NullPtr && "Unexpected kind");
- return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
+ assert(getKind() == NullPtr && "Unexpected kind");
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
}
/// \brief Retrieve the template name for a template name argument.
TemplateName getAsTemplate() const {
- assert(Kind == Template && "Unexpected kind");
+ assert(getKind() == Template && "Unexpected kind");
return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
/// \brief Retrieve the template argument as a template name; if the argument
/// is a pack expansion, return the pattern as a template name.
TemplateName getAsTemplateOrTemplatePattern() const {
- assert((Kind == Template || Kind == TemplateExpansion) &&
+ assert((getKind() == Template || getKind() == TemplateExpansion) &&
"Unexpected kind");
return TemplateName::getFromVoidPointer(TemplateArg.Name);
@@ -270,7 +281,7 @@ public:
/// \brief Retrieve the template argument as an integral value.
// FIXME: Provide a way to read the integral data without copying the value.
llvm::APSInt getAsIntegral() const {
- assert(Kind == Integral && "Unexpected kind");
+ assert(getKind() == Integral && "Unexpected kind");
using namespace llvm;
if (Integer.BitWidth <= 64)
return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
@@ -282,19 +293,19 @@ public:
/// \brief Retrieve the type of the integral value.
QualType getIntegralType() const {
- assert(Kind == Integral && "Unexpected kind");
+ assert(getKind() == Integral && "Unexpected kind");
return QualType::getFromOpaquePtr(Integer.Type);
}
void setIntegralType(QualType T) {
- assert(Kind == Integral && "Unexpected kind");
+ assert(getKind() == Integral && "Unexpected kind");
Integer.Type = T.getAsOpaquePtr();
}
/// \brief Retrieve the template argument as an expression.
Expr *getAsExpr() const {
- assert(Kind == Expression && "Unexpected kind");
- return reinterpret_cast<Expr *>(TypeOrValue);
+ assert(getKind() == Expression && "Unexpected kind");
+ return reinterpret_cast<Expr *>(TypeOrValue.V);
}
/// \brief Iterator that traverses the elements of a template argument pack.
@@ -303,27 +314,27 @@ public:
/// \brief Iterator referencing the first argument of a template argument
/// pack.
pack_iterator pack_begin() const {
- assert(Kind == Pack);
+ assert(getKind() == Pack);
return Args.Args;
}
/// \brief Iterator referencing one past the last argument of a template
/// argument pack.
pack_iterator pack_end() const {
- assert(Kind == Pack);
+ assert(getKind() == Pack);
return Args.Args + Args.NumArgs;
}
/// \brief The number of template arguments in the given template argument
/// pack.
unsigned pack_size() const {
- assert(Kind == Pack);
+ assert(getKind() == Pack);
return Args.NumArgs;
}
/// \brief Return the array of arguments in this template argument pack.
llvm::ArrayRef<TemplateArgument> getPackAsArray() const {
- assert(Kind == Pack);
+ assert(getKind() == Pack);
return llvm::ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
}
@@ -494,17 +505,6 @@ public:
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,
- Optional<unsigned> &NumExpansions,
- ASTContext &Context) const;
};
/// A convenient class for passing around template argument
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 39f10d3393ba..fb829e4d4103 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -441,7 +441,7 @@ public:
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
- operator bool() const { return hasQualifiers(); }
+ LLVM_EXPLICIT operator bool() const { return hasQualifiers(); }
Qualifiers &operator+=(Qualifiers R) {
addQualifiers(R);
@@ -818,7 +818,7 @@ public:
/// an lvalue. It removes a top-level reference (since there are no
/// expressions of reference type) and deletes top-level cvr-qualifiers
/// from non-class types (in C++) or all types (in C).
- QualType getNonLValueExprType(ASTContext &Context) const;
+ QualType getNonLValueExprType(const ASTContext &Context) const;
/// getDesugaredType - Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
@@ -1194,7 +1194,7 @@ private:
mutable unsigned CacheValid : 1;
/// \brief Linkage of this type.
- mutable unsigned CachedLinkage : 2;
+ mutable unsigned CachedLinkage : 3;
/// \brief Whether this type involves and local or unnamed types.
mutable unsigned CachedLocalOrUnnamed : 1;
@@ -1214,7 +1214,7 @@ private:
return CachedLocalOrUnnamed;
}
};
- enum { NumTypeBits = 19 };
+ enum { NumTypeBits = 18 };
protected:
// These classes allow subclasses to somewhat cleanly pack bitfields
@@ -1315,6 +1315,8 @@ protected:
/// NumElements - The number of elements in the vector.
unsigned NumElements : 29 - NumTypeBits;
+
+ enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 };
};
class AttributedTypeBitfields {
@@ -1454,7 +1456,7 @@ public:
/// isLiteralType - Return true if this is a literal type
/// (C++11 [basic.types]p10)
- bool isLiteralType(ASTContext &Ctx) const;
+ bool isLiteralType(const ASTContext &Ctx) const;
/// \brief Test if this type is a standard-layout type.
/// (C++0x [basic.type]p9)
@@ -1512,7 +1514,6 @@ public:
bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
bool isVoidType() const; // C99 6.2.5p19
- bool isDerivedType() const; // C99 6.2.5p20
bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers)
bool isAggregateType() const;
bool isFundamentalType() const;
@@ -1811,6 +1812,10 @@ template <> const TypedefType *Type::getAs() const;
/// non-sugared type.
template <> const TemplateSpecializationType *Type::getAs() const;
+/// \brief This will check for an AttributedType by removing any existing sugar
+/// until it reaches an AttributedType or a non-sugared type.
+template <> const AttributedType *Type::getAs() const;
+
// We can do canonical leaf types faster, because we don't have to
// worry about preserving child type decoration.
#define TYPE(Class, Base)
@@ -1991,6 +1996,44 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
};
+/// \brief Represents a pointer type decayed from an array or function type.
+class DecayedType : public Type, public llvm::FoldingSetNode {
+ QualType OriginalType;
+ QualType DecayedPointer;
+
+ DecayedType(QualType OriginalType, QualType DecayedPointer,
+ QualType CanonicalPtr)
+ : Type(Decayed, CanonicalPtr, OriginalType->isDependentType(),
+ OriginalType->isInstantiationDependentType(),
+ OriginalType->isVariablyModifiedType(),
+ OriginalType->containsUnexpandedParameterPack()),
+ OriginalType(OriginalType), DecayedPointer(DecayedPointer) {
+ assert(isa<PointerType>(DecayedPointer));
+ }
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ QualType getDecayedType() const { return DecayedPointer; }
+ QualType getOriginalType() const { return OriginalType; }
+
+ QualType getPointeeType() const {
+ return cast<PointerType>(DecayedPointer)->getPointeeType();
+ }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return DecayedPointer; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, OriginalType);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType OriginalType) {
+ ID.AddPointer(OriginalType.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Decayed; }
+};
+
/// BlockPointerType - pointer to a block type.
/// This type is to represent types syntactically represented as
/// "void (^)(int)", etc. Pointee is required to always be a function type.
@@ -2487,6 +2530,9 @@ public:
QualType getElementType() const { return ElementType; }
unsigned getNumElements() const { return VectorTypeBits.NumElements; }
+ static bool isVectorSizeTooLarge(unsigned NumElements) {
+ return NumElements > VectorTypeBitfields::MaxNumElements;
+ }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2641,7 +2687,11 @@ class FunctionType : public Type {
// Constructor with all defaults. Use when for example creating a
// function know to use defaults.
- ExtInfo() : Bits(0) {}
+ ExtInfo() : Bits(CC_C) { }
+
+ // Constructor with just the calling convention, which is an important part
+ // of the canonical type.
+ ExtInfo(CallingConv CC) : Bits(CC) { }
bool getNoReturn() const { return Bits & NoReturnMask; }
bool getProducesResult() const { return Bits & ProducesResultMask; }
@@ -2784,6 +2834,12 @@ public:
ExceptionSpecDecl(0), ExceptionSpecTemplate(0),
ConsumedArguments(0) {}
+ ExtProtoInfo(CallingConv CC)
+ : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0),
+ ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0),
+ Exceptions(0), NoexceptExpr(0), ExceptionSpecDecl(0),
+ ExceptionSpecTemplate(0), ConsumedArguments(0) {}
+
FunctionType::ExtInfo ExtInfo;
bool Variadic : 1;
bool HasTrailingReturn : 1;
@@ -2928,7 +2984,7 @@ public:
NR_Nothrow ///< The noexcept specifier evaluates to true.
};
/// \brief Get the meaning of the noexcept spec on this function, if any.
- NoexceptResult getNoexceptSpec(ASTContext &Ctx) const;
+ NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const;
unsigned getNumExceptions() const { return NumExceptions; }
QualType getExceptionType(unsigned i) const {
assert(i < NumExceptions && "Invalid exception number!");
@@ -2959,7 +3015,7 @@ public:
return 0;
return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[1];
}
- bool isNothrow(ASTContext &Ctx) const {
+ bool isNothrow(const ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType();
assert(EST != EST_Unevaluated && EST != EST_Uninstantiated);
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
@@ -3323,9 +3379,10 @@ public:
attr_objc_gc,
attr_objc_ownership,
attr_pcs,
+ attr_pcs_vfp,
FirstEnumOperandKind = attr_objc_gc,
- LastEnumOperandKind = attr_pcs,
+ LastEnumOperandKind = attr_pcs_vfp,
// No operand.
attr_noreturn,
@@ -3335,7 +3392,13 @@ public:
attr_thiscall,
attr_pascal,
attr_pnaclcall,
- attr_inteloclbicc
+ attr_inteloclbicc,
+ attr_ms_abi,
+ attr_sysv_abi,
+ attr_ptr32,
+ attr_ptr64,
+ attr_sptr,
+ attr_uptr
};
private:
@@ -3365,6 +3428,10 @@ public:
bool isSugared() const { return true; }
QualType desugar() const { return getEquivalentType(); }
+ bool isMSTypeSpec() const;
+
+ bool isCallingConv() const;
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
}
@@ -3563,10 +3630,13 @@ public:
/// is no deduced type and an auto type is canonical. In the latter case, it is
/// also a dependent type.
class AutoType : public Type, public llvm::FoldingSetNode {
- AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent)
+ AutoType(QualType DeducedType, bool IsDecltypeAuto,
+ bool IsDependent)
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
- /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
+ /*VariablyModified=*/false,
+ /*ContainsParameterPack=*/DeducedType.isNull()
+ ? false : DeducedType->containsUnexpandedParameterPack()) {
assert((DeducedType.isNull() || !IsDependent) &&
"auto deduced to dependent type");
AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
@@ -3590,7 +3660,8 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType());
+ Profile(ID, getDeducedType(), isDecltypeAuto(),
+ isDependentType());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
@@ -3654,10 +3725,6 @@ class TemplateSpecializationType
public:
/// \brief Determine whether any of the given template arguments are
/// dependent.
- static bool anyDependentTemplateArguments(const TemplateArgument *Args,
- unsigned NumArgs,
- bool &InstantiationDependent);
-
static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
unsigned NumArgs,
bool &InstantiationDependent);
@@ -4154,8 +4221,8 @@ public:
return None;
}
- bool isSugared() const { return false; }
- QualType desugar() const { return QualType(this, 0); }
+ bool isSugared() const { return !Pattern->isDependentType(); }
+ QualType desugar() const { return isSugared() ? Pattern : QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPattern(), getNumExpansions());
@@ -4189,11 +4256,11 @@ public:
///
/// 'C<P>' is an ObjCObjectType with base C and protocol list [P].
///
-/// 'id' is a TypedefType which is sugar for an ObjCPointerType whose
+/// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose
/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType
/// and no protocols.
///
-/// 'id<P>' is an ObjCPointerType whose pointee is an ObjCObjecType
+/// 'id<P>' is an ObjCObjectPointerType whose pointee is an ObjCObjectType
/// 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 {
@@ -4231,7 +4298,7 @@ public:
/// getBaseType - Gets the base type of this object type. This is
/// always (possibly sugar for) one of:
/// - the 'id' builtin type (as opposed to the 'id' type visible to the
- /// user, which is a typedef for an ObjCPointerType)
+ /// user, which is a typedef for an ObjCObjectPointerType)
/// - the 'Class' builtin type (same caveat)
/// - an ObjCObjectType (currently always an ObjCInterfaceType)
QualType getBaseType() const { return BaseType; }
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 11cad9bb9dd9..8ddfac7ad373 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the TypeLoc interface and subclasses.
-//
+///
+/// \file
+/// \brief Defines the clang::TypeLoc interface and its subclasses.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPELOC_H
@@ -34,8 +35,8 @@ namespace clang {
/// \brief Base wrapper for a particular "section" of type source info.
///
-/// A client should use the TypeLoc subclasses through cast/dyn_cast in order to
-/// get at the actual information.
+/// A client should use the TypeLoc subclasses through castAs()/getAs()
+/// in order to get at the actual information.
class TypeLoc {
protected:
// The correctness of this relies on the property that, for Type *Ty,
@@ -46,6 +47,8 @@ protected:
public:
/// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc
/// is of the desired type.
+ ///
+ /// \pre T::isKind(*this)
template<typename T>
T castAs() const {
assert(T::isKind(*this));
@@ -90,11 +93,15 @@ public:
}
bool isNull() const { return !Ty; }
- operator bool() const { return Ty; }
+ LLVM_EXPLICIT operator bool() const { return Ty; }
/// \brief Returns the size of type source info data block for the given type.
static unsigned getFullDataSizeForType(QualType Ty);
+ /// \brief Returns the alignment of type source info data block for
+ /// the given type.
+ static unsigned getLocalAlignmentForType(QualType Ty);
+
/// \brief Get the type for which this source info wrapper provides
/// information.
QualType getType() const {
@@ -229,7 +236,11 @@ public:
}
UnqualTypeLoc getUnqualifiedLoc() const {
- return UnqualTypeLoc(getTypePtr(), Data);
+ unsigned align =
+ TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0));
+ uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data);
+ dataInt = llvm::RoundUpToAlignment(dataInt, align);
+ return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt));
}
/// Initializes the local data of this type source info block to
@@ -250,10 +261,11 @@ public:
return 0;
}
- /// \brief Returns the size of the type source info data block.
- unsigned getFullDataSize() const {
- return getLocalDataSize() +
- getFullDataSizeForType(getType().getLocalUnqualifiedType());
+ /// \brief Returns the alignment of the type source info data block that is
+ /// specific to this type.
+ unsigned getLocalDataAlignment() const {
+ // We don't preserve any location information.
+ return 1;
}
private:
@@ -280,9 +292,6 @@ inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
/// \tparam LocalData the structure type of local location data for
/// this type
///
-/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or
-/// else the world will end.
-///
/// TypeLocs with non-constant amounts of local data should override
/// getExtraLocalDataSize(); getExtraLocalData() will then point to
/// this extra memory.
@@ -309,7 +318,8 @@ class ConcreteTypeLoc : public Base {
friend class TypeLoc;
static bool isKind(const TypeLoc &TL) {
- return Derived::classofType(TL.getTypePtr());
+ return !TL.getType().hasLocalQualifiers() &&
+ Derived::classofType(TL.getTypePtr());
}
static bool classofType(const Type *Ty) {
@@ -317,12 +327,16 @@ class ConcreteTypeLoc : public Base {
}
public:
- unsigned getLocalDataSize() const {
- return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
+ unsigned getLocalDataAlignment() const {
+ return std::max(llvm::alignOf<LocalData>(),
+ asDerived()->getExtraLocalDataAlignment());
}
- // Give a default implementation that's useful for leaf types.
- unsigned getFullDataSize() const {
- return asDerived()->getLocalDataSize() + getInnerTypeSize();
+ unsigned getLocalDataSize() const {
+ unsigned size = sizeof(LocalData);
+ unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
+ size = llvm::RoundUpToAlignment(size, extraAlign);
+ size += asDerived()->getExtraLocalDataSize();
+ return size;
}
TypeLoc getNextTypeLoc() const {
@@ -338,6 +352,10 @@ protected:
return 0;
}
+ unsigned getExtraLocalDataAlignment() const {
+ return 1;
+ }
+
LocalData *getLocalData() const {
return static_cast<LocalData*>(Base::Data);
}
@@ -346,11 +364,17 @@ protected:
/// local data that can't be captured in the Info (e.g. because it's
/// of variable size).
void *getExtraLocalData() const {
- return getLocalData() + 1;
+ unsigned size = sizeof(LocalData);
+ unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
+ size = llvm::RoundUpToAlignment(size, extraAlign);
+ return reinterpret_cast<char*>(Base::Data) + size;
}
void *getNonLocalData() const {
- return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();
+ uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data);
+ data += asDerived()->getLocalDataSize();
+ data = llvm::RoundUpToAlignment(data, getNextTypeAlign());
+ return reinterpret_cast<void*>(data);
}
struct HasNoInnerType {};
@@ -373,6 +397,18 @@ private:
return getInnerTypeLoc().getFullDataSize();
}
+ unsigned getNextTypeAlign() const {
+ return getNextTypeAlign(asDerived()->getInnerType());
+ }
+
+ unsigned getNextTypeAlign(HasNoInnerType _) const {
+ return 1;
+ }
+
+ unsigned getNextTypeAlign(QualType T) const {
+ return TypeLoc::getLocalAlignmentForType(T);
+ }
+
TypeLoc getNextTypeLoc(HasNoInnerType _) const {
return TypeLoc();
}
@@ -393,7 +429,8 @@ class InheritingConcreteTypeLoc : public Base {
}
static bool isKind(const TypeLoc &TL) {
- return Derived::classofType(TL.getTypePtr());
+ return !TL.getType().hasLocalQualifiers() &&
+ Derived::classofType(TL.getTypePtr());
}
static bool isKind(const UnqualTypeLoc &TL) {
return Derived::classofType(TL.getTypePtr());
@@ -417,7 +454,8 @@ class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
Type,
TypeSpecLocInfo> {
public:
- enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
+ enum { LocalDataSize = sizeof(TypeSpecLocInfo),
+ LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment };
SourceLocation getNameLoc() const {
return this->getLocalData()->NameLoc;
@@ -448,8 +486,6 @@ class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
BuiltinType,
BuiltinLocInfo> {
public:
- enum { LocalDataSize = sizeof(BuiltinLocInfo) };
-
SourceLocation getBuiltinLoc() const {
return getLocalData()->BuiltinLoc;
}
@@ -478,6 +514,10 @@ public:
return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
}
+ unsigned getExtraLocalDataAlignment() const {
+ return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>() : 1;
+ }
+
SourceRange getLocalSourceRange() const {
return SourceRange(getBuiltinLoc(), getBuiltinLoc());
}
@@ -840,6 +880,10 @@ public:
return this->getNumProtocols() * sizeof(SourceLocation);
}
+ unsigned getExtraLocalDataAlignment() const {
+ return llvm::alignOf<SourceLocation>();
+ }
+
QualType getInnerType() const {
return getTypePtr()->getBaseType();
}
@@ -933,6 +977,40 @@ inline TypeLoc TypeLoc::IgnoreParens() const {
return *this;
}
+
+struct DecayedLocInfo { }; // Nothing.
+
+/// \brief Wrapper for source info for pointers decayed from arrays and
+/// functions.
+class DecayedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, DecayedTypeLoc,
+ DecayedType, DecayedLocInfo> {
+public:
+ TypeLoc getOriginalLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ // do nothing
+ }
+
+ QualType getInnerType() const {
+ // The inner type is the undecayed type, since that's what we have source
+ // location information for.
+ return getTypePtr()->getOriginalType();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange();
+ }
+
+ unsigned getLocalDataSize() const {
+ // sizeof(DecayedLocInfo) is 1, but we don't need its address to be unique
+ // anyway. TypeLocBuilder can't handle data sizes of 1.
+ return 0; // No data.
+ }
+};
+
+
struct PointerLikeLocInfo {
SourceLocation StarLoc;
};
@@ -1166,6 +1244,10 @@ public:
return getNumArgs() * sizeof(ParmVarDecl*);
}
+ unsigned getExtraLocalDataAlignment() const {
+ return llvm::alignOf<ParmVarDecl*>();
+ }
+
QualType getInnerType() const { return getTypePtr()->getResultType(); }
};
@@ -1357,6 +1439,10 @@ public:
return getNumArgs() * sizeof(TemplateArgumentLocInfo);
}
+ unsigned getExtraLocalDataAlignment() const {
+ return llvm::alignOf<TemplateArgumentLocInfo>();
+ }
+
private:
TemplateArgumentLocInfo *getArgInfos() const {
return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
@@ -1761,6 +1847,10 @@ public:
return getNumArgs() * sizeof(TemplateArgumentLocInfo);
}
+ unsigned getExtraLocalDataAlignment() const {
+ return llvm::alignOf<TemplateArgumentLocInfo>();
+ }
+
private:
TemplateArgumentLocInfo *getArgInfos() const {
return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 840e07d94a0d..3126f48c644a 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -81,6 +81,7 @@ TYPE(FunctionNoProto, FunctionType)
DEPENDENT_TYPE(UnresolvedUsing, Type)
NON_CANONICAL_TYPE(Paren, Type)
NON_CANONICAL_TYPE(Typedef, Type)
+NON_CANONICAL_TYPE(Decayed, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
@@ -98,7 +99,7 @@ TYPE(Auto, Type)
DEPENDENT_TYPE(InjectedClassName, Type)
DEPENDENT_TYPE(DependentName, Type)
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
-DEPENDENT_TYPE(PackExpansion, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h
index 59b59f517168..9c9f15e95323 100644
--- a/include/clang/AST/TypeOrdering.h
+++ b/include/clang/AST/TypeOrdering.h
@@ -6,11 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file provides a function objects and specializations that
-// allow QualType values to be sorted, used in std::maps, std::sets,
-// llvm::DenseMaps, and llvm::DenseSets.
-//
+///
+/// \file
+/// \brief Allows QualTypes to be sorted and hence used in maps and sets.
+///
+/// Defines clang::QualTypeOrdering, a total ordering on clang::QualType,
+/// and hence enables QualType values to be sorted and to be used in
+/// std::maps, std::sets, llvm::DenseMaps, and llvm::DenseSets.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TYPE_ORDERING_H
@@ -22,8 +25,7 @@
namespace clang {
-/// QualTypeOrdering - Function object that provides a total ordering
-/// on QualType values.
+/// \brief Function object that provides a total ordering on QualType values.
struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
bool operator()(QualType T1, QualType T2) const {
return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h
index 242aa586d510..11e5a47f1f29 100644
--- a/include/clang/AST/TypeVisitor.h
+++ b/include/clang/AST/TypeVisitor.h
@@ -22,9 +22,50 @@ namespace clang {
return static_cast<ImplClass*>(this)-> \
Visit##CLASS(static_cast<const CLASS*>(T))
+/// \brief An operation on a type.
+///
+/// \tparam ImplClass Class implementing the operation. Must be inherited from
+/// TypeVisitor.
+/// \tparam RetTy %Type of result produced by the operation.
+///
+/// The class implements polymorphic operation on an object of type derived
+/// from Type. The operation is performed by calling method Visit. It then
+/// dispatches the call to function \c VisitFooType, if actual argument type
+/// is \c FooType.
+///
+/// The class implements static polymorphism using Curiously Recurring
+/// Template Pattern. It is designed to be a base class for some concrete
+/// class:
+///
+/// \code
+/// class SomeVisitor : public TypeVisitor<SomeVisitor,sometype> { ... };
+/// ...
+/// Type *atype = ...
+/// ...
+/// SomeVisitor avisitor;
+/// sometype result = avisitor.Visit(atype);
+/// \endcode
+///
+/// Actual treatment is made by methods of the derived class, TypeVisitor only
+/// dispatches call to the appropriate method. If the implementation class
+/// \c ImplClass provides specific action for some type, say
+/// \c ConstantArrayType, it should define method
+/// <tt>VisitConstantArrayType(const ConstantArrayType*)</tt>. Otherwise
+/// \c TypeVisitor dispatches call to the method that handles parent type. In
+/// this example handlers are tried in the sequence:
+///
+/// \li <tt>ImplClass::VisitConstantArrayType(const ConstantArrayType*)</tt>
+/// \li <tt>ImplClass::VisitArrayType(const ArrayType*)</tt>
+/// \li <tt>ImplClass::VisitType(const Type*)</tt>
+/// \li <tt>TypeVisitor::VisitType(const Type*)</tt>
+///
+/// The first function of this sequence that is defined will handle object of
+/// type \c ConstantArrayType.
template<typename ImplClass, typename RetTy=void>
class TypeVisitor {
public:
+
+ /// \brief Performs the operation associated with this visitor object.
RetTy Visit(const Type *T) {
// Top switch stmt: dispatch to VisitFooType for each FooType.
switch (T->getTypeClass()) {
@@ -42,7 +83,8 @@ public:
}
#include "clang/AST/TypeNodes.def"
- // Base case, ignore it. :)
+ /// \brief Method called if \c ImpClass doesn't provide specific handler
+ /// for some type class.
RetTy VisitType(const Type*) { return RetTy(); }
};
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
index d26065e3745b..759af2537f75 100644
--- a/include/clang/AST/UnresolvedSet.h
+++ b/include/clang/AST/UnresolvedSet.h
@@ -51,6 +51,7 @@ public:
typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
NamedDecl *getDecl() const { return ir->getDecl(); }
+ void setDecl(NamedDecl *ND) const { return ir->setDecl(ND); }
AccessSpecifier getAccess() const { return ir->getAccess(); }
void setAccess(AccessSpecifier AS) { ir->setAccess(AS); }
DeclAccessPair getPair() const { return *ir; }
@@ -88,7 +89,7 @@ public:
bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; }
};
-/// UnresolvedSet - A set of unresolved declarations.
+/// \brief A set of unresolved declarations.
class UnresolvedSetImpl {
typedef SmallVectorImpl<DeclAccessPair> DeclsTy;
@@ -139,15 +140,9 @@ public:
I.ir->set(New, AS);
}
- void erase(unsigned I) {
- decls()[I] = decls().back();
- decls().pop_back();
- }
+ void erase(unsigned I) { decls()[I] = decls().pop_back_val(); }
- void erase(iterator I) {
- *I.ir = decls().back();
- decls().pop_back();
- }
+ void erase(iterator I) { *I.ir = decls().pop_back_val(); }
void setAccess(iterator I, AccessSpecifier AS) {
I.ir->setAccess(AS);
@@ -177,7 +172,7 @@ private:
}
};
-/// A set of unresolved declarations
+/// \brief A set of unresolved declarations.
template <unsigned InlineCapacity> class UnresolvedSet :
public UnresolvedSetImpl {
SmallVector<DeclAccessPair, InlineCapacity> Decls;
diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h
index f24bb3f16b86..727bf5109ad4 100644
--- a/include/clang/AST/VTTBuilder.h
+++ b/include/clang/AST/VTTBuilder.h
@@ -63,54 +63,50 @@ struct VTTComponent {
: VTableIndex(VTableIndex), VTableBase(VTableBase) {}
};
-/// VTT builder - Class for building VTT layout information.
+/// \brief Class for building VTT layout information.
class VTTBuilder {
ASTContext &Ctx;
- /// MostDerivedClass - The most derived class for which we're building this
- /// vtable.
+ /// \brief The most derived class for which we're building this vtable.
const CXXRecordDecl *MostDerivedClass;
typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy;
- /// VTTVTables - The VTT vtables.
+ /// \brief The VTT vtables.
VTTVTablesVectorTy VTTVTables;
typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy;
- /// VTTComponents - The VTT components.
+ /// \brief The VTT components.
VTTComponentsVectorTy VTTComponents;
- /// MostDerivedClassLayout - the AST record layout of the most derived class.
+ /// \brief The AST record layout of the most derived class.
const ASTRecordLayout &MostDerivedClassLayout;
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
- /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived
- /// class.
+ /// \brief The sub-VTT indices for the bases of the most derived class.
llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
- /// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of
- /// all subobjects of the most derived class.
+ /// \brief The secondary virtual pointer indices of all subobjects of
+ /// the most derived class.
llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
- /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for
- /// the VTT.
+ /// \brief Whether the VTT builder should generate LLVM IR for the VTT.
bool GenerateDefinition;
- /// AddVTablePointer - Add a vtable pointer to the VTT currently being built.
+ /// \brief Add a vtable pointer to the VTT currently being built.
void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
const CXXRecordDecl *VTableClass);
- /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
- /// subobject.
+ /// \brief Lay out the secondary VTTs of the given base subobject.
void LayoutSecondaryVTTs(BaseSubobject Base);
- /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
- /// for the given base subobject.
+ /// \brief Lay out the secondary virtual pointers for the given base
+ /// subobject.
///
/// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
/// or a direct or indirect base of a virtual base.
@@ -120,17 +116,17 @@ class VTTBuilder {
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy &VBases);
- /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
- /// for the given base subobject.
+ /// \brief Lay out the secondary virtual pointers for the given base
+ /// subobject.
void LayoutSecondaryVirtualPointers(BaseSubobject Base,
uint64_t VTableIndex);
- /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
- /// given record decl.
+ /// \brief Lay out the VTTs for the virtual base classes of the given
+ /// record declaration.
void LayoutVirtualVTTs(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases);
- /// LayoutVTT - Will lay out the VTT for the given subobject, including any
+ /// \brief Lay out the VTT for the given subobject, including any
/// secondary VTTs, secondary virtual pointers and virtual VTTs.
void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
@@ -138,23 +134,22 @@ public:
VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
bool GenerateDefinition);
- // getVTTComponents - Returns a reference to the VTT components.
+ // \brief Returns a reference to the VTT components.
const VTTComponentsVectorTy &getVTTComponents() const {
return VTTComponents;
}
- // getVTTVTables - Returns a reference to the VTT vtables.
+ // \brief Returns a reference to the VTT vtables.
const VTTVTablesVectorTy &getVTTVTables() const {
return VTTVTables;
}
- /// getSubVTTIndicies - Returns a reference to the sub-VTT indices.
+ /// \brief Returns a reference to the sub-VTT indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
return SubVTTIndicies;
}
- /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary
- /// virtual pointer indices.
+ /// \brief Returns a reference to the secondary virtual pointer indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &
getSecondaryVirtualPointerIndices() const {
return SecondaryVirtualPointerIndices;
diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h
index bcbe8754ea4a..4e451324d734 100644
--- a/include/clang/AST/VTableBuilder.h
+++ b/include/clang/AST/VTableBuilder.h
@@ -20,12 +20,13 @@
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/DenseSet.h"
#include <utility>
namespace clang {
class CXXRecordDecl;
-/// VTableComponent - Represents a single component in a vtable.
+/// \brief Represents a single component in a vtable.
class VTableComponent {
public:
enum Kind {
@@ -35,15 +36,17 @@ public:
CK_RTTI,
CK_FunctionPointer,
- /// CK_CompleteDtorPointer - A pointer to the complete destructor.
+ /// \brief A pointer to the complete destructor.
CK_CompleteDtorPointer,
- /// CK_DeletingDtorPointer - A pointer to the deleting destructor.
+ /// \brief A pointer to the deleting destructor.
CK_DeletingDtorPointer,
- /// CK_UnusedFunctionPointer - In some cases, a vtable function pointer
- /// will end up never being called. Such vtable function pointers are
- /// represented as a CK_UnusedFunctionPointer.
+ /// \brief An entry that is never used.
+ ///
+ /// In some cases, a vtable function pointer will end up never being
+ /// called. Such vtable function pointers are represented as a
+ /// CK_UnusedFunctionPointer.
CK_UnusedFunctionPointer
};
@@ -94,7 +97,7 @@ public:
return VTableComponent(I);
}
- /// getKind - Get the kind of this vtable component.
+ /// \brief Get the kind of this vtable component.
Kind getKind() const {
return (Kind)(Value & 0x7);
}
@@ -189,7 +192,7 @@ private:
/// The kind is stored in the lower 3 bits of the value. For offsets, we
/// make use of the facts that classes can't be larger than 2^55 bytes,
- /// so we store the offset in the lower part of the 61 bytes that remain.
+ /// so we store the offset in the lower part of the 61 bits that remain.
/// (The reason that we're not simply using a PointerIntPair here is that we
/// need the offsets to be 64-bit, even when on a 32-bit machine).
int64_t Value;
@@ -198,7 +201,6 @@ private:
class VTableLayout {
public:
typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy;
- typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
typedef const VTableComponent *vtable_component_iterator;
typedef const VTableThunkTy *vtable_thunk_iterator;
@@ -208,11 +210,11 @@ private:
uint64_t NumVTableComponents;
llvm::OwningArrayPtr<VTableComponent> VTableComponents;
- /// VTableThunks - Contains thunks needed by vtables.
+ /// \brief Contains thunks needed by vtables, sorted by indices.
uint64_t NumVTableThunks;
llvm::OwningArrayPtr<VTableThunkTy> VTableThunks;
- /// Address points - Address points for all vtables.
+ /// \brief Address points for all vtables.
AddressPointsMapTy AddressPoints;
bool IsMicrosoftABI;
@@ -231,23 +233,21 @@ public:
}
vtable_component_iterator vtable_component_begin() const {
- return VTableComponents.get();
+ return VTableComponents.get();
}
vtable_component_iterator vtable_component_end() const {
- return VTableComponents.get()+NumVTableComponents;
+ return VTableComponents.get() + NumVTableComponents;
}
- uint64_t getNumVTableThunks() const {
- return NumVTableThunks;
- }
+ uint64_t getNumVTableThunks() const { return NumVTableThunks; }
vtable_thunk_iterator vtable_thunk_begin() const {
- return VTableThunks.get();
+ return VTableThunks.get();
}
vtable_thunk_iterator vtable_thunk_end() const {
- return VTableThunks.get()+NumVTableThunks;
+ return VTableThunks.get() + NumVTableThunks;
}
uint64_t getAddressPoint(BaseSubobject Base) const {
@@ -266,19 +266,45 @@ public:
}
};
-class VTableContext {
- ASTContext &Context;
-
+class VTableContextBase {
public:
- typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1>
- VTableThunksTy;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
+protected:
+ typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
+
+ /// \brief Contains all thunks that a given method decl will need.
+ ThunksMapTy Thunks;
+
+ /// Compute and store all vtable related information (vtable layout, vbase
+ /// offset offsets, thunks etc) for the given record decl.
+ virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0;
+
+ virtual ~VTableContextBase() {}
+
+public:
+ virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()->getCanonicalDecl());
+ computeVTableRelatedInformation(MD->getParent());
+
+ // This assumes that all the destructors present in the vtable
+ // use exactly the same set of thunks.
+ ThunksMapTy::const_iterator I = Thunks.find(MD);
+ if (I == Thunks.end()) {
+ // We did not find a thunk for this method.
+ return 0;
+ }
+
+ return &I->second;
+ }
+};
+
+class ItaniumVTableContext : public VTableContextBase {
private:
bool IsMicrosoftABI;
- /// MethodVTableIndices - Contains the index (relative to the vtable address
- /// point) where the function pointer for a virtual function is stored.
+ /// \brief Contains the index (relative to the vtable address point)
+ /// where the function pointer for a virtual function is stored.
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
MethodVTableIndicesTy MethodVTableIndices;
@@ -286,49 +312,25 @@ private:
VTableLayoutMapTy;
VTableLayoutMapTy VTableLayouts;
- /// NumVirtualFunctionPointers - Contains the number of virtual function
- /// pointers in the vtable for a given record decl.
- llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
-
typedef std::pair<const CXXRecordDecl *,
const CXXRecordDecl *> ClassPairTy;
- /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to
- /// the address point) in chars where the offsets for virtual bases of a class
- /// are stored.
+ /// \brief vtable offsets for offsets of virtual bases of a class.
+ ///
+ /// Contains the vtable offset (relative to the address point) in chars
+ /// where the offsets for virtual bases of a class are stored.
typedef llvm::DenseMap<ClassPairTy, CharUnits>
VirtualBaseClassOffsetOffsetsMapTy;
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
- typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
-
- /// Thunks - Contains all thunks that a given method decl will need.
- ThunksMapTy Thunks;
-
- void ComputeMethodVTableIndices(const CXXRecordDecl *RD);
-
- /// ComputeVTableRelatedInformation - Compute and store all vtable related
- /// information (vtable layout, vbase offset offsets, thunks etc) for the
- /// given record decl.
- void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
-
- /// ErrorUnsupported - Print out an error that the v-table layout code
- /// doesn't support the particular C++ feature yet.
- void ErrorUnsupported(StringRef Feature, SourceLocation Location);
+ void computeVTableRelatedInformation(const CXXRecordDecl *RD);
public:
- VTableContext(ASTContext &Context);
- ~VTableContext();
-
- bool isMicrosoftABI() const {
- // FIXME: Currently, this method is only used in the VTableContext and
- // VTableBuilder code which is ABI-specific. Probably we can remove it
- // when we add a layer of abstraction for vtable generation.
- return IsMicrosoftABI;
- }
+ ItaniumVTableContext(ASTContext &Context);
+ ~ItaniumVTableContext();
const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
- ComputeVTableRelatedInformation(RD);
+ computeVTableRelatedInformation(RD);
assert(VTableLayouts.count(RD) && "No layout for this record decl!");
return *VTableLayouts[RD];
@@ -340,36 +342,177 @@ public:
bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass);
- const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) {
- ComputeVTableRelatedInformation(MD->getParent());
+ /// \brief Locate a virtual function in the vtable.
+ ///
+ /// Return the index (relative to the vtable address point) where the
+ /// function pointer for the given virtual function is stored.
+ uint64_t getMethodVTableIndex(GlobalDecl GD);
- ThunksMapTy::const_iterator I = Thunks.find(MD);
- if (I == Thunks.end()) {
- // We did not find a thunk for this method.
- return 0;
- }
+ /// Return the offset in chars (relative to the vtable address point) where
+ /// the offset of the virtual base that contains the given base is stored,
+ /// otherwise, if no virtual base contains the given class, return 0.
+ ///
+ /// Base must be a virtual base class or an unambiguous base.
+ CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *VBase);
+};
- return &I->second;
+struct VFPtrInfo {
+ typedef SmallVector<const CXXRecordDecl *, 1> BasePath;
+
+ // Don't pass the PathToMangle as it should be calculated later.
+ VFPtrInfo(CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr)
+ : VBTableIndex(0), LastVBase(0), VFPtrOffset(VFPtrOffset),
+ PathToBaseWithVFPtr(PathToBaseWithVFPtr), VFPtrFullOffset(VFPtrOffset) {
}
- /// getNumVirtualFunctionPointers - Return the number of virtual function
- /// pointers in the vtable for a given record decl.
- uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
+ // Don't pass the PathToMangle as it should be calculated later.
+ VFPtrInfo(uint64_t VBTableIndex, const CXXRecordDecl *LastVBase,
+ CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr,
+ CharUnits VFPtrFullOffset)
+ : VBTableIndex(VBTableIndex), LastVBase(LastVBase),
+ VFPtrOffset(VFPtrOffset), PathToBaseWithVFPtr(PathToBaseWithVFPtr),
+ VFPtrFullOffset(VFPtrFullOffset) {
+ assert(VBTableIndex && "The full constructor should only be used "
+ "for vfptrs in virtual bases");
+ assert(LastVBase);
+ }
- /// getMethodVTableIndex - Return the index (relative to the vtable address
- /// point) where the function pointer for the given virtual function is
- /// stored.
- uint64_t getMethodVTableIndex(GlobalDecl GD);
+ /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
+ uint64_t VBTableIndex;
- /// getVirtualBaseOffsetOffset - Return the offset in chars (relative to the
- /// vtable address point) where the offset of the virtual base that contains
- /// the given base is stored, otherwise, if no virtual base contains the given
- /// class, return 0. Base must be a virtual base class or an unambigious
- /// base.
- CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
- const CXXRecordDecl *VBase);
+ /// Stores the last vbase on the path from the complete type to the vfptr.
+ const CXXRecordDecl *LastVBase;
+
+ /// This is the offset of the vfptr from the start of the last vbase,
+ /// or the complete type if there are no virtual bases.
+ CharUnits VFPtrOffset;
+
+ /// This holds the base classes path from the complete type to the first base
+ /// with the given vfptr offset, in the base-to-derived order.
+ BasePath PathToBaseWithVFPtr;
+
+ /// This holds the subset of records that need to be mangled into the vftable
+ /// symbol name in order to get a unique name, in the derived-to-base order.
+ BasePath PathToMangle;
+
+ /// This is the full offset of the vfptr from the start of the complete type.
+ CharUnits VFPtrFullOffset;
};
+class MicrosoftVTableContext : public VTableContextBase {
+public:
+ struct MethodVFTableLocation {
+ /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
+ uint64_t VBTableIndex;
+
+ /// If nonnull, holds the last vbase which contains the vfptr that the
+ /// method definition is adjusted to.
+ const CXXRecordDecl *VBase;
+
+ /// This is the offset of the vfptr from the start of the last vbase, or the
+ /// complete type if there are no virtual bases.
+ CharUnits VFPtrOffset;
+
+ /// Method's index in the vftable.
+ uint64_t Index;
+
+ MethodVFTableLocation()
+ : VBTableIndex(0), VBase(0), VFPtrOffset(CharUnits::Zero()),
+ Index(0) {}
+
+ MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase,
+ CharUnits VFPtrOffset, uint64_t Index)
+ : VBTableIndex(VBTableIndex), VBase(VBase),
+ VFPtrOffset(VFPtrOffset), Index(Index) {}
+
+ bool operator<(const MethodVFTableLocation &other) const {
+ if (VBTableIndex != other.VBTableIndex) {
+ assert(VBase != other.VBase);
+ return VBTableIndex < other.VBTableIndex;
+ }
+ if (VFPtrOffset != other.VFPtrOffset)
+ return VFPtrOffset < other.VFPtrOffset;
+ if (Index != other.Index)
+ return Index < other.Index;
+ return false;
+ }
+ };
+
+ typedef SmallVector<VFPtrInfo, 1> VFPtrListTy;
+
+private:
+ ASTContext &Context;
+
+ typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
+ MethodVFTableLocationsTy;
+ MethodVFTableLocationsTy MethodVFTableLocations;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, VFPtrListTy>
+ VFPtrLocationsMapTy;
+ VFPtrLocationsMapTy VFPtrLocations;
+
+ typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
+ typedef llvm::DenseMap<VFTableIdTy, const VTableLayout *> VFTableLayoutMapTy;
+ VFTableLayoutMapTy VFTableLayouts;
+
+ typedef llvm::SmallSetVector<const CXXRecordDecl *, 8> BasesSetVectorTy;
+ void enumerateVFPtrs(const CXXRecordDecl *MostDerivedClass,
+ const ASTRecordLayout &MostDerivedClassLayout,
+ BaseSubobject Base, const CXXRecordDecl *LastVBase,
+ const VFPtrInfo::BasePath &PathFromCompleteClass,
+ BasesSetVectorTy &VisitedVBases,
+ MicrosoftVTableContext::VFPtrListTy &Result);
+
+ void enumerateVFPtrs(const CXXRecordDecl *ForClass,
+ MicrosoftVTableContext::VFPtrListTy &Result);
+
+ void computeVTableRelatedInformation(const CXXRecordDecl *RD);
+
+ void dumpMethodLocations(const CXXRecordDecl *RD,
+ const MethodVFTableLocationsTy &NewMethods,
+ raw_ostream &);
+
+ typedef std::pair<const CXXRecordDecl *, const CXXRecordDecl *> ClassPairTy;
+ typedef llvm::DenseMap<ClassPairTy, unsigned> VBTableIndicesTy;
+ VBTableIndicesTy VBTableIndices;
+ llvm::DenseSet<const CXXRecordDecl *> ComputedVBTableIndices;
+
+ void computeVBTableRelatedInformation(const CXXRecordDecl *RD);
+
+public:
+ MicrosoftVTableContext(ASTContext &Context) : Context(Context) {}
+
+ ~MicrosoftVTableContext() { llvm::DeleteContainerSeconds(VFTableLayouts); }
+
+ const VFPtrListTy &getVFPtrOffsets(const CXXRecordDecl *RD);
+
+ const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD,
+ CharUnits VFPtrOffset);
+
+ const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD);
+
+ const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) {
+ // Complete destructors don't have a slot in a vftable, so no thunks needed.
+ if (isa<CXXDestructorDecl>(GD.getDecl()) &&
+ GD.getDtorType() == Dtor_Complete)
+ return 0;
+ return VTableContextBase::getThunkInfo(GD);
+ }
+
+ /// \brief Returns the index of VBase in the vbtable of Derived.
+ /// VBase must be a morally virtual base of Derived.
+ /// The vbtable is an array of i32 offsets. The first entry is a self entry,
+ /// and the rest are offsets from the vbptr to virtual bases.
+ unsigned getVBTableIndex(const CXXRecordDecl *Derived,
+ const CXXRecordDecl *VBase) {
+ computeVBTableRelatedInformation(Derived);
+ ClassPairTy Pair(Derived, VBase);
+ assert(VBTableIndices.count(Pair) == 1 &&
+ "VBase must be a vbase of Derived");
+ return VBTableIndices[Pair];
+ }
+};
}
#endif
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 870a39b39111..db0a83d72262 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -97,6 +97,11 @@ public:
///
/// Optionally override to do per translation unit tasks.
virtual void onStartOfTranslationUnit() {}
+
+ /// \brief Called at the end of each translation unit.
+ ///
+ /// Optionally override to do per translation unit tasks.
+ virtual void onEndOfTranslationUnit() {}
};
/// \brief Called when parsing is finished. Intended for testing only.
@@ -131,6 +136,17 @@ public:
MatchCallback *Action);
/// @}
+ /// \brief Adds a matcher to execute when running over the AST.
+ ///
+ /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
+ /// is more flexible, but the lost type information enables a caller to pass
+ /// a matcher that cannot match anything.
+ ///
+ /// \returns \c true if the matcher is a valid top-level matcher, \c false
+ /// otherwise.
+ bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
+ MatchCallback *Action);
+
/// \brief Creates a clang ASTConsumer that finds all matches.
clang::ASTConsumer *newASTConsumer();
@@ -147,6 +163,9 @@ public:
ASTContext &Context);
/// @}
+ /// \brief Finds all matches in the given AST.
+ void matchAST(ASTContext &Context);
+
/// \brief Registers a callback to notify the end of parsing.
///
/// The provided closure is called after parsing is done, before the AST is
@@ -157,7 +176,7 @@ public:
private:
/// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
/// when it matches.
- std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> >
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> >
MatcherCallbackPairs;
/// \brief Called when parsing is done.
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index ab62dd0c3e81..0a3157dde817 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -45,6 +45,7 @@
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
@@ -85,6 +86,16 @@ public:
}
/// @}
+ /// \brief Type of mapping from binding identifiers to bound nodes. This type
+ /// is an associative container with a key type of \c std::string and a value
+ /// type of \c clang::ast_type_traits::DynTypedNode
+ typedef internal::BoundNodesMap::IDToNodeMap IDToNodeMap;
+
+ /// \brief Retrieve mapping from binding identifiers to bound nodes.
+ const IDToNodeMap &getMap() const {
+ return MyBoundNodes.getMap();
+ }
+
private:
/// \brief Create BoundNodes from a pre-filled map of bindings.
BoundNodes(internal::BoundNodesMap &MyBoundNodes)
@@ -92,7 +103,7 @@ private:
internal::BoundNodesMap MyBoundNodes;
- friend class internal::BoundNodesTree;
+ friend class internal::BoundNodesTreeBuilder;
};
/// \brief If the provided matcher matches a node, binds the node to \c ID.
@@ -204,6 +215,28 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
ClassTemplateSpecializationDecl> classTemplateSpecializationDecl;
+/// \brief Matches declarator declarations (field, variable, function
+/// and non-type template parameter declarations).
+///
+/// Given
+/// \code
+/// class X { int y; };
+/// \endcode
+/// declaratorDecl()
+/// matches \c int y.
+const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
+ declaratorDecl;
+
+/// \brief Matches parameter variable declarations.
+///
+/// Given
+/// \code
+/// void f(int x);
+/// \endcode
+/// parmVarDecl()
+/// matches \c int x.
+const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
+
/// \brief Matches C++ access specifier declarations.
///
/// Given
@@ -219,6 +252,17 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
AccessSpecDecl> accessSpecDecl;
+/// \brief Matches constructor initializers.
+///
+/// Examples matches \c i(42).
+/// \code
+/// class C {
+/// C() : i(42) {}
+/// int i;
+/// };
+/// \endcode
+const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
+
/// \brief Matches public C++ declarations.
///
/// Given
@@ -281,12 +325,9 @@ AST_MATCHER(Decl, isPrivate) {
/// matches the specialization \c A<int>
AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
internal::Matcher<TemplateArgument>, InnerMatcher) {
- const TemplateArgumentList &List = Node.getTemplateArgs();
- for (unsigned i = 0; i < List.size(); ++i) {
- if (InnerMatcher.matches(List.get(i), Finder, Builder))
- return true;
- }
- return false;
+ llvm::ArrayRef<TemplateArgument> List = Node.getTemplateArgs().asArray();
+ return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder,
+ Builder);
}
/// \brief Matches expressions that match InnerMatcher after any implicit casts
@@ -520,6 +561,16 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
FunctionTemplateDecl> functionTemplateDecl;
+/// \brief Matches friend declarations.
+///
+/// Given
+/// \code
+/// class X { friend void foo(); };
+/// \endcode
+/// friendDecl()
+/// matches 'friend void foo()'.
+const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
+
/// \brief Matches statements.
///
/// Given
@@ -607,6 +658,21 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
/// matches \code using X::x \endcode
const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+/// \brief Matches unresolved using value declarations.
+///
+/// Given
+/// \code
+/// template<typename X>
+/// class C : private X {
+/// using X::x;
+/// };
+/// \endcode
+/// unresolvedUsingValueDecl()
+/// matches \code using X::x \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UnresolvedUsingValueDecl> unresolvedUsingValueDecl;
+
/// \brief Matches constructor call expressions (including implicit ones).
///
/// Example matches string(ptr, n) and ptr within arguments of f
@@ -621,6 +687,18 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CXXConstructExpr> constructExpr;
+/// \brief Matches unresolved constructor call expressions.
+///
+/// Example matches T(t) in return statement of f
+/// (matcher = unresolvedConstructExpr())
+/// \code
+/// template <typename T>
+/// void f(const T& t) { return T(t); }
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXUnresolvedConstructExpr> unresolvedConstructExpr;
+
/// \brief Matches implicit and explicit this expressions.
///
/// Example matches the implicit this expression in "return i".
@@ -894,6 +972,26 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
/// matches 'case 42: break;' and 'default: break;'.
const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
+/// \brief Matches case statements inside switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// caseStmt()
+/// matches 'case 42: break;'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
+
+/// \brief Matches default statements inside switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// defaultStmt()
+/// matches 'default: break;'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt;
+
/// \brief Matches compound statements.
///
/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
@@ -981,15 +1079,25 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CharacterLiteral> characterLiteral;
-/// \brief Matches integer literals of all sizes / encodings.
-///
-/// Not matching character-encoded integers such as L'a'.
+/// \brief Matches integer literals of all sizes / encodings, e.g.
+/// 1, 1L, 0x1 and 1U.
///
-/// Example matches 1, 1L, 0x1, 1U
+/// Does not match character-encoded integers such as L'a'.
const internal::VariadicDynCastAllOfMatcher<
Stmt,
IntegerLiteral> integerLiteral;
+/// \brief Matches float literals of all sizes / encodings, e.g.
+/// 1.0, 1.0f, 1.0L and 1e10.
+///
+/// Does not match implicit conversions such as
+/// \code
+/// float a = 10;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ FloatingLiteral> floatLiteral;
+
/// \brief Matches user defined literal operator call.
///
/// Example match: "foo"_suffix
@@ -1171,6 +1279,16 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CXXFunctionalCastExpr> functionalCastExpr;
+/// \brief Matches functional cast expressions having N != 1 arguments
+///
+/// Example: Matches Foo(bar, bar)
+/// \code
+/// Foo h = Foo(bar, bar);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXTemporaryObjectExpr> temporaryObjectExpr;
+
/// \brief Matches \c QualTypes in the clang AST.
const internal::VariadicAllOfMatcher<QualType> qualType;
@@ -1199,93 +1317,23 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// \c b.
///
/// Usable as: Any Matcher
-template <typename M1, typename M2>
-internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, M2>
-eachOf(const M1 &P1, const M2 &P2) {
- return internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1,
- M2>(P1, P2);
-}
-
-/// \brief Various overloads for the anyOf matcher.
-/// @{
+const internal::VariadicOperatorMatcherFunc eachOf = {
+ internal::EachOfVariadicOperator
+};
/// \brief Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
-template<typename M1, typename M2>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1, M2>
-anyOf(const M1 &P1, const M2 &P2) {
- return internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
- M1, M2 >(P1, P2);
-}
-template<typename M1, typename M2, typename M3>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2, M3> >
-anyOf(const M1 &P1, const M2 &P2, const M3 &P3) {
- return anyOf(P1, anyOf(P2, P3));
-}
-template<typename M1, typename M2, typename M3, typename M4>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
- M3, M4> > >
-anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) {
- return anyOf(P1, anyOf(P2, anyOf(P3, P4)));
-}
-template<typename M1, typename M2, typename M3, typename M4, typename M5>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M3,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
- M4, M5> > > >
-anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) {
- return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5))));
-}
-
-/// @}
-
-/// \brief Various overloads for the allOf matcher.
-/// @{
+const internal::VariadicOperatorMatcherFunc anyOf = {
+ internal::AnyOfVariadicOperator
+};
/// \brief Matches if all given matchers match.
///
/// Usable as: Any Matcher
-template <typename M1, typename M2>
-internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2>
-allOf(const M1 &P1, const M2 &P2) {
- return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2>(
- P1, P2);
-}
-template <typename M1, typename M2, typename M3>
-internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M2, M3> >
-allOf(const M1 &P1, const M2 &P2, const M3 &P3) {
- return allOf(P1, allOf(P2, P3));
-}
-template <typename M1, typename M2, typename M3, typename M4>
-internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M2, internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M3, M4> > >
-allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) {
- return allOf(P1, allOf(P2, P3, P4));
-}
-template <typename M1, typename M2, typename M3, typename M4, typename M5>
-internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M2,
- internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M3,
- internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M4,
- M5> > > >
-allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) {
- return allOf(P1, allOf(P2, P3, P4, P5));
-}
-
-/// @}
+const internal::VariadicOperatorMatcherFunc allOf = {
+ internal::AllOfVariadicOperator
+};
/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
///
@@ -1412,10 +1460,13 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
///
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
inline internal::PolymorphicMatcherWithParam1<
- internal::HasOverloadedOperatorNameMatcher, StringRef>
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>
hasOverloadedOperatorName(const StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
- internal::HasOverloadedOperatorNameMatcher, StringRef>(Name);
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>(
+ Name);
}
/// \brief Matches C++ classes that are directly or indirectly derived from
@@ -1445,24 +1496,25 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
}
/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
-inline internal::Matcher<CXXRecordDecl> isDerivedFrom(StringRef BaseName) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, StringRef, BaseName, 1) {
assert(!BaseName.empty());
- return isDerivedFrom(hasName(BaseName));
+ return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly
/// match \c Base.
-inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom(
- internal::Matcher<NamedDecl> Base) {
- return anyOf(Base, isDerivedFrom(Base));
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
+ internal::Matcher<NamedDecl>, Base, 0) {
+ return Matcher<CXXRecordDecl>(anyOf(Base, isDerivedFrom(Base)))
+ .matches(Node, Finder, Builder);
}
/// \brief Overloaded method as shortcut for
/// \c isSameOrDerivedFrom(hasName(...)).
-inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom(
- StringRef BaseName) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, StringRef, BaseName,
+ 1) {
assert(!BaseName.empty());
- return isSameOrDerivedFrom(hasName(BaseName));
+ return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
/// \brief Matches the first method of a class or struct that satisfies \c
@@ -1478,12 +1530,8 @@ inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom(
/// but not \c B.
AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
InnerMatcher) {
- for (CXXRecordDecl::method_iterator I = Node.method_begin(),
- E = Node.method_end();
- I != E; ++I)
- if (InnerMatcher.matches(**I, Finder, Builder))
- return true;
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.method_begin(),
+ Node.method_end(), Finder, Builder);
}
/// \brief Matches AST nodes that have child AST nodes that match the
@@ -1499,12 +1547,8 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
/// ChildT must be an AST base type.
///
/// Usable as: Any Matcher
-template <typename ChildT>
-internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has(
- const internal::Matcher<ChildT> &ChildMatcher) {
- return internal::ArgumentAdaptingMatcher<internal::HasMatcher,
- ChildT>(ChildMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher>
+LLVM_ATTRIBUTE_UNUSED has = {};
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -1520,13 +1564,8 @@ internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has(
/// DescendantT must be an AST base type.
///
/// Usable as: Any Matcher
-template <typename DescendantT>
-internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher, DescendantT>
-hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasDescendantMatcher,
- DescendantT>(DescendantMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
+LLVM_ATTRIBUTE_UNUSED hasDescendant = {};
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
@@ -1544,13 +1583,8 @@ hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) {
/// matches instead of only on the first one.
///
/// Usable as: Any Matcher
-template <typename ChildT>
-internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach(
- const internal::Matcher<ChildT> &ChildMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::ForEachMatcher,
- ChildT>(ChildMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
+LLVM_ATTRIBUTE_UNUSED forEach = {};
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -1576,15 +1610,8 @@ internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach(
/// \endcode
///
/// Usable as: Any Matcher
-template <typename DescendantT>
-internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher,
- DescendantT>
-forEachDescendant(
- const internal::Matcher<DescendantT> &DescendantMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::ForEachDescendantMatcher,
- DescendantT>(DescendantMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher>
+LLVM_ATTRIBUTE_UNUSED forEachDescendant = {};
/// \brief Matches if the node or any descendant matches.
///
@@ -1602,10 +1629,7 @@ forEachDescendant(
///
/// Usable as: Any Matcher
template <typename T>
-internal::PolymorphicMatcherWithParam2<
- internal::EachOfMatcher, internal::Matcher<T>,
- internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, T> >
-findAll(const internal::Matcher<T> &Matcher) {
+internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
return eachOf(Matcher, forEachDescendant(Matcher));
}
@@ -1619,13 +1643,9 @@ findAll(const internal::Matcher<T> &Matcher) {
/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
///
/// Usable as: Any Matcher
-template <typename ParentT>
-internal::ArgumentAdaptingMatcher<internal::HasParentMatcher, ParentT>
-hasParent(const internal::Matcher<ParentT> &ParentMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasParentMatcher,
- ParentT>(ParentMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasParentMatcher, internal::TypeList<Decl, Stmt>,
+ internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasParent = {};
/// \brief Matches AST nodes that have an ancestor that matches the provided
/// matcher.
@@ -1638,13 +1658,9 @@ hasParent(const internal::Matcher<ParentT> &ParentMatcher) {
/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43.
///
/// Usable as: Any Matcher
-template <typename AncestorT>
-internal::ArgumentAdaptingMatcher<internal::HasAncestorMatcher, AncestorT>
-hasAncestor(const internal::Matcher<AncestorT> &AncestorMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasAncestorMatcher,
- AncestorT>(AncestorMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasAncestorMatcher, internal::TypeList<Decl, Stmt>,
+ internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
/// \brief Matches if the provided matcher does not match.
///
@@ -1662,22 +1678,31 @@ unless(const M &InnerMatcher) {
internal::NotMatcher, M>(InnerMatcher);
}
-/// \brief Matches a type if the declaration of the type matches the given
-/// matcher.
+/// \brief Matches a node if the declaration associated with that node
+/// matches the given matcher.
+///
+/// The associated declaration is:
+/// - for type nodes, the declaration of the underlying type
+/// - for CallExpr, the declaration of the callee
+/// - for MemberExpr, the declaration of the referenced member
+/// - for CXXConstructExpr, the declaration of the constructor
///
-/// In addition to being usable as Matcher<TypedefType>, also usable as
-/// Matcher<T> for any T supporting the getDecl() member function. e.g. various
-/// subtypes of clang::Type.
+/// Also usable as Matcher<T> for any T supporting the getDecl() member
+/// function. e.g. various subtypes of clang::Type and various expressions.
///
-/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>,
-/// Matcher<MemberExpr>, Matcher<TypedefType>,
-/// Matcher<TemplateSpecializationType>
-inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher,
- internal::Matcher<Decl> >
- hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
+/// Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
+/// Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
+/// Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
+/// Matcher<RecordType>, Matcher<TagType>,
+/// Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
+/// Matcher<TypedefType>, Matcher<UnresolvedUsingType>
+inline internal::PolymorphicMatcherWithParam1<
+ internal::HasDeclarationMatcher, internal::Matcher<Decl>,
+ void(internal::HasDeclarationSupportedTypes)>
+hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
return internal::PolymorphicMatcherWithParam1<
- internal::HasDeclarationMatcher,
- internal::Matcher<Decl> >(InnerMatcher);
+ internal::HasDeclarationMatcher, internal::Matcher<Decl>,
+ void(internal::HasDeclarationSupportedTypes)>(InnerMatcher);
}
/// \brief Matches on the implicit object argument of a member call expression.
@@ -1728,9 +1753,9 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
/// class Y { public: void x(); };
/// void z() { Y y; y.x();
/// \endcode
-inline internal::Matcher<CallExpr> callee(
- const internal::Matcher<Decl> &InnerMatcher) {
- return callExpr(hasDeclaration(InnerMatcher));
+AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
+ 1) {
+ return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder);
}
/// \brief Matches if the expression's or declaration's type matches a type
@@ -1742,11 +1767,9 @@ inline internal::Matcher<CallExpr> callee(
/// class X {};
/// void y(X &x) { x; X z; }
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value ||
- llvm::is_base_of<ValueDecl, NodeType>::value),
- instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
+ internal::Matcher<QualType>, InnerMatcher, 0) {
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
@@ -1767,11 +1790,27 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
/// \endcode
///
/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
-inline internal::PolymorphicMatcherWithParam1<
- internal::matcher_hasType0Matcher,
- internal::Matcher<QualType> >
-hasType(const internal::Matcher<Decl> &InnerMatcher) {
- return hasType(qualType(hasDeclaration(InnerMatcher)));
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
+ internal::Matcher<Decl>, InnerMatcher, 1) {
+ return qualType(hasDeclaration(InnerMatcher))
+ .matches(Node.getType(), Finder, Builder);
+}
+
+/// \brief Matches if the type location of the declarator decl's type matches
+/// the inner matcher.
+///
+/// Given
+/// \code
+/// int x;
+/// \endcode
+/// declaratorDecl(hasTypeLoc(loc(asString("int"))))
+/// matches int x
+AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) {
+ if (!Node.getTypeSourceInfo())
+ // This happens for example for implicit destructors.
+ return false;
+ return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder);
}
/// \brief Matches if the matched type is represented by the given string.
@@ -1804,9 +1843,10 @@ AST_MATCHER_P(
}
/// \brief Overloaded to match the pointee type's declaration.
-inline internal::Matcher<QualType> pointsTo(
- const internal::Matcher<Decl> &InnerMatcher) {
- return pointsTo(qualType(hasDeclaration(InnerMatcher)));
+AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
+ InnerMatcher, 1) {
+ return pointsTo(qualType(hasDeclaration(InnerMatcher)))
+ .matches(Node, Finder, Builder);
}
/// \brief Matches if the matched type is a reference type and the referenced
@@ -1841,13 +1881,16 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does.
AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>,
InnerMatcher) {
+ if (Node.isNull())
+ return false;
return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder);
}
/// \brief Overloaded to match the referenced type's declaration.
-inline internal::Matcher<QualType> references(
- const internal::Matcher<Decl> &InnerMatcher) {
- return references(qualType(hasDeclaration(InnerMatcher)));
+AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
+ InnerMatcher, 1) {
+ return references(qualType(hasDeclaration(InnerMatcher)))
+ .matches(Node, Finder, Builder);
}
AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
@@ -1859,17 +1902,19 @@ AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
/// \brief Matches if the expression's type either matches the specified
/// matcher, or is a pointer to a type that matches the InnerMatcher.
-inline internal::Matcher<CXXMemberCallExpr> thisPointerType(
- const internal::Matcher<QualType> &InnerMatcher) {
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
+ internal::Matcher<QualType>, InnerMatcher, 0) {
return onImplicitObjectArgument(
- anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+ .matches(Node, Finder, Builder);
}
/// \brief Overloaded to match the type's declaration.
-inline internal::Matcher<CXXMemberCallExpr> thisPointerType(
- const internal::Matcher<Decl> &InnerMatcher) {
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
+ internal::Matcher<Decl>, InnerMatcher, 1) {
return onImplicitObjectArgument(
- anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+ .matches(Node, Finder, Builder);
}
/// \brief Matches a DeclRefExpr that refers to a declaration that matches the
@@ -1953,11 +1998,9 @@ AST_MATCHER_P(
/// void f(int x, int y);
/// f(0, 0);
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(argumentCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ CallExpr, CXXConstructExpr),
+ unsigned, N) {
return Node.getNumArgs() == N;
}
@@ -1970,11 +2013,9 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
/// void x(int) { int y; x(y); }
/// \endcode
AST_POLYMORPHIC_MATCHER_P2(
- hasArgument, unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+ hasArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CallExpr, CXXConstructExpr),
+ unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
return (N < Node.getNumArgs() &&
InnerMatcher.matches(
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
@@ -2037,13 +2078,8 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
- for (CXXConstructorDecl::init_const_iterator I = Node.init_begin();
- I != Node.init_end(); ++I) {
- if (InnerMatcher.matches(**I, Finder, Builder)) {
- return true;
- }
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.init_begin(),
+ Node.init_end(), Finder, Builder);
}
/// \brief Matches the field declaration of a constructor initializer.
@@ -2086,7 +2122,7 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer,
InnerMatcher.matches(*NodeAsExpr, Finder, Builder));
}
-/// \brief Matches a contructor initializer if it is explicitly written in
+/// \brief Matches a constructor initializer if it is explicitly written in
/// code (as opposed to implicitly added by the compiler).
///
/// Given
@@ -2120,15 +2156,19 @@ AST_MATCHER(CXXConstructorDecl, isImplicit) {
/// matches x(1, y, 42)
/// with hasAnyArgument(...)
/// matching y
-AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<Expr>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+///
+/// FIXME: Currently this will ignore parentheses and implicit casts on
+/// the argument before applying the inner matcher. We'll want to remove
+/// this to allow for greater control by the user once \c ignoreImplicit()
+/// has been implemented.
+AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ CallExpr, CXXConstructExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
- if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(),
- Finder, Builder)) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder,
+ &Result)) {
+ *Builder = Result;
return true;
}
}
@@ -2167,12 +2207,8 @@ AST_MATCHER_P2(FunctionDecl, hasParameter,
/// matching int y
AST_MATCHER_P(FunctionDecl, hasAnyParameter,
internal::Matcher<ParmVarDecl>, InnerMatcher) {
- for (unsigned I = 0; I < Node.getNumParams(); ++I) {
- if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) {
- return true;
- }
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
+ Node.param_end(), Finder, Builder);
}
/// \brief Matches \c FunctionDecls that have a specific parameter count.
@@ -2222,27 +2258,68 @@ AST_MATCHER(FunctionDecl, isExternC) {
/// \code
/// if (true) {}
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<IfStmt, NodeType>::value) ||
- (llvm::is_base_of<ForStmt, NodeType>::value) ||
- (llvm::is_base_of<WhileStmt, NodeType>::value) ||
- (llvm::is_base_of<DoStmt, NodeType>::value) ||
- (llvm::is_base_of<ConditionalOperator, NodeType>::value),
- has_condition_requires_if_statement_conditional_operator_or_loop);
+AST_POLYMORPHIC_MATCHER_P(
+ hasCondition, AST_POLYMORPHIC_SUPPORTED_TYPES_5(
+ IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator),
+ internal::Matcher<Expr>, InnerMatcher) {
const Expr *const Condition = Node.getCond();
return (Condition != NULL &&
InnerMatcher.matches(*Condition, Finder, Builder));
}
+namespace internal {
+struct NotEqualsBoundNodePredicate {
+ bool operator()(const internal::BoundNodesMap &Nodes) const {
+ return Nodes.getNode(ID) != Node;
+ }
+ std::string ID;
+ ast_type_traits::DynTypedNode Node;
+};
+} // namespace internal
+
+/// \brief Matches if a node equals a previously bound node.
+///
+/// Matches a node if it equals the node previously bound to \p ID.
+///
+/// Given
+/// \code
+/// class X { int a; int b; };
+/// \endcode
+/// recordDecl(
+/// has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
+/// has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
+/// matches the class \c X, as \c a and \c b have the same type.
+///
+/// Note that when multiple matches are involved via \c forEach* matchers,
+/// \c equalsBoundNodes acts as a filter.
+/// For example:
+/// compoundStmt(
+/// forEachDescendant(varDecl().bind("d")),
+/// forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d"))))))
+/// will trigger a match for each combination of variable declaration
+/// and reference to that variable declaration within a compound statement.
+AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, AST_POLYMORPHIC_SUPPORTED_TYPES_4(
+ Stmt, Decl, Type, QualType),
+ std::string, ID) {
+ // FIXME: Figure out whether it makes sense to allow this
+ // on any other node types.
+ // For *Loc it probably does not make sense, as those seem
+ // unique. For NestedNameSepcifier it might make sense, as
+ // those also have pointer identity, but I'm not sure whether
+ // they're ever reused.
+ internal::NotEqualsBoundNodePredicate Predicate;
+ Predicate.ID = ID;
+ Predicate.Node = ast_type_traits::DynTypedNode::create(Node);
+ return Builder->removeBindings(Predicate);
+}
+
/// \brief Matches the condition variable statement in an if statement.
///
/// Given
/// \code
/// if (A* a = GetAPointer()) {}
/// \endcode
-/// hasConditionVariableStatment(...)
+/// hasConditionVariableStatement(...)
/// matches 'A* a = GetAPointer()'.
AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
internal::Matcher<DeclStmt>, InnerMatcher) {
@@ -2296,13 +2373,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
/// matches 'for (;;) {}'
/// with compoundStmt()
/// matching '{}'
-AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<DoStmt, NodeType>::value) ||
- (llvm::is_base_of<ForStmt, NodeType>::value) ||
- (llvm::is_base_of<WhileStmt, NodeType>::value),
- has_body_requires_for_while_or_do_statement);
+AST_POLYMORPHIC_MATCHER_P(
+ hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES_3(DoStmt, ForStmt, WhileStmt),
+ internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Statement = Node.getBody();
return (Statement != NULL &&
InnerMatcher.matches(*Statement, Finder, Builder));
@@ -2321,12 +2394,8 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
/// matching '{}'
AST_MATCHER_P(CompoundStmt, hasAnySubstatement,
internal::Matcher<Stmt>, InnerMatcher) {
- for (CompoundStmt::const_body_iterator It = Node.body_begin();
- It != Node.body_end();
- ++It) {
- if (InnerMatcher.matches(**It, Finder, Builder)) return true;
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.body_begin(),
+ Node.body_end(), Finder, Builder);
}
/// \brief Checks that a compound statement contains a specific number of
@@ -2367,11 +2436,9 @@ equals(const ValueT &Value) {
/// \code
/// !(a || b)
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<BinaryOperator, NodeType>::value) ||
- (llvm::is_base_of<UnaryOperator, NodeType>::value),
- has_condition_requires_if_statement_or_conditional_operator);
+AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ BinaryOperator, UnaryOperator),
+ std::string, Name) {
return Name == Node.getOpcodeStr(Node.getOpcode());
}
@@ -2493,12 +2560,8 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
/// \endcode
///
/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
-AST_POLYMORPHIC_MATCHER(isDefinition) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<TagDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<FunctionDecl, NodeType>::value),
- is_definition_requires_isThisDeclarationADefinition_method);
+AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3(
+ TagDecl, VarDecl, FunctionDecl)) {
return Node.isThisDeclarationADefinition();
}
@@ -2540,6 +2603,21 @@ AST_MATCHER(CXXMethodDecl, isVirtual) {
return Node.isVirtual();
}
+/// \brief Matches if the given method declaration is const.
+///
+/// Given
+/// \code
+/// struct A {
+/// void foo() const;
+/// void bar();
+/// };
+/// \endcode
+///
+/// methodDecl(isConst()) matches A::foo() but not A::bar()
+AST_MATCHER(CXXMethodDecl, isConst) {
+ return Node.isConst();
+}
+
/// \brief Matches if the given method declaration overrides another method.
///
/// Given
@@ -2672,12 +2750,8 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression,
/// matches \code using X::b \endcode
AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl,
internal::Matcher<UsingShadowDecl>, InnerMatcher) {
- for (UsingDecl::shadow_iterator II = Node.shadow_begin();
- II != Node.shadow_end(); ++II) {
- if (InnerMatcher.matches(**II, Finder, Builder))
- return true;
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.shadow_begin(),
+ Node.shadow_end(), Finder, Builder);
}
/// \brief Matches a using shadow declaration where the target declaration is
@@ -2720,11 +2794,9 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// does not match, as X<A> is an explicit template specialization.
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
- requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+ isTemplateInstantiation,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
Node.getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition);
@@ -2742,11 +2814,9 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
/// matches the specialization A<int>().
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
- requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+ isExplicitTemplateSpecialization,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
}
@@ -2807,7 +2877,9 @@ AST_TYPE_MATCHER(ComplexType, complexType);
/// matches "int b[7]"
///
/// Usable as: Matcher<ArrayType>, Matcher<ComplexType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement);
+AST_TYPELOC_TRAVERSE_MATCHER(
+ hasElementType, getElement,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(ArrayType, ComplexType));
/// \brief Matches C arrays with a specified constant size.
///
@@ -2914,7 +2986,8 @@ AST_TYPE_MATCHER(AtomicType, atomicType);
/// matches "_Atomic(int) i"
///
/// Usable as: Matcher<AtomicType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue);
+AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(AtomicType));
/// \brief Matches types nodes representing C++11 auto types.
///
@@ -2942,7 +3015,8 @@ AST_TYPE_MATCHER(AutoType, autoType);
/// matches "auto a"
///
/// Usable as: Matcher<AutoType>
-AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType);
+AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(AutoType));
/// \brief Matches \c FunctionType nodes.
///
@@ -2979,7 +3053,8 @@ AST_TYPE_MATCHER(ParenType, parenType);
/// \c ptr_to_func but not \c ptr_to_array.
///
/// Usable as: Matcher<ParenType>
-AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType);
+AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(ParenType));
/// \brief Matches block pointer types, i.e. types syntactically represented as
/// "void (^)(int)".
@@ -3073,7 +3148,10 @@ AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType);
///
/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>,
/// Matcher<PointerType>, Matcher<ReferenceType>
-AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee);
+AST_TYPELOC_TRAVERSE_MATCHER(
+ pointee, getPointee,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_4(BlockPointerType, MemberPointerType,
+ PointerType, ReferenceType));
/// \brief Matches typedef types.
///
@@ -3100,6 +3178,16 @@ AST_TYPE_MATCHER(TypedefType, typedefType);
/// instantiation in \c A and the type of the variable declaration in \c B.
AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType);
+/// \brief Matches types nodes representing unary type transformations.
+///
+/// Given:
+/// \code
+/// typedef __underlying_type(T) type;
+/// \endcode
+/// unaryTransformType()
+/// matches "__underlying_type(T)"
+AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType);
+
/// \brief Matches record types (e.g. structs, classes).
///
/// Given
@@ -3331,6 +3419,80 @@ AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, Stmt*, Other, 1) {
/// @}
+/// \brief Matches each case or default statement belonging to the given switch
+/// statement. This matcher may produce multiple matches.
+///
+/// Given
+/// \code
+/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } }
+/// \endcode
+/// switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s")
+/// matches four times, with "c" binding each of "case 1:", "case 2:",
+/// "case 3:" and "case 4:", and "s" respectively binding "switch (1)",
+/// "switch (1)", "switch (2)" and "switch (2)".
+AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
+ InnerMatcher) {
+ BoundNodesTreeBuilder Result;
+ // FIXME: getSwitchCaseList() does not necessarily guarantee a stable
+ // iteration order. We should use the more general iterating matchers once
+ // they are capable of expressing this matcher (for example, it should ignore
+ // case statements belonging to nested switch statements).
+ bool Matched = false;
+ for (const SwitchCase *SC = Node.getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ BoundNodesTreeBuilder CaseBuilder(*Builder);
+ bool CaseMatched = InnerMatcher.matches(*SC, Finder, &CaseBuilder);
+ if (CaseMatched) {
+ Matched = true;
+ Result.addMatch(CaseBuilder);
+ }
+ }
+ *Builder = Result;
+ return Matched;
+}
+
+/// \brief Matches each constructor initializer in a constructor definition.
+///
+/// Given
+/// \code
+/// class A { A() : i(42), j(42) {} int i; int j; };
+/// \endcode
+/// constructorDecl(forEachConstructorInitializer(forField(decl().bind("x"))))
+/// will trigger two matches, binding for 'i' and 'j' respectively.
+AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
+ internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
+ BoundNodesTreeBuilder Result;
+ bool Matched = false;
+ for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(),
+ E = Node.init_end();
+ I != E; ++I) {
+ BoundNodesTreeBuilder InitBuilder(*Builder);
+ if (InnerMatcher.matches(**I, Finder, &InitBuilder)) {
+ Matched = true;
+ Result.addMatch(InitBuilder);
+ }
+ }
+ *Builder = Result;
+ return Matched;
+}
+
+/// \brief If the given case statement does not use the GNU case range
+/// extension, matches the constant given in the statement.
+///
+/// Given
+/// \code
+/// switch (1) { case 1: case 1+1: case 3 ... 4: ; }
+/// \endcode
+/// caseStmt(hasCaseConstant(integerLiteral()))
+/// matches "case 1:"
+AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
+ InnerMatcher) {
+ if (Node.getRHS())
+ return false;
+
+ return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
+}
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 30691ad8f912..69cee2eb5dfd 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -36,12 +36,13 @@
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
#include "clang/AST/ASTTypeTraits.h"
-#include "clang/AST/DeclCXX.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/AST/Type.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/VariadicFunction.h"
#include "llvm/Support/type_traits.h"
#include <map>
@@ -60,7 +61,6 @@ class BoundNodes;
namespace internal {
-class BoundNodesTreeBuilder;
/// \brief Internal version of BoundNodes. Holds all the bound nodes.
class BoundNodesMap {
public:
@@ -71,9 +71,6 @@ public:
void addNode(StringRef ID, const T* Node) {
NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node);
}
- void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) {
- NodeMap[ID] = Node;
- }
/// \brief Returns the AST node bound to \c ID.
///
@@ -88,29 +85,39 @@ public:
return It->second.get<T>();
}
- /// \brief Copies all ID/Node pairs to BoundNodesTreeBuilder \c Builder.
- void copyTo(BoundNodesTreeBuilder *Builder) const;
+ ast_type_traits::DynTypedNode getNode(StringRef ID) const {
+ IDToNodeMap::const_iterator It = NodeMap.find(ID);
+ if (It == NodeMap.end()) {
+ return ast_type_traits::DynTypedNode();
+ }
+ return It->second;
+ }
- /// \brief Copies all ID/Node pairs to BoundNodesMap \c Other.
- void copyTo(BoundNodesMap *Other) const;
+ /// \brief Imposes an order on BoundNodesMaps.
+ bool operator<(const BoundNodesMap &Other) const {
+ return NodeMap < Other.NodeMap;
+ }
-private:
/// \brief A map from IDs to the bound nodes.
+ ///
+ /// Note that we're using std::map here, as for memoization:
+ /// - we need a comparison operator
+ /// - we need an assignment operator
typedef std::map<std::string, ast_type_traits::DynTypedNode> IDToNodeMap;
+ const IDToNodeMap &getMap() const {
+ return NodeMap;
+ }
+
+private:
IDToNodeMap NodeMap;
};
-/// \brief A tree of bound nodes in match results.
-///
-/// If a match can contain multiple matches on the same node with different
-/// matching subexpressions, BoundNodesTree contains a branch for each of
-/// those matching subexpressions.
+/// \brief Creates BoundNodesTree objects.
///
-/// BoundNodesTree's are created during the matching process; when a match
-/// is found, we iterate over the tree and create a BoundNodes object containing
-/// the union of all bound nodes on the path from the root to a each leaf.
-class BoundNodesTree {
+/// The tree builder is used during the matching process to insert the bound
+/// nodes from the Id matcher.
+class BoundNodesTreeBuilder {
public:
/// \brief A visitor interface to visit all BoundNodes results for a
/// BoundNodesTree.
@@ -124,63 +131,36 @@ public:
virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
};
- BoundNodesTree();
-
- /// \brief Create a BoundNodesTree from pre-filled maps of bindings.
- BoundNodesTree(const BoundNodesMap& Bindings,
- const std::vector<BoundNodesTree> RecursiveBindings);
+ /// \brief Add a binding from an id to a node.
+ template <typename T> void setBinding(const std::string &Id, const T *Node) {
+ if (Bindings.empty())
+ Bindings.push_back(BoundNodesMap());
+ for (unsigned i = 0, e = Bindings.size(); i != e; ++i)
+ Bindings[i].addNode(Id, Node);
+ }
- /// \brief Adds all bound nodes to \c Builder.
- void copyTo(BoundNodesTreeBuilder* Builder) const;
+ /// \brief Adds a branch in the tree.
+ void addMatch(const BoundNodesTreeBuilder &Bindings);
/// \brief Visits all matches that this BoundNodesTree represents.
///
/// The ownership of 'ResultVisitor' remains at the caller.
void visitMatches(Visitor* ResultVisitor);
-private:
- void visitMatchesRecursively(
- Visitor* ResultVistior,
- const BoundNodesMap& AggregatedBindings);
-
- // FIXME: Find out whether we want to use different data structures here -
- // first benchmarks indicate that it doesn't matter though.
-
- BoundNodesMap Bindings;
-
- std::vector<BoundNodesTree> RecursiveBindings;
-};
-
-/// \brief Creates BoundNodesTree objects.
-///
-/// The tree builder is used during the matching process to insert the bound
-/// nodes from the Id matcher.
-class BoundNodesTreeBuilder {
-public:
- BoundNodesTreeBuilder();
-
- /// \brief Add a binding from an id to a node.
- template <typename T>
- void setBinding(const std::string &Id, const T *Node) {
- Bindings.addNode(Id, Node);
- }
- void setBinding(const std::string &Id, ast_type_traits::DynTypedNode Node) {
- Bindings.addNode(Id, Node);
+ template <typename ExcludePredicate>
+ bool removeBindings(const ExcludePredicate &Predicate) {
+ Bindings.erase(std::remove_if(Bindings.begin(), Bindings.end(), Predicate),
+ Bindings.end());
+ return !Bindings.empty();
}
- /// \brief Adds a branch in the tree.
- void addMatch(const BoundNodesTree& Bindings);
-
- /// \brief Returns a BoundNodes object containing all current bindings.
- BoundNodesTree build() const;
+ /// \brief Imposes an order on BoundNodesTreeBuilders.
+ bool operator<(const BoundNodesTreeBuilder &Other) const {
+ return Bindings < Other.Bindings;
+ }
private:
- BoundNodesTreeBuilder(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION;
- void operator=(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION;
-
- BoundNodesMap Bindings;
-
- std::vector<BoundNodesTree> RecursiveBindings;
+ SmallVector<BoundNodesMap, 16> Bindings;
};
class ASTMatchFinder;
@@ -225,24 +205,6 @@ private:
}
};
-/// \brief Base class for all matchers that works on a \c DynTypedNode.
-///
-/// Matcher implementations will check whether the \c DynTypedNode is
-/// convertible into the respecitve types and then do the actual match
-/// on the actual node, or return false if it is not convertible.
-class DynTypedMatcher {
-public:
- virtual ~DynTypedMatcher() {}
-
- /// \brief Returns true if the matcher matches the given \c DynNode.
- virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const = 0;
-
- /// \brief Returns a unique ID for the matcher.
- virtual uint64_t getID() const = 0;
-};
-
/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@@ -252,7 +214,7 @@ public:
/// operator rather than a type hierarchy to be able to templatize the
/// type hierarchy instead of spelling it out.
template <typename T>
-class Matcher : public DynTypedMatcher {
+class Matcher {
public:
/// \brief Takes ownership of the provided implementation pointer.
explicit Matcher(MatcherInterface<T> *Implementation)
@@ -282,7 +244,13 @@ public:
bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return Implementation->matches(Node, Finder, Builder);
+ if (Implementation->matches(Node, Finder, Builder))
+ return true;
+ // Delete all bindings when a matcher does not match.
+ // This prevents unexpected exposure of bound nodes in unmatches
+ // branches of the match tree.
+ *Builder = BoundNodesTreeBuilder();
+ return false;
}
/// \brief Returns an ID that uniquely identifies the matcher.
@@ -292,15 +260,6 @@ public:
return reinterpret_cast<uint64_t>(Implementation.getPtr());
}
- /// \brief Returns whether the matcher matches on the given \c DynNode.
- virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- const T *Node = DynNode.get<T>();
- if (!Node) return false;
- return matches(*Node, Finder, Builder);
- }
-
/// \brief Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
///
@@ -353,6 +312,217 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
return Matcher<T>(Implementation);
}
+template <typename T> class BindableMatcher;
+
+/// \brief Matcher that works on a \c DynTypedNode.
+///
+/// It is constructed from a \c Matcher<T> object and redirects most calls to
+/// underlying matcher.
+/// It checks whether the \c DynTypedNode is convertible into the type of the
+/// underlying matcher and then do the actual match on the actual node, or
+/// return false if it is not convertible.
+class DynTypedMatcher {
+public:
+ /// \brief Construct from a \c Matcher<T>. Copies the matcher.
+ template <typename T> inline DynTypedMatcher(const Matcher<T> &M);
+
+ /// \brief Construct from a bindable \c Matcher<T>. Copies the matcher.
+ ///
+ /// This version enables \c tryBind() on the \c DynTypedMatcher.
+ template <typename T> inline DynTypedMatcher(const BindableMatcher<T> &M);
+
+ /// \brief Returns true if the matcher matches the given \c DynNode.
+ bool matches(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const {
+ return Storage->matches(DynNode, Finder, Builder);
+ }
+
+ /// \brief Bind the specified \p ID to the matcher.
+ /// \return A new matcher with the \p ID bound to it if this matcher supports
+ /// binding. Otherwise, returns an empty \c Optional<>.
+ llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const {
+ return Storage->tryBind(ID);
+ }
+
+ /// \brief Returns a unique \p ID for the matcher.
+ uint64_t getID() const { return Storage->getID(); }
+
+ /// \brief Returns the type this matcher works on.
+ ///
+ /// \c matches() will always return false unless the node passed is of this
+ /// or a derived type.
+ ast_type_traits::ASTNodeKind getSupportedKind() const {
+ return Storage->getSupportedKind();
+ }
+
+ /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
+ /// to a \c Matcher<T>.
+ ///
+ /// This method verifies that the underlying matcher in \c Other can process
+ /// nodes of types T.
+ template <typename T> bool canConvertTo() const {
+ return getSupportedKind().isBaseOf(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ }
+
+ /// \brief Construct a \c Matcher<T> interface around the dynamic matcher.
+ ///
+ /// This method asserts that \c canConvertTo() is \c true. Callers
+ /// should call \c canConvertTo() first to make sure that \c this is
+ /// compatible with T.
+ template <typename T> Matcher<T> convertTo() const {
+ assert(canConvertTo<T>());
+ return unconditionalConvertTo<T>();
+ }
+
+ /// \brief Same as \c convertTo(), but does not check that the underlying
+ /// matcher can handle a value of T.
+ ///
+ /// If it is not compatible, then this matcher will never match anything.
+ template <typename T> Matcher<T> unconditionalConvertTo() const {
+ return Matcher<T>(new WrappedMatcher<T>(*this));
+ }
+
+private:
+ class MatcherStorage : public RefCountedBaseVPTR {
+ public:
+ MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID)
+ : SupportedKind(SupportedKind), ID(ID) {}
+ virtual ~MatcherStorage();
+
+ virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const = 0;
+
+ virtual llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const = 0;
+
+ ast_type_traits::ASTNodeKind getSupportedKind() const {
+ return SupportedKind;
+ }
+
+ uint64_t getID() const { return ID; }
+
+ private:
+ const ast_type_traits::ASTNodeKind SupportedKind;
+ const uint64_t ID;
+ };
+
+ /// \brief Typed implementation of \c MatcherStorage.
+ template <typename T> class TypedMatcherStorage;
+
+ /// \brief Simple MatcherInterface<T> wrapper around a DynTypedMatcher.
+ template <typename T> class WrappedMatcher;
+
+ IntrusiveRefCntPtr<const MatcherStorage> Storage;
+};
+
+template <typename T>
+class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage {
+public:
+ TypedMatcherStorage(const Matcher<T> &Other, bool AllowBind)
+ : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ Other.getID()),
+ InnerMatcher(Other), AllowBind(AllowBind) {}
+
+ bool matches(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const
+ LLVM_OVERRIDE {
+ if (const T *Node = DynNode.get<T>()) {
+ return InnerMatcher.matches(*Node, Finder, Builder);
+ }
+ return false;
+ }
+
+ llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const LLVM_OVERRIDE {
+ if (!AllowBind)
+ return llvm::Optional<DynTypedMatcher>();
+ return DynTypedMatcher(BindableMatcher<T>(InnerMatcher).bind(ID));
+ }
+
+private:
+ const Matcher<T> InnerMatcher;
+ const bool AllowBind;
+};
+
+template <typename T>
+inline DynTypedMatcher::DynTypedMatcher(const Matcher<T> &M)
+ : Storage(new TypedMatcherStorage<T>(M, false)) {}
+
+template <typename T>
+inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M)
+ : Storage(new TypedMatcherStorage<T>(M, true)) {}
+
+template <typename T>
+class DynTypedMatcher::WrappedMatcher : public MatcherInterface<T> {
+public:
+ explicit WrappedMatcher(const DynTypedMatcher &Matcher) : Inner(Matcher) {}
+ virtual ~WrappedMatcher() {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return Inner.matches(ast_type_traits::DynTypedNode::create(Node), Finder,
+ Builder);
+ }
+
+private:
+ const DynTypedMatcher Inner;
+};
+
+/// \brief Specialization of the conversion functions for QualType.
+///
+/// These specializations provide the Matcher<Type>->Matcher<QualType>
+/// conversion that the static API does.
+template <> inline bool DynTypedMatcher::canConvertTo<QualType>() const {
+ const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
+ return SourceKind.isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<Type>()) ||
+ SourceKind.isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>());
+}
+
+template <>
+inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
+ assert(canConvertTo<QualType>());
+ const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
+ if (SourceKind.isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<Type>())) {
+ // We support implicit conversion from Matcher<Type> to Matcher<QualType>
+ return unconditionalConvertTo<Type>();
+ }
+ return unconditionalConvertTo<QualType>();
+}
+
+/// \brief Finds the first node in a range that matches the given matcher.
+template <typename MatcherT, typename IteratorT>
+bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
+ IteratorT End, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) {
+ for (IteratorT I = Start; I != End; ++I) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(*I, Finder, &Result)) {
+ *Builder = Result;
+ return true;
+ }
+ }
+ return false;
+}
+
+/// \brief Finds the first node in a pointer range that matches the given
+/// matcher.
+template <typename MatcherT, typename IteratorT>
+bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
+ IteratorT End, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) {
+ for (IteratorT I = Start; I != End; ++I) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(**I, Finder, &Result)) {
+ *Builder = Result;
+ return true;
+ }
+ }
+ return false;
+}
+
/// \brief Metafunction to determine if type T has a member called getDecl.
template <typename T> struct has_getDecl {
struct Default { int getDecl; };
@@ -632,6 +802,94 @@ protected:
AncestorMatchMode MatchMode) = 0;
};
+/// \brief A type-list implementation.
+///
+/// A list is declared as a tree of type list nodes, where the leafs are the
+/// types.
+/// However, it is used as a "linked list" of types, by using the ::head and
+/// ::tail typedefs.
+/// Each node supports up to 4 children (instead of just 2) to reduce the
+/// nesting required by large lists.
+template <typename T1 = void, typename T2 = void, typename T3 = void,
+ typename T4 = void>
+struct TypeList {
+ /// \brief Implementation detail. Combined with the specializations below,
+ /// this typedef allows for flattening of nested structures.
+ typedef TypeList<T1, T2, T3, T4> self;
+
+ /// \brief The first type on the list.
+ typedef T1 head;
+
+ /// \brief A sub list with the tail. ie everything but the head.
+ ///
+ /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
+ /// end of the list.
+ typedef typename TypeList<T2, T3, T4>::self tail;
+};
+
+/// \brief Template specialization to allow nested lists.
+///
+/// First element is a typelist. Pop its first element.
+template <typename Sub1, typename Sub2, typename Sub3, typename Sub4,
+ typename T2, typename T3, typename T4>
+struct TypeList<TypeList<Sub1, Sub2, Sub3, Sub4>, T2, T3,
+ T4> : public TypeList<Sub1,
+ typename TypeList<Sub2, Sub3, Sub4>::self,
+ typename TypeList<T2, T3, T4>::self> {};
+
+/// \brief Template specialization to allow nested lists.
+///
+/// First element is an empty typelist. Skip it.
+template <typename T2, typename T3, typename T4>
+struct TypeList<TypeList<>, T2, T3, T4> : public TypeList<T2, T3, T4> {
+};
+
+/// \brief The empty type list.
+typedef TypeList<> EmptyTypeList;
+
+/// \brief Helper meta-function to determine if some type \c T is present or
+/// a parent type in the list.
+template <typename AnyTypeList, typename T>
+struct TypeListContainsSuperOf {
+ static const bool value =
+ llvm::is_base_of<typename AnyTypeList::head, T>::value ||
+ TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
+};
+template <typename T>
+struct TypeListContainsSuperOf<EmptyTypeList, T> {
+ static const bool value = false;
+};
+
+/// \brief A "type list" that contains all types.
+///
+/// Useful for matchers like \c anything and \c unless.
+typedef TypeList<
+ TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc>,
+ TypeList<QualType, Type, TypeLoc, CXXCtorInitializer> > AllNodeBaseTypes;
+
+/// \brief Helper meta-function to extract the argument out of a function of
+/// type void(Arg).
+///
+/// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details.
+template <class T> struct ExtractFunctionArgMeta;
+template <class T> struct ExtractFunctionArgMeta<void(T)> {
+ typedef T type;
+};
+
+/// \brief Default type lists for ArgumentAdaptingMatcher matchers.
+typedef AllNodeBaseTypes AdaptativeDefaultFromTypes;
+typedef TypeList<TypeList<Decl, Stmt, NestedNameSpecifier>,
+ TypeList<NestedNameSpecifierLoc, TypeLoc, QualType> >
+AdaptativeDefaultToTypes;
+
+/// \brief All types that are supported by HasDeclarationMatcher above.
+typedef TypeList<TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType>,
+ TypeList<InjectedClassNameType, LabelStmt, MemberExpr>,
+ TypeList<QualType, RecordType, TagType>,
+ TypeList<TemplateSpecializationType, TemplateTypeParmType,
+ TypedefType, UnresolvedUsingType> >
+HasDeclarationSupportedTypes;
+
/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
/// "adapting" a \c To into a \c T.
///
@@ -646,19 +904,33 @@ protected:
/// If a matcher does not need knowledge about the inner type, prefer to use
/// PolymorphicMatcherWithParam1.
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
- typename T>
-class ArgumentAdaptingMatcher {
-public:
- explicit ArgumentAdaptingMatcher(const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
+ typename FromTypes = AdaptativeDefaultFromTypes,
+ typename ToTypes = AdaptativeDefaultToTypes>
+struct ArgumentAdaptingMatcherFunc {
+ template <typename T> class Adaptor {
+ public:
+ explicit Adaptor(const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
- template <typename To>
- operator Matcher<To>() const {
- return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ typedef ToTypes ReturnTypes;
+
+ template <typename To> operator Matcher<To>() const {
+ return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ }
+
+ private:
+ const Matcher<T> InnerMatcher;
+ };
+
+ template <typename T>
+ static Adaptor<T> create(const Matcher<T> &InnerMatcher) {
+ return Adaptor<T>(InnerMatcher);
}
-private:
- const Matcher<T> InnerMatcher;
+ template <typename T>
+ Adaptor<T> operator()(const Matcher<T> &InnerMatcher) const {
+ return create(InnerMatcher);
+ }
};
/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
@@ -673,24 +945,33 @@ private:
/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42)
/// creates an object that can be used as a Matcher<T> for any type T
/// where a ValueEqualsMatcher<T, int>(42) can be constructed.
-template <template <typename T> class MatcherT>
+template <template <typename T> class MatcherT,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam0 {
public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T>());
}
};
template <template <typename T, typename P1> class MatcherT,
- typename P1>
+ typename P1,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam1 {
public:
explicit PolymorphicMatcherWithParam1(const P1 &Param1)
: Param1(Param1) {}
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T, P1>(Param1));
}
@@ -699,14 +980,19 @@ private:
};
template <template <typename T, typename P1, typename P2> class MatcherT,
- typename P1, typename P2>
+ typename P1, typename P2,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam2 {
public:
PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
: Param1(Param1), Param2(Param2) {}
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
}
@@ -737,27 +1023,6 @@ public:
}
};
-/// \brief Provides a MatcherInterface<T> for a Matcher<To> that matches if T is
-/// dyn_cast'able into To and the given Matcher<To> matches on the dyn_cast'ed
-/// node.
-template <typename T, typename To>
-class DynCastMatcher : public MatcherInterface<T> {
-public:
- explicit DynCastMatcher(const Matcher<To> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
-
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- const To *InnerMatchValue = dyn_cast<To>(&Node);
- return InnerMatchValue != NULL &&
- InnerMatcher.matches(*InnerMatchValue, Finder, Builder);
- }
-
-private:
- const Matcher<To> InnerMatcher;
-};
-
/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the matched node
/// to an ID if the inner matcher matches on the node.
template <typename T>
@@ -790,7 +1055,8 @@ private:
template <typename T>
class BindableMatcher : public Matcher<T> {
public:
- BindableMatcher(MatcherInterface<T> *Implementation)
+ explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
+ explicit BindableMatcher(MatcherInterface<T> *Implementation)
: Matcher<T>(Implementation) {}
/// \brief Returns a matcher that will bind the matched node on a match.
@@ -867,108 +1133,172 @@ public:
virtual bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return !InnerMatcher.matches(Node, Finder, Builder);
+ // The 'unless' matcher will always discard the result:
+ // If the inner matcher doesn't match, unless returns true,
+ // but the inner matcher cannot have bound anything.
+ // If the inner matcher matches, the result is false, and
+ // any possible binding will be discarded.
+ // We still need to hand in all the bound nodes up to this
+ // point so the inner matcher can depend on bound nodes,
+ // and we need to actively discard the bound nodes, otherwise
+ // the inner matcher will reset the bound nodes if it doesn't
+ // match, but this would be inversed by 'unless'.
+ BoundNodesTreeBuilder Discard(*Builder);
+ return !InnerMatcher.matches(Node, Finder, &Discard);
}
private:
const Matcher<T> InnerMatcher;
};
-/// \brief Matches nodes of type T for which both provided matchers match.
-///
-/// Type arguments MatcherT1 and MatcherT2 are required by
-/// PolymorphicMatcherWithParam2 but not actually used. They will
-/// always be instantiated with types convertible to Matcher<T>.
-template <typename T, typename MatcherT1, typename MatcherT2>
-class AllOfMatcher : public MatcherInterface<T> {
+/// \brief VariadicOperatorMatcher related types.
+/// @{
+
+/// \brief Function signature for any variadic operator. It takes the inner
+/// matchers as an array of DynTypedMatcher.
+typedef bool (*VariadicOperatorFunction)(
+ const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
+
+/// \brief \c MatcherInterface<T> implementation for an variadic operator.
+template <typename T>
+class VariadicOperatorMatcherInterface : public MatcherInterface<T> {
public:
- AllOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2)
- : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
+ VariadicOperatorMatcherInterface(VariadicOperatorFunction Func,
+ ArrayRef<const Matcher<T> *> InputMatchers)
+ : Func(Func) {
+ for (size_t i = 0, e = InputMatchers.size(); i != e; ++i) {
+ InnerMatchers.push_back(*InputMatchers[i]);
+ }
+ }
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
+ virtual bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return InnerMatcher1.matches(Node, Finder, Builder) &&
- InnerMatcher2.matches(Node, Finder, Builder);
+ return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder,
+ InnerMatchers);
}
private:
- const Matcher<T> InnerMatcher1;
- const Matcher<T> InnerMatcher2;
+ const VariadicOperatorFunction Func;
+ std::vector<DynTypedMatcher> InnerMatchers;
};
-/// \brief Matches nodes of type T for which at least one of the two provided
-/// matchers matches.
+/// \brief "No argument" placeholder to use as template paratemers.
+struct VariadicOperatorNoArg {};
+
+/// \brief Polymorphic matcher object that uses a \c VariadicOperatorFunction
+/// operator.
///
-/// Type arguments MatcherT1 and MatcherT2 are
-/// required by PolymorphicMatcherWithParam2 but not actually
-/// used. They will always be instantiated with types convertible to
-/// Matcher<T>.
-template <typename T, typename MatcherT1, typename MatcherT2>
-class EachOfMatcher : public MatcherInterface<T> {
+/// Input matchers can have any type (including other polymorphic matcher
+/// types), and the actual Matcher<T> is generated on demand with an implicit
+/// coversion operator.
+template <typename P1, typename P2,
+ typename P3 = VariadicOperatorNoArg,
+ typename P4 = VariadicOperatorNoArg,
+ typename P5 = VariadicOperatorNoArg>
+class VariadicOperatorMatcher {
public:
- EachOfMatcher(const Matcher<T> &InnerMatcher1,
- const Matcher<T> &InnerMatcher2)
- : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {
+ VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1,
+ const P2 &Param2,
+ const P3 &Param3 = VariadicOperatorNoArg(),
+ const P4 &Param4 = VariadicOperatorNoArg(),
+ const P5 &Param5 = VariadicOperatorNoArg())
+ : Func(Func), Param1(Param1), Param2(Param2), Param3(Param3),
+ Param4(Param4), Param5(Param5) {}
+
+ template <typename T> operator Matcher<T>() const {
+ Matcher<T> *Array[5];
+ size_t Size = 0;
+
+ addMatcher<T>(Param1, Array, Size);
+ addMatcher<T>(Param2, Array, Size);
+ addMatcher<T>(Param3, Array, Size);
+ addMatcher<T>(Param4, Array, Size);
+ addMatcher<T>(Param5, Array, Size);
+ Matcher<T> Result(new VariadicOperatorMatcherInterface<T>(
+ Func, ArrayRef<const Matcher<T> *>(Array, Size)));
+ for (size_t i = 0, e = Size; i != e; ++i) delete Array[i];
+ return Result;
}
- virtual bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- BoundNodesTreeBuilder Builder1;
- bool Matched1 = InnerMatcher1.matches(Node, Finder, &Builder1);
- if (Matched1)
- Builder->addMatch(Builder1.build());
-
- BoundNodesTreeBuilder Builder2;
- bool Matched2 = InnerMatcher2.matches(Node, Finder, &Builder2);
- if (Matched2)
- Builder->addMatch(Builder2.build());
-
- return Matched1 || Matched2;
+private:
+ template <typename T>
+ static void addMatcher(const Matcher<T> &M, Matcher<T> **Array,
+ size_t &Size) {
+ Array[Size++] = new Matcher<T>(M);
}
-private:
- const Matcher<T> InnerMatcher1;
- const Matcher<T> InnerMatcher2;
+ /// \brief Overload to ignore \c VariadicOperatorNoArg arguments.
+ template <typename T>
+ static void addMatcher(VariadicOperatorNoArg, Matcher<T> **Array,
+ size_t &Size) {}
+
+ const VariadicOperatorFunction Func;
+ const P1 Param1;
+ const P2 Param2;
+ const P3 Param3;
+ const P4 Param4;
+ const P5 Param5;
};
-/// \brief Matches nodes of type T for which at least one of the two provided
-/// matchers matches.
+/// \brief Overloaded function object to generate VariadicOperatorMatcher
+/// objects from arbitrary matchers.
///
-/// Type arguments MatcherT1 and MatcherT2 are
-/// required by PolymorphicMatcherWithParam2 but not actually
-/// used. They will always be instantiated with types convertible to
-/// Matcher<T>.
-template <typename T, typename MatcherT1, typename MatcherT2>
-class AnyOfMatcher : public MatcherInterface<T> {
-public:
- AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2)
- : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
+/// It supports 2-5 argument overloaded operator(). More can be added if needed.
+struct VariadicOperatorMatcherFunc {
+ VariadicOperatorFunction Func;
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return InnerMatcher1.matches(Node, Finder, Builder) ||
- InnerMatcher2.matches(Node, Finder, Builder);
+ template <typename M1, typename M2>
+ VariadicOperatorMatcher<M1, M2> operator()(const M1 &P1, const M2 &P2) const {
+ return VariadicOperatorMatcher<M1, M2>(Func, P1, P2);
+ }
+ template <typename M1, typename M2, typename M3>
+ VariadicOperatorMatcher<M1, M2, M3> operator()(const M1 &P1, const M2 &P2,
+ const M3 &P3) const {
+ return VariadicOperatorMatcher<M1, M2, M3>(Func, P1, P2, P3);
+ }
+ template <typename M1, typename M2, typename M3, typename M4>
+ VariadicOperatorMatcher<M1, M2, M3, M4>
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4>(Func, P1, P2, P3, P4);
+ }
+ template <typename M1, typename M2, typename M3, typename M4, typename M5>
+ VariadicOperatorMatcher<M1, M2, M3, M4, M5>
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
+ const M5 &P5) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Func, P1, P2, P3, P4,
+ P5);
}
-
-private:
- const Matcher<T> InnerMatcher1;
- const Matcher<T> InnerMatcher2;
};
+/// @}
+
+/// \brief Matches nodes for which all provided matchers match.
+bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
+
+/// \brief Matches nodes for which at least one of the provided matchers
+/// matches, but doesn't stop at the first match.
+bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
+
+/// \brief Matches nodes for which at least one of the provided matchers
+/// matches.
+bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
+
/// \brief Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
- if (InnerMatchers.empty())
- return BindableMatcher<T>(new TrueMatcher<T>);
- MatcherInterface<T> *InnerMatcher = new TrueMatcher<T>;
- for (int i = InnerMatchers.size() - 1; i >= 0; --i) {
- InnerMatcher = new AllOfMatcher<T, Matcher<T>, Matcher<T> >(
- *InnerMatchers[i], makeMatcher(InnerMatcher));
- }
- return BindableMatcher<T>(InnerMatcher);
+ return BindableMatcher<T>(new VariadicOperatorMatcherInterface<T>(
+ AllOfVariadicOperator, InnerMatchers));
}
/// \brief Creates a Matcher<T> that matches if
@@ -980,8 +1310,8 @@ BindableMatcher<T> makeAllOfComposite(
template<typename T, typename InnerT>
BindableMatcher<T> makeDynCastAllOfComposite(
ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(
- makeAllOfComposite(InnerMatchers)));
+ return BindableMatcher<T>(DynTypedMatcher(makeAllOfComposite(InnerMatchers))
+ .unconditionalConvertTo<T>());
}
/// \brief Matches nodes of type T that have at least one descendant node of
@@ -1233,9 +1563,53 @@ private:
TypeLoc (T::*TraverseFunction)() const;
};
-template <typename T, typename InnerT>
-T makeTypeAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return T(makeAllOfComposite<InnerT>(InnerMatchers));
+/// \brief Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where
+/// \c OuterT is any type that is supported by \c Getter.
+///
+/// \code Getter<OuterT>::value() \endcode returns a
+/// \code InnerTBase (OuterT::*)() \endcode, which is used to adapt a \c OuterT
+/// object into a \c InnerT
+template <typename InnerTBase,
+ template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl,
+ typename ReturnTypesF>
+class TypeTraversePolymorphicMatcher {
+private:
+ typedef TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF> Self;
+ static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers);
+
+public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
+ explicit TypeTraversePolymorphicMatcher(
+ ArrayRef<const Matcher<InnerTBase> *> InnerMatchers)
+ : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
+
+ template <typename OuterT> operator Matcher<OuterT>() const {
+ return Matcher<OuterT>(
+ new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
+ }
+
+ struct Func : public llvm::VariadicFunction<Self, Matcher<InnerTBase>,
+ &Self::create> {
+ Func() {}
+ };
+
+private:
+ const Matcher<InnerTBase> InnerMatcher;
+};
+
+// Define the create() method out of line to silence a GCC warning about
+// the struct "Func" having greater visibility than its base, which comes from
+// using the flag -fvisibility-inlines-hidden.
+template <typename InnerTBase, template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl, typename ReturnTypesF>
+TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
+TypeTraversePolymorphicMatcher<
+ InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF>::create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) {
+ return Self(InnerMatchers);
}
} // end namespace internal
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index f5ca26bca73c..b5d530312515 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -49,23 +49,19 @@
///
/// The code should return true if 'Node' matches.
#define AST_MATCHER(Type, DefineMatcher) \
- AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0)
-
-#define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId) \
namespace internal { \
- class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<Type> { \
+ class matcher_##DefineMatcher##Matcher : public MatcherInterface<Type> { \
public: \
- explicit matcher_##DefineMatcher##OverloadId##Matcher() {} \
+ explicit matcher_##DefineMatcher##Matcher() {} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher() { \
return internal::makeMatcher( \
- new internal::matcher_##DefineMatcher##OverloadId##Matcher()); \
+ new internal::matcher_##DefineMatcher##Matcher()); \
} \
- inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
+ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
@@ -93,10 +89,10 @@
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
const ParamType &A##Param) \
- : Param(A##Param) { \
- } \
+ : Param(A##Param) {} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType Param; \
}; \
@@ -105,6 +101,8 @@
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
} \
+ typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType &Param); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
@@ -136,53 +134,70 @@
public: \
matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
const ParamType2 &A##Param2) \
- : Param1(A##Param1), Param2(A##Param2) { \
- } \
+ : Param1(A##Param1), Param2(A##Param2) {} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
}; \
} \
- inline internal::Matcher<Type> \
- DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
+ inline internal::Matcher<Type> DefineMatcher(const ParamType1 &Param1, \
+ const ParamType2 &Param2) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
Param2)); \
} \
+ typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType1 &Param1, const ParamType2 &Param2); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
+/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
+/// macros.
+///
+/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
+/// will look at that as two arguments. However, you can pass
+/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
+/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
+/// extract the TypeList object.
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_1(t1) void(internal::TypeList<t1>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2) \
+ void(internal::TypeList<t1, t2>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3) \
+ void(internal::TypeList<t1, t2, t3>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_4(t1, t2, t3, t4) \
+ void(internal::TypeList<t1, t2, t3, t4>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_5(t1, t2, t3, t4, t5) \
+ void(internal::TypeList<t1, t2, t3, internal::TypeList<t4, t5> >)
+
/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
/// from the calling context.
-#define AST_POLYMORPHIC_MATCHER(DefineMatcher) \
- AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0)
-
-#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId) \
+#define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \
namespace internal { \
template <typename NodeType> \
- class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<NodeType> { \
+ class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \
public: \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
}; \
} \
inline internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \
+ DefineMatcher() { \
return internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher>(); \
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \
} \
template <typename NodeType> \
- bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
- NodeType>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+ bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \
+ const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const
/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that is
@@ -193,11 +208,13 @@
/// of the matcher Matcher<NodeType> returned by the function matcher().
///
/// FIXME: Pull out common code with above macro?
-#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \
- AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0)
+#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \
+ Param) \
+ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \
+ Param, 0)
-#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, \
- OverloadId) \
+#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType, Param, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT> \
class matcher_##DefineMatcher##OverloadId##Matcher \
@@ -205,21 +222,25 @@
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
const ParamType &A##Param) \
- : Param(A##Param) { \
- } \
+ : Param(A##Param) {} \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType Param; \
}; \
} \
inline internal::PolymorphicMatcherWithParam1< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType> \
- DefineMatcher(const ParamType &Param) { \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF> DefineMatcher(const ParamType &Param) { \
return internal::PolymorphicMatcherWithParam1< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>( \
- Param); \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF>(Param); \
} \
+ typedef internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType &Param); \
template <typename NodeType, typename ParamT> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
@@ -233,13 +254,14 @@
/// The variables are the same as for AST_MATCHER_P2, with the
/// addition of NodeType, which specifies the node type of the matcher
/// Matcher<NodeType> returned by the function DefineMatcher().
-#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2) \
- AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2, 0)
+#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2) \
+ AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2, 0)
-#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2, OverloadId) \
+#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType1, Param1, ParamType2, \
+ Param2, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT1, typename ParamT2> \
class matcher_##DefineMatcher##OverloadId##Matcher \
@@ -247,10 +269,10 @@
public: \
matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
const ParamType2 &A##Param2) \
- : Param1(A##Param1), Param2(A##Param2) { \
- } \
+ : Param1(A##Param1), Param2(A##Param2) {} \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
@@ -258,12 +280,16 @@
} \
inline internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2> \
- DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
+ ParamType2, ReturnTypesF> DefineMatcher(const ParamType1 &Param1, \
+ const ParamType2 &Param2) { \
return internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2>(Param1, Param2); \
+ ParamType2, ReturnTypesF>(Param1, Param2); \
} \
+ typedef internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+ ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType1 &Param1, const ParamType2 &Param2); \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT1, ParamT2>::matches( \
@@ -282,64 +308,29 @@
/// to another.
///
/// For a specific \c SpecificType, the traversal is done using
-/// \c SpecificType::FunctionName. The existance of such a function determines
+/// \c SpecificType::FunctionName. The existence of such a function determines
/// whether a corresponding matcher can be used on \c SpecificType.
-#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \
- class Polymorphic##MatcherName##TypeMatcher { \
- public: \
- Polymorphic##MatcherName##TypeMatcher( \
- const internal::Matcher<QualType> &InnerMatcher) \
- : InnerMatcher(InnerMatcher) { \
- } \
- template <typename T> operator internal:: Matcher< T>() { \
- return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \
- InnerMatcher, &T::FunctionName)); \
- } \
- private: \
- const internal::Matcher<QualType> InnerMatcher; \
- } \
- ; \
- class Variadic##MatcherName##TypeTraverseMatcher \
- : public llvm::VariadicFunction< \
- Polymorphic##MatcherName##TypeMatcher, internal::Matcher<QualType>, \
- internal::makeTypeAllOfComposite< \
- Polymorphic##MatcherName##TypeMatcher, QualType> > { \
- public: \
- Variadic##MatcherName##TypeTraverseMatcher() { \
- } \
+#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeMatcher##MatcherName##Getter { \
+ static QualType (T::*value())() const { return &T::FunctionName; } \
+ }; \
} \
- ; \
- const Variadic##MatcherName##TypeTraverseMatcher MatcherName
+ const internal::TypeTraversePolymorphicMatcher< \
+ QualType, internal::TypeMatcher##MatcherName##Getter, \
+ internal::TypeTraverseMatcher, ReturnTypesF>::Func MatcherName
/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
-#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \
- class Polymorphic##MatcherName##TypeLocMatcher { \
- public: \
- Polymorphic##MatcherName##TypeLocMatcher( \
- const internal::Matcher<TypeLoc> &InnerMatcher) \
- : InnerMatcher(InnerMatcher) { \
- } \
- template <typename T> operator internal:: Matcher< T>() { \
- return internal::Matcher<T>( \
- new internal::TypeLocTraverseMatcher<T>(InnerMatcher, \
- &T::FunctionName##Loc)); \
- } \
- private: \
- const internal::Matcher<TypeLoc> InnerMatcher; \
- } \
- ; \
- class Variadic##MatcherName##TypeLocTraverseMatcher \
- : public llvm::VariadicFunction< \
- Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher<TypeLoc>,\
- internal::makeTypeAllOfComposite< \
- Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \
- public: \
- Variadic##MatcherName##TypeLocTraverseMatcher() { \
- } \
+#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
+ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
+ }; \
} \
- ; \
- const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \
- AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type)
+ const internal::TypeTraversePolymorphicMatcher< \
+ TypeLoc, internal::TypeLocMatcher##MatcherName##Getter, \
+ internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \
+ AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
new file mode 100644
index 000000000000..aec0c0e31ce2
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -0,0 +1,185 @@
+//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Diagnostics class to manage error messages.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+struct SourceLocation {
+ SourceLocation() : Line(), Column() {}
+ unsigned Line;
+ unsigned Column;
+};
+
+struct SourceRange {
+ SourceLocation Start;
+ SourceLocation End;
+};
+
+/// \brief A VariantValue instance annotated with its parser context.
+struct ParserValue {
+ ParserValue() : Text(), Range(), Value() {}
+ StringRef Text;
+ SourceRange Range;
+ VariantValue Value;
+};
+
+/// \brief Helper class to manage error messages.
+class Diagnostics {
+public:
+ /// \brief Parser context types.
+ enum ContextType {
+ CT_MatcherArg = 0,
+ CT_MatcherConstruct = 1
+ };
+
+ /// \brief All errors from the system.
+ enum ErrorType {
+ ET_None = 0,
+
+ ET_RegistryNotFound = 1,
+ ET_RegistryWrongArgCount = 2,
+ ET_RegistryWrongArgType = 3,
+ ET_RegistryNotBindable = 4,
+ ET_RegistryAmbiguousOverload = 5,
+
+ ET_ParserStringError = 100,
+ ET_ParserNoOpenParen = 101,
+ ET_ParserNoCloseParen = 102,
+ ET_ParserNoComma = 103,
+ ET_ParserNoCode = 104,
+ ET_ParserNotAMatcher = 105,
+ ET_ParserInvalidToken = 106,
+ ET_ParserMalformedBindExpr = 107,
+ ET_ParserTrailingCode = 108,
+ ET_ParserUnsignedError = 109,
+ ET_ParserOverloadedType = 110
+ };
+
+ /// \brief Helper stream class.
+ class ArgStream {
+ public:
+ ArgStream(std::vector<std::string> *Out) : Out(Out) {}
+ template <class T> ArgStream &operator<<(const T &Arg) {
+ return operator<<(Twine(Arg));
+ }
+ ArgStream &operator<<(const Twine &Arg);
+
+ private:
+ std::vector<std::string> *Out;
+ };
+
+ /// \brief Class defining a parser context.
+ ///
+ /// Used by the parser to specify (possibly recursive) contexts where the
+ /// parsing/construction can fail. Any error triggered within a context will
+ /// keep information about the context chain.
+ /// This class should be used as a RAII instance in the stack.
+ struct Context {
+ public:
+ /// \brief About to call the constructor for a matcher.
+ enum ConstructMatcherEnum { ConstructMatcher };
+ Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
+ const SourceRange &MatcherRange);
+ /// \brief About to recurse into parsing one argument for a matcher.
+ enum MatcherArgEnum { MatcherArg };
+ Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
+ const SourceRange &MatcherRange, unsigned ArgNumber);
+ ~Context();
+
+ private:
+ Diagnostics *const Error;
+ };
+
+ /// \brief Context for overloaded matcher construction.
+ ///
+ /// This context will take care of merging all errors that happen within it
+ /// as "candidate" overloads for the same matcher.
+ struct OverloadContext {
+ public:
+ OverloadContext(Diagnostics* Error);
+ ~OverloadContext();
+
+ /// \brief Revert all errors that happened within this context.
+ void revertErrors();
+
+ private:
+ Diagnostics *const Error;
+ unsigned BeginIndex;
+ };
+
+ /// \brief Add an error to the diagnostics.
+ ///
+ /// All the context information will be kept on the error message.
+ /// \return a helper class to allow the caller to pass the arguments for the
+ /// error message, using the << operator.
+ ArgStream addError(const SourceRange &Range, ErrorType Error);
+
+ /// \brief Information stored for one frame of the context.
+ struct ContextFrame {
+ ContextType Type;
+ SourceRange Range;
+ std::vector<std::string> Args;
+ };
+
+ /// \brief Information stored for each error found.
+ struct ErrorContent {
+ std::vector<ContextFrame> ContextStack;
+ struct Message {
+ SourceRange Range;
+ ErrorType Type;
+ std::vector<std::string> Args;
+ };
+ std::vector<Message> Messages;
+ };
+ ArrayRef<ErrorContent> errors() const { return Errors; }
+
+ /// \brief Returns a simple string representation of each error.
+ ///
+ /// Each error only shows the error message without any context.
+ void printToStream(llvm::raw_ostream &OS) const;
+ std::string toString() const;
+
+ /// \brief Returns the full string representation of each error.
+ ///
+ /// Each error message contains the full context.
+ void printToStreamFull(llvm::raw_ostream &OS) const;
+ std::string toStringFull() const;
+
+private:
+ /// \brief Helper function used by the constructors of ContextFrame.
+ ArgStream pushContextFrame(ContextType Type, SourceRange Range);
+
+ std::vector<ContextFrame> ContextStack;
+ std::vector<ErrorContent> Errors;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
new file mode 100644
index 000000000000..bb6ac76989d0
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -0,0 +1,151 @@
+//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Simple matcher expression parser.
+///
+/// The parser understands matcher expressions of the form:
+/// MatcherName(Arg0, Arg1, ..., ArgN)
+/// as well as simple types like strings.
+/// The parser does not know how to process the matchers. It delegates this task
+/// to a Sema object received as an argument.
+///
+/// \code
+/// Grammar for the expressions supported:
+/// <Expression> := <Literal> | <MatcherExpression>
+/// <Literal> := <StringLiteral> | <Unsigned>
+/// <StringLiteral> := "quoted string"
+/// <Unsigned> := [0-9]+
+/// <MatcherExpression> := <MatcherName>(<ArgumentList>) |
+/// <MatcherName>(<ArgumentList>).bind(<StringLiteral>)
+/// <MatcherName> := [a-zA-Z]+
+/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
+/// \endcode
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+/// \brief Matcher expression parser.
+class Parser {
+public:
+ /// \brief Interface to connect the parser with the registry and more.
+ ///
+ /// The parser uses the Sema instance passed into
+ /// parseMatcherExpression() to handle all matcher tokens. The simplest
+ /// processor implementation would simply call into the registry to create
+ /// the matchers.
+ /// However, a more complex processor might decide to intercept the matcher
+ /// creation and do some extra work. For example, it could apply some
+ /// transformation to the matcher by adding some id() nodes, or could detect
+ /// specific matcher nodes for more efficient lookup.
+ class Sema {
+ public:
+ virtual ~Sema();
+
+ /// \brief Process a matcher expression.
+ ///
+ /// All the arguments passed here have already been processed.
+ ///
+ /// \param MatcherName The matcher name found by the parser.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param BindID The ID to use to bind the matcher, or a null \c StringRef
+ /// if no ID is specified.
+ ///
+ /// \param Args The argument list for the matcher.
+ ///
+ /// \return The matcher objects constructed by the processor, or a null
+ /// matcher if an error occurred. In that case, \c Error will contain a
+ /// description of the error.
+ virtual VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) = 0;
+ };
+
+ /// \brief Parse a matcher expression, creating matchers from the registry.
+ ///
+ /// This overload creates matchers calling directly into the registry. If the
+ /// caller needs more control over how the matchers are created, then it can
+ /// use the overload below that takes a Sema.
+ ///
+ /// \param MatcherCode The matcher expression to parse.
+ ///
+ /// \return The matcher object constructed, or an empty Optional if an error
+ /// occurred.
+ /// In that case, \c Error will contain a description of the error.
+ /// The caller takes ownership of the DynTypedMatcher object returned.
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error);
+
+ /// \brief Parse a matcher expression.
+ ///
+ /// \param MatcherCode The matcher expression to parse.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers.
+ /// \return The matcher object constructed by the processor, or an empty
+ /// Optional if an error occurred. In that case, \c Error will contain a
+ /// description of the error.
+ /// The caller takes ownership of the DynTypedMatcher object returned.
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error);
+
+ /// \brief Parse an expression, creating matchers from the registry.
+ ///
+ /// Parses any expression supported by this parser. In general, the
+ /// \c parseMatcherExpression function is a better approach to get a matcher
+ /// object.
+ static bool parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error);
+
+ /// \brief Parse an expression.
+ ///
+ /// Parses any expression supported by this parser. In general, the
+ /// \c parseMatcherExpression function is a better approach to get a matcher
+ /// object.
+ static bool parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error);
+
+private:
+ class CodeTokenizer;
+ struct TokenInfo;
+
+ Parser(CodeTokenizer *Tokenizer, Sema *S,
+ Diagnostics *Error);
+
+ bool parseExpressionImpl(VariantValue *Value);
+ bool parseMatcherExpressionImpl(VariantValue *Value);
+
+ CodeTokenizer *const Tokenizer;
+ Sema *const S;
+ Diagnostics *const Error;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
new file mode 100644
index 000000000000..c113c1404ef0
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -0,0 +1,75 @@
+//===--- Registry.h - Matcher registry -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Registry of all known matchers.
+///
+/// The registry provides a generic interface to construct any matcher by name.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+class Registry {
+public:
+ /// \brief Construct a matcher from the registry by name.
+ ///
+ /// Consult the registry of known matchers and construct the appropriate
+ /// matcher by name.
+ ///
+ /// \param MatcherName The name of the matcher to instantiate.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param Args The argument list for the matcher. The number and types of the
+ /// values must be valid for the matcher requested. Otherwise, the function
+ /// will return an error.
+ ///
+ /// \return The matcher object constructed if no error was found.
+ /// A null matcher if the matcher is not found, or if the number of
+ /// arguments or argument types do not match the signature.
+ /// In that case \c Error will contain the description of the error.
+ static VariantMatcher constructMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+ /// \brief Construct a matcher from the registry and bind it.
+ ///
+ /// Similar the \c constructMatcher() above, but it then tries to bind the
+ /// matcher to the specified \c BindID.
+ /// If the matcher is not bindable, it sets an error in \c Error and returns
+ /// a null matcher.
+ static VariantMatcher constructBoundMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+private:
+ Registry() LLVM_DELETED_FUNCTION;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
new file mode 100644
index 000000000000..b9bc017a48c0
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -0,0 +1,261 @@
+//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Polymorphic value type.
+///
+/// Supports all the types required for dynamic Matcher construction.
+/// Used by the registry to construct matchers in a generic way.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+
+#include <vector>
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/type_traits.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+using ast_matchers::internal::DynTypedMatcher;
+
+/// \brief A variant matcher object.
+///
+/// The purpose of this object is to abstract simple and polymorphic matchers
+/// into a single object type.
+/// Polymorphic matchers might be implemented as a list of all the possible
+/// overloads of the matcher. \c VariantMatcher knows how to select the
+/// appropriate overload when needed.
+/// To get a real matcher object out of a \c VariantMatcher you can do:
+/// - getSingleMatcher() which returns a matcher, only if it is not ambiguous
+/// to decide which matcher to return. Eg. it contains only a single
+/// matcher, or a polymorphic one with only one overload.
+/// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
+/// the underlying matcher(s) can unambiguously return a Matcher<T>.
+class VariantMatcher {
+ /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
+ class MatcherOps {
+ public:
+ virtual ~MatcherOps();
+ virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0;
+ virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
+ virtual void constructVariadicOperator(
+ ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> InnerMatchers) = 0;
+ };
+
+ /// \brief Payload interface to be specialized by each matcher type.
+ ///
+ /// It follows a similar interface as VariantMatcher itself.
+ class Payload : public RefCountedBaseVPTR {
+ public:
+ virtual ~Payload();
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
+ virtual std::string getTypeAsString() const = 0;
+ virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
+ };
+
+public:
+ /// \brief A null matcher.
+ VariantMatcher();
+
+ /// \brief Clones the provided matcher.
+ static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
+
+ /// \brief Clones the provided matchers.
+ ///
+ /// They should be the result of a polymorphic matcher.
+ static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers);
+
+ /// \brief Creates a 'variadic' operator matcher.
+ ///
+ /// It will bind to the appropriate type on getTypedMatcher<T>().
+ static VariantMatcher VariadicOperatorMatcher(
+ ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> Args);
+
+ /// \brief Makes the matcher the "null" matcher.
+ void reset();
+
+ /// \brief Whether the matcher is null.
+ bool isNull() const { return !Value; }
+
+ /// \brief Return a single matcher, if there is no ambiguity.
+ ///
+ /// \returns the matcher, if there is only one matcher. An empty Optional, if
+ /// the underlying matcher is a polymorphic matcher with more than one
+ /// representation.
+ llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
+
+ /// \brief Determines if the contained matcher can be converted to
+ /// \c Matcher<T>.
+ ///
+ /// For the Single case, it returns true if it can be converted to
+ /// \c Matcher<T>.
+ /// For the Polymorphic case, it returns true if one, and only one, of the
+ /// overloads can be converted to \c Matcher<T>. If there are more than one
+ /// that can, the result would be ambiguous and false is returned.
+ template <class T>
+ bool hasTypedMatcher() const {
+ TypedMatcherOps<T> Ops;
+ if (Value) Value->makeTypedMatcher(Ops);
+ return Ops.hasMatcher();
+ }
+
+ /// \brief Return this matcher as a \c Matcher<T>.
+ ///
+ /// Handles the different types (Single, Polymorphic) accordingly.
+ /// Asserts that \c hasTypedMatcher<T>() is true.
+ template <class T>
+ ast_matchers::internal::Matcher<T> getTypedMatcher() const {
+ TypedMatcherOps<T> Ops;
+ Value->makeTypedMatcher(Ops);
+ assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
+ return Ops.matcher();
+ }
+
+ /// \brief String representation of the type of the value.
+ ///
+ /// If the underlying matcher is a polymorphic one, the string will show all
+ /// the types.
+ std::string getTypeAsString() const;
+
+private:
+ explicit VariantMatcher(Payload *Value) : Value(Value) {}
+
+ class SinglePayload;
+ class PolymorphicPayload;
+ class VariadicOpPayload;
+
+ template <typename T>
+ class TypedMatcherOps : public MatcherOps {
+ public:
+ typedef ast_matchers::internal::Matcher<T> MatcherT;
+
+ virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const {
+ return Matcher.canConvertTo<T>();
+ }
+
+ virtual void constructFrom(const DynTypedMatcher& Matcher) {
+ Out.reset(new MatcherT(Matcher.convertTo<T>()));
+ }
+
+ virtual void constructVariadicOperator(
+ ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> InnerMatchers) {
+ const size_t NumArgs = InnerMatchers.size();
+ MatcherT **InnerArgs = new MatcherT *[NumArgs]();
+ bool HasError = false;
+ for (size_t i = 0; i != NumArgs; ++i) {
+ // Abort if any of the inner matchers can't be converted to
+ // Matcher<T>.
+ if (!InnerMatchers[i].hasTypedMatcher<T>()) {
+ HasError = true;
+ break;
+ }
+ InnerArgs[i] = new MatcherT(InnerMatchers[i].getTypedMatcher<T>());
+ }
+ if (!HasError) {
+ Out.reset(new MatcherT(
+ new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
+ Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs))));
+ }
+ for (size_t i = 0; i != NumArgs; ++i) {
+ delete InnerArgs[i];
+ }
+ delete[] InnerArgs;
+ }
+
+ bool hasMatcher() const { return Out.get() != NULL; }
+ const MatcherT &matcher() const { return *Out; }
+
+ private:
+ OwningPtr<MatcherT> Out;
+ };
+
+ IntrusiveRefCntPtr<const Payload> Value;
+};
+
+/// \brief Variant value class.
+///
+/// Basically, a tagged union with value type semantics.
+/// It is used by the registry as the return value and argument type for the
+/// matcher factory methods.
+/// It can be constructed from any of the supported types. It supports
+/// copy/assignment.
+///
+/// Supported types:
+/// - \c unsigned
+/// - \c std::string
+/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
+class VariantValue {
+public:
+ VariantValue() : Type(VT_Nothing) {}
+
+ VariantValue(const VariantValue &Other);
+ ~VariantValue();
+ VariantValue &operator=(const VariantValue &Other);
+
+ /// \brief Specific constructors for each supported type.
+ VariantValue(unsigned Unsigned);
+ VariantValue(const std::string &String);
+ VariantValue(const VariantMatcher &Matchers);
+
+ /// \brief Unsigned value functions.
+ bool isUnsigned() const;
+ unsigned getUnsigned() const;
+ void setUnsigned(unsigned Unsigned);
+
+ /// \brief String value functions.
+ bool isString() const;
+ const std::string &getString() const;
+ void setString(const std::string &String);
+
+ /// \brief Matcher value functions.
+ bool isMatcher() const;
+ const VariantMatcher &getMatcher() const;
+ void setMatcher(const VariantMatcher &Matcher);
+
+ /// \brief String representation of the type of the value.
+ std::string getTypeAsString() const;
+
+private:
+ void reset();
+
+ /// \brief All supported value types.
+ enum ValueType {
+ VT_Nothing,
+ VT_Unsigned,
+ VT_String,
+ VT_Matcher
+ };
+
+ /// \brief All supported value types.
+ union AllValues {
+ unsigned Unsigned;
+ std::string *String;
+ VariantMatcher *Matcher;
+ };
+
+ ValueType Type;
+ AllValues Value;
+};
+
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
new file mode 100644
index 000000000000..23a094a79643
--- /dev/null
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -0,0 +1,264 @@
+//===- Consumed.h ----------------------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A intra-procedural analysis for checking consumed properties. This is based,
+// in part, on research on linear types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CONSUMED_H
+#define LLVM_CLANG_CONSUMED_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+namespace consumed {
+
+ enum ConsumedState {
+ // No state information for the given variable.
+ CS_None,
+
+ CS_Unknown,
+ CS_Unconsumed,
+ CS_Consumed
+ };
+
+ class ConsumedStmtVisitor;
+
+ typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
+ typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
+ typedef std::list<DelayedDiag> DiagList;
+
+ class ConsumedWarningsHandlerBase {
+
+ public:
+
+ virtual ~ConsumedWarningsHandlerBase();
+
+ /// \brief Emit the warnings and notes left by the analysis.
+ virtual void emitDiagnostics() {}
+
+ /// \brief Warn that a variable's state doesn't match at the entry and exit
+ /// of a loop.
+ ///
+ /// \param Loc -- The location of the end of the loop.
+ ///
+ /// \param VariableName -- The name of the variable that has a mismatched
+ /// state.
+ virtual void warnLoopStateMismatch(SourceLocation Loc,
+ StringRef VariableName) {}
+
+ /// \brief Warn about parameter typestate mismatches upon return.
+ ///
+ /// \param Loc -- The SourceLocation of the return statement.
+ ///
+ /// \param ExpectedState -- The state the return value was expected to be
+ /// in.
+ ///
+ /// \param ObservedState -- The state the return value was observed to be
+ /// in.
+ virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
+ StringRef VariableName,
+ StringRef ExpectedState,
+ StringRef ObservedState) {};
+
+ // FIXME: Add documentation.
+ virtual void warnParamTypestateMismatch(SourceLocation LOC,
+ StringRef ExpectedState,
+ StringRef ObservedState) {}
+
+ // FIXME: This can be removed when the attr propagation fix for templated
+ // classes lands.
+ /// \brief Warn about return typestates set for unconsumable types.
+ ///
+ /// \param Loc -- The location of the attributes.
+ ///
+ /// \param TypeName -- The name of the unconsumable type.
+ virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
+ StringRef TypeName) {}
+
+ /// \brief Warn about return typestate mismatches.
+ ///
+ /// \param Loc -- The SourceLocation of the return statement.
+ ///
+ /// \param ExpectedState -- The state the return value was expected to be
+ /// in.
+ ///
+ /// \param ObservedState -- The state the return value was observed to be
+ /// in.
+ virtual void warnReturnTypestateMismatch(SourceLocation Loc,
+ StringRef ExpectedState,
+ StringRef ObservedState) {}
+
+ /// \brief Warn about use-while-consumed errors.
+ /// \param MethodName -- The name of the method that was incorrectly
+ /// invoked.
+ ///
+ /// \param State -- The state the object was used in.
+ ///
+ /// \param Loc -- The SourceLocation of the method invocation.
+ virtual void warnUseOfTempInInvalidState(StringRef MethodName,
+ StringRef State,
+ SourceLocation Loc) {}
+
+ /// \brief Warn about use-while-consumed errors.
+ /// \param MethodName -- The name of the method that was incorrectly
+ /// invoked.
+ ///
+ /// \param State -- The state the object was used in.
+ ///
+ /// \param VariableName -- The name of the variable that holds the unique
+ /// value.
+ ///
+ /// \param Loc -- The SourceLocation of the method invocation.
+ virtual void warnUseInInvalidState(StringRef MethodName,
+ StringRef VariableName,
+ StringRef State,
+ SourceLocation Loc) {}
+ };
+
+ class ConsumedStateMap {
+
+ typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType;
+ typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>
+ TmpMapType;
+
+ protected:
+
+ bool Reachable;
+ const Stmt *From;
+ VarMapType VarMap;
+ TmpMapType TmpMap;
+
+ public:
+ ConsumedStateMap() : Reachable(true), From(NULL) {}
+ ConsumedStateMap(const ConsumedStateMap &Other)
+ : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
+ TmpMap() {}
+
+ /// \brief Warn if any of the parameters being tracked are not in the state
+ /// they were declared to be in upon return from a function.
+ void checkParamsForReturnTypestate(SourceLocation BlameLoc,
+ ConsumedWarningsHandlerBase &WarningsHandler) const;
+
+ /// \brief Clear the TmpMap.
+ void clearTemporaries();
+
+ /// \brief Get the consumed state of a given variable.
+ ConsumedState getState(const VarDecl *Var) const;
+
+ /// \brief Get the consumed state of a given temporary value.
+ ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
+
+ /// \brief Merge this state map with another map.
+ void intersect(const ConsumedStateMap *Other);
+
+ void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
+ const ConsumedStateMap *LoopBackStates,
+ ConsumedWarningsHandlerBase &WarningsHandler);
+
+ /// \brief Return true if this block is reachable.
+ bool isReachable() const { return Reachable; }
+
+ /// \brief Mark the block as unreachable.
+ void markUnreachable();
+
+ /// \brief Set the source for a decision about the branching of states.
+ /// \param Source -- The statement that was the origin of a branching
+ /// decision.
+ void setSource(const Stmt *Source) { this->From = Source; }
+
+ /// \brief Set the consumed state of a given variable.
+ void setState(const VarDecl *Var, ConsumedState State);
+
+ /// \brief Set the consumed state of a given temporary value.
+ void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
+
+ /// \brief Remove the variable from our state map.
+ void remove(const VarDecl *Var);
+
+ /// \brief Tests to see if there is a mismatch in the states stored in two
+ /// maps.
+ ///
+ /// \param Other -- The second map to compare against.
+ bool operator!=(const ConsumedStateMap *Other) const;
+ };
+
+ class ConsumedBlockInfo {
+ std::vector<ConsumedStateMap*> StateMapsArray;
+ std::vector<unsigned int> VisitOrder;
+
+ public:
+ ConsumedBlockInfo() { }
+
+ ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
+ : StateMapsArray(NumBlocks, 0), VisitOrder(NumBlocks, 0) {
+ unsigned int VisitOrderCounter = 0;
+ for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
+ BE = SortedGraph->end(); BI != BE; ++BI) {
+ VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++;
+ }
+ }
+
+ bool allBackEdgesVisited(const CFGBlock *CurrBlock,
+ const CFGBlock *TargetBlock);
+
+ void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
+ bool &AlreadyOwned);
+ void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap);
+
+ ConsumedStateMap* borrowInfo(const CFGBlock *Block);
+
+ void discardInfo(const CFGBlock *Block);
+
+ ConsumedStateMap* getInfo(const CFGBlock *Block);
+
+ bool isBackEdge(const CFGBlock *From, const CFGBlock *To);
+ bool isBackEdgeTarget(const CFGBlock *Block);
+ };
+
+ /// A class that handles the analysis of uniqueness violations.
+ class ConsumedAnalyzer {
+
+ ConsumedBlockInfo BlockInfo;
+ ConsumedStateMap *CurrStates;
+
+ ConsumedState ExpectedReturnState;
+
+ void determineExpectedReturnState(AnalysisDeclContext &AC,
+ const FunctionDecl *D);
+ bool hasConsumableAttributes(const CXXRecordDecl *RD);
+ bool splitState(const CFGBlock *CurrBlock,
+ const ConsumedStmtVisitor &Visitor);
+
+ public:
+
+ ConsumedWarningsHandlerBase &WarningsHandler;
+
+ ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
+ : WarningsHandler(WarningsHandler) {}
+
+ ConsumedState getExpectedReturnState() const { return ExpectedReturnState; }
+
+ /// \brief Check a function's CFG for consumed violations.
+ ///
+ /// We traverse the blocks in the CFG, keeping track of the state of each
+ /// value who's type has uniquness annotations. If methods are invoked in
+ /// the wrong state a warning is issued. Each block in the CFG is traversed
+ /// exactly once.
+ void run(AnalysisDeclContext &AC);
+ };
+}} // end namespace clang::consumed
+
+#endif
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 4bd989cf4ef3..c9516b50cae3 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -49,7 +49,7 @@ public:
const char *toString() const { return representation; }
// Overloaded operators for bool like qualities
- operator bool() const { return flag; }
+ LLVM_EXPLICIT operator bool() const { return flag; }
OptionalFlag& operator=(const bool &rhs) {
flag = rhs;
return *this; // Return a reference to myself.
@@ -73,6 +73,9 @@ public:
AsIntMax, // 'j'
AsSizeT, // 'z'
AsPtrDiff, // 't'
+ AsInt32, // 'I32' (MSVCRT, like __int32)
+ AsInt3264, // 'I' (MSVCRT, like __int3264 from MIDL)
+ AsInt64, // 'I64' (MSVCRT, like __int64)
AsLongDouble, // 'L'
AsAllocate, // for '%as', GNU extension to C90 scanf
AsMAllocate, // for '%ms', GNU extension to scanf
@@ -95,6 +98,9 @@ public:
case AsLongLong:
case AsChar:
return 2;
+ case AsInt32:
+ case AsInt64:
+ return 3;
case None:
return 0;
}
diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index 8a888e633322..5def3dd3dfd1 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -11,8 +11,8 @@
// A intra-procedural analysis for thread safety (e.g. deadlocks and race
// conditions), based off of an annotation system.
//
-// See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety for more
-// information.
+// See http://clang.llvm.org/docs/LanguageExtensions.html#thread-safety-annotation-checking
+// for more information.
//
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index e8810c32a140..188722d94b3a 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -38,6 +38,12 @@ private:
/// The expression which uses this variable.
const Expr *User;
+ /// Is this use uninitialized whenever the function is called?
+ bool UninitAfterCall;
+
+ /// Is this use uninitialized whenever the variable declaration is reached?
+ bool UninitAfterDecl;
+
/// Does this use always see an uninitialized value?
bool AlwaysUninit;
@@ -46,13 +52,17 @@ private:
SmallVector<Branch, 2> UninitBranches;
public:
- UninitUse(const Expr *User, bool AlwaysUninit) :
- User(User), AlwaysUninit(AlwaysUninit) {}
+ UninitUse(const Expr *User, bool AlwaysUninit)
+ : User(User), UninitAfterCall(false), UninitAfterDecl(false),
+ AlwaysUninit(AlwaysUninit) {}
void addUninitBranch(Branch B) {
UninitBranches.push_back(B);
}
+ void setUninitAfterCall() { UninitAfterCall = true; }
+ void setUninitAfterDecl() { UninitAfterDecl = true; }
+
/// Get the expression containing the uninitialized use.
const Expr *getUser() const { return User; }
@@ -62,6 +72,12 @@ public:
Maybe,
/// The use is uninitialized whenever a certain branch is taken.
Sometimes,
+ /// The use is uninitialized the first time it is reached after we reach
+ /// the variable's declaration.
+ AfterDecl,
+ /// The use is uninitialized the first time it is reached after the function
+ /// is called.
+ AfterCall,
/// The use is always uninitialized.
Always
};
@@ -69,6 +85,8 @@ public:
/// Get the kind of uninitialized use.
Kind getKind() const {
return AlwaysUninit ? Always :
+ UninitAfterCall ? AfterCall :
+ UninitAfterDecl ? AfterDecl :
!branch_empty() ? Sometimes : Maybe;
}
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 46d7d07e0907..b6f183d21b68 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -16,18 +16,14 @@
#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
#include "clang/AST/Decl.h"
-#include "clang/AST/Expr.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Allocator.h"
namespace clang {
-class Decl;
class Stmt;
class CFGReverseBlockReachabilityAnalysis;
class CFGStmtMap;
@@ -35,7 +31,6 @@ class LiveVariables;
class ManagedAnalysis;
class ParentMap;
class PseudoConstantAnalysis;
-class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
class BlockInvocationContext;
@@ -256,6 +251,7 @@ public:
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
+ void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
LLVM_ATTRIBUTE_USED void dumpStack() const;
public:
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index d4e1f5fb6907..33c940e7bbf0 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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 ee0be736dd5e..14b7ab842675 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -43,6 +43,8 @@ namespace clang {
class PrinterHelper;
class LangOptions;
class ASTContext;
+ class CXXRecordDecl;
+ class CXXDeleteExpr;
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
@@ -53,6 +55,7 @@ public:
Initializer,
// dtor kind
AutomaticObjectDtor,
+ DeleteDtor,
BaseDtor,
MemberDtor,
TemporaryDtor,
@@ -185,6 +188,31 @@ private:
}
};
+/// CFGDeleteDtor - Represents C++ object destructor generated
+/// from a call to delete.
+class CFGDeleteDtor : public CFGImplicitDtor {
+public:
+ CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
+ : CFGImplicitDtor(DeleteDtor, RD, DE) {}
+
+ const CXXRecordDecl *getCXXRecordDecl() const {
+ return static_cast<CXXRecordDecl*>(Data1.getPointer());
+ }
+
+ // Get Delete expression which triggered the destructor call.
+ const CXXDeleteExpr *getDeleteExpr() const {
+ return static_cast<CXXDeleteExpr *>(Data2.getPointer());
+ }
+
+
+private:
+ friend class CFGElement;
+ CFGDeleteDtor() {}
+ static bool isKind(const CFGElement &elem) {
+ return elem.getKind() == DeleteDtor;
+ }
+};
+
/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
/// base object in destructor.
class CFGBaseDtor : public CFGImplicitDtor {
@@ -269,7 +297,7 @@ public:
Stmt &operator*() { return *getStmt(); }
const Stmt &operator*() const { return *getStmt(); }
- operator bool() const { return getStmt(); }
+ LLVM_EXPLICIT operator bool() const { return getStmt(); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
@@ -564,6 +592,10 @@ public:
Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
}
+ void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
+ Elements.push_back(CFGDeleteDtor(RD, DE), 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.
@@ -745,6 +777,35 @@ public:
TryDispatchBlocks.push_back(block);
}
+ /// Records a synthetic DeclStmt and the DeclStmt it was constructed from.
+ ///
+ /// The CFG uses synthetic DeclStmts when a single AST DeclStmt contains
+ /// multiple decls.
+ void addSyntheticDeclStmt(const DeclStmt *Synthetic,
+ const DeclStmt *Source) {
+ assert(Synthetic->isSingleDecl() && "Can handle single declarations only");
+ assert(Synthetic != Source && "Don't include original DeclStmts in map");
+ assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map");
+ SyntheticDeclStmts[Synthetic] = Source;
+ }
+
+ typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator
+ synthetic_stmt_iterator;
+
+ /// Iterates over synthetic DeclStmts in the CFG.
+ ///
+ /// Each element is a (synthetic statement, source statement) pair.
+ ///
+ /// \sa addSyntheticDeclStmt
+ synthetic_stmt_iterator synthetic_stmt_begin() const {
+ return SyntheticDeclStmts.begin();
+ }
+
+ /// \sa synthetic_stmt_begin
+ synthetic_stmt_iterator synthetic_stmt_end() const {
+ return SyntheticDeclStmts.end();
+ }
+
//===--------------------------------------------------------------------===//
// Member templates useful for various batch operations over CFGs.
//===--------------------------------------------------------------------===//
@@ -763,21 +824,6 @@ public:
// CFG Introspection.
//===--------------------------------------------------------------------===//
- struct BlkExprNumTy {
- const signed Idx;
- explicit BlkExprNumTy(signed idx) : Idx(idx) {}
- explicit BlkExprNumTy() : Idx(-1) {}
- operator bool() const { return Idx >= 0; }
- operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
- };
-
- 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();
-
/// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
/// start at 0).
unsigned getNumBlockIDs() const { return NumBlockIDs; }
@@ -800,9 +846,7 @@ public:
//===--------------------------------------------------------------------===//
CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
- BlkExprMap(NULL), Blocks(BlkBVC, 10) {}
-
- ~CFG();
+ Blocks(BlkBVC, 10) {}
llvm::BumpPtrAllocator& getAllocator() {
return BlkBVC.getAllocator();
@@ -819,11 +863,6 @@ private:
// for indirect gotos
unsigned NumBlockIDs;
- // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h.
- // It represents a map from Expr* to integers to record the set of
- // block-level expressions and their "statement number" in the CFG.
- void * BlkExprMap;
-
BumpVectorContext BlkBVC;
CFGBlockListTy Blocks;
@@ -832,6 +871,9 @@ private:
/// This is the collection of such blocks present in the CFG.
std::vector<const CFGBlock *> TryDispatchBlocks;
+ /// Collects DeclStmts synthesized for this CFG and maps each one back to its
+ /// source DeclStmt.
+ llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
};
} // end namespace clang
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index 5015eb61497e..593ba575c78e 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -144,8 +144,8 @@ private:
public:
CallGraphNode(Decl *D) : FD(D) {}
- typedef SmallVector<CallRecord, 5>::iterator iterator;
- typedef SmallVector<CallRecord, 5>::const_iterator const_iterator;
+ typedef SmallVectorImpl<CallRecord>::iterator iterator;
+ typedef SmallVectorImpl<CallRecord>::const_iterator const_iterator;
/// Iterators through all the callees/children of the node.
inline iterator begin() { return CalledFunctions.begin(); }
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
index 0f5e7bf246e8..c611ea2397ec 100644
--- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h
+++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -45,8 +45,7 @@ public:
/// dequeue - Remove a block from the worklist.
const CFGBlock *dequeue() {
assert(!BlockQueue.empty());
- const CFGBlock *B = BlockQueue.back();
- BlockQueue.pop_back();
+ const CFGBlock *B = BlockQueue.pop_back_val();
BlockSet[B] = 0;
return B;
}
diff --git a/include/clang/Analysis/Support/BlkExprDeclBitVector.h b/include/clang/Analysis/Support/BlkExprDeclBitVector.h
deleted file mode 100644
index 35cc799b13bc..000000000000
--- a/include/clang/Analysis/Support/BlkExprDeclBitVector.h
+++ /dev/null
@@ -1,307 +0,0 @@
-// BlkExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- C++ --*--
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides definition of dataflow types used by analyses such
-// as LiveVariables and UninitializedValues. The underlying dataflow values
-// are implemented as bitvectors, but the definitions in this file include
-// the necessary boilerplate to use with our dataflow framework.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STMTDECLBVDVAL_H
-#define LLVM_CLANG_STMTDECLBVDVAL_H
-
-#include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion
-#include "clang/Analysis/CFG.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/DenseMap.h"
-
-namespace clang {
-
- class Stmt;
- class ASTContext;
-
-struct DeclBitVector_Types {
-
- class Idx {
- unsigned I;
- public:
- explicit Idx(unsigned i) : I(i) {}
- Idx() : I(~0U) {}
-
- bool isValid() const {
- return I != ~0U;
- }
- operator unsigned() const {
- assert (isValid());
- return I;
- }
- };
-
- //===--------------------------------------------------------------------===//
- // AnalysisDataTy - Whole-function meta data.
- //===--------------------------------------------------------------------===//
-
- class AnalysisDataTy {
- public:
- typedef llvm::DenseMap<const NamedDecl*, unsigned > DMapTy;
- typedef DMapTy::const_iterator decl_iterator;
-
- protected:
- DMapTy DMap;
- unsigned NDecls;
-
- public:
-
- AnalysisDataTy() : NDecls(0) {}
- virtual ~AnalysisDataTy() {}
-
- bool isTracked(const NamedDecl *SD) { return DMap.find(SD) != DMap.end(); }
-
- Idx getIdx(const NamedDecl *SD) const {
- DMapTy::const_iterator I = DMap.find(SD);
- return I == DMap.end() ? Idx() : Idx(I->second);
- }
-
- unsigned getNumDecls() const { return NDecls; }
-
- void Register(const NamedDecl *SD) {
- if (!isTracked(SD)) DMap[SD] = NDecls++;
- }
-
- decl_iterator begin_decl() const { return DMap.begin(); }
- decl_iterator end_decl() const { return DMap.end(); }
- };
-
- //===--------------------------------------------------------------------===//
- // ValTy - Dataflow value.
- //===--------------------------------------------------------------------===//
-
- class ValTy {
- llvm::BitVector DeclBV;
- public:
-
- void resetDeclValues(AnalysisDataTy& AD) {
- DeclBV.resize(AD.getNumDecls());
- DeclBV.reset();
- }
-
- void setDeclValues(AnalysisDataTy& AD) {
- DeclBV.resize(AD.getNumDecls());
- DeclBV.set();
- }
-
- void resetValues(AnalysisDataTy& AD) {
- resetDeclValues(AD);
- }
-
- bool operator==(const ValTy& RHS) const {
- assert (sizesEqual(RHS));
- return DeclBV == RHS.DeclBV;
- }
-
- void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; }
-
- llvm::BitVector::reference getBit(unsigned i) {
- return DeclBV[i];
- }
-
- bool getBit(unsigned i) const {
- return DeclBV[i];
- }
-
- llvm::BitVector::reference
- operator()(const NamedDecl *ND, const AnalysisDataTy& AD) {
- return getBit(AD.getIdx(ND));
- }
-
- bool operator()(const NamedDecl *ND, const AnalysisDataTy& AD) const {
- return getBit(AD.getIdx(ND));
- }
-
- llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; }
- const llvm::BitVector::reference getDeclBit(unsigned i) const {
- return const_cast<llvm::BitVector&>(DeclBV)[i];
- }
-
- ValTy& operator|=(const ValTy& RHS) {
- assert (sizesEqual(RHS));
- DeclBV |= RHS.DeclBV;
- return *this;
- }
-
- ValTy& operator&=(const ValTy& RHS) {
- assert (sizesEqual(RHS));
- DeclBV &= RHS.DeclBV;
- return *this;
- }
-
- ValTy& OrDeclBits(const ValTy& RHS) {
- return operator|=(RHS);
- }
-
- ValTy& AndDeclBits(const ValTy& RHS) {
- return operator&=(RHS);
- }
-
- bool sizesEqual(const ValTy& RHS) const {
- return DeclBV.size() == RHS.DeclBV.size();
- }
- };
-
- //===--------------------------------------------------------------------===//
- // Some useful merge operations.
- //===--------------------------------------------------------------------===//
-
- struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
- struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
-};
-
-
-struct StmtDeclBitVector_Types {
-
- //===--------------------------------------------------------------------===//
- // AnalysisDataTy - Whole-function meta data.
- //===--------------------------------------------------------------------===//
-
- class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy {
- ASTContext *ctx;
- CFG* cfg;
- public:
- AnalysisDataTy() : ctx(0), cfg(0) {}
- virtual ~AnalysisDataTy() {}
-
- void setContext(ASTContext &c) { ctx = &c; }
- ASTContext &getContext() {
- assert(ctx && "ASTContext should not be NULL.");
- return *ctx;
- }
-
- void setCFG(CFG& c) { cfg = &c; }
- CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
-
- bool isTracked(const Stmt *S) { return cfg->isBlkExpr(S); }
- using DeclBitVector_Types::AnalysisDataTy::isTracked;
-
- unsigned getIdx(const Stmt *S) const {
- CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
- assert(I && "Stmtession not tracked for bitvector.");
- return I;
- }
- using DeclBitVector_Types::AnalysisDataTy::getIdx;
-
- unsigned getNumBlkExprs() const { return cfg->getNumBlkExprs(); }
- };
-
- //===--------------------------------------------------------------------===//
- // ValTy - Dataflow value.
- //===--------------------------------------------------------------------===//
-
- class ValTy : public DeclBitVector_Types::ValTy {
- llvm::BitVector BlkExprBV;
- typedef DeclBitVector_Types::ValTy ParentTy;
-
- static inline ParentTy& ParentRef(ValTy& X) {
- return static_cast<ParentTy&>(X);
- }
-
- static inline const ParentTy& ParentRef(const ValTy& X) {
- return static_cast<const ParentTy&>(X);
- }
-
- public:
-
- void resetBlkExprValues(AnalysisDataTy& AD) {
- BlkExprBV.resize(AD.getNumBlkExprs());
- BlkExprBV.reset();
- }
-
- void setBlkExprValues(AnalysisDataTy& AD) {
- BlkExprBV.resize(AD.getNumBlkExprs());
- BlkExprBV.set();
- }
-
- void resetValues(AnalysisDataTy& AD) {
- resetDeclValues(AD);
- resetBlkExprValues(AD);
- }
-
- void setValues(AnalysisDataTy& AD) {
- setDeclValues(AD);
- setBlkExprValues(AD);
- }
-
- bool operator==(const ValTy& RHS) const {
- return ParentRef(*this) == ParentRef(RHS)
- && BlkExprBV == RHS.BlkExprBV;
- }
-
- void copyValues(const ValTy& RHS) {
- ParentRef(*this).copyValues(ParentRef(RHS));
- BlkExprBV = RHS.BlkExprBV;
- }
-
- llvm::BitVector::reference
- operator()(const Stmt *S, const AnalysisDataTy& AD) {
- return BlkExprBV[AD.getIdx(S)];
- }
- const llvm::BitVector::reference
- operator()(const Stmt *S, const AnalysisDataTy& AD) const {
- return const_cast<ValTy&>(*this)(S,AD);
- }
-
- using DeclBitVector_Types::ValTy::operator();
-
-
- llvm::BitVector::reference getStmtBit(unsigned i) { return BlkExprBV[i]; }
- const llvm::BitVector::reference getStmtBit(unsigned i) const {
- return const_cast<llvm::BitVector&>(BlkExprBV)[i];
- }
-
- ValTy& OrBlkExprBits(const ValTy& RHS) {
- BlkExprBV |= RHS.BlkExprBV;
- return *this;
- }
-
- ValTy& AndBlkExprBits(const ValTy& RHS) {
- BlkExprBV &= RHS.BlkExprBV;
- return *this;
- }
-
- ValTy& operator|=(const ValTy& RHS) {
- assert (sizesEqual(RHS));
- ParentRef(*this) |= ParentRef(RHS);
- BlkExprBV |= RHS.BlkExprBV;
- return *this;
- }
-
- ValTy& operator&=(const ValTy& RHS) {
- assert (sizesEqual(RHS));
- ParentRef(*this) &= ParentRef(RHS);
- BlkExprBV &= RHS.BlkExprBV;
- return *this;
- }
-
- bool sizesEqual(const ValTy& RHS) const {
- return ParentRef(*this).sizesEqual(ParentRef(RHS))
- && BlkExprBV.size() == RHS.BlkExprBV.size();
- }
- };
-
- //===--------------------------------------------------------------------===//
- // Some useful merge operations.
- //===--------------------------------------------------------------------===//
-
- struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
- struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
-
-};
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
deleted file mode 100644
index 2bf3eda070b9..000000000000
--- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//= CFGRecStmtDeclVisitor - Recursive visitor of CFG stmts/decls -*- C++ --*-=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the template class CFGRecStmtDeclVisitor, which extends
-// CFGRecStmtVisitor by implementing (typed) visitation of decls.
-//
-// FIXME: This may not be fully complete. We currently explore only subtypes
-// of ScopedDecl.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
-#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
-
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
-
-#define DISPATCH_CASE(CLASS) \
-case Decl::CLASS: \
-static_cast<ImplClass*>(this)->Visit##CLASS##Decl( \
- static_cast<CLASS##Decl*>(D)); \
-break;
-
-#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS##Decl(CLASS##Decl *D) {}
-#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS##Decl(CLASS##Decl *D)\
- { static_cast<ImplClass*>(this)->VisitVarDecl(D); }
-
-
-namespace clang {
-template <typename ImplClass>
-class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
-public:
-
- void VisitDeclRefExpr(DeclRefExpr *DR) {
- static_cast<ImplClass*>(this)->VisitDecl(DR->getDecl());
- }
-
- void VisitDeclStmt(DeclStmt *DS) {
- for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
- DI != DE; ++DI) {
- Decl *D = *DI;
- static_cast<ImplClass*>(this)->VisitDecl(D);
- // Visit the initializer.
- if (VarDecl *VD = dyn_cast<VarDecl>(D))
- if (Expr *I = VD->getInit())
- static_cast<ImplClass*>(this)->Visit(I);
- }
- }
-
- void VisitDecl(Decl *D) {
- switch (D->getKind()) {
- DISPATCH_CASE(Function)
- DISPATCH_CASE(CXXMethod)
- DISPATCH_CASE(Var)
- DISPATCH_CASE(ParmVar) // FIXME: (same)
- DISPATCH_CASE(ImplicitParam)
- DISPATCH_CASE(EnumConstant)
- DISPATCH_CASE(Typedef)
- DISPATCH_CASE(TypeAlias)
- DISPATCH_CASE(Record) // FIXME: Refine. VisitStructDecl?
- DISPATCH_CASE(CXXRecord)
- DISPATCH_CASE(Enum)
- DISPATCH_CASE(Field)
- DISPATCH_CASE(UsingDirective)
- DISPATCH_CASE(Using)
- DISPATCH_CASE(NamespaceAlias)
- default:
- llvm_unreachable("Subtype of ScopedDecl not handled.");
- }
- }
-
- DEFAULT_DISPATCH(Var)
- DEFAULT_DISPATCH(Function)
- DEFAULT_DISPATCH(CXXMethod)
- DEFAULT_DISPATCH_VARDECL(ParmVar)
- DEFAULT_DISPATCH(ImplicitParam)
- DEFAULT_DISPATCH(EnumConstant)
- DEFAULT_DISPATCH(Typedef)
- DEFAULT_DISPATCH(TypeAlias)
- DEFAULT_DISPATCH(Record)
- DEFAULT_DISPATCH(Enum)
- DEFAULT_DISPATCH(Field)
- DEFAULT_DISPATCH(ObjCInterface)
- DEFAULT_DISPATCH(ObjCMethod)
- DEFAULT_DISPATCH(ObjCProtocol)
- DEFAULT_DISPATCH(ObjCCategory)
- DEFAULT_DISPATCH(UsingDirective)
- DEFAULT_DISPATCH(Using)
- DEFAULT_DISPATCH(NamespaceAlias)
-
- void VisitCXXRecordDecl(CXXRecordDecl *D) {
- static_cast<ImplClass*>(this)->VisitRecordDecl(D);
- }
-};
-
-} // end namespace clang
-
-#undef DISPATCH_CASE
-#undef DEFAULT_DISPATCH
-#endif
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
deleted file mode 100644
index 4d1cabfc5c0b..000000000000
--- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//==- CFGRecStmtVisitor - Recursive visitor of CFG statements ---*- C++ --*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the template class CFGRecStmtVisitor, which extends
-// CFGStmtVisitor by implementing a default recursive visit of all statements.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
-#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
-
-#include "clang/Analysis/Visitors/CFGStmtVisitor.h"
-
-namespace clang {
-template <typename ImplClass>
-class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> {
-public:
-
- void VisitStmt(Stmt *S) {
- 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;
- switch (S->getStmtClass()) {
-#define CONDVAR_CASE(CLASS) \
-case Stmt::CLASS ## Class:\
-CondVar = cast<CLASS>(S)->getConditionVariable();\
-break;
- CONDVAR_CASE(IfStmt)
- CONDVAR_CASE(ForStmt)
- CONDVAR_CASE(SwitchStmt)
- CONDVAR_CASE(WhileStmt)
-#undef CONDVAR_CASE
- default:
- llvm_unreachable("Infeasible");
- }
- static_cast<ImplClass*>(this)->Visit(CondVar->getInit());
- }
-
- // Defining operator() allows the visitor to be used as a C++ style functor.
- void operator()(Stmt *S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
deleted file mode 100644
index b354ba7b1680..000000000000
--- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h
+++ /dev/null
@@ -1,175 +0,0 @@
-//===--- CFGStmtVisitor.h - Visitor for Stmts in a CFG ----------*- 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 CFGStmtVisitor interface, which extends
-// StmtVisitor. This interface is useful for visiting statements in a CFG
-// where some statements have implicit control-flow and thus should
-// be treated specially.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
-#define LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
-
-#include "clang/AST/StmtVisitor.h"
-#include "clang/Analysis/CFG.h"
-
-namespace clang {
-
-#define DISPATCH_CASE(CLASS) \
-case Stmt::CLASS ## Class: return \
-static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S));
-
-#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\
-{ return\
- static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(\
- cast<Expr>(S)); }
-
-template <typename ImplClass, typename RetTy=void>
-class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
- Stmt *CurrentBlkStmt;
-
- struct NullifyStmt {
- Stmt*& S;
-
- NullifyStmt(Stmt*& s) : S(s) {}
- ~NullifyStmt() { S = NULL; }
- };
-
-public:
- CFGStmtVisitor() : CurrentBlkStmt(NULL) {}
-
- Stmt *getCurrentBlkStmt() const { return CurrentBlkStmt; }
-
- RetTy Visit(Stmt *S) {
- if (S == CurrentBlkStmt ||
- !static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S))
- return StmtVisitor<ImplClass,RetTy>::Visit(S);
- else
- return RetTy();
- }
-
- /// VisitConditionVariableInit - Handle the initialization of condition
- /// variables at branches. Valid statements include IfStmt, ForStmt,
- /// WhileStmt, and SwitchStmt.
- RetTy VisitConditionVariableInit(Stmt *S) {
- return RetTy();
- }
-
- /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in
- /// CFGBlocks. Root statements are the statements that appear explicitly in
- /// the list of statements in a CFGBlock. For substatements, or when there
- /// is no implementation provided for a BlockStmt_XXX method, we default
- /// to using StmtVisitor's Visit method.
- RetTy BlockStmt_Visit(Stmt *S) {
- CurrentBlkStmt = S;
- NullifyStmt cleanup(CurrentBlkStmt);
-
- switch (S->getStmtClass()) {
- case Stmt::IfStmtClass:
- case Stmt::ForStmtClass:
- case Stmt::WhileStmtClass:
- case Stmt::SwitchStmtClass:
- return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S);
-
- DISPATCH_CASE(StmtExpr)
- DISPATCH_CASE(ConditionalOperator)
- DISPATCH_CASE(BinaryConditionalOperator)
- DISPATCH_CASE(ObjCForCollectionStmt)
- DISPATCH_CASE(CXXForRangeStmt)
-
- case Stmt::BinaryOperatorClass: {
- BinaryOperator* B = cast<BinaryOperator>(S);
- if (B->isLogicalOp())
- return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B);
- else if (B->getOpcode() == BO_Comma)
- return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B);
- // Fall through.
- }
-
- default:
- if (isa<Expr>(S))
- return
- static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(cast<Expr>(S));
- else
- return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
- }
- }
-
- 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);
- }
-
- RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt *S) {
- return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
- }
-
- RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr *E) {
- return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E);
- }
-
- RetTy BlockStmt_VisitExpr(Expr *E) {
- return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E);
- }
-
- RetTy BlockStmt_VisitStmt(Stmt *S) {
- return static_cast<ImplClass*>(this)->Visit(S);
- }
-
- RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) {
- return
- static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
- }
-
- RetTy BlockStmt_VisitComma(BinaryOperator* B) {
- return
- static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
- }
-
- //===--------------------------------------------------------------------===//
- // Utility methods. Not called by default (but subclasses may use them).
- //===--------------------------------------------------------------------===//
-
- /// VisitChildren: Call "Visit" on each child of S.
- void VisitChildren(Stmt *S) {
-
- switch (S->getStmtClass()) {
- default:
- break;
-
- case Stmt::StmtExprClass: {
- CompoundStmt *CS = cast<StmtExpr>(S)->getSubStmt();
- if (CS->body_empty()) return;
- static_cast<ImplClass*>(this)->Visit(CS->body_back());
- return;
- }
-
- case Stmt::BinaryOperatorClass: {
- BinaryOperator* B = cast<BinaryOperator>(S);
- if (B->getOpcode() != BO_Comma) break;
- static_cast<ImplClass*>(this)->Visit(B->getRHS());
- return;
- }
- }
-
- for (Stmt::child_range I = S->children(); I; ++I)
- if (*I) static_cast<ImplClass*>(this)->Visit(*I);
- }
-};
-
-#undef DEFAULT_BLOCKSTMT_VISIT
-#undef DISPATCH_CASE
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
index fecf613a0461..3b3d59efc015 100644
--- a/include/clang/Basic/ABI.h
+++ b/include/clang/Basic/ABI.h
@@ -39,28 +39,64 @@ struct ReturnAdjustment {
/// \brief The non-virtual adjustment from the derived object to its
/// nearest virtual base.
int64_t NonVirtual;
+
+ /// \brief Holds the ABI-specific information about the virtual return
+ /// adjustment, if needed.
+ union VirtualAdjustment {
+ // Itanium ABI
+ struct {
+ /// \brief The offset (in bytes), relative to the address point
+ /// of the virtual base class offset.
+ int64_t VBaseOffsetOffset;
+ } Itanium;
+
+ // Microsoft ABI
+ struct {
+ /// \brief The offset (in bytes) of the vbptr, relative to the beginning
+ /// of the derived class.
+ uint32_t VBPtrOffset;
+
+ /// \brief Index of the virtual base in the vbtable.
+ uint32_t VBIndex;
+ } Microsoft;
+
+ VirtualAdjustment() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ bool Equals(const VirtualAdjustment &Other) const {
+ return memcmp(this, &Other, sizeof(Other)) == 0;
+ }
+
+ bool isEmpty() const {
+ VirtualAdjustment Zero;
+ return Equals(Zero);
+ }
+
+ bool Less(const VirtualAdjustment &RHS) const {
+ return memcmp(this, &RHS, sizeof(RHS)) < 0;
+ }
+ } Virtual;
- /// \brief The offset (in bytes), relative to the address point
- /// of the virtual base class offset.
- int64_t VBaseOffsetOffset;
-
- ReturnAdjustment() : NonVirtual(0), VBaseOffsetOffset(0) { }
+ ReturnAdjustment() : NonVirtual(0) {}
- bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
+ bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
friend bool operator==(const ReturnAdjustment &LHS,
const ReturnAdjustment &RHS) {
- return LHS.NonVirtual == RHS.NonVirtual &&
- LHS.VBaseOffsetOffset == RHS.VBaseOffsetOffset;
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+ }
+
+ friend bool operator!=(const ReturnAdjustment &LHS, const ReturnAdjustment &RHS) {
+ return !(LHS == RHS);
}
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;
+
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
}
};
@@ -70,18 +106,57 @@ struct ThisAdjustment {
/// nearest virtual base.
int64_t NonVirtual;
- /// \brief The offset (in bytes), relative to the address point,
- /// of the virtual call offset.
- int64_t VCallOffsetOffset;
+ /// \brief Holds the ABI-specific information about the virtual this
+ /// adjustment, if needed.
+ union VirtualAdjustment {
+ // Itanium ABI
+ struct {
+ /// \brief The offset (in bytes), relative to the address point,
+ /// of the virtual call offset.
+ int64_t VCallOffsetOffset;
+ } Itanium;
+
+ struct {
+ /// \brief The offset of the vtordisp (in bytes), relative to the ECX.
+ int32_t VtordispOffset;
+
+ /// \brief The offset of the vbptr of the derived class (in bytes),
+ /// relative to the ECX after vtordisp adjustment.
+ int32_t VBPtrOffset;
+
+ /// \brief The offset (in bytes) of the vbase offset in the vbtable.
+ int32_t VBOffsetOffset;
+ } Microsoft;
+
+ VirtualAdjustment() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ bool Equals(const VirtualAdjustment &Other) const {
+ return memcmp(this, &Other, sizeof(Other)) == 0;
+ }
+
+ bool isEmpty() const {
+ VirtualAdjustment Zero;
+ return Equals(Zero);
+ }
+
+ bool Less(const VirtualAdjustment &RHS) const {
+ return memcmp(this, &RHS, sizeof(RHS)) < 0;
+ }
+ } Virtual;
- ThisAdjustment() : NonVirtual(0), VCallOffsetOffset(0) { }
+ ThisAdjustment() : NonVirtual(0) { }
- bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
+ bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
friend bool operator==(const ThisAdjustment &LHS,
const ThisAdjustment &RHS) {
- return LHS.NonVirtual == RHS.NonVirtual &&
- LHS.VCallOffsetOffset == RHS.VCallOffsetOffset;
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+ }
+
+ friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+ return !(LHS == RHS);
}
friend bool operator<(const ThisAdjustment &LHS,
@@ -89,11 +164,12 @@ struct ThisAdjustment {
if (LHS.NonVirtual < RHS.NonVirtual)
return true;
- return LHS.NonVirtual == RHS.NonVirtual &&
- LHS.VCallOffsetOffset < RHS.VCallOffsetOffset;
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
}
};
+class CXXMethodDecl;
+
/// \brief The \c this pointer adjustment as well as an optional return
/// adjustment for a thunk.
struct ThunkInfo {
@@ -103,23 +179,25 @@ struct ThunkInfo {
/// \brief The return adjustment.
ReturnAdjustment Return;
- ThunkInfo() { }
+ /// \brief Holds a pointer to the overridden method this thunk is for,
+ /// if needed by the ABI to distinguish different thunks with equal
+ /// adjustments. Otherwise, null.
+ /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
+ /// an ABI-specific comparator.
+ const CXXMethodDecl *Method;
- ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return)
- : This(This), Return(Return) { }
+ ThunkInfo() : Method(0) { }
- friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
- return LHS.This == RHS.This && LHS.Return == RHS.Return;
- }
+ ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return,
+ const CXXMethodDecl *Method = 0)
+ : This(This), Return(Return), Method(Method) {}
- 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;
+ friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ return LHS.This == RHS.This && LHS.Return == RHS.Return &&
+ LHS.Method == RHS.Method;
}
- bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
+ bool isEmpty() const { return This.isEmpty() && Return.isEmpty() && Method == 0; }
};
} // end namespace clang
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 441a79a23b26..8c3bdba89a8c 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -1,8 +1,11 @@
-////////////////////////////////////////////////////////////////////////////////
-// Note: This file is a work in progress. Please do not apply non-trivial
-// updates unless you have talked to Sean Hunt <rideau3@gmail.com> prior.
-// Merely adding a new attribute is a trivial update.
-////////////////////////////////////////////////////////////////////////////////
+//==--- Attr.td - attribute definitions -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
// An attribute's subject is whatever it appertains to. In this file, it is
// more accurately a list of things that an attribute can appertain to. All
@@ -36,45 +39,53 @@ def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
S->getKind() != Decl::ImplicitParam &&
S->getKind() != Decl::ParmVar &&
S->getKind() != Decl::NonTypeTemplateParm}]>;
-def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
- [{S->isVirtual()}]>;
def NonBitField : SubsetSubject<Field, "non-bit field",
[{!S->isBitField()}]>;
// A single argument to an attribute
-class Argument<string name> {
+class Argument<string name, bit optional> {
string Name = name;
+ bit Optional = optional;
}
-class BoolArgument<string name> : Argument<name>;
-class IdentifierArgument<string name> : Argument<name>;
-class IntArgument<string name> : Argument<name>;
-class StringArgument<string name> : Argument<name>;
-class ExprArgument<string name> : Argument<name>;
-class FunctionArgument<string name> : Argument<name>;
-class TypeArgument<string name> : Argument<name>;
-class UnsignedArgument<string name> : Argument<name>;
-class SourceLocArgument<string name> : Argument<name>;
-class VariadicUnsignedArgument<string name> : Argument<name>;
-class VariadicExprArgument<string name> : Argument<name>;
+class BoolArgument<string name, bit opt = 0> : Argument<name, opt>;
+class IdentifierArgument<string name, bit opt = 0> : Argument<name, opt>;
+class IntArgument<string name, bit opt = 0> : Argument<name, opt>;
+class StringArgument<string name, bit opt = 0> : Argument<name, opt>;
+class ExprArgument<string name, bit opt = 0> : Argument<name, opt>;
+class FunctionArgument<string name, bit opt = 0> : Argument<name, opt>;
+class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
+class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
+class SourceLocArgument<string name, bit opt = 0> : Argument<name, opt>;
+class VariadicUnsignedArgument<string name> : Argument<name, 1>;
+class VariadicExprArgument<string name> : Argument<name, 1>;
// A version of the form major.minor[.subminor].
-class VersionArgument<string name> : Argument<name>;
+class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;
// This one's a doozy, so it gets its own special type
// It can be an unsigned integer, or a type. Either can
// be dependent.
-class AlignedArgument<string name> : Argument<name>;
+class AlignedArgument<string name, bit opt = 0> : Argument<name, opt>;
// An integer argument with a default value
-class DefaultIntArgument<string name, int default> : IntArgument<name> {
+class DefaultIntArgument<string name, int default> : IntArgument<name, 1> {
int Default = default;
}
// This argument is more complex, it includes the enumerator type name,
// a list of strings to accept, and a list of enumerators to map them to.
class EnumArgument<string name, string type, list<string> values,
- list<string> enums> : Argument<name> {
+ list<string> enums, bit opt = 0> : Argument<name, opt> {
+ string Type = type;
+ list<string> Values = values;
+ list<string> Enums = enums;
+}
+
+// FIXME: There should be a VariadicArgument type that takes any other type
+// of argument and generates the appropriate type.
+class VariadicEnumArgument<string name, string type, list<string> values,
+ list<string> enums> : Argument<name, 1> {
string Type = type;
list<string> Values = values;
list<string> Enums = enums;
@@ -122,13 +133,27 @@ class Attr {
bit Ignored = 0;
// Set to true if each of the spellings is a distinct attribute.
bit DistinctSpellings = 0;
+ // Set to true if the attribute's parsing does not match its semantic
+ // content. Eg) It parses 3 args, but semantically takes 4 args. Opts out of
+ // common attribute error checking.
+ bit HasCustomParsing = 0;
// Any additional text that should be included verbatim in the class.
code AdditionalMembers = [{}];
}
+/// A type attribute is not processed on a declaration or a statement.
+class TypeAttr : Attr {
+ let ASTNode = 0;
+}
+
/// An inheritable attribute is inherited by later redeclarations.
class InheritableAttr : Attr;
+/// A target-specific attribute that is meant to be processed via
+/// TargetAttributesSema::ProcessDeclAttribute. This class is meant to be used
+/// as a mixin with InheritableAttr or Attr depending on the attribute's needs.
+class TargetSpecificAttr;
+
/// An inheritable parameter attribute is inherited by later
/// redeclarations, even when it's written on a parameter.
class InheritableParamAttr : InheritableAttr;
@@ -144,13 +169,12 @@ class IgnoredAttr : Attr {
// Attributes begin here
//
-def AddressSpace : Attr {
+def AddressSpace : TypeAttr {
let Spellings = [GNU<"address_space">];
let Args = [IntArgument<"AddressSpace">];
- let ASTNode = 0;
}
-def Alias : InheritableAttr {
+def Alias : Attr {
let Spellings = [GNU<"alias">, CXX11<"gnu", "alias">];
let Args = [StringArgument<"Aliasee">];
}
@@ -159,7 +183,7 @@ def Aligned : InheritableAttr {
let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">,
Keyword<"alignas">, Keyword<"_Alignas">];
let Subjects = [NonBitField, NormalVar, Tag];
- let Args = [AlignedArgument<"Alignment">];
+ let Args = [AlignedArgument<"Alignment", 1>];
let Accessors = [Accessor<"isGNU", [GNU<"aligned">, CXX11<"gnu","aligned">]>,
Accessor<"isC11", [Keyword<"_Alignas">]>,
Accessor<"isAlignas", [Keyword<"alignas">,
@@ -172,7 +196,7 @@ def AlignMac68k : InheritableAttr {
let SemaHandler = 0;
}
-def AllocSize : Attr {
+def AllocSize : InheritableAttr {
let Spellings = [GNU<"alloc_size">, CXX11<"gnu", "alloc_size">];
let Args = [VariadicUnsignedArgument<"Args">];
}
@@ -196,6 +220,14 @@ def Annotate : InheritableParamAttr {
let Args = [StringArgument<"Annotation">];
}
+def ARMInterrupt : InheritableAttr, TargetSpecificAttr {
+ let Spellings = [GNU<"interrupt">];
+ let Args = [EnumArgument<"Interrupt", "InterruptType",
+ ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
+ ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", "Generic"],
+ 1>];
+}
+
def AsmLabel : InheritableAttr {
let Spellings = [];
let Args = [StringArgument<"Label">];
@@ -214,6 +246,7 @@ def Availability : InheritableAttr {
.Case("macosx", "OS X")
.Default(llvm::StringRef());
} }];
+ let HasCustomParsing = 1;
}
def Blocks : InheritableAttr {
@@ -282,12 +315,13 @@ def Common : InheritableAttr {
}
def Const : InheritableAttr {
- let Spellings = [GNU<"const">, GNU<"__const">, CXX11<"gnu", "const">];
+ let Spellings = [GNU<"const">, GNU<"__const">,
+ CXX11<"gnu", "const">, CXX11<"gnu", "__const">];
}
def Constructor : InheritableAttr {
let Spellings = [GNU<"constructor">, CXX11<"gnu", "constructor">];
- let Args = [IntArgument<"Priority">];
+ let Args = [IntArgument<"Priority", 1>];
}
def CUDAConstant : InheritableAttr {
@@ -326,7 +360,7 @@ def CXX11NoReturn : InheritableAttr {
let Subjects = [Function];
}
-def OpenCLKernel : Attr {
+def OpenCLKernel : InheritableAttr {
let Spellings = [Keyword<"__kernel">, Keyword<"kernel">];
}
@@ -336,13 +370,14 @@ def OpenCLImageAccess : Attr {
}
def Deprecated : InheritableAttr {
- let Spellings = [GNU<"deprecated">, CXX11<"gnu", "deprecated">];
- let Args = [StringArgument<"Message">];
+ let Spellings = [GNU<"deprecated">,
+ CXX11<"gnu", "deprecated">, CXX11<"","deprecated">];
+ let Args = [StringArgument<"Message", 1>];
}
def Destructor : InheritableAttr {
let Spellings = [GNU<"destructor">, CXX11<"gnu", "destructor">];
- let Args = [IntArgument<"Priority">];
+ let Args = [IntArgument<"Priority", 1>];
}
def ExtVectorType : Attr {
@@ -362,7 +397,8 @@ def FastCall : InheritableAttr {
}
def Final : InheritableAttr {
- let Spellings = [];
+ let Spellings = [Keyword<"final">, Keyword<"sealed">];
+ let Accessors = [Accessor<"isSpelledAsSealed", [Keyword<"sealed">]>];
let SemaHandler = 0;
}
@@ -373,7 +409,7 @@ def MinSize : InheritableAttr {
def Format : InheritableAttr {
let Spellings = [GNU<"format">, CXX11<"gnu", "format">];
- let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">,
+ let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,
IntArgument<"FirstArg">];
}
@@ -400,7 +436,7 @@ def IBOutlet : InheritableAttr {
def IBOutletCollection : InheritableAttr {
let Spellings = [GNU<"iboutletcollection">];
- let Args = [TypeArgument<"Interface">, SourceLocArgument<"InterfaceLoc">];
+ let Args = [TypeArgument<"Interface", 1>];
}
def Malloc : InheritableAttr {
@@ -417,23 +453,17 @@ def MayAlias : InheritableAttr {
let Spellings = [GNU<"may_alias">, CXX11<"gnu", "may_alias">];
}
-def MSP430Interrupt : InheritableAttr {
- let Spellings = [];
- let Args = [UnsignedArgument<"Number">];
- let SemaHandler = 0;
-}
-
-def MBlazeInterruptHandler : InheritableAttr {
- let Spellings = [];
- let SemaHandler = 0;
+def MSABI : InheritableAttr {
+ let Spellings = [GNU<"ms_abi">, CXX11<"gnu", "ms_abi">];
}
-def MBlazeSaveVolatiles : InheritableAttr {
+def MSP430Interrupt : InheritableAttr, TargetSpecificAttr {
let Spellings = [];
+ let Args = [UnsignedArgument<"Number">];
let SemaHandler = 0;
}
-def Mips16 : InheritableAttr {
+def Mips16 : InheritableAttr, TargetSpecificAttr {
let Spellings = [GNU<"mips16">, CXX11<"gnu", "mips16">];
let Subjects = [Function];
}
@@ -441,23 +471,20 @@ def Mips16 : InheritableAttr {
def Mode : Attr {
let Spellings = [GNU<"mode">, CXX11<"gnu", "mode">];
let Args = [IdentifierArgument<"Mode">];
- let ASTNode = 0;
}
def Naked : InheritableAttr {
let Spellings = [GNU<"naked">, CXX11<"gnu", "naked">];
}
-def NeonPolyVectorType : Attr {
+def NeonPolyVectorType : TypeAttr {
let Spellings = [GNU<"neon_polyvector_type">];
let Args = [IntArgument<"NumElements">];
- let ASTNode = 0;
}
-def NeonVectorType : Attr {
+def NeonVectorType : TypeAttr {
let Spellings = [GNU<"neon_vector_type">];
let Args = [IntArgument<"NumElements">];
- let ASTNode = 0;
}
def ReturnsTwice : InheritableAttr {
@@ -476,7 +503,7 @@ def NoInline : InheritableAttr {
let Spellings = [GNU<"noinline">, CXX11<"gnu", "noinline">];
}
-def NoMips16 : InheritableAttr {
+def NoMips16 : InheritableAttr, TargetSpecificAttr {
let Spellings = [GNU<"nomips16">, CXX11<"gnu", "nomips16">];
let Subjects = [Function];
}
@@ -513,7 +540,13 @@ def NoThrow : InheritableAttr {
def NSBridged : InheritableAttr {
let Spellings = [GNU<"ns_bridged">];
let Subjects = [Record];
- let Args = [IdentifierArgument<"BridgedType">];
+ let Args = [IdentifierArgument<"BridgedType", 1>];
+}
+
+def ObjCBridge : InheritableAttr {
+ let Spellings = [GNU<"objc_bridge">];
+ let Subjects = [Record];
+ let Args = [IdentifierArgument<"BridgedType", 1>];
}
def NSReturnsRetained : InheritableAttr {
@@ -558,14 +591,14 @@ def ObjCNSObject : InheritableAttr {
let Spellings = [GNU<"NSObject">];
}
-def ObjCPreciseLifetime : Attr {
+def ObjCPreciseLifetime : InheritableAttr {
let Spellings = [GNU<"objc_precise_lifetime">];
let Subjects = [Var];
}
-def ObjCReturnsInnerPointer : Attr {
+def ObjCReturnsInnerPointer : InheritableAttr {
let Spellings = [GNU<"objc_returns_inner_pointer">];
- let Subjects = [ObjCMethod];
+ let Subjects = [ObjCMethod, ObjCProperty];
}
def ObjCRequiresSuper : InheritableAttr {
@@ -573,7 +606,7 @@ def ObjCRequiresSuper : InheritableAttr {
let Subjects = [ObjCMethod];
}
-def ObjCRootClass : Attr {
+def ObjCRootClass : InheritableAttr {
let Spellings = [GNU<"objc_root_class">];
let Subjects = [ObjCInterface];
}
@@ -595,6 +628,7 @@ def Ownership : InheritableAttr {
["ownership_holds", "ownership_returns", "ownership_takes"],
["Holds", "Returns", "Takes"]>,
StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
+ let HasCustomParsing = 1;
}
def Packed : InheritableAttr {
@@ -631,11 +665,6 @@ def ReqdWorkGroupSize : InheritableAttr {
UnsignedArgument<"ZDim">];
}
-def Endian : InheritableAttr {
- let Spellings = [GNU<"endian">];
- let Args = [IdentifierArgument<"platform">];
-}
-
def WorkGroupSizeHint : InheritableAttr {
let Spellings = [GNU<"work_group_size_hint">];
let Args = [UnsignedArgument<"XDim">,
@@ -664,6 +693,10 @@ def StdCall : InheritableAttr {
Keyword<"__stdcall">, Keyword<"_stdcall">];
}
+def SysVABI : InheritableAttr {
+ let Spellings = [GNU<"sysv_abi">, CXX11<"gnu", "sysv_abi">];
+}
+
def ThisCall : InheritableAttr {
let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">,
Keyword<"__thiscall">, Keyword<"_thiscall">];
@@ -679,7 +712,7 @@ def TransparentUnion : InheritableAttr {
def Unavailable : InheritableAttr {
let Spellings = [GNU<"unavailable">];
- let Args = [StringArgument<"Message">];
+ let Args = [StringArgument<"Message", 1>];
}
def ArcWeakrefUnavailable : InheritableAttr {
@@ -687,13 +720,12 @@ def ArcWeakrefUnavailable : InheritableAttr {
let Subjects = [ObjCInterface];
}
-def ObjCGC : Attr {
+def ObjCGC : TypeAttr {
let Spellings = [GNU<"objc_gc">];
let Args = [IdentifierArgument<"Kind">];
- let ASTNode = 0;
}
-def ObjCOwnership : Attr {
+def ObjCOwnership : InheritableAttr {
let Spellings = [GNU<"objc_ownership">];
let Args = [IdentifierArgument<"Kind">];
let ASTNode = 0;
@@ -718,15 +750,14 @@ def Uuid : InheritableAttr {
let Subjects = [CXXRecord];
}
-def VectorSize : Attr {
+def VectorSize : TypeAttr {
let Spellings = [GNU<"vector_size">, CXX11<"gnu", "vector_size">];
let Args = [ExprArgument<"NumBytes">];
- let ASTNode = 0;
}
def VecTypeHint : InheritableAttr {
let Spellings = [GNU<"vec_type_hint">];
- let Args = [TypeArgument<"TypeHint">, SourceLocArgument<"TypeLoc">];
+ let Args = [TypeArgument<"TypeHint">];
}
def Visibility : InheritableAttr {
@@ -750,6 +781,11 @@ def VecReturn : InheritableAttr {
let Subjects = [CXXRecord];
}
+def WarnUnused : InheritableAttr {
+ let Spellings = [GNU<"warn_unused">];
+ let Subjects = [Record];
+}
+
def WarnUnusedResult : InheritableAttr {
let Spellings = [GNU<"warn_unused_result">,
CXX11<"clang", "warn_unused_result">,
@@ -766,16 +802,20 @@ def WeakImport : InheritableAttr {
def WeakRef : InheritableAttr {
let Spellings = [GNU<"weakref">, CXX11<"gnu", "weakref">];
+ // A WeakRef that has an argument is treated as being an AliasAttr
+ let Args = [StringArgument<"Aliasee", 1>];
}
-def X86ForceAlignArgPointer : InheritableAttr {
+def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr {
let Spellings = [];
}
// Attribute to disable AddressSanitizer (or equivalent) checks.
def NoSanitizeAddress : InheritableAttr {
let Spellings = [GNU<"no_address_safety_analysis">,
- GNU<"no_sanitize_address">];
+ GNU<"no_sanitize_address">,
+ CXX11<"gnu", "no_address_safety_analysis">,
+ CXX11<"gnu", "no_sanitize_address">];
}
// Attribute to disable ThreadSanitizer checks.
@@ -852,6 +892,20 @@ def SharedLockFunction : InheritableAttr {
let TemplateDependent = 1;
}
+def AssertExclusiveLock : InheritableAttr {
+ let Spellings = [GNU<"assert_exclusive_lock">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+}
+
+def AssertSharedLock : InheritableAttr {
+ let Spellings = [GNU<"assert_shared_lock">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+}
+
// The first argument is an integer or boolean value specifying the return value
// of a successful lock acquisition.
def ExclusiveTrylockFunction : InheritableAttr {
@@ -905,6 +959,56 @@ def SharedLocksRequired : InheritableAttr {
let TemplateDependent = 1;
}
+// C/C++ consumed attributes.
+
+def Consumable : InheritableAttr {
+ let Spellings = [GNU<"consumable">];
+ let Subjects = [CXXRecord];
+ let Args = [EnumArgument<"DefaultState", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+}
+
+def CallableWhen : InheritableAttr {
+ let Spellings = [GNU<"callable_when">];
+ let Subjects = [CXXMethod];
+ let Args = [VariadicEnumArgument<"CallableState", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+}
+
+def ParamTypestate : InheritableAttr {
+ let Spellings = [GNU<"param_typestate">];
+ let Subjects = [ParmVar];
+ let Args = [EnumArgument<"ParamState", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+}
+
+def ReturnTypestate : InheritableAttr {
+ let Spellings = [GNU<"return_typestate">];
+ let Subjects = [Function, ParmVar];
+ let Args = [EnumArgument<"State", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+}
+
+def SetTypestate : InheritableAttr {
+ let Spellings = [GNU<"set_typestate">];
+ let Subjects = [CXXMethod];
+ let Args = [EnumArgument<"NewState", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+}
+
+def TestTypestate : InheritableAttr {
+ let Spellings = [GNU<"test_typestate">];
+ let Subjects = [CXXMethod];
+ let Args = [EnumArgument<"TestState", "ConsumedState",
+ ["consumed", "unconsumed"],
+ ["Consumed", "Unconsumed"]>];
+}
+
// Type safety attributes for `void *' pointers and type tags.
def ArgumentWithTypeTag : InheritableAttr {
@@ -915,6 +1019,7 @@ def ArgumentWithTypeTag : InheritableAttr {
UnsignedArgument<"TypeTagIdx">,
BoolArgument<"IsPointer">];
let Subjects = [Function];
+ let HasCustomParsing = 1;
}
def TypeTagForDatatype : InheritableAttr {
@@ -924,11 +1029,12 @@ def TypeTagForDatatype : InheritableAttr {
BoolArgument<"LayoutCompatible">,
BoolArgument<"MustBeNull">];
let Subjects = [Var];
+ let HasCustomParsing = 1;
}
// Microsoft-related attributes
-def MsProperty : Attr {
+def MsProperty : IgnoredAttr {
let Spellings = [Declspec<"property">];
}
@@ -936,11 +1042,11 @@ def MsStruct : InheritableAttr {
let Spellings = [Declspec<"ms_struct">];
}
-def DLLExport : InheritableAttr {
+def DLLExport : InheritableAttr, TargetSpecificAttr {
let Spellings = [Declspec<"dllexport">];
}
-def DLLImport : InheritableAttr {
+def DLLImport : InheritableAttr, TargetSpecificAttr {
let Spellings = [Declspec<"dllimport">];
}
@@ -948,18 +1054,30 @@ def ForceInline : InheritableAttr {
let Spellings = [Keyword<"__forceinline">];
}
+def SelectAny : InheritableAttr {
+ let Spellings = [Declspec<"selectany">];
+}
+
def Win64 : InheritableAttr {
let Spellings = [Keyword<"__w64">];
}
-def Ptr32 : InheritableAttr {
+def Ptr32 : TypeAttr {
let Spellings = [Keyword<"__ptr32">];
}
-def Ptr64 : InheritableAttr {
+def Ptr64 : TypeAttr {
let Spellings = [Keyword<"__ptr64">];
}
+def SPtr : TypeAttr {
+ let Spellings = [Keyword<"__sptr">];
+}
+
+def UPtr : TypeAttr {
+ let Spellings = [Keyword<"__uptr">];
+}
+
class MSInheritanceAttr : InheritableAttr;
def SingleInheritance : MSInheritanceAttr {
diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h
index bd090ecc0d1b..7c4e2c75f04d 100644
--- a/include/clang/Basic/AttrKinds.h
+++ b/include/clang/Basic/AttrKinds.h
@@ -24,7 +24,7 @@ enum Kind {
#define ATTR(X) X,
#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X,
-#define LAST_MS_INHERITABLE_ATTR(X) X, LAST_MS_INHERITABLE = X,
+#define LAST_MS_INHERITANCE_ATTR(X) X, LAST_MS_INHERITANCE = X,
#include "clang/Basic/AttrList.inc"
NUM_ATTRS
};
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 0a513efdbc16..55c6ed7deead 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -25,6 +25,7 @@
// c -> char
// s -> short
// i -> int
+// h -> half
// f -> float
// d -> double
// z -> size_t
@@ -70,6 +71,8 @@
// f -> this is a libc/libm function without the '__builtin_' prefix. It can
// be followed by ':headername:' to state which header this function
// comes from.
+// i -> this is a runtime library implemented function without the
+// '__builtin_' prefix. It will be implemented in compiter-rt or libgcc.
// p:N: -> this is a printf-like function whose Nth argument is the format
// string.
// P:N: -> similar to the p:N: attribute, but the function is like vprintf
@@ -89,6 +92,10 @@
# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
#endif
+#if defined(BUILTIN) && !defined(LANGBUILTIN)
+# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
// Standard libc/libm functions:
BUILTIN(__builtin_atan2 , "ddd" , "Fnc")
BUILTIN(__builtin_atan2f, "fff" , "Fnc")
@@ -236,8 +243,8 @@ 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_nexttoward , "ddLd", "Fnc")
+BUILTIN(__builtin_nexttowardf, "ffLd", "Fnc")
BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fnc")
BUILTIN(__builtin_remainder , "ddd", "Fnc")
BUILTIN(__builtin_remainderf, "fff", "Fnc")
@@ -485,6 +492,7 @@ BUILTIN(__builtin_trap, "v", "nr")
BUILTIN(__builtin_debugtrap, "v", "n")
BUILTIN(__builtin_unreachable, "v", "nr")
BUILTIN(__builtin_shufflevector, "v." , "nc")
+BUILTIN(__builtin_convertvector, "v." , "nct")
BUILTIN(__builtin_alloca, "v*z" , "n")
// "Overloaded" Atomic operator builtins. These are overloaded to support data
@@ -666,11 +674,11 @@ 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")
-BUILTIN(__debugbreak, "v", "n")
-
+// Microsoft builtins. These are only active with -fms-extensions.
+LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__noop, "v.", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
// C99 library functions
// C99 stdlib.h
@@ -718,48 +726,47 @@ LIBBUILTIN(vscanf, "icC*Ra", "fS:0:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vfscanf, "iP*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vsscanf, "icC*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES)
// C99
+#undef setjmp
+LIBBUILTIN(setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
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", ALL_LANGUAGES)
+// Non-C library functions, active in GNU mode only.
+LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_GNU_LANGUAGES)
// POSIX 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)
+LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
// POSIX 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)
+LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_GNU_LANGUAGES)
// In some systems str[n]casejmp is a macro that expands to _str[n]icmp.
// We undefine then here to avoid wrong name.
#undef strcasecmp
#undef strncasecmp
-LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_LANGUAGES)
-LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_LANGUAGES)
+LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES)
// POSIX unistd.h
-LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES)
-LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_LANGUAGES)
+LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_GNU_LANGUAGES)
// POSIX setjmp.h
// In some systems setjmp is a macro that expands to _setjmp. We undefine
// it here to avoid having two identical LIBBUILTIN entries.
-#undef setjmp
-LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_LANGUAGES)
-
-LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
-LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+
+LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES)
// non-standard but very common
-LIBBUILTIN(strlcpy, "zc*cC*z", "f", "string.h", ALL_LANGUAGES)
-LIBBUILTIN(strlcat, "zc*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strlcpy, "zc*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strlcat, "zc*cC*z", "f", "string.h", ALL_GNU_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, ...)
@@ -814,109 +821,321 @@ LIBBUILTIN(NSLog, "vG.", "fp:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG)
LIBBUILTIN(NSLogv, "vGa", "fP:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG)
// Builtin math library functions
-LIBBUILTIN(acos, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(acosl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(acosf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan2, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan2f, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan2l, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(asin, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(asinl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(asinf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(abs, "ii", "fnc", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(labs, "LiLi", "fnc", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(llabs, "LLiLLi", "fnc", "stdlib.h", ALL_LANGUAGES)
-LIBBUILTIN(atan, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(atanl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(atanf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(copysign, "ddd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(copysignf, "fff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(copysignl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(atan2, "ddd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(atan2l, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(atan2f, "fff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fabs, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fabsf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fabsl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(ceil, "dd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(ceill, "LdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(ceilf, "ff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmod, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmodf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmodl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cimag, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cimagf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(cimagl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(frexp, "ddi*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(frexpf, "ffi*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(frexpl, "LdLdi*", "fn", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(creal, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(crealf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
-LIBBUILTIN(creall, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ldexp, "ddi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ldexpf, "ffi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ldexpl, "LdLdi", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(modf, "ddd*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(modff, "fff*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(modfl, "LdLdLd*", "fn", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(nan, "dcC*", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nanf, "fcC*", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nanl, "LdcC*", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(pow, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(acos, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acosf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acosl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(acosh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acoshf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acoshl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(asin, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(asinh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(atan, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(atanh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cbrt, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cbrtf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cbrtl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ceil, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ceilf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ceill, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cos, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cosh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(coshf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(coshl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(erf, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erff, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erfl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(erfc, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erfcf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erfcl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(exp, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(exp2, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(exp2f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(exp2l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(expm1, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expm1f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expm1l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fdim, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fdimf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fdiml, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(floor, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(floorf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(floorl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fma, "dddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaf, "ffff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmal, "LdLdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fmax, "ddd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaxf, "fff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaxl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fmin, "ddd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fminf, "fff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fminl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(hypot, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(hypotf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(hypotl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ilogb, "id", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ilogbf, "if", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ilogbl, "iLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(copysign, "ddd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(copysignl, "LdLdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(copysignf, "fff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lgamma, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lgammaf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lgammal, "LdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cos, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cosl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(cosf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llrint, "LLid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llrintf, "LLif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llrintl, "LLiLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(exp, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(expl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(expf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llround, "LLid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llroundf, "LLif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llroundl, "LLiLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(exp2, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(exp2l, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(exp2f, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fabs, "dd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fabsl, "LdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fabsf, "ff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log10, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log10f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log10l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(floor, "dd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(floorl, "LdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(floorf, "ff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log1p, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log1pf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log1pl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fma, "dddd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fmal, "LdLdLdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fmaf, "ffff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log2, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log2f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log2l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fmax, "ddd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fmaxl, "LdLdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fmaxf, "fff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logb, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logbf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logbl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fmin, "ddd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fminl, "LdLdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(fminf, "fff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lrint, "Lid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lrintf, "Lif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lrintl, "LiLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(log, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(logl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(logf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lround, "Lid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lroundf, "Lif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lroundl, "LiLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(log2, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(log2l, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(log2f, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nearbyint, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nearbyintf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nearbyintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(nearbyint, "dd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(nearbyintl, "LdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(nearbyintf, "ff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nextafter, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nextafterf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nextafterl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(powf, "fff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nexttoward, "ddLd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nexttowardf, "ffLd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nexttowardl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(rint, "dd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(rintl, "LdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(rintf, "ff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remainder, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remainderf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remainderl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(round, "dd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(roundl, "LdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(roundf, "ff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(rint, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(rintf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(rintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
-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(round, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(roundf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(roundl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
-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(scalbln, "ddLi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalblnf, "ffLi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalblnl, "LdLdLi", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(tan, "dd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(tanl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(tanf, "ff", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalbn, "ddi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalbnf, "ffi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalbnl, "LdLdi", "fne", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(trunc, "dd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(truncl, "LdLd", "fc", "math.h", ALL_LANGUAGES)
-LIBBUILTIN(truncf, "ff", "fc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sin, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sinh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sqrt, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(tan, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(tanh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(tgamma, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tgammaf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tgammal, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(trunc, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(truncf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(truncl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cabs, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cabsf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cabsl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cacos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cacosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(carg, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cargf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cargl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(casin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(casinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(catan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(catanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ccos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ccosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cexp, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cexpf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cexpl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cimag, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cimagf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cimagl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(conj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(conjf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(conjl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(clog, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(clogf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(clogl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cproj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cprojf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cprojl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cpow, "XdXdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cpowf, "XfXfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cpowl, "XLdXLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(creal, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(crealf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(creall, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(csin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(csinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(csqrt, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csqrtf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csqrtl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ctan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ctanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
// Blocks runtime Builtin math library functions
LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
@@ -927,14 +1146,40 @@ LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
BUILTIN(__builtin_annotation, "v.", "tn")
// Multiprecision Arithmetic Builtins.
+BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n")
BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n")
BUILTIN(__builtin_addc, "UiUiCUiCUiCUi*", "n")
BUILTIN(__builtin_addcl, "ULiULiCULiCULiCULi*", "n")
BUILTIN(__builtin_addcll, "ULLiULLiCULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_subcb, "UcUcCUcCUcCUc*", "n")
BUILTIN(__builtin_subcs, "UsUsCUsCUsCUs*", "n")
BUILTIN(__builtin_subc, "UiUiCUiCUiCUi*", "n")
BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n")
BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n")
+// Checked Arithmetic Builtins for Security.
+BUILTIN(__builtin_uadd_overflow, "bUiCUiCUi*", "n")
+BUILTIN(__builtin_uaddl_overflow, "bULiCULiCULi*", "n")
+BUILTIN(__builtin_uaddll_overflow, "bULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_usub_overflow, "bUiCUiCUi*", "n")
+BUILTIN(__builtin_usubl_overflow, "bULiCULiCULi*", "n")
+BUILTIN(__builtin_usubll_overflow, "bULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_umul_overflow, "bUiCUiCUi*", "n")
+BUILTIN(__builtin_umull_overflow, "bULiCULiCULi*", "n")
+BUILTIN(__builtin_umulll_overflow, "bULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_sadd_overflow, "bSiCSiCSi*", "n")
+BUILTIN(__builtin_saddl_overflow, "bSLiCSLiCSLi*", "n")
+BUILTIN(__builtin_saddll_overflow, "bSLLiCSLLiCSLLi*", "n")
+BUILTIN(__builtin_ssub_overflow, "bSiCSiCSi*", "n")
+BUILTIN(__builtin_ssubl_overflow, "bSLiCSLiCSLi*", "n")
+BUILTIN(__builtin_ssubll_overflow, "bSLLiCSLLiCSLLi*", "n")
+BUILTIN(__builtin_smul_overflow, "bSiCSiCSi*", "n")
+BUILTIN(__builtin_smull_overflow, "bSLiCSLiCSLi*", "n")
+BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n")
+
+// Clang builtins (not available in GCC).
+BUILTIN(__builtin_addressof, "v*v&", "nct")
+
#undef BUILTIN
#undef LIBBUILTIN
+#undef LANGBUILTIN
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 3b88e1550cba..9756f21a1c48 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -31,10 +31,14 @@ namespace clang {
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.
+ GNU_LANG = 0x1, // builtin requires GNU mode.
+ C_LANG = 0x2, // builtin for c only.
+ CXX_LANG = 0x4, // builtin for cplusplus only.
+ OBJC_LANG = 0x8, // builtin for objective-c and objective-c++
+ MS_LANG = 0x10, // builtin requires MS mode.
+ ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
+ ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
+ ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
};
namespace Builtin {
@@ -73,9 +77,8 @@ public:
/// such.
void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
- /// \brief Popular the vector with the names of all of the builtins.
- void GetBuiltinNames(SmallVectorImpl<const char *> &Names,
- bool NoBuiltins);
+ /// \brief Populate the vector with the names of all of the builtins.
+ void GetBuiltinNames(SmallVectorImpl<const char *> &Names);
/// \brief Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs".
@@ -128,6 +131,13 @@ public:
return strchr(GetRecord(ID).Attributes, 'f') != 0;
}
+ /// \brief Determines whether this builtin is a predefined compiler-rt/libgcc
+ /// function, such as "__clear_cache", where we know the signature a
+ /// priori.
+ bool isPredefinedRuntimeFunction(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'i') != 0;
+ }
+
/// \brief Determines whether this builtin has custom typechecking.
bool hasCustomTypechecking(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 't') != 0;
@@ -163,6 +173,10 @@ public:
private:
const Info &GetRecord(unsigned ID) const;
+
+ /// \brief Is this builtin supported according to the given language options?
+ bool BuiltinIsSupported(const Builtin::Info &BuiltinInfo,
+ const LangOptions &LangOpts);
};
}
diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
index 9e9f6d0875db..aafd202aae11 100644
--- a/include/clang/Basic/BuiltinsAArch64.def
+++ b/include/clang/Basic/BuiltinsAArch64.def
@@ -15,4 +15,11 @@
// The format of this database matches clang/Basic/Builtins.def.
// In libgcc
-BUILTIN(__clear_cache, "vv*v*", "")
+BUILTIN(__clear_cache, "vv*v*", "i")
+// NEON
+#define GET_NEON_AARCH64_BUILTINS
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_AARCH64_BUILTINS
+#undef GET_NEON_BUILTINS
+
+#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 888e529111ab..21bb892a8b9b 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -15,7 +15,7 @@
// The format of this database matches clang/Basic/Builtins.def.
// In libgcc
-BUILTIN(__clear_cache, "v.", "")
+BUILTIN(__clear_cache, "vv*v*", "i")
BUILTIN(__builtin_thread_pointer, "v*", "")
// Saturating arithmetic
@@ -24,10 +24,14 @@ BUILTIN(__builtin_arm_qsub, "iii", "nc")
BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
BUILTIN(__builtin_arm_usat, "UiUiUi", "nc")
-// Store and load exclusive doubleword
+// Store and load exclusive
BUILTIN(__builtin_arm_ldrexd, "LLUiv*", "")
BUILTIN(__builtin_arm_strexd, "iLLUiv*", "")
+BUILTIN(__builtin_arm_ldrex, "v.", "t")
+BUILTIN(__builtin_arm_strex, "i.", "t")
+BUILTIN(__builtin_arm_clrex, "v", "")
+
// VFP
BUILTIN(__builtin_arm_get_fpscr, "Ui", "nc")
BUILTIN(__builtin_arm_set_fpscr, "vUi", "nc")
@@ -44,6 +48,23 @@ BUILTIN(__builtin_arm_cdp2, "vUiUiUiUiUiUi", "")
BUILTIN(__builtin_arm_mcrr, "vUiUiUiUiUi", "")
BUILTIN(__builtin_arm_mcrr2, "vUiUiUiUiUi", "")
+// CRC32
+BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc")
+BUILTIN(__builtin_arm_crc32cb, "UiUiUc", "nc")
+BUILTIN(__builtin_arm_crc32h, "UiUiUs", "nc")
+BUILTIN(__builtin_arm_crc32ch, "UiUiUs", "nc")
+BUILTIN(__builtin_arm_crc32w, "UiUiUi", "nc")
+BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc")
+BUILTIN(__builtin_arm_crc32d, "UiUiLLUi", "nc")
+BUILTIN(__builtin_arm_crc32cd, "UiUiLLUi", "nc")
+
+// HINT
+BUILTIN(__builtin_arm_sevl, "v", "")
+
+// Data barrier
+BUILTIN(__builtin_arm_dmb, "vUi", "nc")
+BUILTIN(__builtin_arm_dsb, "vUi", "nc")
+
// NEON
#define GET_NEON_BUILTINS
#include "clang/Basic/arm_neon.inc"
diff --git a/include/clang/Basic/BuiltinsMips.def b/include/clang/Basic/BuiltinsMips.def
index 43fb90756efb..e435d52ed4f9 100644
--- a/include/clang/Basic/BuiltinsMips.def
+++ b/include/clang/Basic/BuiltinsMips.def
@@ -185,4 +185,716 @@ BUILTIN(__builtin_mips_subu_s_ph, "V2sV2sV2s", "n")
BUILTIN(__builtin_mips_subuh_qb, "V4ScV4ScV4Sc", "nc")
BUILTIN(__builtin_mips_subuh_r_qb, "V4ScV4ScV4Sc", "nc")
+// MIPS MSA
+
+BUILTIN(__builtin_msa_add_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_add_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_add_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_add_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_adds_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_adds_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_adds_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_adds_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_adds_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_adds_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_adds_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_adds_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_adds_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_adds_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_adds_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_adds_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_addv_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_addv_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_addv_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_addv_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_addvi_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_addvi_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_addvi_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_addvi_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_and_v, "V16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_andi_b, "V16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_asub_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_asub_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_asub_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_asub_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_asub_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_asub_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_asub_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_asub_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_ave_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_ave_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_ave_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_ave_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ave_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_ave_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_ave_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_ave_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_aver_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_aver_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_aver_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_aver_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_aver_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_aver_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_aver_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_aver_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bclr_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_bclr_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_bclr_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_bclr_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bclri_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_bclri_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_bclri_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_bclri_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_binsl_b, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_binsl_h, "V8UsV8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_binsl_w, "V4UiV4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_binsl_d, "V2ULLiV2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_binsli_b, "V16UcV16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_binsli_h, "V8UsV8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_binsli_w, "V4UiV4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_binsli_d, "V2ULLiV2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_binsr_b, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_binsr_h, "V8UsV8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_binsr_w, "V4UiV4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_binsr_d, "V2ULLiV2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_binsri_b, "V16UcV16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_binsri_h, "V8UsV8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_binsri_w, "V4UiV4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_binsri_d, "V2ULLiV2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_bmnz_v, "V16UcV16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bmnzi_b, "V16UcV16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_bmz_v, "V16UcV16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bmzi_b, "V16UcV16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_bneg_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_bneg_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_bneg_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_bneg_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bnegi_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_bnegi_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_bnegi_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_bnegi_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_bnz_b, "iV16Uc", "nc")
+BUILTIN(__builtin_msa_bnz_h, "iV8Us", "nc")
+BUILTIN(__builtin_msa_bnz_w, "iV4Ui", "nc")
+BUILTIN(__builtin_msa_bnz_d, "iV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bnz_v, "iV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bsel_v, "V16UcV16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bseli_b, "V16UcV16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_bset_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_bset_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_bset_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_bset_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bseti_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_bseti_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_bseti_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_bseti_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_bz_b, "iV16Uc", "nc")
+BUILTIN(__builtin_msa_bz_h, "iV8Us", "nc")
+BUILTIN(__builtin_msa_bz_w, "iV4Ui", "nc")
+BUILTIN(__builtin_msa_bz_d, "iV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bz_v, "iV16Uc", "nc")
+
+BUILTIN(__builtin_msa_ceq_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_ceq_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_ceq_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_ceq_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ceqi_b, "V16ScV16ScISi", "nc")
+BUILTIN(__builtin_msa_ceqi_h, "V8SsV8SsISi", "nc")
+BUILTIN(__builtin_msa_ceqi_w, "V4SiV4SiISi", "nc")
+BUILTIN(__builtin_msa_ceqi_d, "V2SLLiV2SLLiISi", "nc")
+
+BUILTIN(__builtin_msa_cfcmsa, "iIi", "n")
+
+BUILTIN(__builtin_msa_cle_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_cle_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_cle_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_cle_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_cle_u_b, "V16ScV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_cle_u_h, "V8SsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_cle_u_w, "V4SiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_cle_u_d, "V2SLLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_clei_s_b, "V16ScV16ScISi", "nc")
+BUILTIN(__builtin_msa_clei_s_h, "V8SsV8SsISi", "nc")
+BUILTIN(__builtin_msa_clei_s_w, "V4SiV4SiISi", "nc")
+BUILTIN(__builtin_msa_clei_s_d, "V2SLLiV2SLLiISi", "nc")
+
+BUILTIN(__builtin_msa_clei_u_b, "V16ScV16UcIUi", "nc")
+BUILTIN(__builtin_msa_clei_u_h, "V8SsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_clei_u_w, "V4SiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_clei_u_d, "V2SLLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_clt_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_clt_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_clt_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_clt_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_clt_u_b, "V16ScV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_clt_u_h, "V8SsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_clt_u_w, "V4SiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_clt_u_d, "V2SLLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_clti_s_b, "V16ScV16ScISi", "nc")
+BUILTIN(__builtin_msa_clti_s_h, "V8SsV8SsISi", "nc")
+BUILTIN(__builtin_msa_clti_s_w, "V4SiV4SiISi", "nc")
+BUILTIN(__builtin_msa_clti_s_d, "V2SLLiV2SLLiISi", "nc")
+
+BUILTIN(__builtin_msa_clti_u_b, "V16ScV16UcIUi", "nc")
+BUILTIN(__builtin_msa_clti_u_h, "V8SsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_clti_u_w, "V4SiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_clti_u_d, "V2SLLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_copy_s_b, "iV16ScIUi", "nc")
+BUILTIN(__builtin_msa_copy_s_h, "iV8SsIUi", "nc")
+BUILTIN(__builtin_msa_copy_s_w, "iV4SiIUi", "nc")
+BUILTIN(__builtin_msa_copy_s_d, "LLiV2SLLiIUi", "nc")
+
+BUILTIN(__builtin_msa_copy_u_b, "iV16UcIUi", "nc")
+BUILTIN(__builtin_msa_copy_u_h, "iV8UsIUi", "nc")
+BUILTIN(__builtin_msa_copy_u_w, "iV4UiIUi", "nc")
+BUILTIN(__builtin_msa_copy_u_d, "LLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_ctcmsa, "vIii", "n")
+
+BUILTIN(__builtin_msa_div_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_div_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_div_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_div_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_div_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_div_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_div_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_div_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_dotp_s_h, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_dotp_s_w, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_dotp_s_d, "V2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_dotp_u_h, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_dotp_u_w, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_dotp_u_d, "V2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_dpadd_s_h, "V8SsV8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_dpadd_s_w, "V4SiV4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_dpadd_s_d, "V2SLLiV2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_dpadd_u_h, "V8UsV8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_dpadd_u_w, "V4UiV4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_dpadd_u_d, "V2ULLiV2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_dpsub_s_h, "V8SsV8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_dpsub_s_w, "V4SiV4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_dpsub_s_d, "V2SLLiV2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_dpsub_u_h, "V8UsV8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_dpsub_u_w, "V4UiV4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_dpsub_u_d, "V2ULLiV2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_fadd_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fadd_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcaf_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcaf_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fceq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fceq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fclass_w, "V4iV4f", "nc")
+BUILTIN(__builtin_msa_fclass_d, "V2LLiV2d", "nc")
+
+BUILTIN(__builtin_msa_fcle_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcle_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fclt_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fclt_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcne_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcne_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcor_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcor_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcueq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcueq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcule_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcule_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcult_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcult_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcun_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcun_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcune_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcune_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fdiv_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fdiv_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fexdo_h, "V8hV4fV4f", "nc")
+BUILTIN(__builtin_msa_fexdo_w, "V4fV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fexp2_w, "V4fV4fV4i", "nc")
+BUILTIN(__builtin_msa_fexp2_d, "V2dV2dV2LLi", "nc")
+
+BUILTIN(__builtin_msa_fexupl_w, "V4fV8h", "nc")
+BUILTIN(__builtin_msa_fexupl_d, "V2dV4f", "nc")
+
+BUILTIN(__builtin_msa_fexupr_w, "V4fV8h", "nc")
+BUILTIN(__builtin_msa_fexupr_d, "V2dV4f", "nc")
+
+BUILTIN(__builtin_msa_ffint_s_w, "V4fV4Si", "nc")
+BUILTIN(__builtin_msa_ffint_s_d, "V2dV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ffint_u_w, "V4fV4Ui", "nc")
+BUILTIN(__builtin_msa_ffint_u_d, "V2dV2ULLi", "nc")
+
+// ffql uses integers since long _Fract is not implemented
+BUILTIN(__builtin_msa_ffql_w, "V4fV8Ss", "nc")
+BUILTIN(__builtin_msa_ffql_d, "V2dV4Si", "nc")
+
+// ffqr uses integers since long _Fract is not implemented
+BUILTIN(__builtin_msa_ffqr_w, "V4fV8Ss", "nc")
+BUILTIN(__builtin_msa_ffqr_d, "V2dV4Si", "nc")
+
+BUILTIN(__builtin_msa_fill_b, "V16Sci", "nc")
+BUILTIN(__builtin_msa_fill_h, "V8Ssi", "nc")
+BUILTIN(__builtin_msa_fill_w, "V4Sii", "nc")
+BUILTIN(__builtin_msa_fill_d, "V2SLLiLLi", "nc")
+
+BUILTIN(__builtin_msa_flog2_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_flog2_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmadd_w, "V4fV4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmadd_d, "V2dV2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmax_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmax_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmax_a_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmax_a_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmin_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmin_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmin_a_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmin_a_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmsub_w, "V4fV4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmsub_d, "V2dV2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmul_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmul_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_frint_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_frint_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_frcp_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_frcp_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_frsqrt_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_frsqrt_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsaf_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsaf_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fseq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fseq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsle_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsle_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fslt_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fslt_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsne_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsne_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsor_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsor_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsqrt_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_fsqrt_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsub_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsub_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsueq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsueq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsule_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsule_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsult_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsult_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsun_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsun_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsune_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsune_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_ftint_s_w, "V4SiV4f", "nc")
+BUILTIN(__builtin_msa_ftint_s_d, "V2SLLiV2d", "nc")
+
+BUILTIN(__builtin_msa_ftint_u_w, "V4UiV4f", "nc")
+BUILTIN(__builtin_msa_ftint_u_d, "V2ULLiV2d", "nc")
+
+BUILTIN(__builtin_msa_ftq_h, "V4UiV4fV4f", "nc")
+BUILTIN(__builtin_msa_ftq_w, "V2ULLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_ftrunc_s_w, "V4SiV4f", "nc")
+BUILTIN(__builtin_msa_ftrunc_s_d, "V2SLLiV2d", "nc")
+
+BUILTIN(__builtin_msa_ftrunc_u_w, "V4UiV4f", "nc")
+BUILTIN(__builtin_msa_ftrunc_u_d, "V2ULLiV2d", "nc")
+
+BUILTIN(__builtin_msa_hadd_s_h, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_hadd_s_w, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_hadd_s_d, "V2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_hadd_u_h, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_hadd_u_w, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_hadd_u_d, "V2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_hsub_s_h, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_hsub_s_w, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_hsub_s_d, "V2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_hsub_u_h, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_hsub_u_w, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_hsub_u_d, "V2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_ilvev_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvev_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvev_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvev_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_ilvl_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvl_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvl_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvl_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_ilvod_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvod_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvod_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvod_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_ilvr_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvr_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvr_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvr_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_insert_b, "V16ScV16ScIUii", "nc")
+BUILTIN(__builtin_msa_insert_h, "V8SsV8SsIUii", "nc")
+BUILTIN(__builtin_msa_insert_w, "V4SiV4SiIUii", "nc")
+BUILTIN(__builtin_msa_insert_d, "V2SLLiV2SLLiIUiLLi", "nc")
+
+BUILTIN(__builtin_msa_insve_b, "V16ScV16ScIUiV16Sc", "nc")
+BUILTIN(__builtin_msa_insve_h, "V8SsV8SsIUiV8Ss", "nc")
+BUILTIN(__builtin_msa_insve_w, "V4SiV4SiIUiV4Si", "nc")
+BUILTIN(__builtin_msa_insve_d, "V2SLLiV2SLLiIUiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ld_b, "V16Scv*Ii", "nc")
+BUILTIN(__builtin_msa_ld_h, "V8Ssv*Ii", "nc")
+BUILTIN(__builtin_msa_ld_w, "V4Siv*Ii", "nc")
+BUILTIN(__builtin_msa_ld_d, "V2SLLiv*Ii", "nc")
+
+BUILTIN(__builtin_msa_ldi_b, "V16cIi", "nc")
+BUILTIN(__builtin_msa_ldi_h, "V8sIi", "nc")
+BUILTIN(__builtin_msa_ldi_w, "V4iIi", "nc")
+BUILTIN(__builtin_msa_ldi_d, "V2LLiIi", "nc")
+
+BUILTIN(__builtin_msa_madd_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_madd_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_maddr_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_maddr_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_maddv_b, "V16ScV16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_maddv_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_maddv_w, "V4SiV4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_maddv_d, "V2SLLiV2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_max_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_max_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_max_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_max_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_max_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_max_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_max_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_max_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_max_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_max_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_max_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_max_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_maxi_s_b, "V16ScV16ScIi", "nc")
+BUILTIN(__builtin_msa_maxi_s_h, "V8SsV8SsIi", "nc")
+BUILTIN(__builtin_msa_maxi_s_w, "V4SiV4SiIi", "nc")
+BUILTIN(__builtin_msa_maxi_s_d, "V2SLLiV2SLLiIi", "nc")
+
+BUILTIN(__builtin_msa_maxi_u_b, "V16UcV16UcIi", "nc")
+BUILTIN(__builtin_msa_maxi_u_h, "V8UsV8UsIi", "nc")
+BUILTIN(__builtin_msa_maxi_u_w, "V4UiV4UiIi", "nc")
+BUILTIN(__builtin_msa_maxi_u_d, "V2ULLiV2ULLiIi", "nc")
+
+BUILTIN(__builtin_msa_min_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_min_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_min_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_min_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_min_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_min_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_min_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_min_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_min_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_min_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_min_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_min_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_mini_s_b, "V16ScV16ScIi", "nc")
+BUILTIN(__builtin_msa_mini_s_h, "V8SsV8SsIi", "nc")
+BUILTIN(__builtin_msa_mini_s_w, "V4SiV4SiIi", "nc")
+BUILTIN(__builtin_msa_mini_s_d, "V2SLLiV2SLLiIi", "nc")
+
+BUILTIN(__builtin_msa_mini_u_b, "V16UcV16UcIi", "nc")
+BUILTIN(__builtin_msa_mini_u_h, "V8UsV8UsIi", "nc")
+BUILTIN(__builtin_msa_mini_u_w, "V4UiV4UiIi", "nc")
+BUILTIN(__builtin_msa_mini_u_d, "V2ULLiV2ULLiIi", "nc")
+
+BUILTIN(__builtin_msa_mod_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_mod_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mod_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_mod_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_mod_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_mod_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_mod_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_mod_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_move_v, "V16ScV16Sc", "nc")
+
+BUILTIN(__builtin_msa_msub_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_msub_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_msubr_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_msubr_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_msubv_b, "V16ScV16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_msubv_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_msubv_w, "V4SiV4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_msubv_d, "V2SLLiV2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_mul_q_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mul_q_w, "V4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_mulr_q_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mulr_q_w, "V4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_mulv_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_mulv_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mulv_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_mulv_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_nloc_b, "V16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_nloc_h, "V8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_nloc_w, "V4SiV4Si", "nc")
+BUILTIN(__builtin_msa_nloc_d, "V2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_nlzc_b, "V16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_nlzc_h, "V8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_nlzc_w, "V4SiV4Si", "nc")
+BUILTIN(__builtin_msa_nlzc_d, "V2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_nor_v, "V16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_nori_b, "V16UcV16cIUi", "nc")
+
+BUILTIN(__builtin_msa_or_v, "V16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_ori_b, "V16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_pckev_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_pckev_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_pckev_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_pckev_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_pckod_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_pckod_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_pckod_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_pckod_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_pcnt_b, "V16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_pcnt_h, "V8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_pcnt_w, "V4SiV4Si", "nc")
+BUILTIN(__builtin_msa_pcnt_d, "V2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_sat_s_b, "V16ScV16ScIUi", "nc")
+BUILTIN(__builtin_msa_sat_s_h, "V8SsV8SsIUi", "nc")
+BUILTIN(__builtin_msa_sat_s_w, "V4SiV4SiIUi", "nc")
+BUILTIN(__builtin_msa_sat_s_d, "V2SLLiV2SLLiIUi", "nc")
+
+BUILTIN(__builtin_msa_sat_u_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_sat_u_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_sat_u_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_sat_u_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_shf_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_shf_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_shf_w, "V4iV4iIUi", "nc")
+
+BUILTIN(__builtin_msa_sld_b, "V16cV16cUi", "nc")
+BUILTIN(__builtin_msa_sld_h, "V8sV8sUi", "nc")
+BUILTIN(__builtin_msa_sld_w, "V4iV4iUi", "nc")
+BUILTIN(__builtin_msa_sld_d, "V2LLiV2LLiUi", "nc")
+
+BUILTIN(__builtin_msa_sldi_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_sldi_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_sldi_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_sldi_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_sll_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_sll_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_sll_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_sll_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_slli_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_slli_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_slli_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_slli_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_splat_b, "V16cV16cUi", "nc")
+BUILTIN(__builtin_msa_splat_h, "V8sV8sUi", "nc")
+BUILTIN(__builtin_msa_splat_w, "V4iV4iUi", "nc")
+BUILTIN(__builtin_msa_splat_d, "V2LLiV2LLiUi", "nc")
+
+BUILTIN(__builtin_msa_splati_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_splati_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_splati_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_splati_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_sra_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_sra_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_sra_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_sra_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srai_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srai_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srai_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srai_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_srar_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_srar_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_srar_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_srar_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srari_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srari_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srari_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srari_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_srl_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_srl_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_srl_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_srl_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srli_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srli_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srli_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srli_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_srlr_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_srlr_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_srlr_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_srlr_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srlri_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srlri_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srlri_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srlri_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_st_b, "vV16Scv*Ii", "nc")
+BUILTIN(__builtin_msa_st_h, "vV8Ssv*Ii", "nc")
+BUILTIN(__builtin_msa_st_w, "vV4Siv*Ii", "nc")
+BUILTIN(__builtin_msa_st_d, "vV2SLLiv*Ii", "nc")
+
+BUILTIN(__builtin_msa_subs_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_subs_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_subs_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_subs_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_subs_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_subs_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_subs_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_subs_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_subsus_u_b, "V16UcV16UcV16Sc", "nc")
+BUILTIN(__builtin_msa_subsus_u_h, "V8UsV8UsV8Ss", "nc")
+BUILTIN(__builtin_msa_subsus_u_w, "V4UiV4UiV4Si", "nc")
+BUILTIN(__builtin_msa_subsus_u_d, "V2ULLiV2ULLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_subsuu_s_b, "V16ScV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_subsuu_s_h, "V8SsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_subsuu_s_w, "V4SiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_subsuu_s_d, "V2SLLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_subv_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_subv_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_subv_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_subv_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_subvi_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_subvi_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_subvi_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_subvi_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_vshf_b, "V16cV16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_vshf_h, "V8sV8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_vshf_w, "V4iV4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_vshf_d, "V2LLiV2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_xor_v, "V16cV16cV16c", "nc")
+
+BUILTIN(__builtin_msa_xori_b, "V16cV16cIUi", "nc")
+
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def
index 3c3f06c5ea3a..7e9b5eea8325 100644
--- a/include/clang/Basic/BuiltinsNVPTX.def
+++ b/include/clang/Basic/BuiltinsNVPTX.def
@@ -61,248 +61,506 @@ BUILTIN(__builtin_ptx_bar_sync, "vi", "n")
// Builtins exposed as part of NVVM
-BUILTIN(__syncthreads, "v", "n")
-BUILTIN(__nvvm_bar0, "v", "n")
-BUILTIN(__nvvm_bar0_popc, "ii", "n")
-BUILTIN(__nvvm_bar0_and, "ii", "n")
-BUILTIN(__nvvm_bar0_or, "ii", "n")
-BUILTIN(__nvvm_membar_cta, "v", "n")
-BUILTIN(__nvvm_membar_gl, "v", "n")
-BUILTIN(__nvvm_membar_sys, "v", "n")
-BUILTIN(__nvvm_popc_i, "ii", "nc")
-BUILTIN(__nvvm_popc_ll, "LiLi", "nc")
-BUILTIN(__nvvm_prmt, "UiUiUiUi", "nc")
-BUILTIN(__nvvm_min_i, "iii", "nc")
-BUILTIN(__nvvm_min_ui, "UiUiUi", "nc")
-BUILTIN(__nvvm_min_ll, "LLiLLiLLi", "nc")
-BUILTIN(__nvvm_min_ull, "ULLiULLiULLi", "nc")
-BUILTIN(__nvvm_max_i, "iii", "nc")
-BUILTIN(__nvvm_max_ui, "UiUiUi", "nc")
-BUILTIN(__nvvm_max_ll, "LLiLLiLLi", "nc")
-BUILTIN(__nvvm_max_ull, "ULLiULLiULLi", "nc")
-BUILTIN(__nvvm_mulhi_i, "iii", "nc")
-BUILTIN(__nvvm_mulhi_ui, "UiUiUi", "nc")
-BUILTIN(__nvvm_mulhi_ll, "LLiLLiLLi", "nc")
-BUILTIN(__nvvm_mulhi_ull, "ULLiULLiULLi", "nc")
-BUILTIN(__nvvm_mul24_i, "iii", "nc")
-BUILTIN(__nvvm_mul24_ui, "UiUiUi", "nc")
-BUILTIN(__nvvm_brev32, "UiUi", "nc")
-BUILTIN(__nvvm_brev64, "ULLiULLi", "nc")
-BUILTIN(__nvvm_sad_i, "iiii", "nc")
-BUILTIN(__nvvm_sad_ui, "UiUiUiUi", "nc")
-BUILTIN(__nvvm_abs_i, "ii", "nc")
-BUILTIN(__nvvm_abs_ll, "LiLi", "nc")
-BUILTIN(__nvvm_floor_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_floor_f, "ff", "nc")
-BUILTIN(__nvvm_floor_d, "dd", "nc")
-BUILTIN(__nvvm_fabs_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_fabs_f, "ff", "nc")
-BUILTIN(__nvvm_fabs_d, "dd", "nc")
-BUILTIN(__nvvm_rcp_approx_ftz_d, "dd", "nc")
-BUILTIN(__nvvm_fmin_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_fmin_f, "fff", "nc")
-BUILTIN(__nvvm_fmax_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_fmax_f, "fff", "nc")
-BUILTIN(__nvvm_rsqrt_approx_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_rsqrt_approx_f, "ff", "nc")
-BUILTIN(__nvvm_fmin_d, "ddd", "nc")
-BUILTIN(__nvvm_fmax_d, "ddd", "nc")
-BUILTIN(__nvvm_rsqrt_approx_d, "dd", "nc")
-BUILTIN(__nvvm_ceil_d, "dd", "nc")
-BUILTIN(__nvvm_trunc_d, "dd", "nc")
-BUILTIN(__nvvm_round_d, "dd", "nc")
-BUILTIN(__nvvm_ex2_approx_d, "dd", "nc")
-BUILTIN(__nvvm_lg2_approx_d, "dd", "nc")
-BUILTIN(__nvvm_round_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_round_f, "ff", "nc")
-BUILTIN(__nvvm_ex2_approx_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_ex2_approx_f, "ff", "nc")
-BUILTIN(__nvvm_lg2_approx_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_lg2_approx_f, "ff", "nc")
-BUILTIN(__nvvm_sin_approx_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_sin_approx_f, "ff", "nc")
-BUILTIN(__nvvm_cos_approx_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_cos_approx_f, "ff", "nc")
-BUILTIN(__nvvm_trunc_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_trunc_f, "ff", "nc")
-BUILTIN(__nvvm_ceil_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_ceil_f, "ff", "nc")
-BUILTIN(__nvvm_saturate_d, "dd", "nc")
-BUILTIN(__nvvm_saturate_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_saturate_f, "ff", "nc")
-BUILTIN(__nvvm_fma_rn_ftz_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rn_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rz_ftz_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rz_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rm_ftz_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rm_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rp_ftz_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rp_f, "ffff", "nc")
-BUILTIN(__nvvm_fma_rn_d, "dddd", "nc")
-BUILTIN(__nvvm_fma_rz_d, "dddd", "nc")
-BUILTIN(__nvvm_fma_rm_d, "dddd", "nc")
-BUILTIN(__nvvm_fma_rp_d, "dddd", "nc")
-BUILTIN(__nvvm_div_approx_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_div_approx_f, "fff", "nc")
-BUILTIN(__nvvm_div_rn_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_div_rn_f, "fff", "nc")
-BUILTIN(__nvvm_div_rz_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_div_rz_f, "fff", "nc")
-BUILTIN(__nvvm_div_rm_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_div_rm_f, "fff", "nc")
-BUILTIN(__nvvm_div_rp_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_div_rp_f, "fff", "nc")
-BUILTIN(__nvvm_rcp_rn_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_rcp_rn_f, "ff", "nc")
-BUILTIN(__nvvm_rcp_rz_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_rcp_rz_f, "ff", "nc")
-BUILTIN(__nvvm_rcp_rm_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_rcp_rm_f, "ff", "nc")
-BUILTIN(__nvvm_rcp_rp_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_rcp_rp_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rn_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rn_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rz_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rz_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rm_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rm_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rp_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_rp_f, "ff", "nc")
-BUILTIN(__nvvm_div_rn_d, "ddd", "nc")
-BUILTIN(__nvvm_div_rz_d, "ddd", "nc")
-BUILTIN(__nvvm_div_rm_d, "ddd", "nc")
-BUILTIN(__nvvm_div_rp_d, "ddd", "nc")
-BUILTIN(__nvvm_rcp_rn_d, "dd", "nc")
-BUILTIN(__nvvm_rcp_rz_d, "dd", "nc")
-BUILTIN(__nvvm_rcp_rm_d, "dd", "nc")
-BUILTIN(__nvvm_rcp_rp_d, "dd", "nc")
-BUILTIN(__nvvm_sqrt_rn_d, "dd", "nc")
-BUILTIN(__nvvm_sqrt_rz_d, "dd", "nc")
-BUILTIN(__nvvm_sqrt_rm_d, "dd", "nc")
-BUILTIN(__nvvm_sqrt_rp_d, "dd", "nc")
-BUILTIN(__nvvm_sqrt_approx_ftz_f, "ff", "nc")
-BUILTIN(__nvvm_sqrt_approx_f, "ff", "nc")
-BUILTIN(__nvvm_add_rn_d, "ddd", "nc")
-BUILTIN(__nvvm_add_rz_d, "ddd", "nc")
-BUILTIN(__nvvm_add_rm_d, "ddd", "nc")
-BUILTIN(__nvvm_add_rp_d, "ddd", "nc")
-BUILTIN(__nvvm_mul_rn_d, "ddd", "nc")
-BUILTIN(__nvvm_mul_rz_d, "ddd", "nc")
-BUILTIN(__nvvm_mul_rm_d, "ddd", "nc")
-BUILTIN(__nvvm_mul_rp_d, "ddd", "nc")
-BUILTIN(__nvvm_add_rm_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_add_rm_f, "fff", "nc")
-BUILTIN(__nvvm_add_rp_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_add_rp_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rm_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rm_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rp_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rp_f, "fff", "nc")
-BUILTIN(__nvvm_add_rn_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_add_rn_f, "fff", "nc")
-BUILTIN(__nvvm_add_rz_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_add_rz_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rn_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rn_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rz_ftz_f, "fff", "nc")
-BUILTIN(__nvvm_mul_rz_f, "fff", "nc")
-BUILTIN(__nvvm_d2f_rn_ftz, "fd", "nc")
-BUILTIN(__nvvm_d2f_rn, "fd", "nc")
-BUILTIN(__nvvm_d2f_rz_ftz, "fd", "nc")
-BUILTIN(__nvvm_d2f_rz, "fd", "nc")
-BUILTIN(__nvvm_d2f_rm_ftz, "fd", "nc")
-BUILTIN(__nvvm_d2f_rm, "fd", "nc")
-BUILTIN(__nvvm_d2f_rp_ftz, "fd", "nc")
-BUILTIN(__nvvm_d2f_rp, "fd", "nc")
-BUILTIN(__nvvm_d2i_rn, "id", "nc")
-BUILTIN(__nvvm_d2i_rz, "id", "nc")
-BUILTIN(__nvvm_d2i_rm, "id", "nc")
-BUILTIN(__nvvm_d2i_rp, "id", "nc")
-BUILTIN(__nvvm_d2ui_rn, "Uid", "nc")
-BUILTIN(__nvvm_d2ui_rz, "Uid", "nc")
-BUILTIN(__nvvm_d2ui_rm, "Uid", "nc")
-BUILTIN(__nvvm_d2ui_rp, "Uid", "nc")
-BUILTIN(__nvvm_i2d_rn, "di", "nc")
-BUILTIN(__nvvm_i2d_rz, "di", "nc")
-BUILTIN(__nvvm_i2d_rm, "di", "nc")
-BUILTIN(__nvvm_i2d_rp, "di", "nc")
-BUILTIN(__nvvm_ui2d_rn, "dUi", "nc")
-BUILTIN(__nvvm_ui2d_rz, "dUi", "nc")
-BUILTIN(__nvvm_ui2d_rm, "dUi", "nc")
-BUILTIN(__nvvm_ui2d_rp, "dUi", "nc")
-BUILTIN(__nvvm_f2i_rn_ftz, "if", "nc")
-BUILTIN(__nvvm_f2i_rn, "if", "nc")
-BUILTIN(__nvvm_f2i_rz_ftz, "if", "nc")
-BUILTIN(__nvvm_f2i_rz, "if", "nc")
-BUILTIN(__nvvm_f2i_rm_ftz, "if", "nc")
-BUILTIN(__nvvm_f2i_rm, "if", "nc")
-BUILTIN(__nvvm_f2i_rp_ftz, "if", "nc")
-BUILTIN(__nvvm_f2i_rp, "if", "nc")
-BUILTIN(__nvvm_f2ui_rn_ftz, "Uif", "nc")
-BUILTIN(__nvvm_f2ui_rn, "Uif", "nc")
-BUILTIN(__nvvm_f2ui_rz_ftz, "Uif", "nc")
-BUILTIN(__nvvm_f2ui_rz, "Uif", "nc")
-BUILTIN(__nvvm_f2ui_rm_ftz, "Uif", "nc")
-BUILTIN(__nvvm_f2ui_rm, "Uif", "nc")
-BUILTIN(__nvvm_f2ui_rp_ftz, "Uif", "nc")
-BUILTIN(__nvvm_f2ui_rp, "Uif", "nc")
-BUILTIN(__nvvm_i2f_rn, "fi", "nc")
-BUILTIN(__nvvm_i2f_rz, "fi", "nc")
-BUILTIN(__nvvm_i2f_rm, "fi", "nc")
-BUILTIN(__nvvm_i2f_rp, "fi", "nc")
-BUILTIN(__nvvm_ui2f_rn, "fUi", "nc")
-BUILTIN(__nvvm_ui2f_rz, "fUi", "nc")
-BUILTIN(__nvvm_ui2f_rm, "fUi", "nc")
-BUILTIN(__nvvm_ui2f_rp, "fUi", "nc")
-BUILTIN(__nvvm_lohi_i2d, "dii", "nc")
-BUILTIN(__nvvm_d2i_lo, "id", "nc")
-BUILTIN(__nvvm_d2i_hi, "id", "nc")
-BUILTIN(__nvvm_f2ll_rn_ftz, "LLif", "nc")
-BUILTIN(__nvvm_f2ll_rn, "LLif", "nc")
-BUILTIN(__nvvm_f2ll_rz_ftz, "LLif", "nc")
-BUILTIN(__nvvm_f2ll_rz, "LLif", "nc")
-BUILTIN(__nvvm_f2ll_rm_ftz, "LLif", "nc")
-BUILTIN(__nvvm_f2ll_rm, "LLif", "nc")
-BUILTIN(__nvvm_f2ll_rp_ftz, "LLif", "nc")
-BUILTIN(__nvvm_f2ll_rp, "LLif", "nc")
-BUILTIN(__nvvm_f2ull_rn_ftz, "ULLif", "nc")
-BUILTIN(__nvvm_f2ull_rn, "ULLif", "nc")
-BUILTIN(__nvvm_f2ull_rz_ftz, "ULLif", "nc")
-BUILTIN(__nvvm_f2ull_rz, "ULLif", "nc")
-BUILTIN(__nvvm_f2ull_rm_ftz, "ULLif", "nc")
-BUILTIN(__nvvm_f2ull_rm, "ULLif", "nc")
-BUILTIN(__nvvm_f2ull_rp_ftz, "ULLif", "nc")
-BUILTIN(__nvvm_f2ull_rp, "ULLif", "nc")
-BUILTIN(__nvvm_d2ll_rn, "LLid", "nc")
-BUILTIN(__nvvm_d2ll_rz, "LLid", "nc")
-BUILTIN(__nvvm_d2ll_rm, "LLid", "nc")
-BUILTIN(__nvvm_d2ll_rp, "LLid", "nc")
-BUILTIN(__nvvm_d2ull_rn, "ULLid", "nc")
-BUILTIN(__nvvm_d2ull_rz, "ULLid", "nc")
-BUILTIN(__nvvm_d2ull_rm, "ULLid", "nc")
-BUILTIN(__nvvm_d2ull_rp, "ULLid", "nc")
-BUILTIN(__nvvm_ll2f_rn, "fLLi", "nc")
-BUILTIN(__nvvm_ll2f_rz, "fLLi", "nc")
-BUILTIN(__nvvm_ll2f_rm, "fLLi", "nc")
-BUILTIN(__nvvm_ll2f_rp, "fLLi", "nc")
-BUILTIN(__nvvm_ull2f_rn, "fULLi", "nc")
-BUILTIN(__nvvm_ull2f_rz, "fULLi", "nc")
-BUILTIN(__nvvm_ull2f_rm, "fULLi", "nc")
-BUILTIN(__nvvm_ull2f_rp, "fULLi", "nc")
-BUILTIN(__nvvm_ll2d_rn, "dLLi", "nc")
-BUILTIN(__nvvm_ll2d_rz, "dLLi", "nc")
-BUILTIN(__nvvm_ll2d_rm, "dLLi", "nc")
-BUILTIN(__nvvm_ll2d_rp, "dLLi", "nc")
-BUILTIN(__nvvm_ull2d_rn, "dULLi", "nc")
-BUILTIN(__nvvm_ull2d_rz, "dULLi", "nc")
-BUILTIN(__nvvm_ull2d_rm, "dULLi", "nc")
-BUILTIN(__nvvm_ull2d_rp, "dULLi", "nc")
-BUILTIN(__nvvm_f2h_rn_ftz, "Usf", "nc")
-BUILTIN(__nvvm_f2h_rn, "Usf", "nc")
-BUILTIN(__nvvm_h2f, "fUs", "nc")
-BUILTIN(__nvvm_bitcast_i2f, "fi", "nc")
-BUILTIN(__nvvm_bitcast_f2i, "if", "nc")
-BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "nc")
-BUILTIN(__nvvm_bitcast_d2ll, "LLid", "nc")
+// MISC
+
+BUILTIN(__nvvm_clz_i, "ii", "")
+BUILTIN(__nvvm_clz_ll, "iLLi", "")
+BUILTIN(__nvvm_popc_i, "ii", "")
+BUILTIN(__nvvm_popc_ll, "iLLi", "")
+BUILTIN(__nvvm_prmt, "UiUiUiUi", "")
+
+// Min Max
+
+BUILTIN(__nvvm_min_i, "iii", "")
+BUILTIN(__nvvm_min_ui, "UiUiUi", "")
+BUILTIN(__nvvm_min_ll, "LLiLLiLLi", "")
+BUILTIN(__nvvm_min_ull, "ULLiULLiULLi", "")
+
+BUILTIN(__nvvm_max_i, "iii", "")
+BUILTIN(__nvvm_max_ui, "UiUiUi", "")
+BUILTIN(__nvvm_max_ll, "LLiLLiLLi", "")
+BUILTIN(__nvvm_max_ull, "ULLiULLiULLi", "")
+
+BUILTIN(__nvvm_fmax_ftz_f, "fff", "")
+BUILTIN(__nvvm_fmax_f, "fff", "")
+BUILTIN(__nvvm_fmin_ftz_f, "fff", "")
+BUILTIN(__nvvm_fmin_f, "fff", "")
+
+BUILTIN(__nvvm_fmax_d, "ddd", "")
+BUILTIN(__nvvm_fmin_d, "ddd", "")
+
+// Multiplication
+
+BUILTIN(__nvvm_mulhi_i, "iii", "")
+BUILTIN(__nvvm_mulhi_ui, "UiUiUi", "")
+BUILTIN(__nvvm_mulhi_ll, "LLiLLiLLi", "")
+BUILTIN(__nvvm_mulhi_ull, "ULLiULLiULLi", "")
+
+BUILTIN(__nvvm_mul_rn_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rn_f, "fff", "")
+BUILTIN(__nvvm_mul_rz_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rz_f, "fff", "")
+BUILTIN(__nvvm_mul_rm_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rm_f, "fff", "")
+BUILTIN(__nvvm_mul_rp_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rp_f, "fff", "")
+
+BUILTIN(__nvvm_mul_rn_d, "ddd", "")
+BUILTIN(__nvvm_mul_rz_d, "ddd", "")
+BUILTIN(__nvvm_mul_rm_d, "ddd", "")
+BUILTIN(__nvvm_mul_rp_d, "ddd", "")
+
+BUILTIN(__nvvm_mul24_i, "iii", "")
+BUILTIN(__nvvm_mul24_ui, "UiUiUi", "")
+
+// Div
+
+BUILTIN(__nvvm_div_approx_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_approx_f, "fff", "")
+
+BUILTIN(__nvvm_div_rn_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rn_f, "fff", "")
+BUILTIN(__nvvm_div_rz_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rz_f, "fff", "")
+BUILTIN(__nvvm_div_rm_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rm_f, "fff", "")
+BUILTIN(__nvvm_div_rp_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rp_f, "fff", "")
+
+BUILTIN(__nvvm_div_rn_d, "ddd", "")
+BUILTIN(__nvvm_div_rz_d, "ddd", "")
+BUILTIN(__nvvm_div_rm_d, "ddd", "")
+BUILTIN(__nvvm_div_rp_d, "ddd", "")
+
+// Brev
+
+BUILTIN(__nvvm_brev32, "UiUi", "")
+BUILTIN(__nvvm_brev64, "ULLiULLi", "")
+
+// Sad
+
+BUILTIN(__nvvm_sad_i, "iii", "")
+BUILTIN(__nvvm_sad_ui, "UiUiUi", "")
+
+// Floor, Ceil
+
+BUILTIN(__nvvm_floor_ftz_f, "ff", "")
+BUILTIN(__nvvm_floor_f, "ff", "")
+BUILTIN(__nvvm_floor_d, "dd", "")
+
+BUILTIN(__nvvm_ceil_ftz_f, "ff", "")
+BUILTIN(__nvvm_ceil_f, "ff", "")
+BUILTIN(__nvvm_ceil_d, "dd", "")
+
+// Abs
+
+BUILTIN(__nvvm_abs_i, "ii", "")
+BUILTIN(__nvvm_abs_ll, "LLiLLi", "")
+
+BUILTIN(__nvvm_fabs_ftz_f, "ff", "")
+BUILTIN(__nvvm_fabs_f, "ff", "")
+BUILTIN(__nvvm_fabs_d, "dd", "")
+
+// Round
+
+BUILTIN(__nvvm_round_ftz_f, "ff", "")
+BUILTIN(__nvvm_round_f, "ff", "")
+BUILTIN(__nvvm_round_d, "dd", "")
+
+// Trunc
+
+BUILTIN(__nvvm_trunc_ftz_f, "ff", "")
+BUILTIN(__nvvm_trunc_f, "ff", "")
+BUILTIN(__nvvm_trunc_d, "dd", "")
+
+// Saturate
+
+BUILTIN(__nvvm_saturate_ftz_f, "ff", "")
+BUILTIN(__nvvm_saturate_f, "ff", "")
+BUILTIN(__nvvm_saturate_d, "dd", "")
+
+// Exp2, Log2
+
+BUILTIN(__nvvm_ex2_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_ex2_approx_f, "ff", "")
+BUILTIN(__nvvm_ex2_approx_d, "dd", "")
+
+BUILTIN(__nvvm_lg2_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_lg2_approx_f, "ff", "")
+BUILTIN(__nvvm_lg2_approx_d, "dd", "")
+
+// Sin, Cos
+
+BUILTIN(__nvvm_sin_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_sin_approx_f, "ff", "")
+
+BUILTIN(__nvvm_cos_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_cos_approx_f, "ff", "")
+
+// Fma
+
+BUILTIN(__nvvm_fma_rn_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rn_f, "ffff", "")
+BUILTIN(__nvvm_fma_rz_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rm_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rm_f, "ffff", "")
+BUILTIN(__nvvm_fma_rp_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rp_f, "ffff", "")
+BUILTIN(__nvvm_fma_rn_d, "dddd", "")
+BUILTIN(__nvvm_fma_rz_d, "dddd", "")
+BUILTIN(__nvvm_fma_rm_d, "dddd", "")
+BUILTIN(__nvvm_fma_rp_d, "dddd", "")
+
+// Rcp
+
+BUILTIN(__nvvm_rcp_rn_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rn_f, "ff", "")
+BUILTIN(__nvvm_rcp_rz_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rm_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rm_f, "ff", "")
+BUILTIN(__nvvm_rcp_rp_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rp_f, "ff", "")
+
+BUILTIN(__nvvm_rcp_rn_d, "dd", "")
+BUILTIN(__nvvm_rcp_rz_d, "dd", "")
+BUILTIN(__nvvm_rcp_rm_d, "dd", "")
+BUILTIN(__nvvm_rcp_rp_d, "dd", "")
+BUILTIN(__nvvm_rcp_approx_ftz_d, "dd", "")
+
+// Sqrt
+
+BUILTIN(__nvvm_sqrt_rn_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rn_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rz_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rm_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rm_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rp_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rp_f, "ff", "")
+BUILTIN(__nvvm_sqrt_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_approx_f, "ff", "")
+
+BUILTIN(__nvvm_sqrt_rn_d, "dd", "")
+BUILTIN(__nvvm_sqrt_rz_d, "dd", "")
+BUILTIN(__nvvm_sqrt_rm_d, "dd", "")
+BUILTIN(__nvvm_sqrt_rp_d, "dd", "")
+
+// Rsqrt
+
+BUILTIN(__nvvm_rsqrt_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_rsqrt_approx_f, "ff", "")
+BUILTIN(__nvvm_rsqrt_approx_d, "dd", "")
+
+// Add
+
+BUILTIN(__nvvm_add_rn_ftz_f, "ff", "")
+BUILTIN(__nvvm_add_rn_f, "ff", "")
+BUILTIN(__nvvm_add_rz_ftz_f, "ff", "")
+BUILTIN(__nvvm_add_rz_f, "ff", "")
+BUILTIN(__nvvm_add_rm_ftz_f, "ff", "")
+BUILTIN(__nvvm_add_rm_f, "ff", "")
+BUILTIN(__nvvm_add_rp_ftz_f, "ff", "")
+BUILTIN(__nvvm_add_rp_f, "ff", "")
+
+BUILTIN(__nvvm_add_rn_d, "dd", "")
+BUILTIN(__nvvm_add_rz_d, "dd", "")
+BUILTIN(__nvvm_add_rm_d, "dd", "")
+BUILTIN(__nvvm_add_rp_d, "dd", "")
+
+// Convert
+
+BUILTIN(__nvvm_d2f_rn_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rn, "fd", "")
+BUILTIN(__nvvm_d2f_rz_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rz, "fd", "")
+BUILTIN(__nvvm_d2f_rm_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rm, "fd", "")
+BUILTIN(__nvvm_d2f_rp_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rp, "fd", "")
+
+BUILTIN(__nvvm_d2i_rn, "id", "")
+BUILTIN(__nvvm_d2i_rz, "id", "")
+BUILTIN(__nvvm_d2i_rm, "id", "")
+BUILTIN(__nvvm_d2i_rp, "id", "")
+
+BUILTIN(__nvvm_d2ui_rn, "Uid", "")
+BUILTIN(__nvvm_d2ui_rz, "Uid", "")
+BUILTIN(__nvvm_d2ui_rm, "Uid", "")
+BUILTIN(__nvvm_d2ui_rp, "Uid", "")
+
+BUILTIN(__nvvm_i2d_rn, "di", "")
+BUILTIN(__nvvm_i2d_rz, "di", "")
+BUILTIN(__nvvm_i2d_rm, "di", "")
+BUILTIN(__nvvm_i2d_rp, "di", "")
+
+BUILTIN(__nvvm_ui2d_rn, "dUi", "")
+BUILTIN(__nvvm_ui2d_rz, "dUi", "")
+BUILTIN(__nvvm_ui2d_rm, "dUi", "")
+BUILTIN(__nvvm_ui2d_rp, "dUi", "")
+
+BUILTIN(__nvvm_f2i_rn_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rn, "if", "")
+BUILTIN(__nvvm_f2i_rz_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rz, "if", "")
+BUILTIN(__nvvm_f2i_rm_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rm, "if", "")
+BUILTIN(__nvvm_f2i_rp_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rp, "if", "")
+
+BUILTIN(__nvvm_f2ui_rn_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rn, "Uif", "")
+BUILTIN(__nvvm_f2ui_rz_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rm_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rm, "Uif", "")
+BUILTIN(__nvvm_f2ui_rp_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rp, "Uif", "")
+
+BUILTIN(__nvvm_i2f_rn, "fi", "")
+BUILTIN(__nvvm_i2f_rz, "fi", "")
+BUILTIN(__nvvm_i2f_rm, "fi", "")
+BUILTIN(__nvvm_i2f_rp, "fi", "")
+
+BUILTIN(__nvvm_ui2f_rn, "fUi", "")
+BUILTIN(__nvvm_ui2f_rz, "fUi", "")
+BUILTIN(__nvvm_ui2f_rm, "fUi", "")
+BUILTIN(__nvvm_ui2f_rp, "fUi", "")
+
+BUILTIN(__nvvm_lohi_i2d, "dii", "")
+
+BUILTIN(__nvvm_d2i_lo, "id", "")
+BUILTIN(__nvvm_d2i_hi, "id", "")
+
+BUILTIN(__nvvm_f2ll_rn_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rn, "LLif", "")
+BUILTIN(__nvvm_f2ll_rz_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rm_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rm, "LLif", "")
+BUILTIN(__nvvm_f2ll_rp_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rp, "LLif", "")
+
+BUILTIN(__nvvm_f2ull_rn_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rn, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rz_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rm_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rm, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rp_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rp, "ULLif", "")
+
+BUILTIN(__nvvm_d2ll_rn, "LLid", "")
+BUILTIN(__nvvm_d2ll_rz, "LLid", "")
+BUILTIN(__nvvm_d2ll_rm, "LLid", "")
+BUILTIN(__nvvm_d2ll_rp, "LLid", "")
+
+BUILTIN(__nvvm_d2ull_rn, "ULLid", "")
+BUILTIN(__nvvm_d2ull_rz, "ULLid", "")
+BUILTIN(__nvvm_d2ull_rm, "ULLid", "")
+BUILTIN(__nvvm_d2ull_rp, "ULLid", "")
+
+BUILTIN(__nvvm_ll2f_rn, "fLLi", "")
+BUILTIN(__nvvm_ll2f_rz, "fLLi", "")
+BUILTIN(__nvvm_ll2f_rm, "fLLi", "")
+BUILTIN(__nvvm_ll2f_rp, "fLLi", "")
+
+BUILTIN(__nvvm_ull2f_rn, "fULLi", "")
+BUILTIN(__nvvm_ull2f_rz, "fULLi", "")
+BUILTIN(__nvvm_ull2f_rm, "fULLi", "")
+BUILTIN(__nvvm_ull2f_rp, "fULLi", "")
+
+BUILTIN(__nvvm_ll2d_rn, "dLLi", "")
+BUILTIN(__nvvm_ll2d_rz, "dLLi", "")
+BUILTIN(__nvvm_ll2d_rm, "dLLi", "")
+BUILTIN(__nvvm_ll2d_rp, "dLLi", "")
+
+BUILTIN(__nvvm_ull2d_rn, "dULLi", "")
+BUILTIN(__nvvm_ull2d_rz, "dULLi", "")
+BUILTIN(__nvvm_ull2d_rm, "dULLi", "")
+BUILTIN(__nvvm_ull2d_rp, "dULLi", "")
+
+BUILTIN(__nvvm_f2h_rn_ftz, "Usf", "")
+BUILTIN(__nvvm_f2h_rn, "Usf", "")
+
+BUILTIN(__nvvm_h2f, "fUs", "")
+
+// Bitcast
+
+BUILTIN(__nvvm_bitcast_f2i, "if", "")
+BUILTIN(__nvvm_bitcast_i2f, "fi", "")
+
+BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "")
+BUILTIN(__nvvm_bitcast_d2ll, "LLid", "")
+
+// Sync
+
+BUILTIN(__syncthreads, "v", "")
+BUILTIN(__nvvm_bar0, "v", "")
+BUILTIN(__nvvm_bar0_popc, "ii", "")
+BUILTIN(__nvvm_bar0_and, "ii", "")
+BUILTIN(__nvvm_bar0_or, "ii", "")
+
+// Membar
+
+BUILTIN(__nvvm_membar_cta, "v", "")
+BUILTIN(__nvvm_membar_gl, "v", "")
+BUILTIN(__nvvm_membar_sys, "v", "")
+
+// Memcpy, Memset
+
+BUILTIN(__nvvm_memcpy, "vUc*Uc*zi","")
+BUILTIN(__nvvm_memset, "vUc*Uczi","")
+
+// Image
+
+BUILTIN(__builtin_ptx_read_image2Dfi_, "V4fiiii", "")
+BUILTIN(__builtin_ptx_read_image2Dff_, "V4fiiff", "")
+BUILTIN(__builtin_ptx_read_image2Dii_, "V4iiiii", "")
+BUILTIN(__builtin_ptx_read_image2Dif_, "V4iiiff", "")
+
+BUILTIN(__builtin_ptx_read_image3Dfi_, "V4fiiiiii", "")
+BUILTIN(__builtin_ptx_read_image3Dff_, "V4fiiffff", "")
+BUILTIN(__builtin_ptx_read_image3Dii_, "V4iiiiiii", "")
+BUILTIN(__builtin_ptx_read_image3Dif_, "V4iiiffff", "")
+
+BUILTIN(__builtin_ptx_write_image2Df_, "viiiffff", "")
+BUILTIN(__builtin_ptx_write_image2Di_, "viiiiiii", "")
+BUILTIN(__builtin_ptx_write_image2Dui_, "viiiUiUiUiUi", "")
+BUILTIN(__builtin_ptx_get_image_depthi_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_heighti_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_widthi_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_channel_data_typei_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_channel_orderi_, "ii", "")
+
+// Atomic
+//
+// We need the atom intrinsics because
+// - they are used in converging analysis
+// - they are used in address space analysis and optimization
+// So it does not hurt to expose them as builtins.
+//
+BUILTIN(__nvvm_atom_add_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_add_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_add_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_add_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_add_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_add_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_add_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_add_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_add_gen_ll, "LLiLLiD*LLi", "n")
+BUILTIN(__nvvm_atom_add_g_f, "ffD*1f", "n")
+BUILTIN(__nvvm_atom_add_s_f, "ffD*3f", "n")
+BUILTIN(__nvvm_atom_add_gen_f, "ffD*f", "n")
+
+BUILTIN(__nvvm_atom_sub_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_sub_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_sub_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_sub_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_sub_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_sub_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_sub_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_sub_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_sub_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_xchg_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_xchg_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_xchg_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_xchg_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_xchg_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_xchg_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_xchg_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_xchg_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_xchg_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_max_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_max_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_max_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_max_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_max_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_max_gen_ui, "UiUiD*Ui", "n")
+BUILTIN(__nvvm_atom_max_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_max_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_max_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_max_g_ul, "ULiULiD*1ULi", "n")
+BUILTIN(__nvvm_atom_max_s_ul, "ULiULiD*3ULi", "n")
+BUILTIN(__nvvm_atom_max_gen_ul, "ULiULiD*ULi", "n")
+BUILTIN(__nvvm_atom_max_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_max_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_max_gen_ll, "LLiLLiD*LLi", "n")
+BUILTIN(__nvvm_atom_max_g_ull, "ULLiULLiD*1ULLi", "n")
+BUILTIN(__nvvm_atom_max_s_ull, "ULLiULLiD*3ULLi", "n")
+BUILTIN(__nvvm_atom_max_gen_ull, "ULLiULLiD*ULLi", "n")
+
+BUILTIN(__nvvm_atom_min_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_min_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_min_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_min_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_min_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_min_gen_ui, "UiUiD*Ui", "n")
+BUILTIN(__nvvm_atom_min_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_min_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_min_gen_l, "LiLi10D*Li", "n")
+BUILTIN(__nvvm_atom_min_g_ul, "ULiULiD*1ULi", "n")
+BUILTIN(__nvvm_atom_min_s_ul, "ULiULiD*3ULi", "n")
+BUILTIN(__nvvm_atom_min_gen_ul, "ULiULiD*ULi", "n")
+BUILTIN(__nvvm_atom_min_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_min_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_min_gen_ll, "LLiLLiD*LLi", "n")
+BUILTIN(__nvvm_atom_min_g_ull, "ULLiULLiD*1ULLi", "n")
+BUILTIN(__nvvm_atom_min_s_ull, "ULLiULLiD*3ULLi", "n")
+BUILTIN(__nvvm_atom_min_gen_ull, "ULLiULLiD*ULLi", "n")
+
+BUILTIN(__nvvm_atom_inc_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_inc_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_inc_gen_ui, "UiUiD*Ui", "n")
+BUILTIN(__nvvm_atom_dec_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_dec_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_dec_gen_ui, "UiUiD*Ui", "n")
+
+BUILTIN(__nvvm_atom_and_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_and_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_and_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_and_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_and_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_and_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_and_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_and_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_and_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_or_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_or_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_or_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_or_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_or_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_or_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_or_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_or_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_or_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_xor_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_xor_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_xor_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_xor_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_xor_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_xor_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_xor_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_xor_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_xor_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_cas_g_i, "iiD*1ii", "n")
+BUILTIN(__nvvm_atom_cas_s_i, "iiD*3ii", "n")
+BUILTIN(__nvvm_atom_cas_gen_i, "iiD*ii", "n")
+BUILTIN(__nvvm_atom_cas_g_l, "LiLiD*1LiLi", "n")
+BUILTIN(__nvvm_atom_cas_s_l, "LiLiD*3LiLi", "n")
+BUILTIN(__nvvm_atom_cas_gen_l, "LiLiD*LiLi", "n")
+BUILTIN(__nvvm_atom_cas_g_ll, "LLiLLiD*1LLiLLi", "n")
+BUILTIN(__nvvm_atom_cas_s_ll, "LLiLLiD*3LLiLLi", "n")
+BUILTIN(__nvvm_atom_cas_gen_ll, "LLiLLiD*LLiLLi", "n")
+
+// Compiler Error Warn
+BUILTIN(__nvvm_compiler_error, "vcC*4", "n")
+BUILTIN(__nvvm_compiler_warn, "vcC*4", "n")
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index d536821d55d9..51397fa45df6 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -258,6 +258,7 @@ BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "")
BUILTIN(__builtin_ia32_movmskpd, "iV2d", "")
BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "")
BUILTIN(__builtin_ia32_movnti, "vi*i", "")
+BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "")
BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "")
BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "")
BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "")
@@ -559,7 +560,7 @@ BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLi*", "")
BUILTIN(__builtin_ia32_vbroadcastss_ps, "V4fV4f", "")
BUILTIN(__builtin_ia32_vbroadcastss_ps256, "V8fV4f", "")
BUILTIN(__builtin_ia32_vbroadcastsd_pd256, "V4dV2d", "")
-BUILTIN(__builtin_ia32_vbroadcastsi256, "V4LLiV2LLiC*", "")
+BUILTIN(__builtin_ia32_vbroadcastsi256, "V4LLiV2LLi", "")
BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "")
BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "")
BUILTIN(__builtin_ia32_pbroadcastb256, "V32cV16c", "")
@@ -641,6 +642,19 @@ BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "")
BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "")
BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "")
+// TBM
+BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "")
+BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "")
+
+// SHA
+BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "")
+BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "")
+BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "")
+
// FMA4
BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "")
diff --git a/include/clang/Basic/BuiltinsXCore.def b/include/clang/Basic/BuiltinsXCore.def
new file mode 100644
index 000000000000..672d20578a63
--- /dev/null
+++ b/include/clang/Basic/BuiltinsXCore.def
@@ -0,0 +1,22 @@
+//===--- BuiltinsXCore.def - XCore Builtin function database ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the XCore-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+BUILTIN(__builtin_bitrev, "UiUi", "nc")
+BUILTIN(__builtin_getid, "Si", "nc")
+BUILTIN(__builtin_getps, "UiUi", "n")
+BUILTIN(__builtin_setps, "vUiUi", "n")
+
+#undef BUILTIN
diff --git a/include/clang/Basic/CapturedStmt.h b/include/clang/Basic/CapturedStmt.h
index 484bbb1feeef..c4a289b696dd 100644
--- a/include/clang/Basic/CapturedStmt.h
+++ b/include/clang/Basic/CapturedStmt.h
@@ -15,7 +15,8 @@ namespace clang {
/// \brief The different kinds of captured statement.
enum CapturedRegionKind {
- CR_Default
+ CR_Default,
+ CR_OpenMP
};
} // end namespace clang
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index ad2afa7a57cd..18bca5741962 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -44,6 +44,9 @@ def Named : Decl<1>;
def CXXDestructor : DDecl<CXXMethod>;
def CXXConversion : DDecl<CXXMethod>;
def Var : DDecl<Declarator>;
+ def VarTemplateSpecialization : DDecl<Var>;
+ def VarTemplatePartialSpecialization
+ : DDecl<VarTemplateSpecialization>;
def ImplicitParam : DDecl<Var>;
def ParmVar : DDecl<Var>;
def NonTypeTemplateParm : DDecl<Declarator>;
@@ -51,6 +54,7 @@ def Named : Decl<1>;
def RedeclarableTemplate : DDecl<Template, 1>;
def FunctionTemplate : DDecl<RedeclarableTemplate>;
def ClassTemplate : DDecl<RedeclarableTemplate>;
+ def VarTemplate : DDecl<RedeclarableTemplate>;
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
def TemplateTemplateParm : DDecl<Template>;
def Using : DDecl<Named>;
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 3e125944a361..c057bdf63436 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -21,7 +21,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/type_traits.h"
#include <list>
#include <vector>
@@ -490,7 +489,14 @@ public:
FatalErrorOccurred = true;
LastDiagLevel = DiagnosticIDs::Ignored;
}
-
+
+ /// \brief Determine whether the previous diagnostic was ignored. This can
+ /// be used by clients that want to determine whether notes attached to a
+ /// diagnostic will be suppressed.
+ bool isLastDiagnosticIgnored() const {
+ return LastDiagLevel == DiagnosticIDs::Ignored;
+ }
+
/// \brief Controls whether otherwise-unmapped extension diagnostics are
/// mapped onto ignore/warning/error.
///
@@ -983,6 +989,10 @@ public:
bool hasMaxRanges() const {
return NumRanges == DiagnosticsEngine::MaxRanges;
}
+
+ bool hasMaxFixItHints() const {
+ return NumFixits == DiagnosticsEngine::MaxFixItHints;
+ }
};
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -1212,7 +1222,7 @@ public:
~StoredDiagnostic();
/// \brief Evaluates true when this object stores a diagnostic.
- operator bool() const { return Message.size() > 0; }
+ LLVM_EXPLICIT operator bool() const { return Message.size() > 0; }
unsigned getID() const { return ID; }
DiagnosticsEngine::Level getLevel() const { return Level; }
diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
index 6dfecdcb7972..2616548bc009 100644
--- a/include/clang/Basic/Diagnostic.td
+++ b/include/clang/Basic/Diagnostic.td
@@ -26,6 +26,13 @@ def CLASS_WARNING : DiagClass;
def CLASS_EXTENSION : DiagClass;
def CLASS_ERROR : DiagClass;
+// Responses to a diagnostic in a SFINAE context.
+class SFINAEResponse;
+def SFINAE_SubstitutionFailure : SFINAEResponse;
+def SFINAE_Suppress : SFINAEResponse;
+def SFINAE_Report : SFINAEResponse;
+def SFINAE_AccessControl : SFINAEResponse;
+
// Diagnostic Categories. These can be applied to groups or individual
// diagnostics to specify a category.
class DiagCategory<string Name> {
@@ -52,19 +59,30 @@ include "DiagnosticGroups.td"
// All diagnostics emitted by the compiler are an indirect subclass of this.
class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
/// Component is specified by the file with a big let directive.
- string Component = ?;
- string Text = text;
- DiagClass Class = DC;
- bit SFINAE = 1;
- bit AccessControl = 0;
- bit WarningNoWerror = 0;
- bit WarningShowInSystemHeader = 0;
- DiagMapping DefaultMapping = defaultmapping;
- DiagGroup Group;
- string CategoryName = "";
+ string Component = ?;
+ string Text = text;
+ DiagClass Class = DC;
+ SFINAEResponse SFINAE = SFINAE_Suppress;
+ bit AccessControl = 0;
+ bit WarningNoWerror = 0;
+ bit WarningShowInSystemHeader = 0;
+ DiagMapping DefaultMapping = defaultmapping;
+ DiagGroup Group;
+ string CategoryName = "";
+}
+
+class SFINAEFailure {
+ SFINAEResponse SFINAE = SFINAE_SubstitutionFailure;
+}
+class NoSFINAE {
+ SFINAEResponse SFINAE = SFINAE_Report;
+}
+class AccessControl {
+ SFINAEResponse SFINAE = SFINAE_AccessControl;
}
-class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>;
+// FIXME: ExtWarn and Extension should also be SFINAEFailure by default.
+class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>, SFINAEFailure;
class Warning<string str> : Diagnostic<str, CLASS_WARNING, MAP_WARNING>;
class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>;
class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>;
@@ -82,9 +100,6 @@ class DefaultWarnShowInSystemHeader {
bit WarningShowInSystemHeader = 1;
}
-class NoSFINAE { bit SFINAE = 0; }
-class AccessControl { bit AccessControl = 1; }
-
// Definitions for Diagnostics.
include "DiagnosticASTKinds.td"
include "DiagnosticAnalysisKinds.td"
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index c69f85f18d3d..113e56490520 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -38,12 +38,16 @@ def note_constexpr_nonliteral : Note<
def note_constexpr_non_global : Note<
"%select{pointer|reference}0 to %select{|subobject of }1"
"%select{temporary|%3}2 is not a constant expression">;
+def note_constexpr_uninitialized : Note<
+ "%select{|sub}0object of type %1 is not initialized">;
def note_constexpr_array_index : Note<"cannot refer to element %0 of "
"%select{array of %2 elements|non-array object}1 in a constant expression">;
def note_constexpr_float_arithmetic : Note<
"floating point arithmetic produces %select{an infinity|a NaN}0">;
def note_constexpr_pointer_subtraction_not_same_array : Note<
"subtracted pointers are not elements of the same array">;
+def note_constexpr_pointer_subtraction_zero_size : Note<
+ "subtraction of pointers to type %0 of zero size">;
def note_constexpr_pointer_comparison_base_classes : Note<
"comparison of addresses of subobjects of different base classes "
"has unspecified value">;
@@ -83,12 +87,17 @@ def note_constexpr_depth_limit_exceeded : Note<
"constexpr evaluation exceeded maximum depth of %0 calls">;
def note_constexpr_call_limit_exceeded : Note<
"constexpr evaluation hit maximum call limit">;
+def note_constexpr_step_limit_exceeded : Note<
+ "constexpr evaluation hit maximum step limit; possible infinite loop?">;
def note_constexpr_lifetime_ended : Note<
"%select{read of|assignment to|increment of|decrement of}0 "
"%select{temporary|variable}1 whose lifetime has ended">;
def note_constexpr_access_uninit : Note<
"%select{read of|assignment to|increment of|decrement of}0 "
"object outside its lifetime is not allowed in a constant expression">;
+def note_constexpr_use_uninit_reference : Note<
+ "use of reference outside its lifetime "
+ "is not allowed in a constant expression">;
def note_constexpr_modify_const_type : Note<
"modification of object of const-qualified type %0 is not allowed "
"in a constant expression">;
@@ -115,9 +124,16 @@ def note_constexpr_access_inactive_union_member : Note<
"%select{read of|assignment to|increment of|decrement of}0 "
"member %1 of union with %select{active member %3|no active member}2 "
"is not allowed in a constant expression">;
+def note_constexpr_access_static_temporary : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 temporary "
+ "is not allowed in a constant expression outside the expression that "
+ "created the temporary">;
def note_constexpr_modify_global : Note<
"a constant expression cannot modify an object that is visible outside "
"that expression">;
+def note_constexpr_stmt_expr_unsupported : Note<
+ "this use of statement expressions is not supported in a "
+ "constant expression">;
def note_constexpr_calls_suppressed : Note<
"(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to "
"see all)">;
diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td
index c913e31ebad1..49781fec9a9c 100644
--- a/include/clang/Basic/DiagnosticCommentKinds.td
+++ b/include/clang/Basic/DiagnosticCommentKinds.td
@@ -160,5 +160,9 @@ def warn_unknown_comment_command_name : Warning<
"unknown command tag name">,
InGroup<DocumentationUnknownCommand>, DefaultIgnore;
+def warn_correct_comment_command_name : Warning<
+ "unknown command tag name '%0'; did you mean '%1'?">,
+ InGroup<Documentation>, DefaultIgnore;
+
} // end of documentation issue category
} // end of AST component
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 7ff6ae13b4ef..c54bafc07fe8 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -37,6 +37,9 @@ def note_possibility : Note<"one possibility">;
def note_also_found : Note<"also found">;
// Parse && Lex
+
+let CategoryName = "Lexical or Preprocessor Issue" in {
+
def err_expected_colon : Error<"expected ':'">;
def err_expected_colon_after_setter_name : Error<
"method name referenced in property setter attribute "
@@ -51,7 +54,12 @@ def err_invalid_character_udl : Error<
def err_invalid_numeric_udl : Error<
"numeric literal with user-defined suffix cannot be used here">;
+}
+
// Parse && Sema
+
+let CategoryName = "Parse Issue" in {
+
def err_param_redefinition : Error<"redefinition of parameter %0">;
def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">;
def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">,
@@ -79,6 +87,8 @@ def err_attribute_not_type_attr : Error<
"%0 attribute cannot be applied to types">;
def err_enum_template : Error<"enumeration cannot be a template">;
+}
+
// Sema && Lex
def ext_c99_longlong : Extension<
"'long long' is an extension when C99 mode is not enabled">,
@@ -89,10 +99,10 @@ def ext_cxx11_longlong : Extension<
def warn_cxx98_compat_longlong : Warning<
"'long long' is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
-def warn_integer_too_large : Warning<
- "integer constant is too large for its type">;
+def err_integer_too_large : Error<
+ "integer constant is larger than the largest unsigned integer type">;
def warn_integer_too_large_for_signed : Warning<
- "integer constant is so large that it is unsigned">;
+ "integer constant is larger than the largest signed integer type">;
// Sema && AST
def note_invalid_subexpr_in_const_expr : Note<
@@ -105,7 +115,9 @@ def err_target_unknown_triple : Error<
def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
def err_target_unknown_cxxabi : Error<"unknown C++ ABI '%0'">;
-def err_target_invalid_feature : Error<"invalid target feature '%0'">;
+def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">;
+def err_target_unsupported_fpmath : Error<
+ "the '%0' unit is not supported with this instruction set">;
// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index db457b15369d..b48980778c46 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -26,8 +26,6 @@ def err_drv_unsupported_rtlib_for_platform : Error<
"unsupported runtime library '%0' for platform '%1'">;
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<
"cannot use '%0' output with multiple -arch options">;
def err_drv_no_input_files : Error<"no input files">;
@@ -35,8 +33,10 @@ def err_drv_use_of_Z_option : Error<
"unsupported use of internal gcc -Z option '%0'">;
def err_drv_output_argument_with_multiple_files : Error<
"cannot specify -o when generating multiple output files">;
-def err_no_external_windows_assembler : Error<
- "there is no external assembler we can use on windows">;
+def err_drv_out_file_argument_with_multiple_sources : Error<
+ "cannot specify '%0%1' when compiling multiple source files">;
+def err_no_external_assembler : Error<
+ "there is no external assembler that can be used on this platform">;
def err_drv_unable_to_remove_file : Error<
"unable to remove file: %0">;
def err_drv_command_failure : Error<
@@ -77,8 +77,8 @@ def err_drv_invalid_mfloat_abi : Error<
"invalid float ABI '%0'">;
def err_drv_invalid_libcxx_deployment : Error<
"invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
-def err_drv_invalid_feature : Error<
- "invalid feature '%0' for CPU '%1'">;
+def err_drv_malformed_sanitizer_blacklist : Error<
+ "malformed sanitizer blacklist: '%0'">;
def err_drv_I_dash_not_supported : Error<
"'%0' not supported, please use -iquote instead">;
@@ -107,7 +107,14 @@ def err_drv_mg_requires_m_or_mm : Error<
"option '-MG' requires '-M' or '-MM'">;
def err_drv_unknown_objc_runtime : Error<
"unknown or ill-formed Objective-C runtime '%0'">;
+def err_drv_emit_llvm_link : Error<
+ "-emit-llvm cannot be used when linking">;
+def err_drv_unknown_toolchain : Error<
+ "cannot recognize the type of the toolchain">;
+def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
+def warn_drv_optimization_value : Warning<"optimization level '%0' is unsupported; using '%1%2' instead">,
+ InGroup<InvalidCommandLineArgument>;
def warn_c_kext : Warning<
"ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
def warn_drv_input_file_unused : Warning<
@@ -135,6 +142,9 @@ 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_overriding_flag_option : Warning<
+ "overriding '%0' option with '%1'">,
+ InGroup<DiagGroup<"overriding-t-option">>;
def warn_drv_treating_input_as_cxx : Warning<
"treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
InGroup<Deprecated>;
@@ -147,6 +157,8 @@ def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">,
def note_drv_command_failed_diag_msg : Note<
"diagnostic msg: %0">;
+def note_drv_t_option_is_global :
+ Note<"The last /TC or /TP option takes precedence over earlier instances">;
def err_analyzer_config_no_value : Error<
"analyzer-config option '%0' has a key but no value">;
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index f05fb9be82cc..bcf3c41cdb64 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -11,7 +11,7 @@ let Component = "Frontend" in {
def err_fe_error_opening : Error<"error opening '%0': %1">;
def err_fe_error_reading : Error<"error reading '%0'">;
-def err_fe_error_reading_stdin : Error<"error reading stdin">;
+def err_fe_error_reading_stdin : Error<"error reading stdin: %0">;
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
// Error generated by the backend.
@@ -136,9 +136,8 @@ def err_no_submodule_suggest : Error<
"no submodule named %0 in module '%1'; did you mean '%2'?">;
def warn_missing_submodule : Warning<"missing submodule '%0'">,
InGroup<IncompleteUmbrella>;
-def err_module_map_temp_file : Error<
- "unable to write temporary module map file '%0'">, DefaultFatal;
-def err_module_unavailable : Error<"module '%0' requires feature '%1'">;
+def err_module_unavailable : Error<
+ "module '%0' %select{is incompatible with|requires}1 feature '%2'">;
def warn_module_config_macro_undef : Warning<
"%select{definition|#undef}0 of configuration macro '%1' has no effect on "
"the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line "
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index d5f777d3d715..b0d02164ebc4 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -21,12 +21,16 @@ def : DiagGroup<"abi">;
def : DiagGroup<"address">;
def AddressOfTemporary : DiagGroup<"address-of-temporary">;
def : DiagGroup<"aggregate-return">;
+def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
+def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
def ArrayBounds : DiagGroup<"array-bounds">;
def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
def Availability : DiagGroup<"availability">;
def Section : DiagGroup<"section">;
def AutoImport : DiagGroup<"auto-import">;
+def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
+def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
def ConstantConversion :
DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
@@ -45,23 +49,39 @@ def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">;
def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
def C99Compat : DiagGroup<"c99-compat">;
def CXXCompat: DiagGroup<"c++-compat">;
+def ExternCCompat : DiagGroup<"extern-c-compat">;
+def KeywordCompat : DiagGroup<"keyword-compat">;
+def GNUCaseRange : DiagGroup<"gnu-case-range">;
def CastAlign : DiagGroup<"cast-align">;
def : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">;
+def GNUComplexInteger : DiagGroup<"gnu-complex-integer">;
+def GNUConditionalOmittedOperand : DiagGroup<"gnu-conditional-omitted-operand">;
def ConfigMacros : DiagGroup<"config-macros">;
def : DiagGroup<"ctor-dtor-privacy">;
def GNUDesignator : DiagGroup<"gnu-designator">;
+def GNUStringLiteralOperatorTemplate :
+ DiagGroup<"gnu-string-literal-operator-template">;
def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
def AbstractFinalClass : DiagGroup<"abstract-final-class">;
-def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
-def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings">;
-def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >,
- DiagCategory<"Deprecations">;
+def CXX11CompatDeprecatedWritableStr :
+ DiagGroup<"c++11-compat-deprecated-writable-strings">;
+def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
+def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
+def DeprecatedRegister : DiagGroup<"deprecated-register">;
+def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
+ [CXX11CompatDeprecatedWritableStr]>;
+// FIXME: Why are DeprecatedImplementations and DeprecatedWritableStr
+// not in this group?
+def Deprecated : DiagGroup<"deprecated", [DeprecatedDeclarations,
+ DeprecatedIncrementBool,
+ DeprecatedRegister]>,
+ DiagCategory<"Deprecations">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
@@ -77,16 +97,21 @@ def Documentation : DiagGroup<"documentation",
DocumentationDeprecatedSync]>;
def EmptyBody : DiagGroup<"empty-body">;
+def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">;
+def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">;
def ExtraTokens : DiagGroup<"extra-tokens">;
def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>;
+def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">;
+def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
+def GNUFoldingConstant : DiagGroup<"gnu-folding-constant">;
def FormatExtraArgs : DiagGroup<"format-extra-args">;
def FormatZeroLength : DiagGroup<"format-zero-length">;
// Warnings for C++1y code which is not compatible with prior C++ standards.
-def CXXPre1yCompat : DiagGroup<"cxx98-cxx11-compat">;
-def CXXPre1yCompatPedantic : DiagGroup<"cxx98-cxx11-compat-pedantic",
+def CXXPre1yCompat : DiagGroup<"c++98-c++11-compat">;
+def CXXPre1yCompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
[CXXPre1yCompat]>;
def CXX98CompatBindToTemporaryCopy :
@@ -123,6 +148,7 @@ def ReservedUserDefinedLiteral :
def CXX11Compat : DiagGroup<"c++11-compat",
[CXX11Narrowing,
CXX11CompatReservedUserDefinedLiteral,
+ CXX11CompatDeprecatedWritableStr,
CXXPre1yCompat]>;
def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic",
@@ -136,11 +162,13 @@ def FourByteMultiChar : DiagGroup<"four-char-constants">;
def GlobalConstructors : DiagGroup<"global-constructors">;
def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
+def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">;
def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
+def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
def IncompatiblePointerTypesDiscardsQualifiers
@@ -149,15 +177,18 @@ def IncompatiblePointerTypes
: DiagGroup<"incompatible-pointer-types",
[IncompatiblePointerTypesDiscardsQualifiers]>;
def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
+def IncompleteModule : DiagGroup<"incomplete-module", [IncompleteUmbrella]>;
def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
def : DiagGroup<"init-self">;
def : DiagGroup<"inline">;
def : DiagGroup<"invalid-pch">;
+def GNULabelsAsValue : DiagGroup<"gnu-label-as-value">;
def LiteralRange : DiagGroup<"literal-range">;
def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args",
[CXX98CompatLocalTypeTemplateArgs]>;
+def LoopAnalysis : DiagGroup<"loop-analysis">;
def MalformedWarningCheck : DiagGroup<"malformed-warning-check">;
def Main : DiagGroup<"main">;
def MainReturnType : DiagGroup<"main-return-type">;
@@ -176,6 +207,7 @@ def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
def MismatchedTags : DiagGroup<"mismatched-tags">;
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
def ModuleConflict : DiagGroup<"module-conflict">;
+def NewlineEOF : DiagGroup<"newline-eof">;
def NullArithmetic : DiagGroup<"null-arithmetic">;
def NullCharacter : DiagGroup<"null-character">;
def NullDereference : DiagGroup<"null-dereference">;
@@ -202,7 +234,10 @@ def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;
def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">;
+def ObjCInvalidIBOutletProperty : DiagGroup<"invalid-iboutlet">;
def ObjCRootClass : DiagGroup<"objc-root-class">;
+def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
+def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
def Packed : DiagGroup<"packed">;
def Padded : DiagGroup<"padded">;
@@ -213,6 +248,8 @@ def PoundPragmaMessage : DiagGroup<"#pragma-messages">,
DiagCategory<"#pragma message Directive">;
def : DiagGroup<"pointer-to-int-cast">;
def : DiagGroup<"redundant-decls">;
+def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;
+def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
def ReturnStackAddress : DiagGroup<"return-stack-address">;
def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
@@ -237,7 +274,9 @@ def StaticInInline : DiagGroup<"static-in-inline">;
def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
+def GNUStatementExpression : DiagGroup<"gnu-statement-expression">;
def StringPlusInt : DiagGroup<"string-plus-int">;
+def StringPlusChar : DiagGroup<"string-plus-char">;
def StrncatSize : DiagGroup<"strncat-size">;
def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
def TautologicalCompare : DiagGroup<"tautological-compare",
@@ -245,6 +284,9 @@ def TautologicalCompare : DiagGroup<"tautological-compare",
def HeaderHygiene : DiagGroup<"header-hygiene">;
def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
+def GNUUnionCast : DiagGroup<"gnu-union-cast">;
+def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">;
+def Varargs : DiagGroup<"varargs">;
def Unsequenced : DiagGroup<"unsequenced">;
// GCC name for -Wunsequenced
@@ -298,10 +340,12 @@ def UnknownAttributes : DiagGroup<"attributes">;
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
[CXX98CompatUnnamedTypeTemplateArgs]>;
+def UnsupportedFriend : DiagGroup<"unsupported-friend">;
def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">;
def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument",
[UnusedSanitizeArgument]>;
+def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument">;
def UnusedComparison : DiagGroup<"unused-comparison">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">;
@@ -314,7 +358,10 @@ def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedResult : DiagGroup<"unused-result">;
def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult]>;
-def UnusedVariable : DiagGroup<"unused-variable">;
+def UnusedConstVariable : DiagGroup<"unused-const-variable">;
+def UnusedVariable : DiagGroup<"unused-variable",
+ [UnusedConstVariable]>;
+def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">;
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
@@ -336,7 +383,10 @@ def AutomaticReferenceCounting : DiagGroup<"arc",
def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">;
def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak",
[ARCRepeatedUseOfWeakMaybe]>;
-def Selector : DiagGroup<"selector">;
+def ObjCBridge : DiagGroup<"bridge-cast">;
+
+def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
+def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
@@ -348,6 +398,8 @@ def VLAExtension : DiagGroup<"vla-extension">;
def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
def Visibility : DiagGroup<"visibility">;
def ZeroLengthArray : DiagGroup<"zero-length-array">;
+def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
+def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">;
// GCC calls -Wdeprecated-writable-strings -Wwrite-strings.
def GCCWriteStrings : DiagGroup<"write-strings" , [DeprecatedWritableStr]>;
@@ -365,6 +417,7 @@ def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">;
def ParenthesesOnEquality : DiagGroup<"parentheses-equality">;
def Parentheses : DiagGroup<"parentheses",
[LogicalOpParentheses,
+ LogicalNotParentheses,
BitwiseOpParentheses,
ShiftOpParentheses,
OverloadedShiftOpParentheses,
@@ -396,7 +449,7 @@ def Unused : DiagGroup<"unused",
// UnusedParameter, (matches GCC's behavior)
// UnusedMemberFunction, (clean-up llvm before enabling)
UnusedPrivateField,
- UnusedValue, UnusedVariable]>,
+ UnusedValue, UnusedVariable, UnusedPropertyIvar]>,
DiagCategory<"Unused Entity Issue">;
// Format settings.
@@ -414,7 +467,9 @@ def Format2 : DiagGroup<"format=2",
def TypeSafety : DiagGroup<"type-safety">;
-def IntToPointerCast : DiagGroup<"int-to-pointer-cast">;
+def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
+def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
+ [IntToVoidPointerCast]>;
def Extra : DiagGroup<"extra", [
MissingFieldInitializers,
@@ -449,7 +504,8 @@ def Most : DiagGroup<"most", [
ObjCMissingSuperCalls,
OverloadedVirtual,
PrivateExtern,
- SelTypeCast
+ SelTypeCast,
+ ExternCCompat
]>;
// Thread Safety warnings
@@ -462,6 +518,9 @@ def ThreadSafety : DiagGroup<"thread-safety",
ThreadSafetyPrecise]>;
def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">;
+// Uniqueness Analysis warnings
+def Consumed : DiagGroup<"consumed">;
+
// Note that putting warnings in -Wall will not disable them by default. If a
// warning should be active _only_ when -Wall is passed in, mark it as
// DefaultIgnore in addition to putting it here.
@@ -472,7 +531,7 @@ def Pedantic : DiagGroup<"pedantic">;
// Aliases.
def : DiagGroup<"", [Extra]>; // -W = -Wextra
-def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens
+def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wextra-tokens
def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
def : DiagGroup<"conversion-null",
[NullConversion]>; // -Wconversion-null = -Wnull-conversion
@@ -507,8 +566,20 @@ def C11 : DiagGroup<"c11-extensions">;
def C99 : DiagGroup<"c99-extensions">;
// A warning group for warnings about GCC extensions.
-def GNU : DiagGroup<"gnu", [GNUDesignator, VLAExtension,
- ZeroLengthArray, GNUStaticFloatInit]>;
+def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
+ GNUBinaryLiteral, GNUCaseRange,
+ GNUComplexInteger, GNUCompoundLiteralInitializer,
+ GNUConditionalOmittedOperand, GNUDesignator,
+ GNUEmptyInitializer, GNUEmptyStruct,
+ VLAExtension, GNUFlexibleArrayInitializer,
+ GNUFlexibleArrayUnionMember, GNUFoldingConstant,
+ GNUImaginaryConstant, GNULabelsAsValue,
+ RedeclaredClassMember, GNURedeclaredEnum,
+ GNUStatementExpression, GNUStaticFloatInit,
+ GNUStringLiteralOperatorTemplate,
+ GNUUnionCast, GNUVariableSizedTypeNotAtEnd,
+ ZeroLengthArray, GNUZeroLineDirective,
+ GNUZeroVariadicMacroArguments]>;
// A warning group for warnings about code that clang accepts but gcc doesn't.
def GccCompat : DiagGroup<"gcc-compat">;
@@ -532,10 +603,13 @@ def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [
]>;
def ObjCStringComparison : DiagGroup<"objc-string-compare">;
+def ObjCStringConcatenation : DiagGroup<"objc-string-concatenation">;
def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
ObjCStringComparison
]>;
+def ObjCLiteralMissingAtSign : DiagGroup<"objc-literal-missing-atsign">;
+
// Inline ASM warnings.
def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
def ASM : DiagGroup<"asm", [
diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
index d35b90742496..56e30fbda7b0 100644
--- a/include/clang/Basic/DiagnosticIDs.h
+++ b/include/clang/Basic/DiagnosticIDs.h
@@ -22,13 +22,13 @@
namespace clang {
class DiagnosticsEngine;
class SourceLocation;
- struct WarningOption;
// Import the diagnostic enums themselves.
namespace diag {
// Start position for diagnostics.
enum {
- DIAG_START_DRIVER = 300,
+ DIAG_START_COMMON = 0,
+ DIAG_START_DRIVER = DIAG_START_COMMON + 300,
DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
@@ -48,7 +48,8 @@ namespace clang {
// Get typedefs for common diagnostics.
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,CATEGORY,NOWERROR,SHOWINSYSHEADER) ENUM,
+ SFINAE,CATEGORY,NOWERROR,SHOWINSYSHEADER) ENUM,
+#define COMMONSTART
#include "clang/Basic/DiagnosticCommonKinds.inc"
NUM_BUILTIN_COMMON_DIAGNOSTICS
#undef DIAG
@@ -105,11 +106,12 @@ public:
void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
};
-/// \brief Used for handling and querying diagnostic IDs. Can be used and shared
-/// by multiple Diagnostics for multiple translation units.
+/// \brief Used for handling and querying diagnostic IDs.
+///
+/// Can be used and shared by multiple Diagnostics for multiple translation units.
class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
public:
- /// Level The level of the diagnostic, after it has been through mapping.
+ /// \brief The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored, Note, Warning, Error, Fatal
};
@@ -224,8 +226,8 @@ public:
/// \brief Get the set of all diagnostic IDs in the group with the given name.
///
- /// \param Diags [out] - On return, the diagnostics in the group.
- /// \returns True if the given group is unknown, false otherwise.
+ /// \param[out] Diags - On return, the diagnostics in the group.
+ /// \returns \c true if the given group is unknown, \c false otherwise.
bool getDiagnosticsInGroup(StringRef Group,
SmallVectorImpl<diag::kind> &Diags) const;
@@ -237,18 +239,14 @@ public:
static StringRef getNearestWarningOption(StringRef Group);
private:
- /// \brief Get the set of all diagnostic IDs in the given group.
- ///
- /// \param Diags [out] - On return, the diagnostics in the group.
- void getDiagnosticsInGroup(const WarningOption *Group,
- SmallVectorImpl<diag::kind> &Diags) const;
-
- /// \brief Based on the way the client configured the DiagnosticsEngine
- /// object, classify the specified diagnostic ID into a Level, consumable by
+ /// \brief Classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
+ ///
+ /// The classification is based on the way the client configured the
+ /// DiagnosticsEngine object.
///
- /// \param Loc The source location we are interested in finding out the
- /// diagnostic state. Can be null in order to query the latest state.
+ /// \param Loc The source location for which 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 DiagnosticsEngine &Diag) const;
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 2c16000d339d..871f5f65447d 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -47,7 +47,9 @@ def ext_line_comment : Extension<
"// comments are not allowed in this language">,
InGroup<Comment>;
def ext_no_newline_eof : Extension<"no newline at end of file">,
- InGroup<DiagGroup<"newline-eof">>;
+ InGroup<NewlineEOF>;
+def warn_no_newline_eof : Warning<"no newline at end of file">,
+ InGroup<NewlineEOF>, DefaultIgnore;
def warn_cxx98_compat_no_newline_eof : Warning<
"C++98 requires newline at end of file">,
@@ -157,6 +159,11 @@ def err_invalid_suffix_integer_constant : Error<
"invalid suffix '%0' on integer constant">;
def err_invalid_suffix_float_constant : Error<
"invalid suffix '%0' on floating constant">;
+def warn_cxx11_compat_digit_separator : Warning<
+ "digit separators are incompatible with C++ standards before C++1y">,
+ InGroup<CXXPre1yCompat>, DefaultIgnore;
+def err_digit_separator_not_between_digits : Error<
+ "digit separator cannot appear at %select{start|end}0 of digit sequence">;
def warn_extraneous_char_constant : Warning<
"extraneous characters in character constant ignored">;
def warn_char_constant_too_large : Warning<
@@ -165,7 +172,7 @@ def err_multichar_utf_character_literal : Error<
"Unicode character literals may not contain multiple characters">;
def err_exponent_has_no_digits : Error<"exponent has no digits">;
def ext_imaginary_constant : Extension<
- "imaginary constants are a GNU extension">, InGroup<GNU>;
+ "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
def err_hexconstant_requires_exponent : Error<
"hexadecimal floating constants require an exponent">;
def err_hexconstant_requires_digits : Error<
@@ -173,15 +180,15 @@ def err_hexconstant_requires_digits : Error<
def ext_hexconstant_invalid : Extension<
"hexadecimal floating constants are a C99 feature">, InGroup<C99>;
def ext_binary_literal : Extension<
- "binary integer literals are a GNU extension">, InGroup<GNU>;
+ "binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>;
def ext_binary_literal_cxx1y : Extension<
"binary integer literals are a C++1y extension">, InGroup<CXX1y>;
def warn_cxx11_compat_binary_literal : Warning<
"binary integer literals are incompatible with C++ standards before C++1y">,
InGroup<CXXPre1yCompatPedantic>, DefaultIgnore;
def err_pascal_string_too_long : Error<"Pascal string is too long">;
-def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">;
-def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">;
+def err_octal_escape_too_large : Error<"octal escape sequence out of range">;
+def err_hex_escape_too_large : Error<"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>;
@@ -320,7 +327,7 @@ def ext_embedded_directive : Extension<
InGroup<DiagGroup<"embedded-directive">>;
def ext_missing_varargs_arg : Extension<
"must specify at least one argument for '...' parameter of variadic macro">,
- InGroup<GNU>;
+ InGroup<GNUZeroVariadicMacroArguments>;
def ext_empty_fnmacro_arg : Extension<
"empty macro arguments are a C99 feature">, InGroup<C99>;
def warn_cxx98_compat_empty_fnmacro_arg : Warning<
@@ -406,6 +413,21 @@ def warn_pragma_include_alias_expected_filename :
ExtWarn<"pragma include_alias expected include filename">,
InGroup<UnknownPragmas>;
+// - #pragma warning(...)
+def warn_pragma_warning_expected :
+ ExtWarn<"#pragma warning expected '%0'">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_warning_spec_invalid :
+ ExtWarn<"#pragma warning expected 'push', 'pop', 'default', 'disable',"
+ " 'error', 'once', 'suppress', 1, 2, 3, or 4">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_warning_push_level :
+ ExtWarn<"#pragma warning(push, level) requires a level between 0 and 4">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_warning_expected_number :
+ ExtWarn<"#pragma warning expected a warning number">,
+ InGroup<UnknownPragmas>;
+
def err__Pragma_malformed : Error<
"_Pragma takes a parenthesized string literal">;
def err_pragma_message_malformed : Error<
@@ -455,11 +477,16 @@ def err_paste_at_start : Error<
"'##' cannot appear at start of macro expansion">;
def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">;
def ext_paste_comma : Extension<
- "token pasting of ',' and __VA_ARGS__ is a GNU extension">, InGroup<GNU>;
+ "token pasting of ',' and __VA_ARGS__ is a GNU extension">, InGroup<GNUZeroVariadicMacroArguments>;
def err_unterm_macro_invoc : Error<
"unterminated function-like macro invocation">;
def err_too_many_args_in_macro_invoc : Error<
"too many arguments provided to function-like macro invocation">;
+def note_suggest_parens_for_macro : Note<
+ "parentheses are required around macro argument containing braced "
+ "initializer list">;
+def note_init_list_at_beginning_of_macro_argument : Note<
+ "cannot use initializer list at the beginning of a macro argument">;
def err_too_few_args_in_macro_invoc : Error<
"too few arguments provided to function-like macro invocation">;
def err_pp_bad_paste : Error<
@@ -475,7 +502,7 @@ def err_pp_line_requires_integer : Error<
"#line directive requires a positive integer argument">;
def ext_pp_line_zero : Extension<
"#line directive with zero argument is a GNU extension">,
- InGroup<GNU>;
+ InGroup<GNUZeroLineDirective>;
def err_pp_line_invalid_filename : Error<
"invalid filename for #line directive">;
def warn_pp_line_decimal : Warning<
@@ -520,19 +547,18 @@ def note_mmap_lsquare_match : Note<"to match this ']'">;
def err_mmap_expected_member : Error<
"expected umbrella, header, submodule, or module export">;
def err_mmap_expected_header : Error<"expected a header name after '%0'">;
+def err_mmap_expected_mmap_file : Error<"expected a module map file name">;
def err_mmap_module_redefinition : Error<
"redefinition of module '%0'">;
def note_mmap_prev_definition : Note<"previously defined here">;
-def err_mmap_header_conflict : Error<
- "header '%0' is already part of module '%1'">;
def err_mmap_header_not_found : Error<
"%select{|umbrella }0header '%1' not found">;
def err_mmap_umbrella_dir_not_found : Error<
"umbrella directory '%0' not found">;
def err_mmap_umbrella_clash : Error<
"umbrella for module '%0' already covers this directory">;
-def err_mmap_export_module_id : Error<
- "expected an exported module name or '*'">;
+def err_mmap_module_id : Error<
+ "expected a module name or '*'">;
def err_mmap_expected_library_name : Error<
"expected %select{library|framework}0 name as a string">;
def err_mmap_config_macro_submodule : Error<
@@ -579,8 +605,20 @@ def warn_auto_module_import : Warning<
"import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
def warn_uncovered_module_header : Warning<
"umbrella header for module '%0' does not include header '%1'">,
- InGroup<IncompleteUmbrella>;
+ InGroup<IncompleteUmbrella>, DefaultIgnore;
+def warn_forgotten_module_header : Warning<
+ "header '%0' is included in module '%1' but not listed in module map">,
+ InGroup<IncompleteModule>, DefaultIgnore;
def err_expected_id_building_module : Error<
"expected a module name in '__building_module' expression">;
-
+def error_use_of_private_header_outside_module : Error<
+ "use of private header from outside its module: '%0'">;
+def error_undeclared_use_of_module : Error<
+ "use of a module not declared used: '%0'">;
+
+def warn_header_guard : Warning<
+ "%0 is used as a header guard here, followed by #define of a different macro">,
+ InGroup<DiagGroup<"header-guard">>;
+def note_header_guard : Note<
+ "%0 is defined here; did you mean %1?">;
}
diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def
index 41bbff2edec2..a360a5a84e98 100644
--- a/include/clang/Basic/DiagnosticOptions.def
+++ b/include/clang/Basic/DiagnosticOptions.def
@@ -72,6 +72,7 @@ DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected
DIAGOPT(ElideType, 1, 0) /// Elide identical types in template diffing
DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing
+DIAGOPT(CLFallbackMode, 1, 0) /// Format for clang-cl fallback mode
VALUE_DIAGOPT(ErrorLimit, 32, 0) /// Limit # errors emitted.
/// Limit depth of macro expansion backtrace.
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index e001bd46a230..2feab52ef4d1 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -23,6 +23,8 @@ def err_asm_empty : Error<"__asm used with no assembly instructions">;
def err_inline_ms_asm_parsing : Error<"%0">;
def err_msasm_unsupported_arch : Error<
"Unsupported architecture '%0' for MS-style inline assembly">;
+def err_msasm_unable_to_create_target : Error<
+ "MS-style inline assembly is not available: %0">;
}
let CategoryName = "Parse Issue" in {
@@ -54,13 +56,12 @@ def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
def ext_integer_complex : Extension<
- "complex integer types are a GNU extension">, InGroup<GNU>;
+ "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;
def ext_thread_before : Extension<"'__thread' before '%0'">;
+def ext_keyword_as_ident : ExtWarn<
+ "keyword '%0' will be treated as an identifier %select{here|for the remainder of the translation unit}1">,
+ InGroup<KeywordCompat>;
-def ext_empty_struct_union : Extension<
- "empty %select{struct|union}0 is a GNU extension">, InGroup<GNU>;
-def warn_empty_struct_union_compat : Warning<"empty %select{struct|union}0 "
- "has size 0 in C, size 1 in C++">, InGroup<CXXCompat>, DefaultIgnore;
def error_empty_enum : Error<"use of empty enum">;
def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
def err_invalid_short_spec : Error<"'short %0' is invalid">;
@@ -75,8 +76,6 @@ def ext_c99_variable_decl_in_for_loop : Extension<
"variable declaration in for loop is a C99-specific feature">, InGroup<C99>;
def ext_c99_compound_literal : Extension<
"compound literals are a C99-specific feature">, InGroup<C99>;
-def ext_c99_flexible_array_member : Extension<
- "Flexible array members are a C99-specific feature">, InGroup<C99>;
def ext_enumerator_list_comma_c : Extension<
"commas at the end of enumerator lists are a C99-specific "
"feature">, InGroup<C99>;
@@ -103,7 +102,7 @@ def warn_cxx98_compat_alignof : Warning<
"alignof expressions are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def ext_alignof_expr : ExtWarn<
- "%0 applied to an expression is a GNU extension">, InGroup<GNU>;
+ "%0 applied to an expression is a GNU extension">, InGroup<GNUAlignofExpression>;
def warn_microsoft_dependent_exists : Warning<
"dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">,
@@ -123,17 +122,15 @@ def ext_c11_noreturn : Extension<
"_Noreturn functions are a C11-specific feature">, InGroup<C11>;
def ext_gnu_indirect_goto : Extension<
- "use of GNU indirect-goto extension">, InGroup<GNU>;
+ "use of GNU indirect-goto extension">, InGroup<GNULabelsAsValue>;
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>;
+ "use of GNU address-of-label extension">, InGroup<GNULabelsAsValue>;
def ext_gnu_statement_expr : Extension<
- "use of GNU statement expression extension">, InGroup<GNU>;
+ "use of GNU statement expression extension">, InGroup<GNUStatementExpression>;
def ext_gnu_conditional_expr : Extension<
- "use of GNU ?: expression extension, eliding middle term">, InGroup<GNU>;
+ "use of GNU ?: conditional expression extension, omitting middle operand">, InGroup<GNUConditionalOmittedOperand>;
def ext_gnu_empty_initializer : Extension<
- "use of GNU empty initializer extension">, InGroup<GNU>;
+ "use of GNU empty initializer extension">, InGroup<GNUEmptyInitializer>;
def ext_gnu_array_range : Extension<"use of GNU array range extension">,
InGroup<GNUDesignator>;
def ext_gnu_missing_equal_designator : ExtWarn<
@@ -144,7 +141,7 @@ def ext_gnu_old_style_field_designator : ExtWarn<
"use of GNU old-style field designator extension">,
InGroup<GNUDesignator>;
def ext_gnu_case_range : Extension<"use of GNU case range extension">,
- InGroup<GNU>;
+ InGroup<GNUCaseRange>;
// Generic errors.
def err_expected_expression : Error<"expected expression">;
@@ -156,7 +153,7 @@ def err_expected_ident_lparen : Error<"expected identifier or '('">;
def err_expected_ident_lbrace : Error<"expected identifier or '{'">;
def err_expected_lbrace : Error<"expected '{'">;
def err_expected_lparen : Error<"expected '('">;
-def err_expected_lparen_or_lbrace : Error<"expected '('or '{'">;
+def err_expected_lparen_or_lbrace : Error<"expected '(' or '{'">;
def err_expected_rparen : Error<"expected ')'">;
def err_expected_lsquare : Error<"expected '['">;
def err_expected_rsquare : Error<"expected ']'">;
@@ -173,10 +170,6 @@ def err_expected_member_name_or_semi : Error<
"expected member name or ';' after declaration specifiers">;
def err_function_declared_typedef : Error<
"function definition declared 'typedef'">;
-def err_iboutletcollection_builtintype : Error<
- "type argument of iboutletcollection attribute cannot be a builtin type">;
-def err_iboutletcollection_with_protocol : Error<
- "invalid argument of iboutletcollection attribute">;
def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
def err_at_in_class : Error<"unexpected '@' in member specification">;
@@ -313,6 +306,11 @@ def err_expected_class_name_not_template :
Error<"'typename' is redundant; base classes are implicitly types">;
def err_unspecified_vla_size_with_static : Error<
"'static' may not be used with an unspecified variable length array size">;
+def warn_deprecated_register : Warning<
+ "'register' storage class specifier is deprecated">,
+ InGroup<DeprecatedRegister>;
+def err_expected_parentheses_around_typename : Error<
+ "expected parentheses around type name in %0 expression">;
def err_expected_case_before_expression: Error<
"expected 'case' keyword before expression">;
@@ -451,6 +449,7 @@ def err_invalid_operator_on_type : Error<
"cannot use %select{dot|arrow}0 operator on a type">;
def err_expected_unqualified_id : Error<
"expected %select{identifier|unqualified-id}0">;
+def err_unexpected_unqualified_id : Error<"type-id cannot have a name">;
def err_func_def_no_params : Error<
"function definition does not declare parameters">;
def err_expected_lparen_after_type : Error<
@@ -468,6 +467,10 @@ def err_expected_member_or_base_name : Error<
"expected class member or base class name">;
def err_expected_lbrace_after_base_specifiers : Error<
"expected '{' after base class list">;
+def err_missing_end_of_definition : Error<
+ "missing '}' at end of definition of %q0">;
+def note_missing_end_of_definition_before : Note<
+ "still within definition of %q0 here">;
def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">,
InGroup<Microsoft>;
@@ -482,6 +485,8 @@ def err_expected_rbrace_or_comma : Error<"expected '}' or ','">;
def err_expected_rsquare_or_comma : Error<"expected ']' or ','">;
def err_using_namespace_in_class : Error<
"'using namespace' is not allowed in classes">;
+def err_constructor_bad_name : Error<
+ "missing return type for function %0; did you mean the constructor name %1?">;
def err_destructor_tilde_identifier : Error<
"expected a class name after '~' to name a destructor">;
def err_destructor_template_id : Error<
@@ -498,6 +503,9 @@ def err_misplaced_ellipsis_in_declaration : Error<
def ext_abstract_pack_declarator_parens : ExtWarn<
"ISO C++11 requires a parenthesized pack declaration to have a name">,
InGroup<DiagGroup<"anonymous-pack-parens">>;
+def err_function_is_not_record : Error<
+ "unexpected '%select{.|->}0' in function call; perhaps remove the "
+ "'%select{.|->}0'?">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -579,7 +587,7 @@ def err_two_right_angle_brackets_need_space : Error<
def err_right_angle_bracket_equal_needs_space : Error<
"a space is required between a right angle bracket and an equals sign "
"(use '> =')">;
-def warn_cxx0x_right_shift_in_template_arg : Warning<
+def warn_cxx11_right_shift_in_template_arg : Warning<
"use of right-shift operator ('>>') in template argument will require "
"parentheses in C++11">, InGroup<CXX11Compat>;
def warn_cxx98_compat_two_right_angle_brackets : Warning<
@@ -593,6 +601,12 @@ def err_explicit_instantiation_with_definition : Error<
"explicit template instantiation cannot have a definition; if this "
"definition is meant to be an explicit specialization, add '<>' after the "
"'template' keyword">;
+def err_template_defn_explicit_instantiation : Error<
+ "%select{function|class|variable}0 cannot be defined in an explicit instantiation; if this "
+ "declaration is meant to be a %select{function|class|variable}0 definition, remove the 'template' keyword">;
+def err_friend_explicit_instantiation : Error<
+ "friend cannot be declared in an explicit instantiation; if this "
+ "declaration is meant to be a friend declaration, remove the 'template' keyword">;
def err_explicit_instantiation_enum : Error<
"enumerations cannot be explicitly instantiated">;
def err_expected_template_parameter : Error<"expected template parameter">;
@@ -609,7 +623,7 @@ def warn_cxx98_compat_extern_template : Warning<
InGroup<CXX98CompatPedantic>, DefaultIgnore;
def warn_static_inline_explicit_inst_ignored : Warning<
"ignoring '%select{static|inline}0' keyword on explicit template "
- "instantiation">;
+ "instantiation">, InGroup<DiagGroup<"static-inline-explicit-instantiation">>;
// Constructor template diagnostics.
def err_out_of_line_constructor_template_id : Error<
@@ -693,6 +707,9 @@ def warn_cxx98_compat_override_control_keyword : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def err_override_control_interface : Error<
"'%0' keyword not permitted with interface types">;
+def ext_ms_sealed_keyword : ExtWarn<
+ "'sealed' keyword is a Microsoft extension">,
+ InGroup<Microsoft>;
def err_access_specifier_interface : Error<
"interface types cannot specify '%select{private|protected}0' access">;
@@ -783,13 +800,16 @@ def warn_pragma_unused_expected_punc : Warning<
"expected ')' or ',' in '#pragma unused'">;
// - #pragma fp_contract
def err_pragma_fp_contract_scope : Error<
- "'#pragma fp_contract' should only appear at file scope or at the start of a "
- "compound expression">;
+ "'#pragma fp_contract' can only appear at file scope or at the start of a "
+ "compound statement">;
// - #pragma comment
def err_pragma_comment_malformed : Error<
"pragma comment requires parenthesized identifier and optional string">;
def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
-
+// - #pragma detect_mismatch
+def err_pragma_detect_mismatch_malformed : Error<
+ "pragma detect_mismatch is malformed; it requires two comma-separated "
+ "string literals">;
// OpenCL Section 6.8.g
def err_not_opencl_storage_class_specifier : Error<
@@ -819,13 +839,18 @@ def err_seh___finally_block : Error<
def warn_pragma_omp_ignored : Warning <
"unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
def warn_omp_extra_tokens_at_eol : Warning <
- "extra tokens at end of '#pragma omp %0' are ignored">,
+ "extra tokens at the end of '#pragma omp %0' are ignored">,
InGroup<ExtraTokens>;
def err_omp_unknown_directive : Error <
"expected an OpenMP directive">;
def err_omp_unexpected_directive : Error <
"unexpected OpenMP directive '#pragma omp %0'">;
-
+def err_omp_expected_punc : Error <
+ "expected ',' or ')' in %select{'#pragma omp %1'|'%1' clause}0">;
+def err_omp_unexpected_clause : Error <
+ "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;
+def err_omp_more_one_clause : Error <
+ "directive '#pragma omp %0' cannot contain more than one '%1' clause">;
} // end of Parse Issue category.
let CategoryName = "Modules Issue" in {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index f5345eb8c359..6c7cb001808a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -18,7 +18,12 @@ let CategoryName = "Semantic Issue" in {
def warn_variables_not_in_loop_body : Warning<
"variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 "
"used in loop condition not modified in loop body">,
- InGroup<DiagGroup<"loop-analysis">>, DefaultIgnore;
+ InGroup<LoopAnalysis>, DefaultIgnore;
+def warn_redundant_loop_iteration : Warning<
+ "variable %0 is %select{decremented|incremented}1 both in the loop header "
+ "and in the loop body">,
+ InGroup<LoopAnalysis>, DefaultIgnore;
+def note_loop_iteration_here : Note<"%select{decremented|incremented}0 here">;
def warn_duplicate_enum_values : Warning<
"element %0 has been implicitly assigned %1 which another element has "
@@ -30,23 +35,19 @@ def err_expr_not_ice : Error<
"expression is not an %select{integer|integral}0 constant expression">;
def ext_expr_not_ice : Extension<
"expression is not an %select{integer|integral}0 constant expression; "
- "folding it to a constant is a GNU extension">, InGroup<GNU>;
+ "folding it to a constant is a GNU extension">, InGroup<GNUFoldingConstant>;
def err_typecheck_converted_constant_expression : Error<
"value of type %0 is not implicitly convertible to %1">;
def err_typecheck_converted_constant_expression_disallowed : Error<
"conversion from %0 to %1 is not allowed in a converted constant expression">;
def err_expr_not_cce : Error<
- "%select{case value|enumerator value|non-type template argument}0 "
+ "%select{case value|enumerator value|non-type template argument|array size}0 "
"is not a constant expression">;
-def err_cce_narrowing : ExtWarn<
- "%select{case value|enumerator value|non-type template argument}0 "
+def ext_cce_narrowing : ExtWarn<
+ "%select{case value|enumerator value|non-type template argument|array size}0 "
"%select{cannot be narrowed from type %2 to %3|"
"evaluates to %2, which cannot be narrowed to type %3}1">,
- InGroup<CXX11Narrowing>, DefaultError;
-def err_cce_narrowing_sfinae : Error<
- "%select{case value|enumerator value|non-type template argument}0 "
- "%select{cannot be narrowed from type %2 to %3|"
- "evaluates to %2, which cannot be narrowed to type %3}1">;
+ InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
def err_ice_not_integral : Error<
"integral constant expression must have integral or unscoped enumeration "
"type, not %0">;
@@ -78,9 +79,6 @@ def ext_vla : Extension<"variable length arrays are a C99 feature">,
InGroup<VLAExtension>;
def warn_vla_used : Warning<"variable length array used">,
InGroup<VLA>, DefaultIgnore;
-def warn_cxx11_compat_array_of_runtime_bound : Warning<
- "arrays of runtime bound are incompatible with C++ standards before C++1y">,
- InGroup<CXXPre1yCompatPedantic>, DefaultIgnore;
def err_vla_non_pod : Error<"variable length array of non-POD element type %0">;
def err_vla_in_sfinae : Error<
"variable length array cannot be formed during template argument deduction">;
@@ -93,7 +91,7 @@ def err_vla_decl_has_static_storage : Error<
def err_vla_decl_has_extern_linkage : Error<
"variable length array declaration can not have 'extern' linkage">;
def ext_vla_folded_to_constant : Extension<
- "variable length array folded to constant array as an extension">;
+ "variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>;
// C99 variably modified types
def err_variably_modified_template_arg : Error<
@@ -138,7 +136,7 @@ def err_designator_into_flexible_array_member : Error<
def note_flexible_array_member : Note<
"initialized flexible array member %0 is here">;
def ext_flexible_array_init : Extension<
- "flexible array initialization is a GNU extension">, InGroup<GNU>;
+ "flexible array initialization is a GNU extension">, InGroup<GNUFlexibleArrayInitializer>;
// Declarations.
def err_bad_variable_name : Error<
@@ -150,6 +148,12 @@ def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
def warn_unused_variable : Warning<"unused variable %0">,
InGroup<UnusedVariable>, DefaultIgnore;
+def warn_unused_property_backing_ivar :
+ Warning<"ivar %0 which backs the property is not "
+ "referenced in this property's accessor">,
+ InGroup<UnusedPropertyIvar>, DefaultIgnore;
+def warn_unused_const_variable : Warning<"unused variable %0">,
+ InGroup<UnusedConstVariable>, DefaultIgnore;
def warn_unused_exception_param : Warning<"unused exception parameter %0">,
InGroup<UnusedExceptionParameter>, DefaultIgnore;
def warn_decl_in_param_list : Warning<
@@ -287,6 +291,18 @@ def note_using_decl : Note<"%select{|previous }0using declaration">;
def warn_access_decl_deprecated : Warning<
"access declarations are deprecated; use using declarations instead">,
InGroup<Deprecated>;
+def err_access_decl : Error<
+ "ISO C++11 does not allow access declarations; "
+ "use using declarations instead">;
+def warn_exception_spec_deprecated : Warning<
+ "dynamic exception specifications are deprecated">,
+ InGroup<Deprecated>, DefaultIgnore;
+def note_exception_spec_deprecated : Note<"use '%0' instead">;
+def warn_deprecated_copy_operation : Warning<
+ "definition of implicit copy %select{constructor|assignment operator}1 "
+ "for %0 is deprecated because it has a user-declared "
+ "%select{copy %select{assignment operator|constructor}1|destructor}2">,
+ InGroup<Deprecated>, DefaultIgnore;
def warn_global_constructor : Warning<
"declaration requires a global constructor">,
@@ -400,7 +416,7 @@ def ext_noreturn_main : ExtWarn<
def note_main_remove_noreturn : Note<"remove '_Noreturn'">;
def err_constexpr_main : Error<
"'main' is not allowed to be declared constexpr">;
-def err_main_template_decl : Error<"'main' cannot be a template">;
+def err_mainlike_template_decl : Error<"'%0' cannot be a template">;
def err_main_returns_nonint : Error<"'main' must return 'int'">;
def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">,
InGroup<MainReturnType>;
@@ -447,6 +463,7 @@ def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
def warn_pragma_pack_pop_identifer_and_alignment : Warning<
"specifying both a name and alignment to 'pop' is undefined">;
def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
+def warn_pragma_ms_struct_failed : Warning<"#pramga ms_struct can not be used with dynamic classes or structures">, InGroup<IgnoredAttributes>;
def warn_pragma_unused_undeclared_var : Warning<
"undeclared variable %0 used as an argument for '#pragma unused'">;
@@ -472,7 +489,6 @@ def err_no_nsconstant_string_class : Error<
"cannot find interface declaration for %0">;
def err_recursive_superclass : Error<
"trying to recursively use %0 as superclass of %1">;
-def warn_previous_alias_decl : Warning<"previously declared alias is ignored">;
def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">;
def warn_undef_interface : Warning<"cannot find interface declaration for %0">;
def warn_duplicate_protocol_def : Warning<"duplicate protocol definition of %0 is ignored">;
@@ -488,6 +504,9 @@ def warn_property_attribute : Warning<
"'%1' attribute on property %0 does not match the property inherited from %2">;
def warn_property_types_are_incompatible : Warning<
"property type %0 is incompatible with type %1 inherited from %2">;
+def warn_protocol_property_mismatch : Warning<
+ "property of type %0 was selected for synthesis">,
+ InGroup<DiagGroup<"protocol-property-synthesis-ambiguity">>;
def err_undef_interface : Error<"cannot find interface declaration for %0">;
def err_category_forward_interface : Error<
"cannot define %select{category|class extension}0 for undefined class %1">;
@@ -499,6 +518,8 @@ def note_while_in_implementation : Note<
"detected while default synthesizing properties in class implementation">;
def note_class_declared : Note<
"class is declared here">;
+def note_receiver_class_declared : Note<
+ "receiver is instance of class declared here">;
def note_receiver_is_id : Note<
"receiver is treated with 'id' type for purpose of method lookup">;
def note_suppressed_class_declare : Note<
@@ -506,7 +527,7 @@ def note_suppressed_class_declare : Note<
def err_objc_root_class_subclass : Error<
"objc_root_class attribute may only be specified on a root class declaration">;
def warn_objc_root_class_missing : Warning<
- "class %0 defined without specifying a base class">,
+ "class %0 defined without specifying a base class">,
InGroup<ObjCRootClass>;
def note_objc_needs_superclass : Note<
"add a super class to fix this problem">;
@@ -645,12 +666,18 @@ def warn_objc_isa_assign : Warning<
def warn_objc_pointer_masking : Warning<
"bitmasking for introspection of Objective-C object pointers is strongly "
"discouraged">,
- InGroup<DiagGroup<"deprecated-objc-pointer-introspection">>;
+ InGroup<ObjCPointerIntrospect>;
+def warn_objc_pointer_masking_performSelector : Warning<warn_objc_pointer_masking.Text>,
+ InGroup<ObjCPointerIntrospectPerformSelector>;
def warn_objc_property_default_assign_on_object : Warning<
"default property attribute 'assign' not appropriate for non-GC object">,
InGroup<ObjCPropertyNoAttribute>;
def warn_property_attr_mismatch : Warning<
"property attribute in class extension does not match the primary class">;
+def warn_property_implicitly_mismatched : Warning <
+ "primary property declaration is implicitly strong while redeclaration "
+ "in class extension is weak">,
+ InGroup<DiagGroup<"objc-property-implicit-mismatch">>;
def warn_objc_property_copy_missing_on_block : Warning<
"'copy' attribute must be specified for the block property "
"when -fobjc-gc-only is specified">;
@@ -727,6 +754,8 @@ def error_category_property : Error<
"class implementation">;
def note_property_declare : Note<
"property declared here">;
+def note_protocol_property_declare : Note<
+ "it could also be property of type %0 declared here">;
def note_property_synthesize : Note<
"property synthesized here">;
def error_synthesize_category_decl : Error<
@@ -804,6 +833,9 @@ def error_dealloc_bad_result_type : Error<
"instead of %0">;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
+def warn_undeclared_selector_with_typo : Warning<
+ "undeclared selector %0; did you mean %1?">,
+ InGroup<UndeclaredSelector>, DefaultIgnore;
def warn_implicit_atomic_property : Warning<
"property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore;
def note_auto_readonly_iboutlet_fixup_suggest : Note<
@@ -813,10 +845,12 @@ def warn_auto_readonly_iboutlet_property : Warning<
"not work correctly with 'nib' loader">,
InGroup<DiagGroup<"readonly-iboutlet-property">>;
def warn_auto_implicit_atomic_property : Warning<
- "property is assumed atomic when auto-synthesizing the property">,
+ "property is assumed atomic when auto-synthesizing the property">,
InGroup<ImplicitAtomic>, DefaultIgnore;
def warn_unimplemented_selector: Warning<
- "unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
+ "creating selector for nonexistent method %0">, InGroup<Selector>, DefaultIgnore;
+def warning_multiple_selectors: Warning<
+ "multiple selectors named %0 found">, InGroup<SelectorTypeMismatch>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"method %0 in protocol not implemented">, InGroup<Protocol>;
@@ -834,7 +868,7 @@ def err_inline_namespace_mismatch : Error<
def err_unexpected_friend : Error<
"friends can only be classes or functions">;
def ext_enum_friend : ExtWarn<
- "enumeration type %0 cannot be a friend">;
+ "befriending enumeration type %0 is a C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_enum_friend : Warning<
"befriending enumeration type %0 is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -865,7 +899,7 @@ def err_tagless_friend_type_template : Error<
def err_no_matching_local_friend : Error<
"no matching function found in local scope">;
def err_no_matching_local_friend_suggest : Error<
- "no matching function %0 found in local scope; did you mean %2?">;
+ "no matching function %0 found in local scope; did you mean %3?">;
def err_partial_specialization_friend : Error<
"partial specialization cannot be declared as a friend">;
def err_qualified_friend_def : Error<
@@ -876,6 +910,14 @@ def err_friend_not_first_in_declaration : Error<
"'friend' must appear first in a non-function declaration">;
def err_using_decl_friend : Error<
"cannot befriend target of using declaration">;
+def warn_template_qualified_friend_unsupported : Warning<
+ "dependent nested name specifier '%0' for friend class declaration is "
+ "not supported; turning off access control for %1">,
+ InGroup<UnsupportedFriend>;
+def warn_template_qualified_friend_ignored : Warning<
+ "dependent nested name specifier '%0' for friend template declaration is "
+ "not supported; ignoring this friend declaration">,
+ InGroup<UnsupportedFriend>;
def err_invalid_member_in_interface : Error<
"%select{data member |non-public member function |static member function |"
@@ -886,12 +928,15 @@ def err_invalid_base_in_interface : Error<
"%select{'struct|non-public 'interface|'class}0 %1'">;
def err_abstract_type_in_decl : Error<
- "%select{return|parameter|variable|field|instance variable}0 type %1 is an abstract class">;
+ "%select{return|parameter|variable|field|instance variable|"
+ "synthesized instance variable}0 type %1 is an abstract class">;
def err_allocation_of_abstract_type : Error<
"allocating an object of abstract class type %0">;
def err_throw_abstract_type : Error<
"cannot throw an object of abstract type %0">;
def err_array_of_abstract_type : Error<"array of abstract class type %0">;
+def err_capture_of_abstract_type : Error<
+ "by-copy capture of value of abstract type %0">;
def err_multiple_final_overriders : Error<
"virtual function %q0 has more than one final overrider in %1">;
@@ -999,8 +1044,8 @@ def err_access_dtor_base :
Error<"base class %0 has %select{private|protected}1 destructor">,
AccessControl;
def err_access_dtor_vbase :
- Error<"inherited virtual base class %0 has "
- "%select{private|protected}1 destructor">,
+ Error<"inherited virtual base class %1 has "
+ "%select{private|protected}2 destructor">,
AccessControl;
def err_access_dtor_temp :
Error<"temporary of type %0 has %select{private|protected}1 destructor">,
@@ -1086,6 +1131,8 @@ def err_explicit_non_ctor_or_conv_function : Error<
def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
def err_static_out_of_line : Error<
"'static' can only be specified inside the class definition">;
+def err_storage_class_for_static_member : Error<
+ "static data member definition cannot specify a storage class">;
def err_typedef_not_bitfield : Error<"typedef member %0 cannot be a bit-field">;
def err_not_integral_type_bitfield : Error<
"bit-field %0 has non-integral type %1">;
@@ -1114,7 +1161,7 @@ def note_bitfield_decl : Note<"bit-field is declared here">;
def note_previous_decl : Note<"%0 declared here">;
def note_implicit_param_decl : Note<"%0 is an implicit parameter">;
def note_member_synthesized_at : Note<
- "implicit default %select{constructor|copy constructor|move constructor|copy "
+ "implicit %select{default constructor|copy constructor|move constructor|copy "
"assignment operator|move assignment operator|destructor}0 for %1 first "
"required here">;
def note_inhctor_synthesized_at : Note<
@@ -1172,6 +1219,9 @@ def ext_static_data_member_in_union : ExtWarn<
def warn_cxx98_compat_static_data_member_in_union : Warning<
"static data member %0 in union is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def ext_union_member_of_reference_type : ExtWarn<
+ "union member %0 has reference type %1, which is a Microsoft extension">,
+ InGroup<Microsoft>;
def err_union_member_of_reference_type : Error<
"union member %0 has reference type %1">;
def ext_anonymous_struct_union_qualified : Extension<
@@ -1261,7 +1311,9 @@ def err_destructor_template : Error<
def err_init_conversion_failed : Error<
"cannot initialize %select{a variable|a parameter|return object|an "
"exception object|a member subobject|an array element|a new value|a value|a "
- "base class|a constructor delegation|a vector element}0 "
+ "base class|a constructor delegation|a vector element|a block element|a "
+ "complex element|a lambda capture|a compound literal initializer|a "
+ "related result|a parameter of CF audited function}0 "
"%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
"with an %select{rvalue|lvalue}2 of incompatible type}1,3"
"%select{|: different classes%diff{ ($ vs $)|}5,6"
@@ -1330,6 +1382,9 @@ def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">,
def warn_reference_field_is_uninit : Warning<
"reference %0 is not yet bound to a value when used here">,
InGroup<Uninitialized>;
+def note_uninit_in_this_constructor : Note<
+ "during field initialization in %select{this|the implicit default}0 "
+ "constructor">;
def warn_static_self_reference_in_init : Warning<
"static variable %0 is suspiciously used within its own initialization">,
InGroup<UninitializedStaticSelfInit>;
@@ -1348,7 +1403,10 @@ def warn_sometimes_uninit_var : Warning<
"%select{'%3' condition is %select{true|false}4|"
"'%3' loop %select{is entered|exits because its condition is false}4|"
"'%3' loop %select{condition is true|exits because its condition is false}4|"
- "switch %3 is taken}2">, InGroup<UninitializedSometimes>, DefaultIgnore;
+ "switch %3 is taken|"
+ "its declaration is reached|"
+ "%3 is called}2">,
+ InGroup<UninitializedSometimes>, DefaultIgnore;
def warn_maybe_uninit_var : Warning<
"variable %0 may be uninitialized when "
"%select{used here|captured by block}1">,
@@ -1425,11 +1483,14 @@ def err_illegal_decl_array_of_auto : Error<
def err_new_array_of_auto : Error<
"cannot allocate array of 'auto'">;
def err_auto_not_allowed : Error<
- "'auto' not allowed %select{in function prototype|in non-static struct member"
+ "%select{'auto'|'decltype(auto)'}0 not allowed %select{in function prototype"
+ "|in non-static struct member"
"|in non-static union member|in non-static class member|in interface member"
"|in exception declaration|in template parameter|in block literal"
"|in template argument|in typedef|in type alias|in function return type"
- "|in conversion function type|here}0">;
+ "|in conversion function type|here|in lambda parameter}1">;
+def err_auto_not_allowed_var_inst : Error<
+ "'auto' variable template instantiation is not allowed">;
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<
@@ -1498,19 +1559,22 @@ def err_auto_fn_virtual : Error<
// C++11 override control
def override_keyword_only_allowed_on_virtual_member_functions : Error<
"only virtual member functions can be marked '%0'">;
+def override_keyword_hides_virtual_member_function : Error<
+ "non-virtual member function marked '%0' hides virtual member "
+ "%select{function|functions}1">;
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'">;
+ "base %0 is marked '%select{final|sealed}1'">;
def warn_abstract_final_class : Warning<
- "abstract class is marked 'final'">, InGroup<AbstractFinalClass>;
+ "abstract class is marked '%select{final|sealed}0'">, InGroup<AbstractFinalClass>;
// C++11 attributes
def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">;
// C++11 final
def err_final_function_overridden : Error<
- "declaration of %0 overrides a 'final' function">;
+ "declaration of %0 overrides a '%select{final|sealed}1' function">;
// C++11 scoped enumerations
def err_enum_invalid_underlying : Error<
@@ -1572,6 +1636,9 @@ def note_in_for_range: Note<
def err_for_range_invalid: Error<
"invalid range expression of type %0; no viable '%select{begin|end}1' "
"function available">;
+def err_range_on_array_parameter : Error<
+ "cannot build range expression with array function parameter %0 since "
+ "parameter with array type %1 is treated as pointer type %2">;
def err_for_range_dereference : Error<
"invalid range expression of type %0; did you mean to dereference it "
"with '*'?">;
@@ -1725,8 +1792,8 @@ def err_attribute_can_be_applied_only_to_symbol_declaration : Error<
def err_attributes_are_not_compatible : Error<
"%0 and %1 attributes are not compatible">;
def err_attribute_wrong_number_arguments : Error<
- "attribute %plural{0:takes no arguments|1:takes one argument|"
- ":requires exactly %0 arguments}0">;
+ "%0 attribute %plural{0:takes no arguments|1:takes one argument|"
+ ":requires exactly %1 arguments}1">;
def err_attribute_too_many_arguments : Error<
"attribute takes no more than %0 argument%s0">;
def err_suppress_autosynthesis : Error<
@@ -1734,13 +1801,11 @@ def err_suppress_autosynthesis : Error<
"to a class declaration">;
def err_attribute_too_few_arguments : Error<
"attribute takes at least %0 argument%s0">;
-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_unsupported : Error<
+ "%0 attribute is not supported for this target">;
def err_aligned_attribute_argument_not_int : Error<
"'aligned' attribute requires integer constant">;
def err_alignas_attribute_wrong_decl_type : Error<
@@ -1756,8 +1821,12 @@ def err_alignas_mismatch : Error<
"redeclaration has different alignment requirement (%1 vs %0)">;
def err_alignas_underaligned : Error<
"requested alignment is less than minimum alignment of %1 for type %0">;
-def err_attribute_first_argument_not_int_or_bool : Error<
- "%0 attribute first argument must be of int or bool type">;
+def err_attribute_argument_n_type : Error<
+ "%0 attribute requires parameter %1 to be %select{int or bool|an integer "
+ "constant|a string|an identifier}2">;
+def err_attribute_argument_type : Error<
+ "%0 attribute requires %select{int or bool|an integer "
+ "constant|a string|an identifier}1">;
def err_attribute_argument_outof_range : Error<
"init_priority attribute requires integer constant between "
"101 and 65535 inclusive">;
@@ -1766,26 +1835,20 @@ def err_init_priority_object_attr : Error<
"of objects of class type">;
def err_attribute_argument_vec_type_hint : Error<
"invalid attribute argument %0 - expecting a vector or vectorizable scalar type">;
-def err_attribute_argument_n_not_int : Error<
- "'%0' attribute requires parameter %1 to be an integer constant">;
-def err_attribute_argument_n_not_string : Error<
- "'%0' attribute requires parameter %1 to be a string">;
-def err_attribute_argument_n_not_identifier : Error<
- "'%0' attribute requires parameter %1 to be an identifier">;
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_pointers_only : Error<
- "'%0' attribute only applies to pointer arguments">;
+ "%0 attribute only applies to pointer arguments">;
+def err_attribute_no_member_pointers : Error<
+ "%0 attribute cannot be used with pointers to members">;
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">;
+ "%0 attribute only applies to %select{pointer|integer}1 arguments">;
def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">;
def err_format_attribute_requires_variadic : Error<
@@ -1795,12 +1858,14 @@ 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 warn_unknown_method_family : Warning<"unrecognized method family">;
+def err_common_not_supported_cplusplus : Error<
+ "common attribute is not supported in C++">;
def err_init_method_bad_return_type : Error<
"init methods must return an object pointer type, not %0">;
def err_attribute_invalid_size : Error<
"vector size not an integral multiple of component size">;
def err_attribute_zero_size : Error<"zero vector size">;
+def err_attribute_size_too_large : Error<"vector size too large">;
def err_typecheck_vector_not_convertable : Error<
"can't convert between vector values of different size (%0 and %1)">;
def err_typecheck_ext_vector_not_typedef : Error<
@@ -1809,8 +1874,6 @@ def err_ext_vector_component_exceeds_length : Error<
"vector component access exceeds type %0">;
def err_ext_vector_component_name_illegal : Error<
"illegal vector component name '%0'">;
-def err_attribute_address_space_not_int : Error<
- "address space attribute requires an integer constant">;
def err_attribute_address_space_negative : Error<
"address space is negative">;
def err_attribute_address_space_too_high : Error<
@@ -1827,8 +1890,6 @@ def err_field_with_address_space : Error<
"field may not be qualified with an address space">;
def err_attr_objc_ownership_redundant : Error<
"the type %0 is already explicitly ownership-qualified">;
-def err_attribute_not_string : Error<
- "argument to %0 attribute was not a string literal">;
def err_undeclared_nsnumber : Error<
"NSNumber must be available to use Objective-C literals">;
def err_invalid_nsnumber_type : Error<
@@ -1862,9 +1923,15 @@ def warn_objc_literal_comparison : Warning<
"direct comparison of %select{an array literal|a dictionary literal|"
"a numeric literal|a boxed expression|}0 has undefined behavior">,
InGroup<ObjCLiteralComparison>;
+def warn_missing_atsign_prefix : Warning<
+ "string literal must be prefixed by '@' ">, InGroup<ObjCLiteralMissingAtSign>;
def warn_objc_string_literal_comparison : Warning<
"direct comparison of a string literal has undefined behavior">,
InGroup<ObjCStringComparison>;
+def warn_concatenated_nsarray_literal : Warning<
+ "concatenated NSString literal for an NSArray expression - "
+ "possibly missing a comma">,
+ InGroup<ObjCStringConcatenation>;
def note_objc_literal_comparison_isequal : Note<
"use 'isEqual:' instead">;
@@ -1948,8 +2015,10 @@ def warn_weak_identifier_undeclared : Warning<
"weak identifier %0 never declared">;
def err_attribute_weak_static : Error<
"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_selectany_non_extern_data : Error<
+ "'selectany' can only be applied to data items with external linkage">;
+def warn_attribute_invalid_on_definition : Warning<
+ "'%0' attribute cannot be specified on a definition">,
InGroup<IgnoredAttributes>;
def err_attribute_weakref_not_static : Error<
"weakref declaration must have internal linkage">;
@@ -1959,6 +2028,12 @@ 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 err_alias_to_undefined : Error<
+ "alias must point to a defined variable or function">;
+def err_duplicate_mangled_name : Error<
+ "definition with same mangled name as another definition">;
+def err_cyclic_alias : Error<
+ "alias definition is part of a cycle">;
def warn_attribute_wrong_decl_type : Warning<
"%0 attribute only applies to %select{functions|unions|"
"variables and functions|functions and methods|parameters|"
@@ -1967,7 +2042,7 @@ def warn_attribute_wrong_decl_type : Warning<
"variables, functions and labels|fields and global variables|structs|"
"variables, functions and tag types|thread-local variables|"
"variables and fields|variables, data members and tag types|"
- "types and namespaces}1">,
+ "types and namespaces|Objective-C interfaces}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{functions|unions|"
@@ -1977,15 +2052,11 @@ def err_attribute_wrong_decl_type : Error<
"variables, functions and labels|fields and global variables|structs|"
"variables, functions and tag types|thread-local variables|"
"variables and fields|variables, data members and tag types|"
- "types and namespaces}1">;
-def warn_function_attribute_wrong_type : Warning<
- "'%0' only applies to function types; type here is %1">,
- InGroup<IgnoredAttributes>;
-def warn_pointer_attribute_wrong_type : Warning<
- "'%0' only applies to pointer types; type here is %1">,
- InGroup<IgnoredAttributes>;
-def warn_objc_object_attribute_wrong_type : Warning<
- "'%0' only applies to Objective-C object or block pointer types; type here is %1">,
+ "types and namespaces|Objective-C interfaces|"
+ "methods and properties|struct or union|struct, union or class}1">;
+def warn_type_attribute_wrong_type : Warning<
+ "'%0' only applies to %select{function|pointer|"
+ "Objective-C object or block pointer}1 types; type here is %2">,
InGroup<IgnoredAttributes>;
def warn_attribute_requires_functions_or_static_globals : Warning<
"%0 only applies to variables with static storage duration and functions">,
@@ -2007,6 +2078,9 @@ def err_cconv_knr : Error<
"function with no prototype cannot use %0 calling convention">;
def err_cconv_varargs : Error<
"variadic function cannot use %0 calling convention">;
+def warn_cconv_varargs : Warning<
+ "%0 calling convention ignored on variadic function">,
+ InGroup<IgnoredAttributes>;
def err_regparm_mismatch : Error<"function declared with regparm(%0) "
"attribute was previously declared "
"%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
@@ -2148,6 +2222,32 @@ def note_found_mutex_near_match : Note<"found near match '%0'">;
def warn_thread_safety_beta : Warning<
"Thread safety beta warning.">, InGroup<ThreadSafetyBeta>, DefaultIgnore;
+// Consumed warnings
+def warn_use_in_invalid_state : Warning<
+ "invalid invocation of method '%0' on object '%1' while it is in the '%2' "
+ "state">, InGroup<Consumed>, DefaultIgnore;
+def warn_use_of_temp_in_invalid_state : Warning<
+ "invalid invocation of method '%0' on a temporary object while it is in the "
+ "'%1' state">, InGroup<Consumed>, DefaultIgnore;
+def warn_attr_on_unconsumable_class : Warning<
+ "consumed analysis attribute is attached to member of class '%0' which isn't "
+ "marked as consumable">, InGroup<Consumed>, DefaultIgnore;
+def warn_return_typestate_for_unconsumable_type : Warning<
+ "return state set for an unconsumable type '%0'">, InGroup<Consumed>,
+ DefaultIgnore;
+def warn_return_typestate_mismatch : Warning<
+ "return value not in expected state; expected '%0', observed '%1'">,
+ InGroup<Consumed>, DefaultIgnore;
+def warn_loop_state_mismatch : Warning<
+ "state of variable '%0' must match at the entry and exit of loop">,
+ InGroup<Consumed>, DefaultIgnore;
+def warn_param_return_typestate_mismatch : Warning<
+ "parameter '%0' not in expected state when the function returns: expected "
+ "'%1', observed '%2'">, InGroup<Consumed>, DefaultIgnore;
+def warn_param_typestate_mismatch : Warning<
+ "argument not in expected state; expected '%0', observed '%1'">,
+ InGroup<Consumed>, DefaultIgnore;
+
def warn_impcast_vector_scalar : Warning<
"implicit conversion turns vector to scalar: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
@@ -2211,9 +2311,17 @@ def warn_cast_align : Warning<
"cast from %0 to %1 increases required alignment from %2 to %3">,
InGroup<CastAlign>, DefaultIgnore;
+// Separate between casts to void* and non-void* pointers.
+// Some APIs use (abuse) void* for something like a user context,
+// and often that value is an integer even if it isn't a pointer itself.
+// Having a separate warning flag allows users to control the warning
+// for their workflow.
def warn_int_to_pointer_cast : Warning<
"cast to %1 from smaller integer type %0">,
InGroup<IntToPointerCast>;
+def warn_int_to_void_pointer_cast : Warning<
+ "cast to %1 from smaller integer type %0">,
+ InGroup<IntToVoidPointerCast>;
def warn_attribute_ignored_for_field_of_type : Warning<
"%0 attribute ignored for field of type %1">,
@@ -2238,16 +2346,14 @@ def warn_transparent_union_attribute_zero_fields : Warning<
"transparent_union attribute ignored">,
InGroup<IgnoredAttributes>;
def warn_attribute_type_not_supported : Warning<
- "'%0' attribute argument not supported: %1">,
+ "%0 attribute argument not supported: %1">,
InGroup<IgnoredAttributes>;
-def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">,
+def warn_attribute_unknown_visibility : Warning<"unknown visibility %0">,
InGroup<IgnoredAttributes>;
def warn_attribute_protected_visibility :
Warning<"target does not support 'protected' visibility; using 'default'">,
InGroup<DiagGroup<"unsupported-visibility">>;
def err_mismatched_visibility: Error<"visibility does not match previous declaration">;
-def warn_attribute_unknown_endian : Warning<"unknown endian '%0'">,
- InGroup<IgnoredAttributes>;
def note_previous_attribute : Note<"previous attribute is here">;
def err_unknown_machine_mode : Error<"unknown machine mode %0">;
def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
@@ -2273,10 +2379,12 @@ def err_attribute_sentinel_less_than_zero : Error<
"'sentinel' parameter 1 less than zero">;
def err_attribute_sentinel_not_zero_or_one : Error<
"'sentinel' parameter 2 not 0 or 1">;
-def err_attribute_cleanup_arg_not_found : Error<
- "'cleanup' argument %0 not found">;
+def warn_cleanup_ext : Warning<
+ "GCC does not allow the 'cleanup' attribute argument to be anything other "
+ "than a simple identifier">,
+ InGroup<GccCompat>;
def err_attribute_cleanup_arg_not_function : Error<
- "'cleanup' argument %0 is not a function">;
+ "'cleanup' argument %select{|%1 |%1 }0is not a %select{||single }0function">;
def err_attribute_cleanup_func_must_take_one_arg : Error<
"'cleanup' function %0 must take 1 parameter">;
def err_attribute_cleanup_func_arg_incompatible_type : Error<
@@ -2297,10 +2405,15 @@ def warn_attribute_ibaction: Warning<
InGroup<IgnoredAttributes>;
def err_iboutletcollection_type : Error<
"invalid type %0 as argument of iboutletcollection attribute">;
+def err_iboutletcollection_builtintype : Error<
+ "type argument of iboutletcollection attribute cannot be a builtin type">;
def warn_iboutlet_object_type : Warning<
"%select{instance variable|property}2 with %0 attribute must "
- "be an object type (invalid %1)">,
- InGroup<DiagGroup<"invalid-iboutlet">>;
+ "be an object type (invalid %1)">, InGroup<ObjCInvalidIBOutletProperty>;
+def warn_iboutletcollection_property_assign : Warning<
+ "IBOutletCollection properties should be copy/strong and not assign">,
+ InGroup<ObjCInvalidIBOutletProperty>;
+
def err_attribute_overloadable_not_function : Error<
"'overloadable' attribute can only be applied to a function">;
def err_attribute_overloadable_missing : Error<
@@ -2311,7 +2424,7 @@ 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 %select{functions|methods}1 that "
+ "%0 attribute only applies to %select{functions|methods|properties}1 that "
"return %select{an Objective-C object|a pointer|a non-retainable pointer}2">,
InGroup<IgnoredAttributes>;
def warn_ns_attribute_wrong_parameter_type : Warning<
@@ -2326,6 +2439,18 @@ def note_protocol_decl : Note<
def err_ns_bridged_not_interface : Error<
"parameter of 'ns_bridged' attribute does not name an Objective-C class">;
+
+// objc_bridge attribute diagnostics.
+def err_objc_bridge_not_id : Error<
+ "parameter of 'objc_bridge' attribute must be a single name of an Objective-C class">;
+def err_objc_cf_bridged_not_interface : Error<
+ "CF object of type %0 is bridged to '%1', which is not an Objective-C class">;
+def err_objc_ns_bridged_invalid_cfobject : Error<
+ "ObjectiveC object of type %0 is bridged to %1, which is not valid CF object">;
+def warn_objc_invalid_bridge : Warning<
+ "%0 bridges to %1, not %2">, InGroup<ObjCBridge>;
+def warn_objc_invalid_bridge_to_cf : Warning<
+ "%0 cannot bridge to %1">, InGroup<ObjCBridge>;
// Function Parameter Semantic Analysis.
def err_param_with_void_type : Error<"argument may not have 'void' type">;
@@ -2366,8 +2491,8 @@ def err_param_default_argument_member_template_redecl : Error<
"of a %select{class template|class template partial specialization|nested "
"class in a template}0">;
def err_uninitialized_member_for_assign : Error<
- "cannot define the implicit default assignment operator for %0, because "
- "non-static %select{reference|const}1 member %2 can't use default "
+ "cannot define the implicit copy assignment operator for %0, because "
+ "non-static %select{reference|const}1 member %2 can't use copy "
"assignment operator">;
def err_uninitialized_member_in_ctor : Error<
"%select{|implicit default |inheriting }0constructor for %1 must explicitly "
@@ -2688,6 +2813,7 @@ def err_ovl_ambiguous_oper_unary : Error<
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 note_assign_lhs_incomplete : Note<"type %0 is incomplete">;
def err_ovl_deleted_oper : Error<
"overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">;
def err_ovl_deleted_special_oper : Error<
@@ -2731,7 +2857,8 @@ def err_addr_ovl_no_qualifier : Error<
def err_ovl_no_viable_literal_operator : Error<
"no matching literal operator for call to %0"
"%select{| with argument of type %2| with arguments of types %2 and %3}1"
- "%select{| or 'const char *', and no matching literal operator template}4">;
+ "%select{| or 'const char *'}4"
+ "%select{|, and no matching literal operator template}5">;
// C++ Template Declarations
def err_template_param_shadow : Error<
@@ -2741,6 +2868,8 @@ def warn_template_export_unsupported : Warning<
"exported templates are unsupported">;
def err_template_outside_namespace_or_class_scope : Error<
"templates can only be declared in namespace or class scope">;
+def err_template_inside_local_class : Error<
+ "templates cannot be declared inside of a local class">;
def err_template_linkage : Error<"templates must have C++ linkage">;
def err_template_typedef : Error<"a typedef cannot be a template">;
def err_template_unnamed_class : Error<
@@ -2789,7 +2918,11 @@ def err_template_parameter_default_friend_template : Error<
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 ext_variable_template : ExtWarn<"variable templates are a C++1y extension">,
+ InGroup<CXX1y>;
+def warn_cxx11_compat_variable_template : Warning<
+ "variable templates are incompatible with C++ standards before C++1y">,
+ InGroup<CXXPre1yCompat>, DefaultIgnore;
def err_template_variable_noparams : Error<
"extraneous 'template<>' in declaration of variable %0">;
def err_template_member : Error<"member %0 declared as a template">;
@@ -2798,7 +2931,7 @@ def err_template_member_noparams : Error<
def err_template_tag_noparams : Error<
"extraneous 'template<>' in declaration of %0 %1">;
def err_template_decl_ref : Error<
- "cannot refer to class template %0 without a template argument list">;
+ "cannot refer to %select{class|variable}0 template %1 without a template argument list">;
// C++ Template Argument Lists
def err_template_missing_args : Error<
@@ -2879,9 +3012,6 @@ def err_template_arg_ref_bind_ignores_quals : Error<
"ignores qualifiers">;
def err_template_arg_not_decl_ref : Error<
"non-type template argument does not refer to any declaration">;
-def err_template_arg_not_object_or_func_form : Error<
- "non-type template argument does not directly refer to an object or "
- "function">;
def err_template_arg_not_address_of : Error<
"non-type template argument for template parameter of pointer type %0 must "
"have its address taken">;
@@ -2926,11 +3056,14 @@ def err_pointer_to_member_call_drops_quals : Error<
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">;
+def ext_ms_deref_template_argument: ExtWarn<
+ "non-type template argument containing a dereference operation is a "
+ "Microsoft extension">, InGroup<Microsoft>;
// C++ template specialization
def err_template_spec_unknown_kind : Error<
"can only provide an explicit specialization for a class template, function "
- "template, or a member function, static data member, "
+ "template, variable template, or a member function, static data member, "
"%select{or member class|member class, or member enumeration}0 of a "
"class template">;
def note_specialized_entity : Note<
@@ -2942,29 +3075,35 @@ def err_template_spec_decl_class_scope : Error<
def err_template_spec_decl_friend : Error<
"cannot declare an explicit specialization in a friend">;
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|member enumeration}0 "
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member function|"
+ "static data member|member class|member enumeration}0 "
"specialization of %1 must originally be declared in the global scope">;
def err_template_spec_decl_out_of_scope : Error<
- "%select{class template|class template partial|function template|member "
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
"specialization of %1 must originally be declared in namespace %2">;
def ext_template_spec_decl_out_of_scope : ExtWarn<
"first declaration of %select{class template|class template partial|"
+ "variable template|variable template partial|"
"function template|member function|static data member|member class|"
"member enumeration}0 specialization of %1 outside namespace %2 is a "
"C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning<
- "%select{class template|class template partial|function template|member "
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
"specialization of %1 outside namespace %2 is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_template_spec_redecl_out_of_scope : Error<
- "%select{class template|class template partial|function template|member "
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
"specialization of %1 not in a namespace enclosing %2">;
def err_template_spec_redecl_global_scope : Error<
- "%select{class template|class template partial|function template|member "
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
"specialization of %1 must occur at global scope">;
def err_spec_member_not_instantiated : Error<
@@ -3029,12 +3168,12 @@ def err_dependent_typed_non_type_arg_in_partial_spec : Error<
"non-type template argument specializes a template parameter with "
"dependent type %0">;
def err_partial_spec_args_match_primary_template : Error<
- "class template partial specialization does not specialize any template "
- "argument; to %select{declare|define}0 the primary template, remove the "
- "template argument list">;
+ "%select{class|variable}0 template partial specialization does not "
+ "specialize any template argument; to %select{declare|define}1 the "
+ "primary template, remove the template argument list">;
def warn_partial_specs_not_deducible : Warning<
- "class template partial specialization contains "
- "%select{a template parameter|template parameters}0 that can not be "
+ "%select{class|variable}0 template partial specialization contains "
+ "%select{a template parameter|template parameters}1 that can not be "
"deduced; this partial specialization will never be used">;
def note_partial_spec_unused_parameter : Note<
"non-deducible template parameter %0">;
@@ -3047,6 +3186,14 @@ def note_prev_partial_spec_here : Note<
"previous declaration of class template partial specialization %0 is here">;
def err_partial_spec_fully_specialized : Error<
"partial specialization of %0 does not use any of its template parameters">;
+
+// C++ Variable Template Partial Specialization
+def err_var_partial_spec_redeclared : Error<
+ "variable template partial specialization %0 cannot be redefined">;
+def note_var_prev_partial_spec_here : Note<
+ "previous declaration of variable template partial specialization is here">;
+def err_var_spec_no_template : Error<
+ "no variable template matches%select{| partial}0 specialization">;
// C++ Function template specializations
def err_function_template_spec_no_match : Error<
@@ -3084,6 +3231,8 @@ def note_function_template_spec_here : Note<
"in instantiation of function template specialization %q0 requested here">;
def note_template_static_data_member_def_here : Note<
"in instantiation of static data member %q0 requested here">;
+def note_template_variable_def_here : Note<
+ "in instantiation of variable template specialization %q0 requested here">;
def note_template_enum_def_here : Note<
"in instantiation of enumeration %q0 requested here">;
def note_template_type_alias_instantiation_here : Note<
@@ -3160,8 +3309,8 @@ def err_explicit_instantiation_of_typedef : Error<
def err_explicit_instantiation_storage_class : Error<
"explicit instantiation cannot have a storage class">;
def err_explicit_instantiation_not_known : Error<
- "explicit instantiation of %0 does not refer to a function template, member "
- "function, member class, or static data member">;
+ "explicit instantiation of %0 does not refer to a function template, "
+ "variable template, member function, member class, or static data member">;
def note_explicit_instantiation_here : Note<
"explicit instantiation refers here">;
def err_explicit_instantiation_data_member_not_instantiated : Error<
@@ -3184,6 +3333,8 @@ def err_explicit_instantiation_constexpr : Error<
def ext_explicit_instantiation_without_qualified_id : Extension<
"qualifier in explicit instantiation of %q0 requires a template-id "
"(a typedef is not permitted)">;
+def err_explicit_instantiation_without_template_id : Error<
+ "explicit instantiation of %q0 must specify a template argument list">;
def err_explicit_instantiation_unqualified_wrong_namespace : Error<
"explicit instantiation of %q0 must occur in namespace %1">;
def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning<
@@ -3194,11 +3345,17 @@ def err_explicit_instantiation_undefined_member : Error<
"static data member}0 %1 of class template %2">;
def err_explicit_instantiation_undefined_func_template : Error<
"explicit instantiation of undefined function template %0">;
+def err_explicit_instantiation_undefined_var_template : Error<
+ "explicit instantiation of undefined variable template %q0">;
def err_explicit_instantiation_declaration_after_definition : Error<
"explicit instantiation declaration (with 'extern') follows explicit "
"instantiation definition (without 'extern')">;
def note_explicit_instantiation_definition_here : Note<
"explicit instantiation definition is here">;
+def err_invalid_var_template_spec_type : Error<"type %2 "
+ "of %select{explicit instantiation|explicit specialization|"
+ "partial specialization|redeclaration}0 of %1 does not match"
+ " expected type %3">;
// C++ typename-specifiers
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
@@ -3244,7 +3401,8 @@ def err_non_type_template_in_nested_name_specifier : Error<
def err_template_id_not_a_type : Error<
"template name refers to non-type template %0">;
def note_template_declared_here : Note<
- "%select{function template|class template|type alias template|template template parameter}0 "
+ "%select{function template|class template|variable template"
+ "|type alias template|template template parameter}0 "
"%1 declared here">;
def note_parameter_type : Note<
"parameter of type %0 is declared here">;
@@ -3350,6 +3508,10 @@ def note_unavailable_here : Note<
"%select{unavailable|deleted|deprecated}1 here">;
def note_implicitly_deleted : Note<
"explicitly defaulted function was implicitly deleted here">;
+def note_inherited_deleted_here : Note<
+ "deleted constructor was inherited here">;
+def note_cannot_inherit : Note<
+ "constructor cannot be inherited">;
def warn_not_enough_argument : Warning<
"not enough variable arguments in %0 declaration to fit a sentinel">,
InGroup<Sentinel>;
@@ -3367,10 +3529,14 @@ def warn_missing_variable_declarations : Warning<
"no previous extern declaration for non-static variable %0">,
InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;
def err_redefinition : Error<"redefinition of %0">;
+def err_alias_after_tentative :
+ Error<"alias definition of %0 after tentative definition">;
+def err_tentative_after_alias :
+ Error<"tentative definition of %0 after alias definition">;
def err_definition_of_implicitly_declared_member : Error<
"definition of implicitly declared %select{default constructor|copy "
"constructor|move constructor|copy assignment operator|move assignment "
- "operator|destructor}1">;
+ "operator|destructor|function}1">;
def err_definition_of_explicitly_defaulted_member : Error<
"definition of explicitly defaulted %select{default constructor|copy "
"constructor|move constructor|copy assignment operator|move assignment "
@@ -3444,6 +3610,14 @@ def err_static_non_static : Error<
"static declaration of %0 follows non-static declaration">;
def err_different_language_linkage : Error<
"declaration of %0 has a different language linkage">;
+def ext_retained_language_linkage : Extension<
+ "friend function %0 retaining previous language linkage is an extension">,
+ InGroup<DiagGroup<"retained-language-linkage">>;
+def err_extern_c_global_conflict : Error<
+ "declaration of %1 %select{with C language linkage|in global scope}0 "
+ "conflicts with declaration %select{in global scope|with C language linkage}0">;
+def note_extern_c_global_conflict : Note<
+ "declared %select{in global scope|with C language linkage}0 here">;
def warn_weak_import : Warning <
"an already-declared variable is made a weak_import declaration %0">;
def warn_static_non_static : ExtWarn<
@@ -3503,7 +3677,7 @@ def err_forward_ref_enum : Error<
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>;
+ "redeclaration of already-defined enum %0 is a GNU extension">, InGroup<GNURedeclaredEnum>;
def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
def err_duplicate_member : Error<"duplicate member %0">;
@@ -3574,6 +3748,8 @@ def warn_typecheck_zero_static_array_size : Warning<
def err_array_size_non_int : Error<"size of array has non-integer type %0">;
def err_init_element_not_constant : Error<
"initializer element is not a compile-time constant">;
+def ext_aggregate_init_not_constant : Extension<
+ "initializer for aggregate is not a compile-time constant">, InGroup<C99>;
def err_local_cant_init : Error<
"'__local' variable cannot have an initializer">;
def err_block_extern_cant_init : Error<
@@ -3620,22 +3796,15 @@ def warn_cxx98_compat_ctor_list_init : Warning<
def err_illegal_initializer : Error<
"illegal initializer (only variables can be initialized)">;
def err_illegal_initializer_type : Error<"illegal initializer type %0">;
-def err_init_list_type_narrowing_sfinae : Error<
- "type %0 cannot be narrowed to %1 in initializer list">;
-def err_init_list_type_narrowing : ExtWarn<
+def ext_init_list_type_narrowing : ExtWarn<
"type %0 cannot be narrowed to %1 in initializer list">,
- InGroup<CXX11Narrowing>, DefaultError;
-def err_init_list_variable_narrowing_sfinae : Error<
- "non-constant-expression cannot be narrowed from type %0 to %1 in "
- "initializer list">;
-def err_init_list_variable_narrowing : ExtWarn<
+ InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
+def ext_init_list_variable_narrowing : ExtWarn<
"non-constant-expression cannot be narrowed from type %0 to %1 in "
- "initializer list">, InGroup<CXX11Narrowing>, DefaultError;
-def err_init_list_constant_narrowing_sfinae : Error<
- "constant expression evaluates to %0 which cannot be narrowed to type %1">;
-def err_init_list_constant_narrowing : ExtWarn<
+ "initializer list">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
+def ext_init_list_constant_narrowing : ExtWarn<
"constant expression evaluates to %0 which cannot be narrowed to type %1">,
- InGroup<CXX11Narrowing>, DefaultError;
+ InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
def warn_init_list_type_narrowing : Warning<
"type %0 cannot be narrowed to %1 in initializer list in C++11">,
InGroup<CXX11Narrowing>, DefaultIgnore;
@@ -3676,9 +3845,6 @@ def warn_anon_bitfield_width_exceeds_type_size : Warning<
def warn_missing_braces : Warning<
"suggest braces around initialization of subobject">,
InGroup<MissingBraces>, DefaultIgnore;
-def err_missing_braces : Error<
- "cannot omit braces around initialization of subobject when using direct "
- "list-initialization">;
def err_redefinition_of_label : Error<"redefinition of label %0">;
def err_undeclared_label_use : Error<"use of undeclared label %0">;
@@ -3778,10 +3944,16 @@ def err_field_declared_as_function : Error<"field %0 declared as a function">;
def err_field_incomplete : Error<"field has incomplete type %0">;
def ext_variable_sized_type_in_struct : ExtWarn<
"field %0 with variable sized type %1 not at the end of a struct or class is"
- " a GNU extension">, InGroup<GNU>;
-
-def err_flexible_array_empty_struct : Error<
- "flexible array %0 not allowed in otherwise empty struct">;
+ " a GNU extension">, InGroup<GNUVariableSizedTypeNotAtEnd>;
+
+def ext_c99_flexible_array_member : Extension<
+ "flexible array members are a C99 feature">, InGroup<C99>;
+def err_flexible_array_virtual_base : Error<
+ "flexible array member %0 not allowed in "
+ "%select{struct|interface|union|class|enum}1 which has a virtual base class">;
+def err_flexible_array_empty_aggregate : Error<
+ "flexible array member %0 not allowed in otherwise empty "
+ "%select{struct|interface|union|class|enum}1">;
def err_flexible_array_has_nonpod_type : Error<
"flexible array member %0 of non-POD element type %1">;
def ext_flexible_array_in_struct : Extension<
@@ -3796,15 +3968,17 @@ def ext_flexible_array_empty_aggregate_ms : Extension<
"flexible array member %0 in otherwise empty "
"%select{struct|interface|union|class|enum}1 is a Microsoft extension">,
InGroup<Microsoft>;
+def err_flexible_array_union : Error<
+ "flexible array member %0 in a union is not allowed">;
def ext_flexible_array_union_ms : Extension<
"flexible array member %0 in a union is a Microsoft extension">,
InGroup<Microsoft>;
def ext_flexible_array_empty_aggregate_gnu : Extension<
"flexible array member %0 in otherwise empty "
"%select{struct|interface|union|class|enum}1 is a GNU extension">,
- InGroup<GNU>;
+ InGroup<GNUEmptyStruct>;
def ext_flexible_array_union_gnu : Extension<
- "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>;
+ "flexible array member %0 in a union is a GNU extension">, InGroup<GNUFlexibleArrayUnionMember>;
let CategoryName = "ARC Semantic Issue" in {
@@ -3852,7 +4026,7 @@ def err_arc_objc_property_default_assign_on_object : Error<
def err_arc_illegal_selector : Error<
"ARC forbids use of %0 in a @selector">;
def err_arc_illegal_method_def : Error<
- "ARC forbids implementation of %0">;
+ "ARC forbids %select{implementation|synthesis}0 of %1">;
def warn_arc_strong_pointer_objc_pointer : Warning<
"method parameter of type %0 with no explicit ownership">,
InGroup<DiagGroup<"explicit-ownership-type">>, DefaultIgnore;
@@ -4053,6 +4227,9 @@ def ext_sizeof_alignof_void_type : Extension<
def err_sizeof_alignof_incomplete_type : Error<
"invalid application of '%select{sizeof|alignof|vec_step}0' to an "
"incomplete type %1">;
+def err_sizeof_alignof_function_type : Error<
+ "invalid application of '%select{sizeof|alignof|vec_step}0' to a "
+ "function type">;
def err_sizeof_alignof_bitfield : Error<
"invalid application of '%select{sizeof|alignof}0' to bit-field">;
def err_alignof_member_of_incomplete_type : Error<
@@ -4072,6 +4249,11 @@ def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
def warn_offsetof_non_standardlayout_type : ExtWarn<
"offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>;
def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
+def err_offsetof_field_of_virtual_base : Error<
+ "invalid application of 'offsetof' to a field of a virtual base">;
+def warn_sub_ptr_zero_size_types : Warning<
+ "subtraction of pointers to type %0 of zero size has undefined behavior">,
+ InGroup<PointerArith>;
def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
@@ -4139,7 +4321,10 @@ def warn_self_assignment : Warning<
def warn_string_plus_int : Warning<
"adding %0 to a string does not append to the string">,
InGroup<StringPlusInt>;
-def note_string_plus_int_silence : Note<
+def warn_string_plus_char : Warning<
+ "adding %0 to a string pointer does not append to the string">,
+ InGroup<StringPlusChar>;
+def note_string_plus_scalar_silence : Note<
"use array indexing to silence this warning">;
def warn_sizeof_array_param : Warning<
@@ -4189,6 +4374,10 @@ def err_typecheck_member_reference_arrow : Error<
"member reference type %0 is not a pointer">;
def err_typecheck_member_reference_suggestion : Error<
"member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">;
+def note_typecheck_member_reference_suggestion : Note<
+ "did you mean to use '.' instead?">;
+def note_member_reference_arrow_from_operator_arrow : Note<
+ "'->' applied to return value of the operator->() declared here">;
def err_typecheck_member_reference_type : Error<
"cannot refer to type member %0 in %1 with '%select{.|->}2'">;
def err_typecheck_member_reference_unknown : Error<
@@ -4215,20 +4404,28 @@ def note_enum_specialized_here : Note<
"enum %0 was explicitly specialized here">;
def err_member_redeclared : Error<"class member cannot be redeclared">;
+def ext_member_redeclared : ExtWarn<"class member cannot be redeclared">,
+ InGroup<RedeclaredClassMember>;
def err_member_redeclared_in_instantiation : Error<
"multiple overloads of %0 instantiate to the same signature %1">;
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_decl_does_not_match : Error<
+ "out-of-line %select{declaration|definition}2 of %0 "
+ "does not match any declaration in %1">;
+def err_friend_decl_with_def_arg_must_be_def : Error<
+ "friend declaration specifying a default argument must be a definition">;
+def err_friend_decl_with_def_arg_redeclared : Error<
+ "friend declaration specifying a default argument must be the only declaration">;
def err_friend_decl_does_not_match : Error<
"friend declaration of %0 does not match any declaration in %1">;
-def err_member_def_does_not_match_suggest : Error<
- "out-of-line definition of %0 does not match any declaration in %1; "
- "did you mean %2?">;
+def err_member_decl_does_not_match_suggest : Error<
+ "out-of-line %select{declaration|definition}2 of %0 "
+ "does not match any declaration in %1; did you mean %3?">;
def err_member_def_does_not_match_ret_type : Error<
- "out-of-line definition of %q0 differs from the declaration in the return type">;
+ "return type of out-of-line definition of %q0 differs from "
+ "that in the declaration">;
def err_nonstatic_member_out_of_line : Error<
"non-static data member defined out-of-line">;
def err_qualified_typedef_declarator : Error<
@@ -4251,6 +4448,10 @@ def note_member_def_close_const_match : Note<
def note_member_def_close_param_match : Note<
"type of %ordinal0 parameter of member declaration does not match definition"
"%diff{ ($ vs $)|}1,2">;
+def note_local_decl_close_match : Note<"local declaration nearly matches">;
+def note_local_decl_close_param_match : Note<
+ "type of %ordinal0 parameter of local declaration does not match definition"
+ "%diff{ ($ vs $)|}1,2">;
def err_typecheck_ivar_variable_size : Error<
"instance variables must have a constant size">;
def err_ivar_reference_type : Error<
@@ -4266,13 +4467,13 @@ def err_typecheck_pointer_arith_void_type : Error<
"arithmetic on%select{ a|}0 pointer%select{|s}0 to void">;
def err_typecheck_decl_incomplete_type : Error<
"variable has incomplete type %0">;
+def err_typecheck_decl_incomplete_type___float128 : Error<
+ "support for type '__float128' is not yet implemented">;
def ext_typecheck_decl_incomplete_type : ExtWarn<
"tentative definition of variable with internal linkage has incomplete non-array type %0">,
InGroup<DiagGroup<"tentative-definition-incomplete-type">>;
def err_tentative_def_incomplete_type : Error<
"tentative definition has type %0 that is never completed">;
-def err_tentative_def_incomplete_type_arr : Error<
- "tentative definition has array of type %0 that is never completed">;
def warn_tentative_incomplete_array : Warning<
"tentative array definition assumed to have one element">;
def err_typecheck_incomplete_array_needs_initializer : Error<
@@ -4280,7 +4481,13 @@ def err_typecheck_incomplete_array_needs_initializer : Error<
"or an initializer">;
def err_array_init_not_init_list : Error<
"array initializer must be an initializer "
- "list%select{| or string literal}0">;
+ "list%select{| or string literal| or wide string literal}0">;
+def err_array_init_narrow_string_into_wchar : Error<
+ "initializing wide char array with non-wide string literal">;
+def err_array_init_wide_string_into_char : Error<
+ "initializing char array with wide string literal">;
+def err_array_init_incompat_wide_string_into_wchar : Error<
+ "initializing wide char array with incompatible wide string literal">;
def err_array_init_different_type : Error<
"cannot initialize array %diff{of type $ with array of type $|"
"with different type of array}0,1">;
@@ -4290,13 +4497,16 @@ def err_array_init_non_constant_array : Error<
def ext_array_init_copy : Extension<
"initialization of an array "
"%diff{of type $ from a compound literal of type $|"
- "from a compound literal}0,1 is a GNU extension">, InGroup<GNU>;
+ "from a compound literal}0,1 is a GNU extension">, InGroup<GNUCompoundLiteralInitializer>;
// This is intentionally not disabled by -Wno-gnu.
def ext_array_init_parens : ExtWarn<
"parenthesized initialization of a member array is a GNU extension">,
InGroup<DiagGroup<"gnu-array-member-paren-init">>, DefaultError;
def warn_deprecated_string_literal_conversion : Warning<
- "conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>;
+ "conversion from string literal to %0 is deprecated">,
+ InGroup<CXX11CompatDeprecatedWritableStr>;
+def warn_deprecated_string_literal_conversion_c : Warning<
+ "dummy warning to enable -fconst-strings">, InGroup<DeprecatedWritableStr>, DefaultIgnore;
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">;
@@ -4331,6 +4541,8 @@ def ext_typecheck_addrof_temporary : ExtWarn<
InGroup<DiagGroup<"address-of-temporary">>, DefaultError;
def err_typecheck_addrof_temporary : Error<
"taking the address of a temporary object of type %0">;
+def err_typecheck_addrof_dtor : Error<
+ "taking the address of a destructor">;
def err_typecheck_unary_expr : Error<
"invalid argument type %0 to unary expression">;
def err_typecheck_indirection_requires_pointer : Error<
@@ -4405,6 +4617,14 @@ def warn_null_in_comparison_operation : Warning<
"%select{(%1 and NULL)|(NULL and %1)}0">,
InGroup<NullArithmetic>;
+def warn_logical_not_on_lhs_of_comparison : Warning<
+ "logical not is only applied to the left hand side of this comparison">,
+ InGroup<LogicalNotParentheses>;
+def note_logical_not_fix : Note<
+ "add parentheses after the '!' to evaluate the comparison first">;
+def note_logical_not_silence_with_parens : Note<
+ "add parentheses around left hand side expression to silence this warning">;
+
def err_invalid_this_use : Error<
"invalid use of 'this' outside of a non-static member function">;
def err_this_static_member_func : Error<
@@ -4547,6 +4767,15 @@ def warn_instance_method_on_class_found : Warning<
def warn_inst_method_not_found : Warning<
"instance method %objcinstance0 not found (return type defaults to 'id')">,
InGroup<MethodAccess>;
+def warn_instance_method_not_found_with_typo : Warning<
+ "instance method %objcinstance0 not found (return type defaults to 'id')"
+ "; did you mean %objcinstance2?">, InGroup<MethodAccess>;
+def warn_class_method_not_found_with_typo : Warning<
+ "class method %objcclass0 not found (return type defaults to 'id')"
+ "; did you mean %objcclass2?">, InGroup<MethodAccess>;
+def error_method_not_found_with_typo : Error<
+ "%select{instance|class}1 method %0 not found "
+ "; did you mean %2?">;
def error_no_super_class_message : Error<
"no @interface declaration found in class messaging of %0">;
def error_root_class_cannot_use_super : Error<
@@ -4561,6 +4790,7 @@ def warn_bad_receiver_type : Warning<
"receiver type %0 is not 'id' or interface pointer, consider "
"casting it to 'id'">,InGroup<ObjCReceiver>;
def err_bad_receiver_type : Error<"bad receiver type %0">;
+def err_incomplete_receiver_type : Error<"incomplete receiver type %0">;
def err_unknown_receiver_suggest : Error<
"unknown receiver %0; did you mean %1?">;
def error_objc_throw_expects_object : Error<
@@ -4602,6 +4832,8 @@ def note_parameter_named_here : Note<
"passing argument to parameter %0 here">;
def note_parameter_here : Note<
"passing argument to parameter here">;
+def note_method_return_type_change : Note<
+ "compiler has implicitly changed method %0 return type">;
// C++ casts
// These messages adhere to the TryCast pattern: %0 is an int specifying the
@@ -4695,6 +4927,8 @@ 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_uuidof_with_multiple_guids : Error<
+ "cannot call operator __uuidof on a type with multiple GUIDs">;
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">;
@@ -4744,13 +4978,17 @@ def err_default_init_const : Error<
def err_delete_operand : Error<"cannot delete expression of type %0">;
def ext_delete_void_ptr_operand : ExtWarn<
"cannot delete expression with pointer-to-'void' type %0">;
-def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
- "expression of type %0 to a pointer">;
+def err_ambiguous_delete_operand : Error<
+ "ambiguous conversion of delete expression of type %0 to a pointer">;
def warn_delete_incomplete : Warning<
"deleting pointer to incomplete type %0 may cause undefined behavior">,
InGroup<DiagGroup<"delete-incomplete">>;
def err_delete_incomplete_class_type : Error<
"deleting incomplete class type %0; no conversions to pointer type">;
+def err_delete_explicit_conversion : Error<
+ "converting delete expression from type %0 to type %1 invokes an explicit "
+ "conversion function">;
+def note_delete_conversion : Note<"conversion to pointer type %0">;
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<
@@ -4761,7 +4999,10 @@ def note_member_declared_here : Note<
"member %0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
def warn_increment_bool : Warning<
- "incrementing expression of type bool is deprecated">, InGroup<Deprecated>;
+ "incrementing expression of type bool is deprecated">,
+ InGroup<DeprecatedIncrementBool>;
+def err_increment_decrement_enum : Error<
+ "cannot %select{decrement|increment}0 expression of enum type %1">;
def err_catch_incomplete_ptr : Error<
"cannot catch pointer to incomplete type %0">;
def err_catch_incomplete_ref : Error<
@@ -4848,8 +5089,6 @@ let CategoryName = "Lambda Issue" in {
"duration">;
def err_this_capture : Error<
"'this' cannot be %select{implicitly |}0captured in this context">;
- def err_lambda_capture_block : Error<
- "__block variable %0 cannot be captured in a lambda expression">;
def err_lambda_capture_anonymous_var : Error<
"unnamed variable cannot be implicitly captured in a lambda expression">;
def err_lambda_capture_vm_type : Error<
@@ -4864,14 +5103,14 @@ let CategoryName = "Lambda Issue" in {
def note_lambda_decl : Note<"lambda expression begins here">;
def err_lambda_unevaluated_operand : Error<
"lambda expression in an unevaluated operand">;
+ def err_lambda_in_constant_expression : Error<
+ "a lambda expression may not appear inside of a constant expression">;
def err_lambda_return_init_list : Error<
"cannot deduce lambda return type from initializer list">;
def err_lambda_capture_default_arg : Error<
"lambda expression in default argument cannot capture any entity">;
def err_lambda_incomplete_result : Error<
"incomplete result type %0 in lambda expression">;
- def err_lambda_objc_object_result : Error<
- "non-pointer Objective-C class type %0 in lambda expression result">;
def err_noreturn_lambda_has_return_expr : Error<
"lambda declared 'noreturn' should not return">;
def warn_maybe_falloff_nonvoid_lambda : Warning<
@@ -4889,13 +5128,41 @@ let CategoryName = "Lambda Issue" in {
def note_lambda_to_block_conv : Note<
"implicit capture of lambda object due to conversion to block pointer "
"here">;
+
+ // C++1y lambda init-captures.
+ def warn_cxx11_compat_init_capture : Warning<
+ "initialized lambda captures are incompatible with C++ standards "
+ "before C++1y">, InGroup<CXXPre1yCompat>, DefaultIgnore;
+ def ext_init_capture : ExtWarn<
+ "initialized lambda captures are a C++1y extension">, InGroup<CXX1y>;
+ def err_init_capture_no_expression : Error<
+ "initializer missing for lambda capture %0">;
+ def err_init_capture_multiple_expressions : Error<
+ "initializer for lambda capture %0 contains multiple expressions">;
+ def err_init_capture_deduction_failure : Error<
+ "cannot deduce type for lambda capture %0 from initializer of type %2">;
+ def err_init_capture_deduction_failure_from_init_list : Error<
+ "cannot deduce type for lambda capture %0 from initializer list">;
}
def err_return_in_captured_stmt : Error<
"cannot return from %0">;
+def err_capture_block_variable : Error<
+ "__block variable %0 cannot be captured in a "
+ "%select{lambda expression|captured statement}1">;
def err_operator_arrow_circular : Error<
"circular pointer delegation detected">;
+def err_operator_arrow_depth_exceeded : Error<
+ "use of 'operator->' on type %0 would invoke a sequence of more than %1 "
+ "'operator->' calls">;
+def note_operator_arrow_here : Note<
+ "'operator->' declared here produces an object of type %0">;
+def note_operator_arrows_suppressed : Note<
+ "(skipping %0 'operator->'%s0 in backtrace)">;
+def note_operator_arrow_depth : Note<
+ "use -foperator-arrow-depth=N to increase 'operator->' limit">;
+
def err_pseudo_dtor_base_not_scalar : Error<
"object expression of non-scalar type %0 cannot be used in a "
"pseudo-destructor expression">;
@@ -4926,6 +5193,8 @@ def err_typecheck_ambiguous_condition : Error<
"conversion %diff{from $ to $|between types}0,1 is ambiguous">;
def err_typecheck_nonviable_condition : Error<
"no viable conversion%diff{ from $ to $|}0,1">;
+def err_typecheck_nonviable_condition_incomplete : Error<
+ "no viable conversion%diff{ from $ to incomplete type $|}0,1">;
def err_typecheck_deleted_function : Error<
"conversion function %diff{from $ to $|between types}0,1 "
"invokes a deleted function">;
@@ -4939,11 +5208,15 @@ def err_invalid_declarator_global_scope : Error<
"definition or redeclaration of %0 cannot name the global scope">;
def err_invalid_declarator_in_function : Error<
"definition or redeclaration of %0 not allowed inside a function">;
+def err_invalid_declarator_in_block : Error<
+ "definition or redeclaration of %0 not allowed inside a block">;
def err_not_tag_in_scope : Error<
"no %select{struct|interface|union|class|enum}0 named %1 in %2">;
def err_no_typeid_with_fno_rtti : Error<
"cannot use typeid with -fno-rtti">;
+def err_no_dynamic_cast_with_fno_rtti : Error<
+ "cannot use dynamic_cast with -fno-rtti">;
def err_cannot_form_pointer_to_member_of_reference_type : Error<
"cannot form a pointer-to-member to member %0 of reference type %1">;
@@ -5243,6 +5516,14 @@ def err_typecheck_call_too_few_args_at_least_one : Error<
"too few %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"at least argument %1 must be specified">;
+def err_typecheck_call_too_few_args_suggest : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2; did you mean %3?">;
+def err_typecheck_call_too_few_args_at_least_suggest : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at least %1, have %2; did you mean %3?">;
def err_typecheck_call_too_many_args : Error<
"too many %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
@@ -5259,6 +5540,19 @@ def err_typecheck_call_too_many_args_at_most_one : Error<
"too many %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"expected at most single argument %1, have %2 arguments">;
+def err_typecheck_call_too_many_args_suggest : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2; did you mean %3?">;
+def err_typecheck_call_too_many_args_at_most_suggest : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at most %1, have %2; did you mean %3?">;
+
+def err_arc_typecheck_convert_incompatible_pointer : Error<
+ "incompatible pointer types passing retainable parameter of type %0"
+ "to a CF function expecting %1 type">;
+
def note_callee_decl : Note<
"%0 declared here">;
def note_defined_here : Note<"%0 defined here">;
@@ -5268,28 +5562,38 @@ def err_builtin_fn_use : Error<"builtin functions must be directly called">;
def warn_call_wrong_number_of_arguments : Warning<
"too %select{few|many}0 arguments in call to %1">;
def err_atomic_builtin_must_be_pointer : Error<
- "first argument to atomic builtin must be a pointer (%0 invalid)">;
+ "address argument to atomic builtin must be a pointer (%0 invalid)">;
def err_atomic_builtin_must_be_pointer_intptr : Error<
- "first argument to atomic builtin must be a pointer to integer or pointer"
+ "address argument to atomic builtin must be a pointer to integer or pointer"
" (%0 invalid)">;
+def err_atomic_builtin_must_be_pointer_intfltptr : Error<
+ "address argument to atomic builtin must be a pointer to integer,"
+ " floating-point or pointer (%0 invalid)">;
def err_atomic_builtin_pointer_size : Error<
- "first argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte "
+ "address argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte "
"type (%0 invalid)">;
+def err_atomic_exclusive_builtin_pointer_size : Error<
+ "address argument to load or store exclusive builtin must be a pointer to"
+ " 1,2,4 or 8 byte type (%0 invalid)">;
def err_atomic_op_needs_atomic : Error<
- "first argument to atomic operation must be a pointer to _Atomic "
+ "address argument to atomic operation must be a pointer to _Atomic "
"type (%0 invalid)">;
def err_atomic_op_needs_non_const_atomic : Error<
- "first argument to atomic operation must be a pointer to non-const _Atomic "
+ "address argument to atomic operation must be a pointer to non-const _Atomic "
"type (%0 invalid)">;
def err_atomic_op_needs_trivial_copy : Error<
- "first argument to atomic operation must be a pointer to a trivially-copyable"
- " type (%0 invalid)">;
+ "address argument to atomic operation must be a pointer to a "
+ "trivially-copyable type (%0 invalid)">;
def err_atomic_op_needs_atomic_int_or_ptr : Error<
- "first argument to atomic operation must be a pointer to %select{|atomic }0"
+ "address argument to atomic operation must be a pointer to %select{|atomic }0"
"integer or pointer (%1 invalid)">;
def err_atomic_op_bitwise_needs_atomic_int : Error<
- "first argument to bitwise atomic operation must be a pointer to "
+ "address argument to bitwise atomic operation must be a pointer to "
"%select{|atomic }0integer (%1 invalid)">;
+
+def err_atomic_load_store_uses_lib : Error<
+ "atomic %select{load|store}0 requires runtime support that is not "
+ "available for this target">;
def err_deleted_function_use : Error<"attempt to use a deleted function">;
@@ -5326,6 +5630,13 @@ def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning<
"passing object of trivial but non-POD type %0 through variadic"
" %select{function|block|method|constructor}1 is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def err_cannot_pass_to_vararg : Error<
+ "cannot pass %select{expression of type %1|initializer list}0 to variadic "
+ "%select{function|block|method|constructor}2">;
+def err_cannot_pass_to_vararg_format : Error<
+ "cannot pass %select{expression of type %1|initializer list}0 to variadic "
+ "%select{function|block|method|constructor}2; expected type from format "
+ "string was %3">;
def err_typecheck_call_invalid_ordered_compare : Error<
"ordered compare requires two args of floating point type"
@@ -5345,7 +5656,7 @@ def ext_typecheck_cast_nonscalar : Extension<
"C99 forbids casting nonscalar type %0 to the same type">;
def ext_typecheck_cast_to_union : Extension<
"cast to union type is a GNU extension">,
- InGroup<GNU>;
+ InGroup<GNUUnionCast>;
def err_typecheck_cast_to_union_no_type : Error<
"cast to union type from type %0 not present in union">;
def err_cast_pointer_from_non_pointer_int : Error<
@@ -5415,6 +5726,16 @@ 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">;
+def ext_empty_struct_union : Extension<
+ "empty %select{struct|union}0 is a GNU extension">, InGroup<GNUEmptyStruct>;
+def ext_no_named_members_in_struct_union : Extension<
+ "%select{struct|union}0 without named members is a GNU extension">, InGroup<GNUEmptyStruct>;
+def warn_zero_size_struct_union_compat : Warning<"%select{|empty }0"
+ "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">,
+ InGroup<CXXCompat>, DefaultIgnore;
+def warn_zero_size_struct_union_in_extern_c : Warning<"%select{|empty }0"
+ "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">,
+ InGroup<ExternCCompat>;
} // End of general sema category.
// inline asm.
@@ -5447,8 +5768,8 @@ let CategoryName = "Inline Assembly Issue" in {
"accepted due to -fheinous-gnu-extensions, but clang may remove support "
"for this in the future">;
def warn_asm_mismatched_size_modifier : Warning<
- "the value is truncated when put into register, "
- "use a modifier to specify the size">,
+ "value size does not match register size specified by the constraint "
+ "and modifier">,
InGroup<ASMOperandWidths>;
}
@@ -5483,6 +5804,10 @@ def warn_initializer_out_of_order : Warning<
"%select{field|base class}0 %1 will be initialized after "
"%select{field|base}2 %3">,
InGroup<Reorder>, DefaultIgnore;
+def warn_abstract_vbase_init_ignored : Warning<
+ "initializer for virtual base class %0 of abstract class %1 "
+ "will never be used">,
+ InGroup<DiagGroup<"abstract-vbase-init">>, DefaultIgnore;
def err_base_init_does_not_name_class : Error<
"constructor initializer %0 does not name a class">;
@@ -5516,7 +5841,7 @@ def err_in_class_initializer_references_def_ctor : Error<
def ext_in_class_initializer_non_constant : Extension<
"in-class initializer for static data member is not a constant expression; "
- "folding it to a constant is a GNU extension">, InGroup<GNU>;
+ "folding it to a constant is a GNU extension">, InGroup<GNUFoldingConstant>;
def err_thread_dynamic_init : Error<
"initializer for thread-local variable must be a constant expression">;
@@ -5529,7 +5854,7 @@ def note_use_thread_local : Note<
def ext_anonymous_union : Extension<
"anonymous unions are a C11 extension">, InGroup<C11>;
def ext_gnu_anonymous_struct : Extension<
- "anonymous structs are a GNU extension">, InGroup<GNU>;
+ "anonymous structs are a GNU extension">, InGroup<GNUAnonymousStruct>;
def ext_c11_anonymous_struct : Extension<
"anonymous structs are a C11 extension">, InGroup<C11>;
def err_anonymous_union_not_static : Error<
@@ -5584,6 +5909,8 @@ def err_base_must_be_class : Error<"base specifier must name a class">;
def err_union_as_base_class : Error<"unions cannot be base classes">;
def err_circular_inheritance : Error<
"circular inheritance between %0 and %1">;
+def err_base_class_has_flexible_array_member : Error<
+ "base class %0 has a flexible array member">;
def err_incomplete_base_class : Error<"base class has incomplete type">;
def err_duplicate_base_class : Error<
"base class %0 specified more than once as a direct base class">;
@@ -5636,6 +5963,9 @@ def err_operator_new_delete_declared_in_namespace : Error<
"%0 cannot be declared inside a namespace">;
def err_operator_new_delete_declared_static : Error<
"%0 cannot be declared static in global scope">;
+def ext_operator_new_delete_declared_inline : ExtWarn<
+ "replacement function %0 cannot be declared 'inline'">,
+ InGroup<DiagGroup<"inline-new-delete">>;
def err_operator_new_delete_invalid_result_type : Error<
"%0 must return type %1">;
def err_operator_new_delete_dependent_result_type : Error<
@@ -5667,9 +5997,12 @@ def err_literal_operator_params : Error<
"parameter declaration for literal operator %0 is not valid">;
def err_literal_operator_extern_c : Error<
"literal operator must have C++ linkage">;
+def ext_string_literal_operator_template : ExtWarn<
+ "string literal operator templates are a GNU extension">,
+ InGroup<GNUStringLiteralOperatorTemplate>;
def warn_user_literal_reserved : Warning<
- "user-defined literal suffixes not starting with '_' are reserved; "
- "no literal will invoke this operator">,
+ "user-defined literal suffixes not starting with '_' are reserved"
+ "%select{; no literal will invoke this operator|}0">,
InGroup<UserDefinedLiterals>;
// C++ conversion functions
@@ -5718,7 +6051,7 @@ def err_defaulted_special_member_return_type : Error<
"return %1">;
def err_defaulted_special_member_quals : Error<
"an explicitly-defaulted %select{copy|move}0 assignment operator may not "
- "have 'const', 'constexpr' or 'volatile' qualifiers">;
+ "have 'const'%select{, 'constexpr'|}1 or 'volatile' qualifiers">;
def err_defaulted_special_member_volatile_param : Error<
"the parameter for an explicitly-defaulted %select{<<ERROR>>|"
"copy constructor|move constructor|copy assignment operator|"
@@ -5740,11 +6073,19 @@ def err_incorrect_defaulted_exception_spec : Error<
"calculated one">;
def err_incorrect_defaulted_constexpr : Error<
"defaulted definition of %select{default constructor|copy constructor|"
- "move constructor}0 is not constexpr">;
+ "move constructor|copy assignment operator|move assignment operator}0 "
+ "is not constexpr">;
def err_out_of_line_default_deletes : Error<
"defaulting this %select{default constructor|copy constructor|move "
"constructor|copy assignment operator|move assignment operator|destructor}0 "
"would delete it after its first declaration">;
+def warn_vbase_moved_multiple_times : Warning<
+ "defaulted move assignment operator of %0 will move assign virtual base "
+ "class %1 multiple times">, InGroup<DiagGroup<"multiple-move-vbase">>;
+def note_vbase_moved_here : Note<
+ "%select{%1 is a virtual base class of base class %2 declared here|"
+ "virtual base class %1 declared here}0">;
+
def ext_implicit_exception_spec_mismatch : ExtWarn<
"function previously declared with an %select{explicit|implicit}0 exception "
"specification redeclared with an %select{implicit|explicit}0 exception "
@@ -5876,10 +6217,12 @@ def warn_init_ptr_member_to_parameter_addr : Warning<
"initializing pointer member %0 with the stack address of parameter %1">,
InGroup<DanglingField>;
def warn_bind_ref_member_to_temporary : Warning<
- "binding reference member %0 to a temporary value">,
+ "binding reference %select{|subobject of }1member %0 to a temporary value">,
InGroup<DanglingField>;
def note_ref_or_ptr_member_declared_here : Note<
"%select{reference|pointer}0 member declared here">;
+def note_ref_subobject_of_member_declared_here : Note<
+ "member with reference subobject declared here">;
// For non-floating point, expressions of the form x == x or x != x
// should result in a warning, since these always evaluate to a constant.
@@ -6023,7 +6366,7 @@ def warn_unreachable_default : Warning<
InGroup<CoveredSwitchDefault>, DefaultIgnore;
def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
InGroup<Switch>;
-def warn_not_in_enum_assignement : Warning<"integer constant not in range "
+def warn_not_in_enum_assignment : Warning<"integer constant not in range "
"of enumerated type %0">, InGroup<DiagGroup<"assign-enum">>, DefaultIgnore;
def err_typecheck_statement_requires_scalar : Error<
"statement requires expression of scalar type (%0 invalid)">;
@@ -6057,7 +6400,9 @@ def note_empty_body_on_separate_line : Note<
def err_va_start_used_in_non_variadic_function : Error<
"'va_start' used in function with fixed args">;
def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
- "second parameter of 'va_start' not last named argument">;
+ "second parameter of 'va_start' not last named argument">, InGroup<Varargs>;
+def warn_va_start_of_reference_type_is_undefined : Warning<
+ "'va_start' has undefined behavior with reference types">, InGroup<Varargs>;
def err_first_argument_to_va_arg_not_of_type_va_list : Error<
"first argument to 'va_arg' is of type %0 and not 'va_list'">;
def err_second_parameter_to_va_arg_incomplete: Error<
@@ -6072,7 +6417,7 @@ def warn_second_parameter_to_va_arg_ownership_qualified : Warning<
InGroup<NonPODVarargs>, DefaultError;
def warn_second_parameter_to_va_arg_never_compatible : Warning<
"second argument to 'va_arg' is of promotable type %0; this va_arg has "
- "undefined behavior because arguments will be promoted to %1">;
+ "undefined behavior because arguments will be promoted to %1">, InGroup<Varargs>;
def warn_return_missing_expr : Warning<
"non-void %select{function|method}1 %0 should return a value">, DefaultError,
@@ -6124,6 +6469,13 @@ def err_shufflevector_argument_too_large : Error<
"index for __builtin_shufflevector must be less than the total number "
"of vector elements">;
+def err_convertvector_non_vector : Error<
+ "first argument to __builtin_convertvector must be a vector">;
+def err_convertvector_non_vector_type : Error<
+ "second argument to __builtin_convertvector must be a vector type">;
+def err_convertvector_incompatible_vector : Error<
+ "first two arguments to __builtin_convertvector must have the same number of elements">;
+
def err_vector_incorrect_num_initializers : Error<
"%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">;
def err_altivec_empty_initializer : Error<"expected initializer">;
@@ -6153,6 +6505,8 @@ def err_selector_element_not_lvalue : Error<
"selector element is not a valid lvalue">;
def err_selector_element_type : Error<
"selector element type %0 is not a valid object">;
+def err_selector_element_const_type : Error<
+ "selector element of type %0 cannot be a constant l-value expression">;
def err_collection_expr_type : Error<
"the type %0 is not a pointer to a fast-enumerable object">;
def warn_collection_expr_type : Warning<
@@ -6161,6 +6515,9 @@ def warn_collection_expr_type : Warning<
def err_invalid_conversion_between_ext_vectors : Error<
"invalid conversion between ext-vector type %0 and %1">;
+def warn_duplicate_attribute_exact : Warning<
+ "attribute %0 is already applied">, InGroup<IgnoredAttributes>;
+
def warn_duplicate_attribute : Warning<
"attribute %0 is already applied with different parameters">,
InGroup<IgnoredAttributes>;
@@ -6231,19 +6588,19 @@ def warn_direct_ivar_access : Warning<"instance variable %0 is being "
// Spell-checking diagnostics
def err_unknown_type_or_class_name_suggest : Error<
- "unknown %select{type|class}2 name %0; did you mean %1?">;
+ "unknown %select{type|class}1 name %0; did you mean %2?">;
def err_unknown_typename_suggest : Error<
"unknown type name %0; did you mean %1?">;
def err_unknown_nested_typename_suggest : Error<
- "no type named %0 in %1; did you mean %2?">;
-def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">;
+ "no type named %0 in %1; did you mean %select{|simply }2%3?">;
+def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %select{|simply }2%3?">;
def err_undeclared_use_suggest : Error<
"use of undeclared %0; did you mean %1?">;
def err_undeclared_var_use_suggest : Error<
"use of undeclared identifier %0; did you mean %1?">;
def err_no_template_suggest : Error<"no template named %0; did you mean %1?">;
def err_no_member_template_suggest : Error<
- "no template named %0 in %1; did you mean %2?">;
+ "no template named %0 in %1; did you mean %select{|simply }2%3?">;
def err_mem_init_not_member_or_class_suggest : Error<
"initializer %0 does not name a non-static data member or base "
"class; did you mean the %select{base class|member}1 %2?">;
@@ -6273,7 +6630,7 @@ def note_base_class_specified_here : Note<
def err_using_directive_suggest : Error<
"no namespace named %0; did you mean %1?">;
def err_using_directive_member_suggest : Error<
- "no namespace named %0 in %1; did you mean %2?">;
+ "no namespace named %0 in %1; did you mean %select{|simply }2%3?">;
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?">;
@@ -6308,16 +6665,22 @@ def err_invalid_astype_of_different_size : Error<
"invalid reinterpretation: sizes of %0 and %1 must match">;
def err_static_kernel : Error<
"kernel functions cannot be declared static">;
-def err_opencl_ptrptr_kernel_arg : Error<
- "kernel argument cannot be declared as a pointer to a pointer">;
+def err_opencl_ptrptr_kernel_param : Error<
+ "kernel parameter cannot be declared as a pointer to a pointer">;
def err_static_function_scope : Error<
"variables in function scope cannot be declared static">;
def err_opencl_bitfields : Error<
"bitfields are not supported in OpenCL">;
def err_opencl_vla : Error<
"variable length arrays are not supported in OpenCL">;
-def err_event_t_kernel_arg : Error<
- "the event_t type cannot be used to declare a kernel function argument">;
+def err_bad_kernel_param_type : Error<
+ "%0 cannot be used as the type of a kernel parameter">;
+def err_record_with_pointers_kernel_param : Error<
+ "%select{struct|union}0 kernel parameters may not contain pointers">;
+def note_within_field_of_type : Note<
+ "within field of type %0 declared here">;
+def note_illegal_field_declared_here : Note<
+ "field of illegal %select{type|pointer type}0 %1 declared here">;
def err_event_t_global_var : Error<
"the event_t type cannot be used to declare a program scope variable">;
def err_event_t_struct_field : Error<
@@ -6332,24 +6695,49 @@ def err_wrong_sampler_addressspace: Error<
"sampler type cannot be used with the __local and __global address space qualifiers">;
def err_opencl_global_invalid_addr_space : Error<
"global variables must have a constant address space qualifier">;
-
+def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
+} // end of sema category
+
+let CategoryName = "OpenMP Issue" in {
// OpenMP support.
+def err_omp_expected_var_arg : Error<
+ "%0 is not a global variable, static local variable or static data member">;
def err_omp_expected_var_arg_suggest : Error<
- "%0 is not a global variable, static local variable or static data member%select{|; did you mean %2?}1">;
+ "%0 is not a global variable, static local variable or static data member; "
+ "did you mean %1">;
def err_omp_global_var_arg : Error<
"arguments of '#pragma omp %0' must have %select{global storage|static storage duration}1">;
def err_omp_ref_type_arg : Error<
"arguments of '#pragma omp %0' cannot be of reference type %1">;
def err_omp_var_scope : Error<
- "'#pragma omp %0' must appear in the scope of the %1 variable declaration">;
+ "'#pragma omp %0' must appear in the scope of the %q1 variable declaration">;
def err_omp_var_used : Error<
- "'#pragma omp %0' must precede all references to variable %1">;
+ "'#pragma omp %0' must precede all references to variable %q1">;
def err_omp_var_thread_local : Error<
"variable %0 cannot be threadprivate because it is thread-local">;
-def err_omp_incomplete_type : Error<
- "a threadprivate variable must not have incomplete type %0">;
-
-} // end of sema category
+def err_omp_private_incomplete_type : Error<
+ "a private variable with incomplete type %0">;
+def err_omp_firstprivate_incomplete_type : Error<
+ "a firstprivate variable with incomplete type %0">;
+def err_omp_unexpected_clause_value : Error <
+ "expected %0 in OpenMP clause '%1'">;
+def err_omp_expected_var_name : Error <
+ "expected variable name">;
+def err_omp_required_method : Error <
+ "%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">;
+def err_omp_clause_ref_type_arg : Error<
+ "arguments of OpenMP clause '%0' cannot be of reference type %1">;
+def err_omp_threadprivate_incomplete_type : Error<
+ "threadprivate variable with incomplete type %0">;
+def err_omp_no_dsa_for_variable : Error <
+ "variable %0 must have explicitly specified data sharing attributes">;
+def err_omp_wrong_dsa : Error<
+ "%0 variable cannot be %1">;
+def note_omp_explicit_dsa : Note <
+ "defined as %0">;
+def note_omp_predetermined_dsa : Note <
+ "predetermined as %0">;
+} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
// Objective-C related result type compatibility
@@ -6386,6 +6774,8 @@ def err_module_private_local : Error<
def err_module_private_local_class : Error<
"local %select{struct|interface|union|class|enum}0 cannot be declared "
"__module_private__">;
+def err_module_private_declaration : Error<
+ "declaration of %0 must be imported from module '%1' before it is required">;
def err_module_private_definition : Error<
"definition of %0 must be imported from module '%1' before it is required">;
}
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 1b45b10c1221..81509cc18821 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -14,7 +14,7 @@ def err_fe_unable_to_read_pch_file : Error<
def err_fe_not_a_pch_file : Error<
"input is not a PCH file: '%0'">;
def err_fe_pch_malformed : Error<
- "malformed or corrupted PCH file: '%0'">, DefaultFatal;
+ "malformed or corrupted AST file: '%0'">, DefaultFatal;
def err_fe_pch_malformed_block : Error<
"malformed block record in PCH file: '%0'">, DefaultFatal;
def err_fe_pch_file_modified : Error<
@@ -22,6 +22,8 @@ def err_fe_pch_file_modified : Error<
DefaultFatal;
def err_fe_pch_file_overridden : Error<
"file '%0' from the precompiled header has been overridden">;
+def note_module_cache_path : Note<
+ "after modifying system headers, please delete the module cache at '%0'">;
def err_pch_targetopt_mismatch : Error<
"PCH file was compiled for the %0 '%1' but the current translation "
@@ -65,4 +67,13 @@ def err_pch_pp_detailed_record : Error<
def err_not_a_pch_file : Error<
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
+
+def err_module_odr_violation_missing_decl : Error<
+ "%q0 from module '%1' is not present in definition of %q2"
+ "%select{ in module '%4'| provided earlier}3">, NoSFINAE;
+def note_module_odr_violation_no_possible_decls : Note<
+ "definition has no member %0">;
+def note_module_odr_violation_possible_decl : Note<
+ "declaration of %0 does not match">;
+
}
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index 6d9e53b7eb0d..255eee3084b5 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/FileSystem.h"
// FIXME: Enhance libsystem to support inode and other fields in stat.
#include <sys/types.h>
@@ -35,7 +36,6 @@ struct stat;
namespace llvm {
class MemoryBuffer;
-namespace sys { class Path; }
}
namespace clang {
@@ -63,9 +63,9 @@ class FileEntry {
time_t ModTime; // Modification time of file.
const DirectoryEntry *Dir; // Directory file lives in.
unsigned UID; // A unique (small) ID for the file.
- 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'.
+ llvm::sys::fs::UniqueID UniqueID;
+ bool IsNamedPipe;
+ bool InPCH;
/// FD - The file descriptor for the file entry if it is opened and owned
/// by the FileEntry. If not, this is set to -1.
@@ -73,10 +73,12 @@ class FileEntry {
friend class FileManager;
public:
- FileEntry(dev_t device, ino_t inode, mode_t m)
- : Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {}
+ FileEntry(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe, bool InPCH)
+ : Name(0), UniqueID(UniqueID), IsNamedPipe(IsNamedPipe), InPCH(InPCH),
+ FD(-1) {}
// Add a default constructor for use with llvm::StringMap
- FileEntry() : Name(0), Device(0), Inode(0), FileMode(0), FD(-1) {}
+ FileEntry()
+ : Name(0), UniqueID(0, 0), IsNamedPipe(false), InPCH(false), FD(-1) {}
FileEntry(const FileEntry &FE) {
memcpy(this, &FE, sizeof(FE));
@@ -93,23 +95,22 @@ public:
const char *getName() const { return Name; }
off_t getSize() const { return Size; }
unsigned getUID() const { return UID; }
- ino_t getInode() const { return Inode; }
- dev_t getDevice() const { return Device; }
+ const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
+ bool isInPCH() const { return InPCH; }
time_t getModificationTime() const { return ModTime; }
- mode_t getFileMode() const { return FileMode; }
/// \brief Return the directory the file lives in.
const DirectoryEntry *getDir() const { return Dir; }
- bool operator<(const FileEntry &RHS) const {
- return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode);
- }
+ bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; }
/// \brief Check whether the file is a named pipe (and thus can't be opened by
/// the native FileManager methods).
- bool isNamedPipe() const;
+ bool isNamedPipe() const { return IsNamedPipe; }
};
+struct FileData;
+
/// \brief Implements support for file system lookup, file system caching,
/// and directory search management.
///
@@ -170,8 +171,8 @@ class FileManager : public RefCountedBase<FileManager> {
// Caching.
OwningPtr<FileSystemStatCache> StatCache;
- bool getStatValue(const char *Path, struct stat &StatBuf,
- bool isFile, int *FileDescriptor);
+ bool getStatValue(const char *Path, FileData &Data, bool isFile,
+ int *FileDescriptor);
/// Add all ancestors of the given path (pointing to either a file
/// or a directory) as virtual directories.
@@ -244,7 +245,8 @@ public:
///
/// If the path is relative, it will be resolved against the WorkingDir of the
/// FileManager's FileSystemOptions.
- bool getNoncachedStatValue(StringRef Path, struct stat &StatBuf);
+ bool getNoncachedStatValue(StringRef Path,
+ llvm::sys::fs::file_status &Result);
/// \brief Remove the real file \p Entry from the cache.
void invalidateCache(const FileEntry *Entry);
diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
index ff70373ffb06..23d82569437f 100644
--- a/include/clang/Basic/FileSystemStatCache.h
+++ b/include/clang/Basic/FileSystemStatCache.h
@@ -18,11 +18,21 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/FileSystem.h"
#include <sys/stat.h>
#include <sys/types.h>
namespace clang {
+struct FileData {
+ uint64_t Size;
+ time_t ModTime;
+ llvm::sys::fs::UniqueID UniqueID;
+ bool IsDirectory;
+ bool IsNamedPipe;
+ bool InPCH;
+};
+
/// \brief Abstract interface for introducing a FileManager cache for 'stat'
/// system calls, which is used by precompiled and pretokenized headers to
/// improve performance.
@@ -49,10 +59,9 @@ public:
/// 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,
- bool isFile, int *FileDescriptor, FileSystemStatCache *Cache);
-
-
+ static bool get(const char *Path, FileData &Data, bool isFile,
+ 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) {
@@ -68,18 +77,18 @@ public:
FileSystemStatCache *takeNextStatCache() { return NextStatCache.take(); }
protected:
- virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
- bool isFile, int *FileDescriptor) = 0;
+ virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ int *FileDescriptor) = 0;
- LookupResult statChained(const char *Path, struct stat &StatBuf,
- bool isFile, int *FileDescriptor) {
+ LookupResult statChained(const char *Path, FileData &Data, bool isFile,
+ int *FileDescriptor) {
if (FileSystemStatCache *Next = getNextStatCache())
- return Next->getStat(Path, StatBuf, isFile, FileDescriptor);
-
+ return Next->getStat(Path, Data, isFile, 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,
- isFile, FileDescriptor, 0) ? CacheMissing : CacheExists;
+ return get(Path, Data, isFile, FileDescriptor, 0) ? CacheMissing
+ : CacheExists;
}
};
@@ -89,16 +98,16 @@ protected:
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
+ llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
+
+ typedef llvm::StringMap<FileData, 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,
- bool isFile, int *FileDescriptor);
+
+ virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ int *FileDescriptor);
};
} // end namespace clang
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index d4d53390bdb3..304ff364bfc9 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -19,6 +19,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
@@ -147,7 +148,7 @@ public:
return HadMacro;
}
- /// getTokenID - If this is a source-language token (e.g. 'for'), this API
+ /// If this is a source-language token (e.g. 'for'), this API
/// can be used to cause the lexer to map identifiers to source-language
/// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
@@ -183,8 +184,9 @@ public:
}
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
- /// getBuiltinID - Return a value indicating whether this is a builtin
- /// function. 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
+ /// \brief Return a value indicating whether this is a builtin function.
+ ///
+ /// 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
/// 2+ are specific builtin functions.
unsigned getBuiltinID() const {
if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS)
@@ -236,7 +238,7 @@ public:
RecomputeNeedsHandleIdentifier();
}
- /// isPoisoned - Return true if this token has been poisoned.
+ /// \brief Return true if this token has been poisoned.
bool isPoisoned() const { return IsPoisoned; }
/// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
@@ -256,12 +258,14 @@ public:
T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
void setFETokenInfo(void *T) { FETokenInfo = T; }
- /// isHandleIdentifierCase - Return true if the Preprocessor::HandleIdentifier
- /// must be called on a token of this identifier. If this returns false, we
- /// know that HandleIdentifier will not affect the token.
+ /// \brief Return true if the Preprocessor::HandleIdentifier must be called
+ /// on a token of this identifier.
+ ///
+ /// If this returns false, we know that HandleIdentifier will not affect
+ /// the token.
bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
- /// isFromAST - Return true if the identifier in its current state was loaded
+ /// \brief Return true if the identifier in its current state was loaded
/// from an AST file.
bool isFromAST() const { return IsFromAST; }
@@ -293,12 +297,10 @@ public:
RecomputeNeedsHandleIdentifier();
}
- /// \brief Determine whether this is the contextual keyword
- /// 'import'.
+ /// \brief Determine whether this is the contextual keyword \c import.
bool isModulesImport() const { return IsModulesImport; }
- /// \brief Set whether this identifier is the contextual keyword
- /// 'import'.
+ /// \brief Set whether this identifier is the contextual keyword \c import.
void setModulesImport(bool I) {
IsModulesImport = I;
if (I)
@@ -308,10 +310,9 @@ public:
}
private:
- /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
- /// several special (but rare) things to identifiers of various sorts. For
- /// example, it changes the "for" keyword token from tok::identifier to
- /// tok::for.
+ /// The Preprocessor::HandleIdentifier does several special (but rare)
+ /// things to identifiers of various sorts. For example, it changes the
+ /// \c for keyword token from tok::identifier to tok::for.
///
/// This method is very tied to the definition of HandleIdentifier. Any
/// change to it should be reflected here.
@@ -323,9 +324,10 @@ private:
}
};
-/// \brief an RAII object for [un]poisoning an identifier
-/// within a certain scope. II is allowed to be null, in
-/// which case, objects of this type have no effect.
+/// \brief An RAII object for [un]poisoning an identifier within a scope.
+///
+/// \p II is allowed to be null, in which case objects of this type have
+/// no effect.
class PoisonIdentifierRAIIObject {
IdentifierInfo *const II;
const bool OldValue;
@@ -371,17 +373,16 @@ public:
virtual StringRef Next() = 0;
};
-/// IdentifierInfoLookup - An abstract class used by IdentifierTable that
-/// provides an interface for performing lookups from strings
-/// (const char *) to IdentiferInfo objects.
+/// \brief Provides lookups to, and iteration over, IdentiferInfo objects.
class IdentifierInfoLookup {
public:
virtual ~IdentifierInfoLookup();
- /// get - Return the identifier token info for the specified named identifier.
- /// Unlike the version in IdentifierTable, this returns a pointer instead
- /// of a reference. If the pointer is NULL then the IdentifierInfo cannot
- /// be found.
+ /// \brief Return the IdentifierInfo for the specified named identifier.
+ ///
+ /// Unlike the version in IdentifierTable, this returns a pointer instead
+ /// of a reference. If the pointer is null then the IdentifierInfo cannot
+ /// be found.
virtual IdentifierInfo* get(StringRef Name) = 0;
/// \brief Retrieve an iterator into the set of all identifiers
@@ -577,6 +578,19 @@ enum { ObjCMethodFamilyBitWidth = 4 };
/// \brief An invalid value of ObjCMethodFamily.
enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 };
+/// \brief A family of Objective-C methods.
+///
+/// These are family of methods whose result type is initially 'id', but
+/// but are candidate for the result type to be changed to 'instancetype'.
+enum ObjCInstanceTypeFamily {
+ OIT_None,
+ OIT_Array,
+ OIT_Dictionary,
+ OIT_Singleton,
+ OIT_Init,
+ OIT_ReturnsSelf
+};
+
/// \brief Smart pointer class that efficiently represents Objective-C method
/// names.
///
@@ -697,6 +711,8 @@ public:
static Selector getTombstoneMarker() {
return Selector(uintptr_t(-2));
}
+
+ static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel);
};
/// \brief This table allows us to fully hide how we implement
@@ -725,13 +741,19 @@ public:
/// \brief Return the total amount of memory allocated for managing selectors.
size_t getTotalMemory() const;
- /// \brief Return the setter name for the given identifier.
+ /// \brief Return the default setter name for the given identifier.
+ ///
+ /// This is "set" + \p Name where the initial character of \p Name
+ /// has been capitalized.
+ static SmallString<64> constructSetterName(StringRef Name);
+
+ /// \brief Return the default setter selector for the given identifier.
///
/// This is "set" + \p Name where the initial character of \p Name
/// has been capitalized.
- static Selector constructSetterName(IdentifierTable &Idents,
- SelectorTable &SelTable,
- const IdentifierInfo *Name);
+ static Selector constructSetterSelector(IdentifierTable &Idents,
+ SelectorTable &SelTable,
+ const IdentifierInfo *Name);
};
/// DeclarationNameExtra - Common base of the MultiKeywordSelector,
diff --git a/include/clang/Basic/Lambda.h b/include/clang/Basic/Lambda.h
index b1ad6acda3b4..280ae94fedc5 100644
--- a/include/clang/Basic/Lambda.h
+++ b/include/clang/Basic/Lambda.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines several types used to describe C++ lambda expressions
+/// \brief Defines several types used to describe C++ lambda expressions
/// that are shared between the parser and AST.
///
//===----------------------------------------------------------------------===//
@@ -26,12 +26,15 @@ enum LambdaCaptureDefault {
LCD_ByRef
};
-/// \brief The different capture forms in a lambda introducer: 'this' or a
-/// copied or referenced variable.
+/// \brief The different capture forms in a lambda introducer
+///
+/// C++11 allows capture of \c this, or of local variables by copy or
+/// by reference. C++1y also allows "init-capture", where the initializer
+/// is an expression.
enum LambdaCaptureKind {
- LCK_This,
- LCK_ByCopy,
- LCK_ByRef
+ LCK_This, ///< Capturing the \c this pointer
+ LCK_ByCopy, ///< Capturing by copy (a.k.a., by value)
+ LCK_ByRef ///< Capturing by reference
};
} // end namespace clang
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index b17dfbc9b520..5a1025cba7ec 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -1,4 +1,4 @@
-//===--- LangOptions.def - Language option database --------------- C++ -*-===//
+//===--- LangOptions.def - Language option database -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This file defines the language options. Users of this file must
-// define the LANGOPT macro to make use of this information.
+// define the LANGOPT macro to make use of this information.
// Optionally, the user may also define BENIGN_LANGOPT
// (for options that don't affect the construction of the AST in an
// incompatible way), ENUM_LANGOPT (for options that have enumeration,
@@ -52,11 +52,11 @@ LANGOPT(CPlusPlus11 , 1, 0, "C++0x")
LANGOPT(CPlusPlus1y , 1, 0, "C++1y")
LANGOPT(ObjC1 , 1, 0, "Objective-C 1")
LANGOPT(ObjC2 , 1, 0, "Objective-C 2")
-BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0,
+BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0,
"Objective-C auto-synthesized properties")
-BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0,
+BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0,
"Encoding extended block type signature")
-BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1,
+BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1,
"Objective-C related result type inference")
LANGOPT(Trigraphs , 1, 0,"trigraphs")
LANGOPT(LineComment , 1, 0, "'//' comments")
@@ -85,6 +85,7 @@ LANGOPT(RTTI , 1, 1, "run-time type information")
LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
LANGOPT(Freestanding, 1, 0, "freestanding implementation")
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
+LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")
@@ -93,10 +94,11 @@ BENIGN_LANGOPT(EmitAllDecls , 1, 0, "support for emitting all declarations"
LANGOPT(MathErrno , 1, 1, "errno support for math functions")
BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time")
LANGOPT(Modules , 1, 0, "modules extension to C")
+LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses")
LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
-VALUE_LANGOPT(PackStruct , 32, 0,
+VALUE_LANGOPT(PackStruct , 32, 0,
"default struct packing maximum alignment")
VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level")
VALUE_LANGOPT(PIELevel , 2, 0, "__PIE__ level")
@@ -121,6 +123,7 @@ LANGOPT(CUDA , 1, 0, "CUDA")
LANGOPT(OpenMP , 1, 0, "OpenMP support")
LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators")
+LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions")
BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records")
BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form")
@@ -140,31 +143,37 @@ LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
LANGOPT(ObjCARCWeak , 1, 0, "__weak support in the ARC runtime")
+LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
+ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
LANGOPT(MRTD , 1, 0, "-mrtd calling convention")
BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing")
LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime")
ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode")
-ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility,
+ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility,
"value symbol visibility")
-ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility,
+ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility,
"type symbol visibility")
-ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff,
+ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff,
"stack protector mode")
ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
"signed integer overflow handling")
-BENIGN_LANGOPT(InstantiationDepth, 32, 256,
+BENIGN_LANGOPT(ArrowDepth, 32, 256,
+ "maximum number of operator->s to follow")
+BENIGN_LANGOPT(InstantiationDepth, 32, 256,
"maximum template instantiation depth")
BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
"maximum constexpr call depth")
+BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576,
+ "maximum constexpr evaluation steps")
BENIGN_LANGOPT(BracketDepth, 32, 256,
"maximum bracket nesting depth")
-BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
+BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
"if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.")
-VALUE_LANGOPT(MSCVersion, 32, 0,
+VALUE_LANGOPT(MSCVersion, 32, 0,
"version of Microsoft Visual C/C++")
LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling")
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index 21ca7eb201c9..d4e8b4eb5bad 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -66,6 +66,8 @@ public:
SOB_Trapping // -ftrapv
};
+ enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
+
public:
clang::ObjCRuntime ObjCRuntime;
@@ -95,6 +97,11 @@ public:
bool isSignedOverflowDefined() const {
return getSignedOverflowBehavior() == SOB_Defined;
}
+
+ bool isSubscriptPointerArithmetic() const {
+ return ObjCRuntime.isSubscriptPointerArithmetic() &&
+ !ObjCSubscriptingLegacyRuntime;
+ }
/// \brief Reset all of the options that are not considered when building a
/// module.
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 01b8db15f511..699620784ecd 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -37,6 +37,10 @@ enum Linkage {
/// point of view.
UniqueExternalLinkage,
+ /// \brief No linkage according to the standard, but is visible from other
+ /// translation units because of types defined in a inline function.
+ VisibleNoLinkage,
+
/// \brief External linkage, which indicates that the entity can
/// be referred to from other translation units.
ExternalLinkage
@@ -62,14 +66,40 @@ enum GVALinkage {
GVA_ExplicitTemplateInstantiation
};
-/// \brief Determine whether the given linkage is semantically external.
-inline bool isExternalLinkage(Linkage L) {
- return L == UniqueExternalLinkage || L == ExternalLinkage;
+inline bool isExternallyVisible(Linkage L) {
+ return L == ExternalLinkage || L == VisibleNoLinkage;
+}
+
+inline Linkage getFormalLinkage(Linkage L) {
+ if (L == UniqueExternalLinkage)
+ return ExternalLinkage;
+ if (L == VisibleNoLinkage)
+ return NoLinkage;
+ return L;
}
-/// \brief Compute the minimum linkage given two linages.
+inline bool isExternalFormalLinkage(Linkage L) {
+ return getFormalLinkage(L) == ExternalLinkage;
+}
+
+/// \brief Compute the minimum linkage given two linkages.
+///
+/// The linkage can be interpreted as a pair formed by the formal linkage and
+/// a boolean for external visibility. This is just what getFormalLinkage and
+/// isExternallyVisible return. We want the minimum of both components. The
+/// Linkage enum is defined in an order that makes this simple, we just need
+/// special cases for when VisibleNoLinkage would lose the visible bit and
+/// become NoLinkage.
inline Linkage minLinkage(Linkage L1, Linkage L2) {
- return L1 < L2? L1 : L2;
+ if (L2 == VisibleNoLinkage)
+ std::swap(L1, L2);
+ if (L1 == VisibleNoLinkage) {
+ if (L2 == InternalLinkage)
+ return NoLinkage;
+ if (L2 == UniqueExternalLinkage)
+ return NoLinkage;
+ }
+ return L1 < L2 ? L1 : L2;
}
} // end namespace clang
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index d2a43f0219e6..e8d774e1eb54 100644
--- a/include/clang/Basic/Module.h
+++ b/include/clang/Basic/Module.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_BASIC_MODULE_H
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SetVector.h"
@@ -37,6 +38,7 @@ class FileEntry;
class FileManager;
class LangOptions;
class TargetInfo;
+class IdentifierInfo;
/// \brief Describes the name of a module.
typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
@@ -75,19 +77,28 @@ private:
/// \brief top-level header filenames that aren't resolved to FileEntries yet.
std::vector<std::string> TopHeaderNames;
+ /// \brief Cache of modules visible to lookup in this module.
+ mutable llvm::DenseSet<const Module*> VisibleModulesCache;
+
public:
/// \brief The headers that are part of this module.
- SmallVector<const FileEntry *, 2> Headers;
+ SmallVector<const FileEntry *, 2> NormalHeaders;
/// \brief The headers that are explicitly excluded from this module.
SmallVector<const FileEntry *, 2> ExcludedHeaders;
+ /// \brief The headers that are private to this module.
+ llvm::SmallVector<const FileEntry *, 2> PrivateHeaders;
+
+ /// \brief An individual requirement: a feature name and a flag indicating
+ /// the required state of that feature.
+ typedef std::pair<std::string, bool> Requirement;
+
/// \brief The set of language features required to use this module.
///
- /// If any of these features is not present, the \c IsAvailable bit
- /// will be false to indicate that this (sub)module is not
- /// available.
- SmallVector<std::string, 2> Requires;
+ /// If any of these requirements are not available, the \c IsAvailable bit
+ /// will be false to indicate that this (sub)module is not available.
+ SmallVector<Requirement, 2> Requirements;
/// \brief Whether this module is available in the current
/// translation unit.
@@ -176,6 +187,12 @@ public:
/// \brief The set of export declarations that have yet to be resolved.
SmallVector<UnresolvedExportDecl, 2> UnresolvedExports;
+ /// \brief The directly used modules.
+ SmallVector<Module *, 2> DirectUses;
+
+ /// \brief The set of use declarations that have yet to be resolved.
+ SmallVector<ModuleId, 2> UnresolvedDirectUses;
+
/// \brief A library or framework to link against when an entity from this
/// module is used.
struct LinkLibrary {
@@ -254,12 +271,12 @@ public:
///
/// \param Target The target options used for the current translation unit.
///
- /// \param Feature If this module is unavailable, this parameter
- /// will be set to one of the features that is required for use of
- /// this module (but is not available).
+ /// \param Req If this module is unavailable, this parameter
+ /// will be set to one of the requirements that is not met for use of
+ /// this module.
bool isAvailable(const LangOptions &LangOpts,
const TargetInfo &Target,
- StringRef &Feature) const;
+ Requirement &Req) const;
/// \brief Determine whether this module is a submodule.
bool isSubModule() const { return Parent != 0; }
@@ -353,12 +370,16 @@ public:
/// \param Feature The feature that is required by this module (and
/// its submodules).
///
+ /// \param RequiredState The required state of this feature: \c true
+ /// if it must be present, \c false if it must be absent.
+ ///
/// \param LangOpts The set of language options that will be used to
/// evaluate the availability of this feature.
///
/// \param Target The target options that will be used to evaluate the
/// availability of this feature.
- void addRequirement(StringRef Feature, const LangOptions &LangOpts,
+ void addRequirement(StringRef Feature, bool RequiredState,
+ const LangOptions &LangOpts,
const TargetInfo &Target);
/// \brief Find the submodule with the given name.
@@ -366,6 +387,14 @@ public:
/// \returns The submodule if found, or NULL otherwise.
Module *findSubmodule(StringRef Name) const;
+ /// \brief Determine whether the specified module would be visible to
+ /// a lookup at the end of this module.
+ bool isModuleVisible(const Module *M) const {
+ if (VisibleModulesCache.empty())
+ buildVisibleModulesCache();
+ return VisibleModulesCache.count(M);
+ }
+
typedef std::vector<Module *>::iterator submodule_iterator;
typedef std::vector<Module *>::const_iterator submodule_const_iterator;
@@ -374,7 +403,10 @@ public:
submodule_iterator submodule_end() { return SubModules.end(); }
submodule_const_iterator submodule_end() const { return SubModules.end(); }
- /// \brief Returns the exported modules based on the wildcard restrictions.
+ /// \brief Appends this module's list of exported modules to \p Exported.
+ ///
+ /// This provides a subset of immediately imported modules (the ones that are
+ /// directly exported), not the complete set of exported modules.
void getExportedModules(SmallVectorImpl<Module *> &Exported) const;
static StringRef getModuleInputBufferName() {
@@ -387,6 +419,9 @@ public:
/// \brief Dump the contents of this module to the given output stream.
void dump() const;
+
+private:
+ void buildVisibleModulesCache() const;
};
} // end namespace clang
diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
index 18ef64a31527..4c6449750373 100644
--- a/include/clang/Basic/ObjCRuntime.h
+++ b/include/clang/Basic/ObjCRuntime.h
@@ -79,7 +79,7 @@ public:
case GCC: return false;
case MacOSX: return true;
case GNUstep: return true;
- case ObjFW: return false;
+ case ObjFW: return true;
case iOS: return true;
}
llvm_unreachable("bad kind");
@@ -98,9 +98,8 @@ public:
Arch == llvm::Triple::x86 ||
Arch == llvm::Triple::x86_64)
return false;
- // Mac runtimes use legacy dispatch everywhere except x86-64
- } else if (isNeXTFamily() && isNonFragile())
- return Arch != llvm::Triple::x86_64;
+ }
+ // Mac runtimes use legacy dispatch everywhere now.
return true;
}
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index f968977f64bc..6d1a7b27b749 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
/// \file
-/// \brief This file defines the list of supported OpenMP directives and
+/// \brief This file defines the list of supported OpenMP directives and
/// clauses.
///
//===----------------------------------------------------------------------===//
@@ -15,9 +15,38 @@
#ifndef OPENMP_DIRECTIVE
# define OPENMP_DIRECTIVE(Name)
#endif
+#ifndef OPENMP_CLAUSE
+# define OPENMP_CLAUSE(Name, Class)
+#endif
+#ifndef OPENMP_PARALLEL_CLAUSE
+# define OPENMP_PARALLEL_CLAUSE(Name)
+#endif
+#ifndef OPENMP_DEFAULT_KIND
+# define OPENMP_DEFAULT_KIND(Name)
+#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
OPENMP_DIRECTIVE(parallel)
+OPENMP_DIRECTIVE(task)
+
+// OpenMP clauses.
+OPENMP_CLAUSE(default, OMPDefaultClause)
+OPENMP_CLAUSE(private, OMPPrivateClause)
+OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
+OPENMP_CLAUSE(shared, OMPSharedClause)
+
+// Clauses allowed for OpenMP directives.
+OPENMP_PARALLEL_CLAUSE(default)
+OPENMP_PARALLEL_CLAUSE(private)
+OPENMP_PARALLEL_CLAUSE(firstprivate)
+OPENMP_PARALLEL_CLAUSE(shared)
+
+// Static attributes for 'default' clause.
+OPENMP_DEFAULT_KIND(none)
+OPENMP_DEFAULT_KIND(shared)
+#undef OPENMP_DEFAULT_KIND
#undef OPENMP_DIRECTIVE
+#undef OPENMP_CLAUSE
+#undef OPENMP_PARALLEL_CLAUSE
diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h
index c90e9a0a76d5..5b4573124f21 100644
--- a/include/clang/Basic/OpenMPKinds.h
+++ b/include/clang/Basic/OpenMPKinds.h
@@ -28,9 +28,37 @@ enum OpenMPDirectiveKind {
NUM_OPENMP_DIRECTIVES
};
+/// \brief OpenMP clauses.
+enum OpenMPClauseKind {
+ OMPC_unknown = 0,
+#define OPENMP_CLAUSE(Name, Class) \
+ OMPC_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_threadprivate,
+ NUM_OPENMP_CLAUSES
+};
+
+/// \brief OpenMP attributes for 'default' clause.
+enum OpenMPDefaultClauseKind {
+ OMPC_DEFAULT_unknown = 0,
+#define OPENMP_DEFAULT_KIND(Name) \
+ OMPC_DEFAULT_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ NUM_OPENMP_DEFAULT_KINDS
+};
+
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
+OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str);
+const char *getOpenMPClauseName(OpenMPClauseKind Kind);
+
+unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str);
+const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);
+
+bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind);
+
}
#endif
diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
index 108014faabe1..2ceab9cbab9d 100644
--- a/include/clang/Basic/OperatorKinds.h
+++ b/include/clang/Basic/OperatorKinds.h
@@ -30,7 +30,7 @@ enum OverloadedOperatorKind {
/// \brief Retrieve the spelling of the given overloaded operator, without
/// the preceding "operator" keyword.
const char *getOperatorSpelling(OverloadedOperatorKind Operator);
-
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index 3f68160f69a6..dd29926fce73 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -368,6 +368,27 @@ public:
}
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const IdentifierInfo *II) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(II),
+ DiagnosticsEngine::ak_identifierinfo);
+ return PD;
+ }
+
+ // Adds a DeclContext to the diagnostic. The enable_if template magic is here
+ // so that we only match those arguments that are (statically) DeclContexts;
+ // other arguments that derive from DeclContext (e.g., RecordDecls) will not
+ // match.
+ template<typename T>
+ friend inline
+ typename llvm::enable_if<llvm::is_same<T, DeclContext>,
+ const PartialDiagnostic &>::type
+ operator<<(const PartialDiagnostic &PD, T *DC) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
+ DiagnosticsEngine::ak_declcontext);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const SourceRange &R) {
PD.AddSourceRange(CharSourceRange::getTokenRange(R));
return PD;
diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def
index 709ec8d0376f..c9b31a39aa55 100644
--- a/include/clang/Basic/Sanitizers.def
+++ b/include/clang/Basic/Sanitizers.def
@@ -54,13 +54,17 @@ SANITIZER("memory", Memory)
// ThreadSanitizer
SANITIZER("thread", Thread)
+// LeakSanitizer
+SANITIZER("leak", Leak)
+
// UndefinedBehaviorSanitizer
SANITIZER("alignment", Alignment)
+SANITIZER("array-bounds", ArrayBounds)
SANITIZER("bool", Bool)
-SANITIZER("bounds", Bounds)
SANITIZER("enum", Enum)
SANITIZER("float-cast-overflow", FloatCastOverflow)
SANITIZER("float-divide-by-zero", FloatDivideByZero)
+SANITIZER("function", Function)
SANITIZER("integer-divide-by-zero", IntegerDivideByZero)
SANITIZER("null", Null)
SANITIZER("object-size", ObjectSize)
@@ -74,20 +78,23 @@ SANITIZER("vptr", Vptr)
// IntegerSanitizer
SANITIZER("unsigned-integer-overflow", UnsignedIntegerOverflow)
+// DataFlowSanitizer
+SANITIZER("dataflow", DataFlow)
+
// -fsanitize=undefined includes all the sanitizers which have low overhead, no
// ABI or address space layout implications, and only catch undefined behavior.
SANITIZER_GROUP("undefined", Undefined,
- Alignment | Bool | Bounds | Enum | FloatCastOverflow |
- FloatDivideByZero | IntegerDivideByZero | Null | ObjectSize |
- Return | Shift | SignedIntegerOverflow | Unreachable |
- VLABound | Vptr)
+ Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
+ FloatDivideByZero | Function | IntegerDivideByZero | Null |
+ ObjectSize | Return | Shift | SignedIntegerOverflow |
+ Unreachable | VLABound | Vptr)
// -fsanitize=undefined-trap (and its alias -fcatch-undefined-behavior) includes
// all sanitizers included by -fsanitize=undefined, except those that require
// runtime support. This group is generally used in conjunction with the
// -fsanitize-undefined-trap-on-error flag.
SANITIZER_GROUP("undefined-trap", UndefinedTrap,
- Alignment | Bool | Bounds | Enum | FloatCastOverflow |
+ Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
FloatDivideByZero | IntegerDivideByZero | Null | ObjectSize |
Return | Shift | SignedIntegerOverflow | Unreachable |
VLABound)
@@ -96,5 +103,9 @@ SANITIZER_GROUP("integer", Integer,
SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
IntegerDivideByZero)
+// -fbounds-checking
+SANITIZER("local-bounds", LocalBounds)
+SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
+
#undef SANITIZER
#undef SANITIZER_GROUP
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 143beb67e0b7..10ae07b82498 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -89,7 +89,7 @@ class SourceLocation {
friend class SourceManager;
friend class ASTReader;
friend class ASTWriter;
- enum {
+ enum LLVM_ENUM_INT_TYPE(unsigned) {
MacroIDBit = 1U << 31
};
public:
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index f82b196929a3..6aab998bd898 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -1005,7 +1005,7 @@ public:
return SourceLocation();
unsigned FileOffset = Entry.getOffset();
- return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID) - 1);
+ return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID));
}
/// \brief Returns the include location if \p FID is a \#include'd file
@@ -1161,6 +1161,22 @@ public:
/// expansion but not the expansion of an argument to a function-like macro.
bool isMacroBodyExpansion(SourceLocation Loc) const;
+ /// \brief Returns true if the given MacroID location points at the beginning
+ /// of the immediate macro expansion.
+ ///
+ /// \param MacroBegin If non-null and function returns true, it is set to the
+ /// begin location of the immediate macro expansion.
+ bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc,
+ SourceLocation *MacroBegin = 0) const;
+
+ /// \brief Returns true if the given MacroID location points at the character
+ /// end of the immediate macro expansion.
+ ///
+ /// \param MacroEnd If non-null and function returns true, it is set to the
+ /// character end location of the immediate macro expansion.
+ bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
+ SourceLocation *MacroEnd = 0) const;
+
/// \brief Returns true if \p Loc is inside the [\p Start, +\p Length)
/// chunk of the source location address space.
///
@@ -1276,14 +1292,28 @@ public:
PresumedLoc getPresumedLoc(SourceLocation Loc,
bool UseLineDirectives = true) const;
- /// \brief Returns true if both SourceLocations correspond to the same file.
- bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
+ /// \brief Returns whether the PresumedLoc for a given SourceLocation is
+ /// in the main file.
+ ///
+ /// This computes the "presumed" location for a SourceLocation, then checks
+ /// whether it came from a file other than the main file. This is different
+ /// from isWrittenInMainFile() because it takes line marker directives into
+ /// account.
+ bool isInMainFile(SourceLocation Loc) const;
+
+ /// \brief Returns true if the spelling locations for both SourceLocations
+ /// are part of the same file buffer.
+ ///
+ /// This check ignores line marker directives.
+ bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
return getFileID(Loc1) == getFileID(Loc2);
}
- /// \brief Returns true if the file of provided SourceLocation is the main
- /// file.
- bool isFromMainFile(SourceLocation Loc) const {
+ /// \brief Returns true if the spelling location for the given location
+ /// is in the main file buffer.
+ ///
+ /// This check ignores line marker directives.
+ bool isWrittenInMainFile(SourceLocation Loc) const {
return getFileID(Loc) == getMainFileID();
}
@@ -1467,7 +1497,7 @@ public:
if (Invalid) *Invalid = true;
return LocalSLocEntryTable[0];
}
- return getSLocEntryByID(FID.ID);
+ return getSLocEntryByID(FID.ID, Invalid);
}
unsigned getNextLocalOffset() const { return NextLocalOffset; }
@@ -1531,11 +1561,11 @@ private:
const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const;
/// \brief Get the entry with the given unwrapped FileID.
- const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const {
+ const SrcMgr::SLocEntry &getSLocEntryByID(int ID, bool *Invalid = 0) const {
assert(ID != -1 && "Using FileID sentinel value");
if (ID < 0)
- return getLoadedSLocEntryByID(ID);
- return getLocalSLocEntry(static_cast<unsigned>(ID));
+ return getLoadedSLocEntryByID(ID, Invalid);
+ return getLocalSLocEntry(static_cast<unsigned>(ID), Invalid);
}
const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID,
@@ -1570,6 +1600,14 @@ private:
return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset();
}
+ /// \brief Returns the previous in-order FileID or an invalid FileID if there
+ /// is no previous one.
+ FileID getPreviousFileID(FileID FID) const;
+
+ /// \brief Returns the next in-order FileID or an invalid FileID if there is
+ /// no next one.
+ FileID getNextFileID(FileID FID) const;
+
/// \brief Create a new fileID for the specified ContentCache and
/// include position.
///
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index eb3fc659a874..0b8093969ae3 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -131,8 +131,8 @@ namespace clang {
OK_ObjCSubscript
};
- // \brief Describes the kind of template specialization that a
- // particular template specialization declaration represents.
+ /// \brief Describes the kind of template specialization that a
+ /// particular template specialization declaration represents.
enum TemplateSpecializationKind {
/// This template specialization was formed from a template-id but
/// has not yet been declared, defined, or instantiated.
@@ -154,6 +154,13 @@ namespace clang {
TSK_ExplicitInstantiationDefinition
};
+ /// \brief Determine whether this template specialization kind refers
+ /// to an instantiation of an entity (as opposed to a non-template or
+ /// an explicit specialization).
+ inline bool isTemplateInstantiation(TemplateSpecializationKind Kind) {
+ return Kind != TSK_Undeclared && Kind != TSK_ExplicitSpecialization;
+ }
+
/// \brief Thread storage-class-specifier.
enum ThreadStorageClassSpecifier {
TSCS_unspecified,
@@ -200,18 +207,40 @@ namespace clang {
/// \brief CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
- CC_Default,
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall, // __attribute__((thiscall))
CC_X86Pascal, // __attribute__((pascal))
+ CC_X86_64Win64, // __attribute__((ms_abi))
+ CC_X86_64SysV, // __attribute__((sysv_abi))
CC_AAPCS, // __attribute__((pcs("aapcs")))
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
CC_PnaclCall, // __attribute__((pnaclcall))
CC_IntelOclBicc // __attribute__((intel_ocl_bicc))
};
+ /// \brief Checks whether the given calling convention is callee-cleanup.
+ inline bool isCalleeCleanup(CallingConv CC) {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86FastCall:
+ case CC_X86ThisCall:
+ case CC_X86Pascal:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /// \brief The storage duration for an object (per C++ [basic.stc]).
+ enum StorageDuration {
+ SD_FullExpression, ///< Full-expression storage duration (for temporaries).
+ SD_Automatic, ///< Automatic storage duration (most local variables).
+ SD_Thread, ///< Thread storage duration.
+ SD_Static, ///< Static storage duration.
+ SD_Dynamic ///< Dynamic storage duration.
+ };
} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index cbfce83c4b57..69851a9d5283 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -110,6 +110,7 @@ def CXXThrowExpr : DStmt<Expr>;
def CXXDefaultArgExpr : DStmt<Expr>;
def CXXDefaultInitExpr : DStmt<Expr>;
def CXXScalarValueInitExpr : DStmt<Expr>;
+def CXXStdInitializerListExpr : DStmt<Expr>;
def CXXNewExpr : DStmt<Expr>;
def CXXDeleteExpr : DStmt<Expr>;
def CXXPseudoDestructorExpr : DStmt<Expr>;
@@ -161,6 +162,7 @@ def CUDAKernelCallExpr : DStmt<CallExpr>;
// Clang Extensions.
def ShuffleVectorExpr : DStmt<Expr>;
+def ConvertVectorExpr : DStmt<Expr>;
def BlockExpr : DStmt<Expr>;
def OpaqueValueExpr : DStmt<Expr>;
@@ -174,3 +176,7 @@ def MSDependentExistsStmt : Stmt;
// OpenCL Extensions.
def AsTypeExpr : DStmt<Expr>;
+
+// OpenMP Directives.
+def OMPExecutableDirective : Stmt<1>;
+def OMPParallelDirective : DStmt<OMPExecutableDirective>;
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index 66e378fa9b45..ed3cc49fedb9 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -90,8 +90,10 @@ namespace clang {
Int64,
Poly8,
Poly16,
+ Poly64,
Float16,
- Float32
+ Float32,
+ Float64
};
NeonTypeFlags(unsigned F) : Flags(F) {}
@@ -130,6 +132,16 @@ namespace clang {
LastTSBuiltin
};
}
+
+ /// \brief XCore builtins
+ namespace XCore {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsXCore.def"
+ LastTSBuiltin
+ };
+ }
} // end namespace clang.
#endif
diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h
index c9d28f8774b6..1590cca62337 100644
--- a/include/clang/Basic/TargetCXXABI.h
+++ b/include/clang/Basic/TargetCXXABI.h
@@ -131,24 +131,36 @@ public:
/// \brief Is the default C++ member function calling convention
/// the same as the default calling convention?
bool isMemberFunctionCCDefault() const {
- // Right now, this is always true for Microsoft.
+ // Right now, this is always false for Microsoft.
return !isMicrosoft();
}
+ /// Are temporary objects passed by value to a call destroyed by the callee?
+ /// This is a fundamental language change, since it implies that objects
+ /// passed by value do *not* live to the end of the full expression.
+ /// Temporaries passed to a function taking a const reference live to the end
+ /// of the full expression as usual. Both the caller and the callee must
+ /// have access to the destructor, while only the caller needs the
+ /// destructor if this is false.
+ bool isArgumentDestroyedByCallee() const {
+ return isMicrosoft();
+ }
+
/// \brief Does this ABI have different entrypoints for complete-object
/// and base-subobject constructors?
bool hasConstructorVariants() const {
return isItaniumFamily();
}
- /// \brief Does this ABI have different entrypoints for complete-object
- /// and base-subobject destructors?
- bool hasDestructorVariants() const {
+ /// \brief Does this ABI allow virtual bases to be primary base classes?
+ bool hasPrimaryVBases() const {
return isItaniumFamily();
}
- /// \brief Does this ABI allow virtual bases to be primary base classes?
- bool hasPrimaryVBases() const {
+ /// \brief Does this ABI use key functions? If so, class data such as the
+ /// vtable is emitted with strong linkage by the TU containing the key
+ /// function.
+ bool hasKeyFunctions() const {
return isItaniumFamily();
}
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 49b26ac8e372..047872dd4017 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -86,7 +86,7 @@ protected:
unsigned ComplexLongDoubleUsesFP2Ret : 1;
// TargetInfo Constructor. Default initializes all fields.
- TargetInfo(const std::string &T);
+ TargetInfo(const llvm::Triple &T);
public:
/// \brief Construct a target for the given options.
@@ -112,6 +112,8 @@ public:
///===---- Target Data Type Query Methods -------------------------------===//
enum IntType {
NoInt = 0,
+ SignedChar,
+ UnsignedChar,
SignedShort,
UnsignedShort,
SignedInt,
@@ -123,6 +125,7 @@ public:
};
enum RealType {
+ NoFloat = 255,
Float = 0,
Double,
LongDouble
@@ -199,6 +202,10 @@ protected:
/// zero length bitfield, regardless of the zero length bitfield type.
unsigned ZeroLengthBitfieldBoundary;
+ /// \brief Specify if mangling based on address space map should be used or
+ /// not for language specific address spaces
+ bool UseAddrSpaceMapMangling;
+
public:
IntType getSizeType() const { return SizeType; }
IntType getIntMaxType() const { return IntMaxType; }
@@ -220,6 +227,12 @@ public:
/// For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
+ /// \brief Return integer type with specified width.
+ IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
+
+ /// \brief Return floating point type with specified width.
+ RealType getRealTypeByWidth(unsigned BitWidth) const;
+
/// \brief Return the alignment (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntAlign().
@@ -345,11 +358,11 @@ public:
unsigned getUnwindWordWidth() const { return getPointerWidth(0); }
/// \brief Return the "preferred" register width on this target.
- uint64_t getRegisterWidth() const {
+ unsigned getRegisterWidth() const {
// Currently we assume the register width on the target matches the pointer
// width, we can introduce a new variable for this if/when some target wants
// it.
- return LongWidth;
+ return PointerWidth;
}
/// \brief Returns the default value of the __USER_LABEL_PREFIX__ macro,
@@ -422,6 +435,12 @@ public:
return ComplexLongDoubleUsesFP2Ret;
}
+ /// \brief Specify if mangling based on address space map should be used or
+ /// not for language specific address spaces
+ bool useAddressSpaceMapMangling() const {
+ return UseAddrSpaceMapMangling;
+ }
+
///===---- Other target property query methods --------------------------===//
/// \brief Appends the target-specific \#define values for this
@@ -653,6 +672,13 @@ public:
return false;
}
+ /// \brief Use the specified unit for FP math.
+ ///
+ /// \return False on error (invalid unit name).
+ virtual bool setFPMath(StringRef Name) {
+ return false;
+ }
+
/// \brief Use this specified C++ ABI.
///
/// \return False on error (invalid C++ ABI name).
@@ -672,12 +698,10 @@ public:
/// \brief Enable or disable a specific target feature;
/// the feature name must be valid.
- ///
- /// \return False on error (invalid feature name).
- virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
+ virtual void setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
bool Enabled) const {
- return false;
+ Features[Name] = Enabled;
}
/// \brief Perform initialization based on the user configured
@@ -687,7 +711,11 @@ public:
///
/// The target may modify the features list, to change which options are
/// passed onwards to the backend.
- virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ ///
+ /// \return False on error.
+ virtual bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ return true;
}
/// \brief Determine whether the given target has the given feature.
@@ -770,7 +798,6 @@ public:
default:
return CCCR_Warning;
case CC_C:
- case CC_Default:
return CCCR_OK;
}
}
@@ -790,7 +817,7 @@ protected:
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const = 0;
virtual void getGCCAddlRegNames(const AddlRegName *&Addl,
- unsigned &NumAddl) const {
+ unsigned &NumAddl) const {
Addl = 0;
NumAddl = 0;
}
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index c2183fd29d56..9909182ab6dd 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -32,6 +32,9 @@ public:
/// If given, the name of the target CPU to generate code for.
std::string CPU;
+ /// If given, the unit to use for floating point math.
+ std::string FPMath;
+
/// If given, the name of the target ABI to use.
std::string ABI;
diff --git a/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h
index dda011a54e18..c5218933a226 100644
--- a/include/clang/Basic/TemplateKinds.h
+++ b/include/clang/Basic/TemplateKinds.h
@@ -27,6 +27,9 @@ enum TemplateNameKind {
/// type. The template itself could be a class template, template
/// template parameter, or C++0x template alias.
TNK_Type_template,
+ /// The name refers to a variable template whose specialization produces a
+ /// variable.
+ TNK_Var_template,
/// The name refers to a dependent template name. Whether the
/// template name is assumed to refer to a type template or a
/// function template depends on the context in which the template
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index bcf0f31dcbf6..6812cce2dbea 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -270,7 +270,7 @@ KEYWORD(__objc_no , KEYALL)
// C++ 2.11p1: Keywords.
KEYWORD(asm , KEYCXX|KEYGNU)
-KEYWORD(bool , BOOLSUPPORT|KEYALTIVEC)
+KEYWORD(bool , BOOLSUPPORT)
KEYWORD(catch , KEYCXX)
KEYWORD(class , KEYCXX)
KEYWORD(const_cast , KEYCXX)
@@ -278,7 +278,7 @@ KEYWORD(delete , KEYCXX)
KEYWORD(dynamic_cast , KEYCXX)
KEYWORD(explicit , KEYCXX)
KEYWORD(export , KEYCXX)
-KEYWORD(false , BOOLSUPPORT|KEYALTIVEC)
+KEYWORD(false , BOOLSUPPORT)
KEYWORD(friend , KEYCXX)
KEYWORD(mutable , KEYCXX)
KEYWORD(namespace , KEYCXX)
@@ -292,7 +292,7 @@ KEYWORD(static_cast , KEYCXX)
KEYWORD(template , KEYCXX)
KEYWORD(this , KEYCXX)
KEYWORD(throw , KEYCXX)
-KEYWORD(true , BOOLSUPPORT|KEYALTIVEC)
+KEYWORD(true , BOOLSUPPORT)
KEYWORD(try , KEYCXX)
KEYWORD(typename , KEYCXX)
KEYWORD(typeid , KEYCXX)
@@ -349,7 +349,10 @@ KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
KEYWORD(typeof , KEYGNU)
// MS Extensions
+KEYWORD(__FUNCDNAME__ , KEYMS)
KEYWORD(L__FUNCTION__ , KEYMS)
+KEYWORD(__is_interface_class , KEYMS)
+KEYWORD(__is_sealed , KEYMS)
// GNU and MS Type Traits
KEYWORD(__has_nothrow_assign , KEYCXX)
@@ -370,7 +373,6 @@ KEYWORD(__is_convertible_to , KEYCXX)
KEYWORD(__is_empty , KEYCXX)
KEYWORD(__is_enum , KEYCXX)
KEYWORD(__is_final , KEYCXX)
-KEYWORD(__is_interface_class , KEYCXX)
// Tentative name - there's no implementation of std::is_literal_type yet.
KEYWORD(__is_literal , KEYCXX)
// Name for GCC 4.6 compatibility - people have already written libraries using
@@ -509,6 +511,8 @@ ALIAS("__volatile__" , volatile , KEYALL)
// Microsoft extensions which should be disabled in strict conformance mode
KEYWORD(__ptr64 , KEYMS)
KEYWORD(__ptr32 , KEYMS)
+KEYWORD(__sptr , KEYMS)
+KEYWORD(__uptr , KEYMS)
KEYWORD(__w64 , KEYMS)
KEYWORD(__uuidof , KEYMS | KEYBORLAND)
KEYWORD(__try , KEYMS | KEYBORLAND)
@@ -524,6 +528,7 @@ KEYWORD(__interface , KEYMS)
ALIAS("__int8" , char , KEYMS)
ALIAS("__int16" , short , KEYMS)
ALIAS("__int32" , int , KEYMS)
+ALIAS("__wchar_t" , wchar_t , KEYMS)
ALIAS("_asm" , asm , KEYMS)
ALIAS("_alignof" , __alignof , KEYMS)
ALIAS("__builtin_alignof", __alignof , KEYMS)
@@ -539,6 +544,7 @@ ALIAS("_declspec" , __declspec , KEYMS)
ALIAS("_pascal" , __pascal , KEYBORLAND)
// Clang Extensions.
+KEYWORD(__builtin_convertvector , KEYALL)
ALIAS("__char16_t" , char16_t , KEYCXX)
ALIAS("__char32_t" , char32_t , KEYCXX)
@@ -661,6 +667,9 @@ ANNOTATION(pragma_opencl_extension)
ANNOTATION(pragma_openmp)
ANNOTATION(pragma_openmp_end)
+// Annotation for module import translated from #include etc.
+ANNOTATION(module_include)
+
#undef ANNOTATION
#undef TESTING_KEYWORD
#undef OBJC2_AT_KEYWORD
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index 16457969862a..fc53527188bb 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -57,6 +57,7 @@ namespace clang {
UTT_IsReference,
UTT_IsRvalueReference,
UTT_IsScalar,
+ UTT_IsSealed,
UTT_IsSigned,
UTT_IsStandardLayout,
UTT_IsTrivial,
diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h
index b623b94a6787..6ac52ed6b5e1 100644
--- a/include/clang/Basic/Visibility.h
+++ b/include/clang/Basic/Visibility.h
@@ -49,7 +49,7 @@ inline Visibility minVisibility(Visibility L, Visibility R) {
}
class LinkageInfo {
- uint8_t linkage_ : 2;
+ uint8_t linkage_ : 3;
uint8_t visibility_ : 2;
uint8_t explicit_ : 1;
@@ -89,6 +89,20 @@ public:
mergeLinkage(other.getLinkage());
}
+ void mergeExternalVisibility(Linkage L) {
+ Linkage ThisL = getLinkage();
+ if (!isExternallyVisible(L)) {
+ if (ThisL == VisibleNoLinkage)
+ ThisL = NoLinkage;
+ else if (ThisL == ExternalLinkage)
+ ThisL = UniqueExternalLinkage;
+ }
+ setLinkage(ThisL);
+ }
+ void mergeExternalVisibility(LinkageInfo Other) {
+ mergeExternalVisibility(Other.getLinkage());
+ }
+
/// Merge in the visibility 'newVis'.
void mergeVisibility(Visibility newVis, bool newExplicit) {
Visibility oldVis = getVisibility();
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index 77bc797c5056..b918459f4e4a 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -18,31 +18,58 @@ def OP_NONE : Op;
def OP_UNAVAILABLE : Op;
def OP_ADD : Op;
def OP_ADDL : Op;
+def OP_ADDLHi : Op;
def OP_ADDW : Op;
+def OP_ADDWHi : Op;
def OP_SUB : Op;
def OP_SUBL : Op;
+def OP_SUBLHi : Op;
def OP_SUBW : Op;
+def OP_SUBWHi : Op;
def OP_MUL : Op;
def OP_MLA : Op;
def OP_MLAL : Op;
+def OP_MULLHi : Op;
+def OP_MULLHi_N : Op;
+def OP_MLALHi : Op;
+def OP_MLALHi_N : Op;
def OP_MLS : Op;
def OP_MLSL : Op;
+def OP_MLSLHi : Op;
+def OP_MLSLHi_N : Op;
def OP_MUL_N : Op;
def OP_MLA_N : Op;
def OP_MLS_N : Op;
+def OP_FMLA_N : Op;
+def OP_FMLS_N : Op;
def OP_MLAL_N : Op;
def OP_MLSL_N : Op;
def OP_MUL_LN: Op;
+def OP_MULX_LN: Op;
def OP_MULL_LN : Op;
+def OP_MULLHi_LN : Op;
def OP_MLA_LN: Op;
def OP_MLS_LN: Op;
def OP_MLAL_LN : Op;
+def OP_MLALHi_LN : Op;
def OP_MLSL_LN : Op;
+def OP_MLSLHi_LN : Op;
def OP_QDMULL_LN : Op;
+def OP_QDMULLHi_LN : Op;
def OP_QDMLAL_LN : Op;
+def OP_QDMLALHi_LN : Op;
def OP_QDMLSL_LN : Op;
+def OP_QDMLSLHi_LN : Op;
def OP_QDMULH_LN : Op;
def OP_QRDMULH_LN : Op;
+def OP_FMS_LN : Op;
+def OP_FMS_LNQ : Op;
+def OP_TRN1 : Op;
+def OP_ZIP1 : Op;
+def OP_UZP1 : Op;
+def OP_TRN2 : Op;
+def OP_ZIP2 : Op;
+def OP_UZP2 : Op;
def OP_EQ : Op;
def OP_GE : Op;
def OP_LE : Op;
@@ -65,10 +92,49 @@ def OP_SEL : Op;
def OP_REV64 : Op;
def OP_REV32 : Op;
def OP_REV16 : Op;
+def OP_XTN : Op;
+def OP_SQXTUN : Op;
+def OP_QXTN : Op;
+def OP_VCVT_NA_HI : Op;
+def OP_VCVT_EX_HI : Op;
+def OP_VCVTX_HI : Op;
def OP_REINT : Op;
+def OP_ADDHNHi : Op;
+def OP_RADDHNHi : Op;
+def OP_SUBHNHi : Op;
+def OP_RSUBHNHi : Op;
def OP_ABDL : Op;
+def OP_ABDLHi : Op;
def OP_ABA : Op;
def OP_ABAL : Op;
+def OP_ABALHi : Op;
+def OP_QDMULLHi : Op;
+def OP_QDMULLHi_N : Op;
+def OP_QDMLALHi : Op;
+def OP_QDMLALHi_N : Op;
+def OP_QDMLSLHi : Op;
+def OP_QDMLSLHi_N : Op;
+def OP_DIV : Op;
+def OP_LONG_HI : Op;
+def OP_NARROW_HI : Op;
+def OP_MOVL_HI : Op;
+def OP_COPY_LN : Op;
+def OP_COPYQ_LN : Op;
+def OP_COPY_LNQ : Op;
+def OP_SCALAR_MUL_LN : Op;
+def OP_SCALAR_MUL_LNQ : Op;
+def OP_SCALAR_MULX_LN : Op;
+def OP_SCALAR_MULX_LNQ : Op;
+def OP_SCALAR_VMULX_LN : Op;
+def OP_SCALAR_VMULX_LNQ : Op;
+def OP_SCALAR_QDMULL_LN : Op;
+def OP_SCALAR_QDMULL_LNQ : Op;
+def OP_SCALAR_QDMULH_LN : Op;
+def OP_SCALAR_QDMULH_LNQ : Op;
+def OP_SCALAR_QRDMULH_LN : Op;
+def OP_SCALAR_QRDMULH_LNQ : Op;
+def OP_SCALAR_GET_LN : Op;
+def OP_SCALAR_SET_LN : Op;
class Inst <string n, string p, string t, Op o> {
string Name = n;
@@ -76,7 +142,11 @@ class Inst <string n, string p, string t, Op o> {
string Types = t;
Op Operand = o;
bit isShift = 0;
+ bit isScalarShift = 0;
+ bit isScalarNarrowShift = 0;
bit isVCVT_N = 0;
+ bit isA64 = 0;
+ bit isCrypto = 0;
// Certain intrinsics have different names than their representative
// instructions. This field allows us to handle this correctly when we
@@ -123,18 +193,29 @@ class NoTestOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {}
// x: signed integer (int/float args)
// u: unsigned integer (int/float args)
// f: float (int args)
+// F: double (int args)
// d: default
// g: default, ignore 'Q' size modifier.
+// j: default, force 'Q' size modifier.
// w: double width elements, same num elts
// n: double width elements, half num elts
// h: half width elements, double num elts
+// q: half width elements, quad num elts
// e: half width elements, double num elts, unsigned
+// m: half width elements, same num elts
// i: constant int
// l: constant uint64
// s: scalar of element type
+// z: scalar of half width element type, signed
+// r: scalar of double width element type, signed
// a: scalar of element type (splat to vector type)
+// b: scalar of unsigned integer/long type (int/float args)
+// $: scalar of signed integer/long type (int/float args)
+// y: scalar of float
+// o: scalar of double
// k: default elt width, double num elts
-// #: array of default vectors
+// 2,3,4: array of default vectors
+// B,C,D: array of default elts, force 'Q' size modifier.
// p: pointer type
// c: const pointer type
@@ -145,10 +226,13 @@ class NoTestOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {}
// l: long
// f: float
// h: half-float
+// d: double
// size modifiers:
+// S: scalar, only used for function mangling.
// U: unsigned
// Q: 128b
+// H: 128b without mangling 'q'
// P: polynomial
////////////////////////////////////////////////////////////////////////////////
@@ -206,7 +290,7 @@ let InstName = "vacgt" in {
def VCAGT : IInst<"vcagt", "udd", "fQf">;
def VCALT : IInst<"vcalt", "udd", "fQf">;
}
-def VTST : WInst<"vtst", "udd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc">;
+def VTST : WInst<"vtst", "udd", "csiUcUsUiPcPsQcQsQiQUcQUsQUiQPcQPs">;
////////////////////////////////////////////////////////////////////////////////
// E.3.5 Absolute Difference
@@ -452,3 +536,803 @@ def VREINTERPRET
// Vector fused multiply-add operations
def VFMA : SInst<"vfma", "dddd", "fQf">;
+
+////////////////////////////////////////////////////////////////////////////////
+// AArch64 Intrinsics
+
+let isA64 = 1 in {
+
+////////////////////////////////////////////////////////////////////////////////
+// Load/Store
+// With additional QUl, Ql, d, Qd, Pl, QPl type.
+def LD1 : WInst<"vld1", "dc",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+def LD2 : WInst<"vld2", "2c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+def LD3 : WInst<"vld3", "3c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+def LD4 : WInst<"vld4", "4c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+def ST1 : WInst<"vst1", "vpd",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+def ST2 : WInst<"vst2", "vp2",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+def ST3 : WInst<"vst3", "vp3",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+def ST4 : WInst<"vst4", "vp4",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+
+def LD1_X2 : WInst<"vld1_x2", "2c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD3_x3 : WInst<"vld1_x3", "3c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD4_x4 : WInst<"vld1_x4", "4c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+
+def ST1_X2 : WInst<"vst1_x2", "vp2",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def ST1_X3 : WInst<"vst1_x3", "vp3",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def ST1_X4 : WInst<"vst1_x4", "vp4",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+
+// With additional QUl, Ql, d, Qd, Pl, QPl type.
+def LD1_LANE : WInst<"vld1_lane", "dcdi",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD2_LANE : WInst<"vld2_lane", "2c2i",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD3_LANE : WInst<"vld3_lane", "3c3i",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD4_LANE : WInst<"vld4_lane", "4c4i",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def ST1_LANE : WInst<"vst1_lane", "vpdi",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def ST2_LANE : WInst<"vst2_lane", "vp2i",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def ST3_LANE : WInst<"vst3_lane", "vp3i",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def ST4_LANE : WInst<"vst4_lane", "vp4i",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+
+def LD1_DUP : WInst<"vld1_dup", "dc",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD2_DUP : WInst<"vld2_dup", "2c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD3_DUP : WInst<"vld3_dup", "3c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+def LD4_DUP : WInst<"vld4_dup", "4c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Addition
+// With additional d, Qd type.
+def ADD : IOpInst<"vadd", "ddd", "csilfdUcUsUiUlQcQsQiQlQfQUcQUsQUiQUlQd",
+ OP_ADD>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Subtraction
+// With additional Qd type.
+def SUB : IOpInst<"vsub", "ddd", "csildfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUlQd",
+ OP_SUB>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Multiplication
+// With additional Qd type.
+def MUL : IOpInst<"vmul", "ddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MUL>;
+def MLA : IOpInst<"vmla", "dddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MLA>;
+def MLS : IOpInst<"vmls", "dddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MLS>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Multiplication Extended
+def MULX : SInst<"vmulx", "ddd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Division
+def FDIV : IOpInst<"vdiv", "ddd", "fdQfQd", OP_DIV>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Vector fused multiply-add operations
+// With additional d, Qd type.
+def FMLA : SInst<"vfma", "dddd", "fdQfQd">;
+def FMLS : SInst<"vfms", "dddd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// MUL, FMA, FMS definitions with scalar argument
+def VMUL_N_A64 : IOpInst<"vmul_n", "dds", "Qd", OP_MUL_N>;
+def FMLA_N : SOpInst<"vfma_n", "ddds", "fQf", OP_FMLA_N>;
+def FMLS_N : SOpInst<"vfms_n", "ddds", "fQf", OP_FMLS_N>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Logical operations
+// With additional Qd, Ql, QPl type.
+def BSL : SInst<"vbsl", "dudd",
+ "csilUcUsUiUlfdPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPsQdPlQPl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Absolute Difference
+// With additional Qd type.
+def ABD : SInst<"vabd", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// saturating absolute/negate
+// With additional Qd/Ql type.
+def ABS : SInst<"vabs", "dd", "csilfdQcQsQiQfQlQd">;
+def QABS : SInst<"vqabs", "dd", "csilQcQsQiQl">;
+def NEG : SOpInst<"vneg", "dd", "csilfdQcQsQiQfQdQl", OP_NEG>;
+def QNEG : SInst<"vqneg", "dd", "csilQcQsQiQl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Accumulated of Unsigned Value
+def SUQADD : SInst<"vuqadd", "ddd", "csilQcQsQiQl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Unsigned Saturating Accumulated of Signed Value
+def USQADD : SInst<"vsqadd", "ddd", "UcUsUiUlQUcQUsQUiQUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Reciprocal/Sqrt
+// With additional d, Qd type.
+def FRECPS : IInst<"vrecps", "ddd", "fdQfQd">;
+def FRSQRTS : IInst<"vrsqrts", "ddd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// bitwise reverse
+def RBIT : IInst<"vrbit", "dd", "cUcPcQcQUcQPc">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Integer extract and narrow to high
+def XTN2 : SOpInst<"vmovn_high", "qhk", "silUsUiUl", OP_XTN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed integer saturating extract and unsigned narrow to high
+def SQXTUN2 : SOpInst<"vqmovun_high", "qhk", "sil", OP_SQXTUN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Integer saturating extract and narrow to high
+def QXTN2 : SOpInst<"vqmovn_high", "qhk", "silUsUiUl", OP_QXTN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Converting vectors
+def VCVT_HIGH_F16 : SOpInst<"vcvt_high_f16", "qhj", "f", OP_VCVT_NA_HI>;
+def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI>;
+def VCVT_F32_F64 : SInst<"vcvt_f32_f64", "fj", "d">;
+def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI>;
+def VCVT_F64_F32 : SInst<"vcvt_f64_f32", "wd", "f">;
+def VCVT_F64 : SInst<"vcvt_f64", "Fd", "lUlQlQUl">;
+def VCVT_HIGH_F64_F32 : SOpInst<"vcvt_high_f64", "wj", "f", OP_VCVT_EX_HI>;
+def VCVTX_F32_F64 : SInst<"vcvtx_f32", "fj", "d">;
+def VCVTX_HIGH_F32_F64 : SOpInst<"vcvtx_high_f32", "qfj", "d", OP_VCVTX_HI>;
+def FRINTN : SInst<"vrndn", "dd", "fdQfQd">;
+def FRINTA : SInst<"vrnda", "dd", "fdQfQd">;
+def FRINTP : SInst<"vrndp", "dd", "fdQfQd">;
+def FRINTM : SInst<"vrndm", "dd", "fdQfQd">;
+def FRINTX : SInst<"vrndx", "dd", "fdQfQd">;
+def FRINTZ : SInst<"vrnd", "dd", "fdQfQd">;
+def FRINTI : SInst<"vrndi", "dd", "fdQfQd">;
+def VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">;
+def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">;
+def FCVTNS_S32 : SInst<"vcvtn_s32", "xd", "fQf">;
+def FCVTNS_S64 : SInst<"vcvtn_s64", "xd", "dQd">;
+def FCVTNU_S32 : SInst<"vcvtn_u32", "ud", "fQf">;
+def FCVTNU_S64 : SInst<"vcvtn_u64", "ud", "dQd">;
+def FCVTPS_S32 : SInst<"vcvtp_s32", "xd", "fQf">;
+def FCVTPS_S64 : SInst<"vcvtp_s64", "xd", "dQd">;
+def FCVTPU_S32 : SInst<"vcvtp_u32", "ud", "fQf">;
+def FCVTPU_S64 : SInst<"vcvtp_u64", "ud", "dQd">;
+def FCVTMS_S32 : SInst<"vcvtm_s32", "xd", "fQf">;
+def FCVTMS_S64 : SInst<"vcvtm_s64", "xd", "dQd">;
+def FCVTMU_S32 : SInst<"vcvtm_u32", "ud", "fQf">;
+def FCVTMU_S64 : SInst<"vcvtm_u64", "ud", "dQd">;
+def FCVTAS_S32 : SInst<"vcvta_s32", "xd", "fQf">;
+def FCVTAS_S64 : SInst<"vcvta_s64", "xd", "dQd">;
+def FCVTAU_S32 : SInst<"vcvta_u32", "ud", "fQf">;
+def FCVTAU_S64 : SInst<"vcvta_u64", "ud", "dQd">;
+def FRECPE : SInst<"vrecpe", "dd", "fdUiQfQUiQd">;
+def FRSQRTE : SInst<"vrsqrte", "dd", "fdUiQfQUiQd">;
+def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Comparison
+// With additional Qd, Ql, QPl type.
+def FCAGE : IInst<"vcage", "udd", "fdQfQd">;
+def FCAGT : IInst<"vcagt", "udd", "fdQfQd">;
+def FCALE : IInst<"vcale", "udd", "fdQfQd">;
+def FCALT : IInst<"vcalt", "udd", "fdQfQd">;
+// With additional Ql, QUl, Qd types.
+def CMTST : WInst<"vtst", "udd",
+ "csiUcUsUiPcPsQcQsQiQUcQUsQUiQPcQPslUlQlQUlPlQPl">;
+// With additional l, Ul,d, Qd, Ql, QUl, Qd types.
+def CFMEQ : SOpInst<"vceq", "udd",
+ "csilfUcUsUiUlPcQcdQdQsQiQfQUcQUsQUiQUlQlQPcPlQPl", OP_EQ>;
+def CFMGE : SOpInst<"vcge", "udd",
+ "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_GE>;
+def CFMLE : SOpInst<"vcle", "udd",
+ "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_LE>;
+def CFMGT : SOpInst<"vcgt", "udd",
+ "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_GT>;
+def CFMLT : SOpInst<"vclt", "udd",
+ "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_LT>;
+
+def CMEQ : SInst<"vceqz", "ud",
+ "csilfUcUsUiUlPcPsPlQcQsQiQlQfQUcQUsQUiQUlQPcQPsdQdQPl">;
+def CMGE : SInst<"vcgez", "ud", "csilfdQcQsQiQlQfQd">;
+def CMLE : SInst<"vclez", "ud", "csilfdQcQsQiQlQfQd">;
+def CMGT : SInst<"vcgtz", "ud", "csilfdQcQsQiQlQfQd">;
+def CMLT : SInst<"vcltz", "ud", "csilfdQcQsQiQlQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Max/Min Integer
+// With additional Qd type.
+def MAX : SInst<"vmax", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">;
+def MIN : SInst<"vmin", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// MaxNum/MinNum Floating Point
+def FMAXNM : SInst<"vmaxnm", "ddd", "fdQfQd">;
+def FMINNM : SInst<"vminnm", "ddd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Pairwise Max/Min
+// With additional Qc Qs Qi QUc QUs QUi Qf Qd types.
+def MAXP : SInst<"vpmax", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQfQd">;
+def MINP : SInst<"vpmin", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Pairwise MaxNum/MinNum Floating Point
+def FMAXNMP : SInst<"vpmaxnm", "ddd", "fQfQd">;
+def FMINNMP : SInst<"vpminnm", "ddd", "fQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Pairwise Addition
+// With additional Qc Qs Qi QUc QUs QUi Qf Qd types.
+def ADDP : IInst<"vpadd", "ddd", "csiUcUsUifQcQsQiQlQUcQUsQUiQUlQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Shifts by constant
+let isShift = 1 in {
+// Left shift long high
+def SHLL_HIGH_N : SOpInst<"vshll_high_n", "ndi", "HcHsHiHUcHUsHUi",
+ OP_LONG_HI>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Shifts with insert, with additional Ql, QPl type.
+def SRI_N : WInst<"vsri_n", "dddi",
+ "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPsPlQPl">;
+def SLI_N : WInst<"vsli_n", "dddi",
+ "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPsPlQPl">;
+
+// Right shift narrow high
+def SHRN_HIGH_N : IOpInst<"vshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+def QSHRUN_HIGH_N : SOpInst<"vqshrun_high_n", "hmdi",
+ "HsHiHl", OP_NARROW_HI>;
+def RSHRN_HIGH_N : IOpInst<"vrshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+def QRSHRUN_HIGH_N : SOpInst<"vqrshrun_high_n", "hmdi",
+ "HsHiHl", OP_NARROW_HI>;
+def QSHRN_HIGH_N : SOpInst<"vqshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+def QRSHRN_HIGH_N : SOpInst<"vqrshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Converting vectors
+def VMOVL_HIGH : SOpInst<"vmovl_high", "nd", "HcHsHiHUcHUsHUi", OP_MOVL_HI>;
+
+let isVCVT_N = 1 in {
+def CVTF_N_F64 : SInst<"vcvt_n_f64", "Fdi", "lUlQlQUl">;
+def FCVTZS_N_S64 : SInst<"vcvt_n_s64", "xdi", "dQd">;
+def FCVTZS_N_U64 : SInst<"vcvt_n_u64", "udi", "dQd">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 3VDiff class using high 64-bit in operands
+def VADDL_HIGH : SOpInst<"vaddl_high", "wkk", "csiUcUsUi", OP_ADDLHi>;
+def VADDW_HIGH : SOpInst<"vaddw_high", "wwk", "csiUcUsUi", OP_ADDWHi>;
+def VSUBL_HIGH : SOpInst<"vsubl_high", "wkk", "csiUcUsUi", OP_SUBLHi>;
+def VSUBW_HIGH : SOpInst<"vsubw_high", "wwk", "csiUcUsUi", OP_SUBWHi>;
+
+def VABDL_HIGH : SOpInst<"vabdl_high", "wkk", "csiUcUsUi", OP_ABDLHi>;
+def VABAL_HIGH : SOpInst<"vabal_high", "wwkk", "csiUcUsUi", OP_ABALHi>;
+
+def VMULL_HIGH : SOpInst<"vmull_high", "wkk", "csiUcUsUiPc", OP_MULLHi>;
+def VMULL_HIGH_N : SOpInst<"vmull_high_n", "wks", "siUsUi", OP_MULLHi_N>;
+def VMLAL_HIGH : SOpInst<"vmlal_high", "wwkk", "csiUcUsUi", OP_MLALHi>;
+def VMLAL_HIGH_N : SOpInst<"vmlal_high_n", "wwks", "siUsUi", OP_MLALHi_N>;
+def VMLSL_HIGH : SOpInst<"vmlsl_high", "wwkk", "csiUcUsUi", OP_MLSLHi>;
+def VMLSL_HIGH_N : SOpInst<"vmlsl_high_n", "wwks", "siUsUi", OP_MLSLHi_N>;
+
+def VADDHN_HIGH : SOpInst<"vaddhn_high", "qhkk", "silUsUiUl", OP_ADDHNHi>;
+def VRADDHN_HIGH : SOpInst<"vraddhn_high", "qhkk", "silUsUiUl", OP_RADDHNHi>;
+def VSUBHN_HIGH : SOpInst<"vsubhn_high", "qhkk", "silUsUiUl", OP_SUBHNHi>;
+def VRSUBHN_HIGH : SOpInst<"vrsubhn_high", "qhkk", "silUsUiUl", OP_RSUBHNHi>;
+
+def VQDMULL_HIGH : SOpInst<"vqdmull_high", "wkk", "si", OP_QDMULLHi>;
+def VQDMULL_HIGH_N : SOpInst<"vqdmull_high_n", "wks", "si", OP_QDMULLHi_N>;
+def VQDMLAL_HIGH : SOpInst<"vqdmlal_high", "wwkk", "si", OP_QDMLALHi>;
+def VQDMLAL_HIGH_N : SOpInst<"vqdmlal_high_n", "wwks", "si", OP_QDMLALHi_N>;
+def VQDMLSL_HIGH : SOpInst<"vqdmlsl_high", "wwkk", "si", OP_QDMLSLHi>;
+def VQDMLSL_HIGH_N : SOpInst<"vqdmlsl_high_n", "wwks", "si", OP_QDMLSLHi_N>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Extract or insert element from vector
+def GET_LANE : IInst<"vget_lane", "sdi",
+ "csilPcPsUcUsUiUlQcQsQiQlQUcQUsQUiQUlPcPsQPcQPsfdQfQdPlQPl">;
+def SET_LANE : IInst<"vset_lane", "dsdi",
+ "csilPcPsUcUsUiUlQcQsQiQlQUcQUsQUiQUlPcPsQPcQPsfdQfQdPlQPl">;
+def COPY_LANE : IOpInst<"vcopy_lane", "ddidi",
+ "csilPcPsUcUsUiUlPcPsPlfd", OP_COPY_LN>;
+def COPYQ_LANE : IOpInst<"vcopy_lane", "ddigi",
+ "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPYQ_LN>;
+def COPY_LANEQ : IOpInst<"vcopy_laneq", "ddiki",
+ "csilPcPsPlUcUsUiUlfd", OP_COPY_LNQ>;
+def COPYQ_LANEQ : IOpInst<"vcopy_laneq", "ddidi",
+ "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPY_LN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Set all lanes to same value
+def VDUP_LANE1: WOpInst<"vdup_lane", "dgi",
+ "csilPcPsUcUsUiUlhfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl",
+ OP_DUP_LN>;
+def VDUP_LANE2: WOpInst<"vdup_laneq", "dki",
+ "csilPcPsUcUsUiUlhfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl",
+ OP_DUP_LN>;
+def DUP_N : WOpInst<"vdup_n", "ds",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUldQdPlQPl",
+ OP_DUP>;
+def MOV_N : WOpInst<"vmov_n", "ds",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUldQd",
+ OP_DUP>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Combining vectors, with additional Pl
+def COMBINE : NoTestOpInst<"vcombine", "kdd", "csilhfdUcUsUiUlPcPsPl", OP_CONC>;
+
+////////////////////////////////////////////////////////////////////////////////
+//Initialize a vector from bit pattern, with additional Pl
+def CREATE : NoTestOpInst<"vcreate", "dl", "csihfdUcUsUiUlPcPslPl", OP_CAST>;
+
+////////////////////////////////////////////////////////////////////////////////
+
+def VMLA_LANEQ : IOpInst<"vmla_laneq", "dddji",
+ "siUsUifQsQiQUsQUiQf", OP_MLA_LN>;
+def VMLS_LANEQ : IOpInst<"vmls_laneq", "dddji",
+ "siUsUifQsQiQUsQUiQf", OP_MLS_LN>;
+
+def VFMA_LANE : IInst<"vfma_lane", "dddgi", "fdQfQd">;
+def VFMA_LANEQ : IInst<"vfma_laneq", "dddji", "fdQfQd">;
+def VFMS_LANE : IOpInst<"vfms_lane", "dddgi", "fdQfQd", OP_FMS_LN>;
+def VFMS_LANEQ : IOpInst<"vfms_laneq", "dddji", "fdQfQd", OP_FMS_LNQ>;
+
+def VMLAL_LANEQ : SOpInst<"vmlal_laneq", "wwdki", "siUsUi", OP_MLAL_LN>;
+def VMLAL_HIGH_LANE : SOpInst<"vmlal_high_lane", "wwkdi", "siUsUi",
+ OP_MLALHi_LN>;
+def VMLAL_HIGH_LANEQ : SOpInst<"vmlal_high_laneq", "wwkki", "siUsUi",
+ OP_MLALHi_LN>;
+def VMLSL_LANEQ : SOpInst<"vmlsl_laneq", "wwdki", "siUsUi", OP_MLSL_LN>;
+def VMLSL_HIGH_LANE : SOpInst<"vmlsl_high_lane", "wwkdi", "siUsUi",
+ OP_MLSLHi_LN>;
+def VMLSL_HIGH_LANEQ : SOpInst<"vmlsl_high_laneq", "wwkki", "siUsUi",
+ OP_MLSLHi_LN>;
+
+def VQDMLAL_LANEQ : SOpInst<"vqdmlal_laneq", "wwdki", "si", OP_QDMLAL_LN>;
+def VQDMLAL_HIGH_LANE : SOpInst<"vqdmlal_high_lane", "wwkdi", "si",
+ OP_QDMLALHi_LN>;
+def VQDMLAL_HIGH_LANEQ : SOpInst<"vqdmlal_high_laneq", "wwkki", "si",
+ OP_QDMLALHi_LN>;
+def VQDMLSL_LANEQ : SOpInst<"vqdmlsl_laneq", "wwdki", "si", OP_QDMLSL_LN>;
+def VQDMLSL_HIGH_LANE : SOpInst<"vqdmlsl_high_lane", "wwkdi", "si",
+ OP_QDMLSLHi_LN>;
+def VQDMLSL_HIGH_LANEQ : SOpInst<"vqdmlsl_high_laneq", "wwkki", "si",
+ OP_QDMLSLHi_LN>;
+
+// Newly add double parameter for vmul_lane in aarch64
+// Note: d type is handled by SCALAR_VMUL_LANE
+def VMUL_LANE_A64 : IOpInst<"vmul_lane", "ddgi", "Qd", OP_MUL_LN>;
+
+// Note: d type is handled by SCALAR_VMUL_LANEQ
+def VMUL_LANEQ : IOpInst<"vmul_laneq", "ddji",
+ "sifUsUiQsQiQfQUsQUiQfQd", OP_MUL_LN>;
+def VMULL_LANEQ : SOpInst<"vmull_laneq", "wdki", "siUsUi", OP_MULL_LN>;
+def VMULL_HIGH_LANE : SOpInst<"vmull_high_lane", "wkdi", "siUsUi",
+ OP_MULLHi_LN>;
+def VMULL_HIGH_LANEQ : SOpInst<"vmull_high_laneq", "wkki", "siUsUi",
+ OP_MULLHi_LN>;
+
+def VQDMULL_LANEQ : SOpInst<"vqdmull_laneq", "wdki", "si", OP_QDMULL_LN>;
+def VQDMULL_HIGH_LANE : SOpInst<"vqdmull_high_lane", "wkdi", "si",
+ OP_QDMULLHi_LN>;
+def VQDMULL_HIGH_LANEQ : SOpInst<"vqdmull_high_laneq", "wkki", "si",
+ OP_QDMULLHi_LN>;
+
+def VQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ddji", "siQsQi", OP_QDMULH_LN>;
+def VQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ddji", "siQsQi", OP_QRDMULH_LN>;
+
+// Note: d type implemented by SCALAR_VMULX_LANE
+def VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "fQfQd", OP_MULX_LN>;
+// Note: d type is implemented by SCALAR_VMULX_LANEQ
+def VMULX_LANEQ : IOpInst<"vmulx_laneq", "ddji", "fQfQd", OP_MULX_LN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Across vectors class
+def VADDLV : SInst<"vaddlv", "rd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VMAXV : SInst<"vmaxv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQd">;
+def VMINV : SInst<"vminv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQd">;
+def VADDV : SInst<"vaddv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQdQlQUl">;
+def FMAXNMV : SInst<"vmaxnmv", "sd", "fQfQd">;
+def FMINNMV : SInst<"vminnmv", "sd", "fQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Newly added Vector Extract for f64
+def VEXT_A64 : WInst<"vext", "dddi",
+ "cUcPcsUsPsiUilUlfdQcQUcQPcQsQUsQPsQiQUiQlQUlQfQdPlQPl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Crypto
+let isCrypto = 1 in {
+def AESE : SInst<"vaese", "ddd", "QUc">;
+def AESD : SInst<"vaesd", "ddd", "QUc">;
+def AESMC : SInst<"vaesmc", "dd", "QUc">;
+def AESIMC : SInst<"vaesimc", "dd", "QUc">;
+
+def SHA1H : SInst<"vsha1h", "ss", "Ui">;
+def SHA1SU1 : SInst<"vsha1su1", "ddd", "QUi">;
+def SHA256SU0 : SInst<"vsha256su0", "ddd", "QUi">;
+
+def SHA1C : SInst<"vsha1c", "ddsd", "QUi">;
+def SHA1P : SInst<"vsha1p", "ddsd", "QUi">;
+def SHA1M : SInst<"vsha1m", "ddsd", "QUi">;
+def SHA1SU0 : SInst<"vsha1su0", "dddd", "QUi">;
+def SHA256H : SInst<"vsha256h", "dddd", "QUi">;
+def SHA256H2 : SInst<"vsha256h2", "dddd", "QUi">;
+def SHA256SU1 : SInst<"vsha256su1", "dddd", "QUi">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Permutation
+def VTRN1 : SOpInst<"vtrn1", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_TRN1>;
+def VZIP1 : SOpInst<"vzip1", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_ZIP1>;
+def VUZP1 : SOpInst<"vuzp1", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_UZP1>;
+def VTRN2 : SOpInst<"vtrn2", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_TRN2>;
+def VZIP2 : SOpInst<"vzip2", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_ZIP2>;
+def VUZP2 : SOpInst<"vuzp2", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_UZP2>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Table lookup
+let InstName = "vtbl" in {
+def VQTBL1_A64 : WInst<"vqtbl1", "djt", "UccPcQUcQcQPc">;
+def VQTBL2_A64 : WInst<"vqtbl2", "dBt", "UccPcQUcQcQPc">;
+def VQTBL3_A64 : WInst<"vqtbl3", "dCt", "UccPcQUcQcQPc">;
+def VQTBL4_A64 : WInst<"vqtbl4", "dDt", "UccPcQUcQcQPc">;
+}
+let InstName = "vtbx" in {
+def VQTBX1_A64 : WInst<"vqtbx1", "ddjt", "UccPcQUcQcQPc">;
+def VQTBX2_A64 : WInst<"vqtbx2", "ddBt", "UccPcQUcQcQPc">;
+def VQTBX3_A64 : WInst<"vqtbx3", "ddCt", "UccPcQUcQcQPc">;
+def VQTBX4_A64 : WInst<"vqtbx4", "ddDt", "UccPcQUcQcQPc">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Vector reinterpret cast operations
+// With additional d, Qd, pl, Qpl types
+def REINTERPRET
+ : NoTestOpInst<"vreinterpret", "dd",
+ "csilUcUsUiUlhfdPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQdQPcQPsQPl", OP_REINT>;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Intrinsics
+// Scalar Arithmetic
+
+// Scalar Addition
+def SCALAR_ADD : SInst<"vadd", "sss", "SlSUl">;
+// Scalar Saturating Add
+def SCALAR_QADD : SInst<"vqadd", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+
+// Scalar Subtraction
+def SCALAR_SUB : SInst<"vsub", "sss", "SlSUl">;
+// Scalar Saturating Sub
+def SCALAR_QSUB : SInst<"vqsub", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+
+let InstName = "vmov" in {
+def VGET_HIGH_A64 : NoTestOpInst<"vget_high", "dk", "csilhfdUcUsUiUlPcPsPl",
+ OP_HI>;
+def VGET_LOW_A64 : NoTestOpInst<"vget_low", "dk", "csilhfdUcUsUiUlPcPsPl",
+ OP_LO>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Shift
+// Scalar Shift Left
+def SCALAR_SHL: SInst<"vshl", "sss", "SlSUl">;
+// Scalar Saturating Shift Left
+def SCALAR_QSHL: SInst<"vqshl", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+// Scalar Saturating Rounding Shift Left
+def SCALAR_QRSHL: SInst<"vqrshl", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+// Scalar Shift Rouding Left
+def SCALAR_RSHL: SInst<"vrshl", "sss", "SlSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Shift (Immediate)
+let isScalarShift = 1 in {
+// Signed/Unsigned Shift Right (Immediate)
+def SCALAR_SSHR_N: SInst<"vshr_n", "ssi", "SlSUl">;
+// Signed/Unsigned Rounding Shift Right (Immediate)
+def SCALAR_SRSHR_N: SInst<"vrshr_n", "ssi", "SlSUl">;
+
+// Signed/Unsigned Shift Right and Accumulate (Immediate)
+def SCALAR_SSRA_N: SInst<"vsra_n", "sssi", "SlSUl">;
+// Signed/Unsigned Rounding Shift Right and Accumulate (Immediate)
+def SCALAR_SRSRA_N: SInst<"vrsra_n", "sssi", "SlSUl">;
+
+// Shift Left (Immediate)
+def SCALAR_SHL_N: SInst<"vshl_n", "ssi", "SlSUl">;
+// Signed/Unsigned Saturating Shift Left (Immediate)
+def SCALAR_SQSHL_N: SInst<"vqshl_n", "ssi", "ScSsSiSlSUcSUsSUiSUl">;
+// Signed Saturating Shift Left Unsigned (Immediate)
+def SCALAR_SQSHLU_N: SInst<"vqshlu_n", "ssi", "ScSsSiSl">;
+
+// Shift Right And Insert (Immediate)
+def SCALAR_SRI_N: SInst<"vsri_n", "sssi", "SlSUl">;
+// Shift Left And Insert (Immediate)
+def SCALAR_SLI_N: SInst<"vsli_n", "sssi", "SlSUl">;
+
+let isScalarNarrowShift = 1 in {
+ // Signed/Unsigned Saturating Shift Right Narrow (Immediate)
+ def SCALAR_SQSHRN_N: SInst<"vqshrn_n", "zsi", "SsSiSlSUsSUiSUl">;
+ // Signed/Unsigned Saturating Rounded Shift Right Narrow (Immediate)
+ def SCALAR_SQRSHRN_N: SInst<"vqrshrn_n", "zsi", "SsSiSlSUsSUiSUl">;
+ // Signed Saturating Shift Right Unsigned Narrow (Immediate)
+ def SCALAR_SQSHRUN_N: SInst<"vqshrun_n", "zsi", "SsSiSl">;
+ // Signed Saturating Rounded Shift Right Unsigned Narrow (Immediate)
+ def SCALAR_SQRSHRUN_N: SInst<"vqrshrun_n", "zsi", "SsSiSl">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed/Unsigned Fixed-point Convert To Floating-Point (Immediate)
+def SCALAR_SCVTF_N_F32: SInst<"vcvt_n_f32", "ysi", "SiSUi">;
+def SCALAR_SCVTF_N_F64: SInst<"vcvt_n_f64", "osi", "SlSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Convert To Signed/Unsigned Fixed-point (Immediate)
+def SCALAR_FCVTZS_N_S32 : SInst<"vcvt_n_s32", "$si", "Sf">;
+def SCALAR_FCVTZU_N_U32 : SInst<"vcvt_n_u32", "bsi", "Sf">;
+def SCALAR_FCVTZS_N_S64 : SInst<"vcvt_n_s64", "$si", "Sd">;
+def SCALAR_FCVTZU_N_U64 : SInst<"vcvt_n_u64", "bsi", "Sd">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Reduce Pairwise Addition (Scalar and Floating Point)
+def SCALAR_ADDP : SInst<"vpadd", "sd", "SfSHlSHdSHUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Reduce Floating Point Pairwise Max/Min
+def SCALAR_FMAXP : SInst<"vpmax", "sd", "SfSQd">;
+
+def SCALAR_FMINP : SInst<"vpmin", "sd", "SfSQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Reduce Floating Point Pairwise maxNum/minNum
+def SCALAR_FMAXNMP : SInst<"vpmaxnm", "sd", "SfSQd">;
+def SCALAR_FMINNMP : SInst<"vpminnm", "sd", "SfSQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Integer Saturating Doubling Multiply Half High
+def SCALAR_SQDMULH : SInst<"vqdmulh", "sss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Integer Saturating Rounding Doubling Multiply Half High
+def SCALAR_SQRDMULH : SInst<"vqrdmulh", "sss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Multiply Extended
+def SCALAR_FMULX : IInst<"vmulx", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Step
+def SCALAR_FRECPS : IInst<"vrecps", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Square Root Step
+def SCALAR_FRSQRTS : IInst<"vrsqrts", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Integer Convert To Floating-point
+def SCALAR_SCVTFS : SInst<"vcvt_f32", "ys", "Si">;
+def SCALAR_SCVTFD : SInst<"vcvt_f64", "os", "Sl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Unsigned Integer Convert To Floating-point
+def SCALAR_UCVTFS : SInst<"vcvt_f32", "ys", "SUi">;
+def SCALAR_UCVTFD : SInst<"vcvt_f64", "os", "SUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Converts
+def SCALAR_FCVTXN : IInst<"vcvtx_f32", "ys", "Sd">;
+def SCALAR_FCVTNSS : SInst<"vcvtn_s32", "$s", "Sf">;
+def SCALAR_FCVTNUS : SInst<"vcvtn_u32", "bs", "Sf">;
+def SCALAR_FCVTNSD : SInst<"vcvtn_s64", "$s", "Sd">;
+def SCALAR_FCVTNUD : SInst<"vcvtn_u64", "bs", "Sd">;
+def SCALAR_FCVTMSS : SInst<"vcvtm_s32", "$s", "Sf">;
+def SCALAR_FCVTMUS : SInst<"vcvtm_u32", "bs", "Sf">;
+def SCALAR_FCVTMSD : SInst<"vcvtm_s64", "$s", "Sd">;
+def SCALAR_FCVTMUD : SInst<"vcvtm_u64", "bs", "Sd">;
+def SCALAR_FCVTASS : SInst<"vcvta_s32", "$s", "Sf">;
+def SCALAR_FCVTAUS : SInst<"vcvta_u32", "bs", "Sf">;
+def SCALAR_FCVTASD : SInst<"vcvta_s64", "$s", "Sd">;
+def SCALAR_FCVTAUD : SInst<"vcvta_u64", "bs", "Sd">;
+def SCALAR_FCVTPSS : SInst<"vcvtp_s32", "$s", "Sf">;
+def SCALAR_FCVTPUS : SInst<"vcvtp_u32", "bs", "Sf">;
+def SCALAR_FCVTPSD : SInst<"vcvtp_s64", "$s", "Sd">;
+def SCALAR_FCVTPUD : SInst<"vcvtp_u64", "bs", "Sd">;
+def SCALAR_FCVTZSS : SInst<"vcvt_s32", "$s", "Sf">;
+def SCALAR_FCVTZUS : SInst<"vcvt_u32", "bs", "Sf">;
+def SCALAR_FCVTZSD : SInst<"vcvt_s64", "$s", "Sd">;
+def SCALAR_FCVTZUD : SInst<"vcvt_u64", "bs", "Sd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Estimate
+def SCALAR_FRECPE : IInst<"vrecpe", "ss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Exponent
+def SCALAR_FRECPX : IInst<"vrecpx", "ss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Square Root Estimate
+def SCALAR_FRSQRTE : IInst<"vrsqrte", "ss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Integer Comparison
+def SCALAR_CMEQ : SInst<"vceq", "sss", "SlSUl">;
+def SCALAR_CMEQZ : SInst<"vceqz", "ss", "SlSUl">;
+def SCALAR_CMGE : SInst<"vcge", "sss", "Sl">;
+def SCALAR_CMGEZ : SInst<"vcgez", "ss", "Sl">;
+def SCALAR_CMHS : SInst<"vcge", "sss", "SUl">;
+def SCALAR_CMLE : SInst<"vcle", "sss", "SlSUl">;
+def SCALAR_CMLEZ : SInst<"vclez", "ss", "Sl">;
+def SCALAR_CMLT : SInst<"vclt", "sss", "SlSUl">;
+def SCALAR_CMLTZ : SInst<"vcltz", "ss", "Sl">;
+def SCALAR_CMGT : SInst<"vcgt", "sss", "Sl">;
+def SCALAR_CMGTZ : SInst<"vcgtz", "ss", "Sl">;
+def SCALAR_CMHI : SInst<"vcgt", "sss", "SUl">;
+def SCALAR_CMTST : SInst<"vtst", "sss", "SlSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Comparison
+def SCALAR_FCMEQ : IInst<"vceq", "bss", "SfSd">;
+def SCALAR_FCMEQZ : IInst<"vceqz", "bs", "SfSd">;
+def SCALAR_FCMGE : IInst<"vcge", "bss", "SfSd">;
+def SCALAR_FCMGEZ : IInst<"vcgez", "bs", "SfSd">;
+def SCALAR_FCMGT : IInst<"vcgt", "bss", "SfSd">;
+def SCALAR_FCMGTZ : IInst<"vcgtz", "bs", "SfSd">;
+def SCALAR_FCMLE : IInst<"vcle", "bss", "SfSd">;
+def SCALAR_FCMLEZ : IInst<"vclez", "bs", "SfSd">;
+def SCALAR_FCMLT : IInst<"vclt", "bss", "SfSd">;
+def SCALAR_FCMLTZ : IInst<"vcltz", "bs", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Absolute Compare Mask Greater Than Or Equal
+def SCALAR_FACGE : IInst<"vcage", "bss", "SfSd">;
+def SCALAR_FACLE : IInst<"vcale", "bss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Absolute Compare Mask Greater Than
+def SCALAR_FACGT : IInst<"vcagt", "bss", "SfSd">;
+def SCALAR_FACLT : IInst<"vcalt", "bss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Absolute Value
+def SCALAR_ABS : SInst<"vabs", "ss", "Sl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Absolute Difference
+def SCALAR_ABD : IInst<"vabd", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Absolute Value
+def SCALAR_SQABS : SInst<"vqabs", "ss", "ScSsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Negate
+def SCALAR_NEG : SInst<"vneg", "ss", "Sl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Negate
+def SCALAR_SQNEG : SInst<"vqneg", "ss", "ScSsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Accumulated of Unsigned Value
+def SCALAR_SUQADD : SInst<"vuqadd", "sss", "ScSsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Unsigned Saturating Accumulated of Signed Value
+def SCALAR_USQADD : SInst<"vsqadd", "sss", "SUcSUsSUiSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Doubling Multiply-Add Long
+def SCALAR_SQDMLAL : SInst<"vqdmlal", "rrss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Doubling Multiply-Subtract Long
+def SCALAR_SQDMLSL : SInst<"vqdmlsl", "rrss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Doubling Multiply Long
+def SCALAR_SQDMULL : SInst<"vqdmull", "rss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Extract Unsigned Narrow
+def SCALAR_SQXTUN : SInst<"vqmovun", "zs", "SsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Extract Narrow
+def SCALAR_SQXTN : SInst<"vqmovn", "zs", "SsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Unsigned Saturating Extract Narrow
+def SCALAR_UQXTN : SInst<"vqmovn", "zs", "SUsSUiSUl">;
+
+// Scalar Floating Point multiply (scalar, by element)
+def SCALAR_FMUL_LANE : IOpInst<"vmul_lane", "ssdi", "SfSd", OP_SCALAR_MUL_LN>;
+def SCALAR_FMUL_LANEQ : IOpInst<"vmul_laneq", "ssji", "SfSd", OP_SCALAR_MUL_LNQ>;
+
+// Scalar Floating Point multiply extended (scalar, by element)
+def SCALAR_FMULX_LANE : IOpInst<"vmulx_lane", "ssdi", "SfSd", OP_SCALAR_MULX_LN>;
+def SCALAR_FMULX_LANEQ : IOpInst<"vmulx_laneq", "ssji", "SfSd", OP_SCALAR_MULX_LNQ>;
+
+def SCALAR_VMUL_N : IInst<"vmul_n", "dds", "d">;
+
+// VMUL_LANE_A64 d type implemented using scalar mul lane
+def SCALAR_VMUL_LANE : IInst<"vmul_lane", "ddgi", "d">;
+
+// VMUL_LANEQ d type implemented using scalar mul lane
+def SCALAR_VMUL_LANEQ : IInst<"vmul_laneq", "ddji", "d">;
+
+// VMULX_LANE d type implemented using scalar vmulx_lane
+def SCALAR_VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "d", OP_SCALAR_VMULX_LN>;
+
+// VMULX_LANEQ d type implemented using scalar vmulx_laneq
+def SCALAR_VMULX_LANEQ : IOpInst<"vmulx_laneq", "ddji", "d", OP_SCALAR_VMULX_LNQ>;
+
+// Scalar Floating Point fused multiply-add (scalar, by element)
+def SCALAR_FMLA_LANE : IInst<"vfma_lane", "sssdi", "SfSd">;
+def SCALAR_FMLA_LANEQ : IInst<"vfma_laneq", "sssji", "SfSd">;
+
+// Scalar Floating Point fused multiply-subtract (scalar, by element)
+def SCALAR_FMLS_LANE : IOpInst<"vfms_lane", "sssdi", "SfSd", OP_FMS_LN>;
+def SCALAR_FMLS_LANEQ : IOpInst<"vfms_laneq", "sssji", "SfSd", OP_FMS_LNQ>;
+
+// Signed Saturating Doubling Multiply Long (scalar by element)
+def SCALAR_SQDMULL_LANE : SOpInst<"vqdmull_lane", "rsdi", "SsSi", OP_SCALAR_QDMULL_LN>;
+def SCALAR_SQDMULL_LANEQ : SOpInst<"vqdmull_laneq", "rsji", "SsSi", OP_SCALAR_QDMULL_LNQ>;
+
+// Signed Saturating Doubling Multiply-Add Long (scalar by element)
+def SCALAR_SQDMLAL_LANE : SInst<"vqdmlal_lane", "rrsdi", "SsSi">;
+def SCALAR_SQDMLAL_LANEQ : SInst<"vqdmlal_laneq", "rrsji", "SsSi">;
+
+// Signed Saturating Doubling Multiply-Subtract Long (scalar by element)
+def SCALAR_SQDMLS_LANE : SInst<"vqdmlsl_lane", "rrsdi", "SsSi">;
+def SCALAR_SQDMLS_LANEQ : SInst<"vqdmlsl_laneq", "rrsji", "SsSi">;
+
+// Scalar Integer Saturating Doubling Multiply Half High (scalar by element)
+def SCALAR_SQDMULH_LANE : SOpInst<"vqdmulh_lane", "ssdi", "SsSi", OP_SCALAR_QDMULH_LN>;
+def SCALAR_SQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QDMULH_LNQ>;
+
+// Scalar Integer Saturating Rounding Doubling Multiply Half High
+def SCALAR_SQRDMULH_LANE : SOpInst<"vqrdmulh_lane", "ssdi", "SsSi", OP_SCALAR_QRDMULH_LN>;
+def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QRDMULH_LNQ>;
+
+def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
+def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
+
+def SCALAR_GET_LANE : IOpInst<"vget_lane", "sdi", "hQh", OP_SCALAR_GET_LN>;
+def SCALAR_SET_LANE : IOpInst<"vset_lane", "dsdi", "hQh", OP_SCALAR_SET_LN>;
+}
diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
new file mode 100644
index 000000000000..96da0e9de1ad
--- /dev/null
+++ b/include/clang/CodeGen/CGFunctionInfo.h
@@ -0,0 +1,361 @@
+//==-- CGFunctionInfo.h - Representation of function argument/return types -==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines CGFunctionInfo and associated types used in representing the
+// LLVM source types and ABI-coerced types for function arguments and
+// return values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_FUNCTION_INFO_H
+#define LLVM_CLANG_CODEGEN_FUNCTION_INFO_H
+
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/FoldingSet.h"
+
+#include <cassert>
+
+namespace llvm {
+ class Type;
+}
+
+namespace clang {
+namespace CodeGen {
+
+/// ABIArgInfo - Helper class to encapsulate information about how a
+/// specific C type should be passed to or returned from a function.
+class ABIArgInfo {
+public:
+ enum Kind {
+ /// Direct - Pass the argument directly using the normal converted LLVM
+ /// type, or by coercing to another specified type stored in
+ /// 'CoerceToType'). If an offset is specified (in UIntData), then the
+ /// argument passed is offset by some number of bytes in the memory
+ /// representation. A dummy argument is emitted before the real argument
+ /// if the specified type stored in "PaddingType" is not zero.
+ Direct,
+
+ /// Extend - Valid only for integer argument types. Same as 'direct'
+ /// but also emit a zero/sign extension attribute.
+ Extend,
+
+ /// Indirect - Pass the argument indirectly via a hidden pointer
+ /// with the specified alignment (0 indicates default alignment).
+ Indirect,
+
+ /// Ignore - Ignore the argument (treat as void). Useful for void and
+ /// empty structs.
+ Ignore,
+
+ /// Expand - Only valid for aggregate argument types. The structure should
+ /// be expanded into consecutive arguments for its constituent fields.
+ /// Currently expand is only allowed on structures whose fields
+ /// are all scalar types or are themselves expandable types.
+ Expand,
+
+ KindFirst=Direct, KindLast=Expand
+ };
+
+private:
+ Kind TheKind;
+ llvm::Type *TypeData;
+ llvm::Type *PaddingType;
+ unsigned UIntData;
+ bool BoolData0;
+ bool BoolData1;
+ bool InReg;
+ bool PaddingInReg;
+
+ ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR,
+ bool PIR, llvm::Type* P)
+ : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
+ BoolData1(B1), InReg(IR), PaddingInReg(PIR) {}
+
+public:
+ ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
+
+ static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
+ llvm::Type *Padding = 0) {
+ return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding);
+ }
+ static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
+ return ABIArgInfo(Direct, T, 0, false, false, true, false, 0);
+ }
+ static ABIArgInfo getExtend(llvm::Type *T = 0) {
+ return ABIArgInfo(Extend, T, 0, false, false, false, false, 0);
+ }
+ static ABIArgInfo getExtendInReg(llvm::Type *T = 0) {
+ return ABIArgInfo(Extend, T, 0, false, false, true, false, 0);
+ }
+ static ABIArgInfo getIgnore() {
+ return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0);
+ }
+ static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
+ , bool Realign = false
+ , llvm::Type *Padding = 0) {
+ return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false,
+ Padding);
+ }
+ static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true
+ , bool Realign = false) {
+ return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0);
+ }
+ static ABIArgInfo getExpand() {
+ return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0);
+ }
+ static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
+ llvm::Type *Padding) {
+ return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg,
+ Padding);
+ }
+
+ Kind getKind() const { return TheKind; }
+ bool isDirect() const { return TheKind == Direct; }
+ bool isExtend() const { return TheKind == Extend; }
+ bool isIgnore() const { return TheKind == Ignore; }
+ bool isIndirect() const { return TheKind == Indirect; }
+ bool isExpand() const { return TheKind == Expand; }
+
+ bool canHaveCoerceToType() const {
+ return TheKind == Direct || TheKind == Extend;
+ }
+
+ // Direct/Extend accessors
+ unsigned getDirectOffset() const {
+ assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+ return UIntData;
+ }
+
+ llvm::Type *getPaddingType() const {
+ return PaddingType;
+ }
+
+ bool getPaddingInReg() const {
+ return PaddingInReg;
+ }
+
+ llvm::Type *getCoerceToType() const {
+ assert(canHaveCoerceToType() && "Invalid kind!");
+ return TypeData;
+ }
+
+ void setCoerceToType(llvm::Type *T) {
+ assert(canHaveCoerceToType() && "Invalid kind!");
+ TypeData = T;
+ }
+
+ bool getInReg() const {
+ assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
+ return InReg;
+ }
+
+ // Indirect accessors
+ unsigned getIndirectAlign() const {
+ assert(TheKind == Indirect && "Invalid kind!");
+ return UIntData;
+ }
+
+ bool getIndirectByVal() const {
+ assert(TheKind == Indirect && "Invalid kind!");
+ return BoolData0;
+ }
+
+ bool getIndirectRealign() const {
+ assert(TheKind == Indirect && "Invalid kind!");
+ return BoolData1;
+ }
+
+ void dump() const;
+};
+
+/// A class for recording the number of arguments that a function
+/// signature requires.
+class RequiredArgs {
+ /// The number of required arguments, or ~0 if the signature does
+ /// not permit optional arguments.
+ unsigned NumRequired;
+public:
+ enum All_t { All };
+
+ RequiredArgs(All_t _) : NumRequired(~0U) {}
+ explicit RequiredArgs(unsigned n) : NumRequired(n) {
+ assert(n != ~0U);
+ }
+
+ /// Compute the arguments required by the given formal prototype,
+ /// given that there may be some additional, non-formal arguments
+ /// in play.
+ static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
+ unsigned additional) {
+ if (!prototype->isVariadic()) return All;
+ return RequiredArgs(prototype->getNumArgs() + additional);
+ }
+
+ static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
+ return forPrototypePlus(prototype, 0);
+ }
+
+ static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
+ return forPrototype(prototype.getTypePtr());
+ }
+
+ static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
+ unsigned additional) {
+ return forPrototypePlus(prototype.getTypePtr(), additional);
+ }
+
+ bool allowsOptionalArgs() const { return NumRequired != ~0U; }
+ unsigned getNumRequiredArgs() const {
+ assert(allowsOptionalArgs());
+ return NumRequired;
+ }
+
+ unsigned getOpaqueData() const { return NumRequired; }
+ static RequiredArgs getFromOpaqueData(unsigned value) {
+ if (value == ~0U) return All;
+ return RequiredArgs(value);
+ }
+};
+
+/// CGFunctionInfo - Class to encapsulate the information about a
+/// function definition.
+class CGFunctionInfo : public llvm::FoldingSetNode {
+ struct ArgInfo {
+ CanQualType type;
+ ABIArgInfo info;
+ };
+
+ /// The LLVM::CallingConv to use for this function (as specified by the
+ /// user).
+ unsigned CallingConvention : 8;
+
+ /// The LLVM::CallingConv to actually use for this function, which may
+ /// depend on the ABI.
+ unsigned EffectiveCallingConvention : 8;
+
+ /// The clang::CallingConv that this was originally created with.
+ unsigned ASTCallingConvention : 8;
+
+ /// Whether this function is noreturn.
+ unsigned NoReturn : 1;
+
+ /// Whether this function is returns-retained.
+ unsigned ReturnsRetained : 1;
+
+ /// How many arguments to pass inreg.
+ unsigned HasRegParm : 1;
+ unsigned RegParm : 4;
+
+ RequiredArgs Required;
+
+ unsigned NumArgs;
+ ArgInfo *getArgsBuffer() {
+ return reinterpret_cast<ArgInfo*>(this+1);
+ }
+ const ArgInfo *getArgsBuffer() const {
+ return reinterpret_cast<const ArgInfo*>(this + 1);
+ }
+
+ CGFunctionInfo() : Required(RequiredArgs::All) {}
+
+public:
+ static CGFunctionInfo *create(unsigned llvmCC,
+ const FunctionType::ExtInfo &extInfo,
+ CanQualType resultType,
+ ArrayRef<CanQualType> argTypes,
+ RequiredArgs required);
+
+ typedef const ArgInfo *const_arg_iterator;
+ typedef ArgInfo *arg_iterator;
+
+ const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
+ const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
+ arg_iterator arg_begin() { return getArgsBuffer() + 1; }
+ arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
+
+ unsigned arg_size() const { return NumArgs; }
+
+ bool isVariadic() const { return Required.allowsOptionalArgs(); }
+ RequiredArgs getRequiredArgs() const { return Required; }
+
+ bool isNoReturn() const { return NoReturn; }
+
+ /// In ARC, whether this function retains its return value. This
+ /// is not always reliable for call sites.
+ bool isReturnsRetained() const { return ReturnsRetained; }
+
+ /// getASTCallingConvention() - Return the AST-specified calling
+ /// convention.
+ CallingConv getASTCallingConvention() const {
+ return CallingConv(ASTCallingConvention);
+ }
+
+ /// getCallingConvention - Return the user specified calling
+ /// convention, which has been translated into an LLVM CC.
+ unsigned getCallingConvention() const { return CallingConvention; }
+
+ /// getEffectiveCallingConvention - Return the actual calling convention to
+ /// use, which may depend on the ABI.
+ unsigned getEffectiveCallingConvention() const {
+ return EffectiveCallingConvention;
+ }
+ void setEffectiveCallingConvention(unsigned Value) {
+ EffectiveCallingConvention = Value;
+ }
+
+ bool getHasRegParm() const { return HasRegParm; }
+ unsigned getRegParm() const { return RegParm; }
+
+ FunctionType::ExtInfo getExtInfo() const {
+ return FunctionType::ExtInfo(isNoReturn(),
+ getHasRegParm(), getRegParm(),
+ getASTCallingConvention(),
+ isReturnsRetained());
+ }
+
+ CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
+
+ ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
+ const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ ID.AddInteger(getASTCallingConvention());
+ ID.AddBoolean(NoReturn);
+ ID.AddBoolean(ReturnsRetained);
+ ID.AddBoolean(HasRegParm);
+ ID.AddInteger(RegParm);
+ ID.AddInteger(Required.getOpaqueData());
+ getReturnType().Profile(ID);
+ for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
+ it->type.Profile(ID);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const FunctionType::ExtInfo &info,
+ RequiredArgs required,
+ CanQualType resultType,
+ ArrayRef<CanQualType> argTypes) {
+ ID.AddInteger(info.getCC());
+ ID.AddBoolean(info.getNoReturn());
+ ID.AddBoolean(info.getProducesResult());
+ ID.AddBoolean(info.getHasRegParm());
+ ID.AddInteger(info.getRegParm());
+ ID.AddInteger(required.getOpaqueData());
+ resultType.Profile(ID);
+ for (ArrayRef<CanQualType>::iterator
+ i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
+ i->Profile(ID);
+ }
+ }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/include/clang/CodeGen/CodeGenABITypes.h b/include/clang/CodeGen/CodeGenABITypes.h
new file mode 100644
index 000000000000..81e2cdc1901b
--- /dev/null
+++ b/include/clang/CodeGen/CodeGenABITypes.h
@@ -0,0 +1,80 @@
+//==---- CodeGenABITypes.h - Convert Clang types to LLVM types for ABI -----==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CodeGenABITypes is a simple interface for getting LLVM types for
+// the parameters and the return value of a function given the Clang
+// types.
+//
+// The class is implemented as a public wrapper around the private
+// CodeGenTypes class in lib/CodeGen.
+//
+// It allows other clients, like LLDB, to determine the LLVM types that are
+// actually used in function calls, which makes it possible to then determine
+// the acutal ABI locations (e.g. registers, stack locations, etc.) that
+// these parameters are stored in.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_ABITYPES_H
+#define LLVM_CLANG_CODEGEN_ABITYPES_H
+
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/Type.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
+
+namespace llvm {
+ class DataLayout;
+ class Module;
+}
+
+namespace clang {
+class ASTContext;
+class CXXRecordDecl;
+class CodeGenOptions;
+class DiagnosticsEngine;
+class ObjCMethodDecl;
+
+namespace CodeGen {
+class CGFunctionInfo;
+class CodeGenModule;
+
+class CodeGenABITypes
+{
+public:
+ CodeGenABITypes(ASTContext &C, const CodeGenOptions &CodeGenOpts,
+ llvm::Module &M, const llvm::DataLayout &TD,
+ DiagnosticsEngine &Diags);
+
+ ~CodeGenABITypes();
+
+ /// These methods all forward to methods in the private implementation class
+ /// CodeGenTypes.
+
+ const CGFunctionInfo &arrangeObjCMessageSendSignature(
+ const ObjCMethodDecl *MD,
+ QualType receiverType);
+ const CGFunctionInfo &arrangeFreeFunctionType(
+ CanQual<FunctionProtoType> Ty);
+ const CGFunctionInfo &arrangeFreeFunctionType(
+ CanQual<FunctionNoProtoType> Ty);
+ const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
+ const FunctionProtoType *FTP);
+ const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType,
+ llvm::ArrayRef<CanQualType> argTypes,
+ FunctionType::ExtInfo info,
+ RequiredArgs args);
+
+private:
+ CodeGen::CodeGenModule *CGM;
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 4057e48f69a4..289dbe3ee4f8 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -14,9 +14,14 @@
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallVector.h"
+namespace llvm {
+namespace opt {
+ class Arg;
+}
+}
+
namespace clang {
namespace driver {
- class Arg;
/// Action - Represent an abstract compilation step to perform.
///
@@ -94,11 +99,12 @@ public:
class InputAction : public Action {
virtual void anchor();
- const Arg &Input;
+ const llvm::opt::Arg &Input;
+
public:
- InputAction(const Arg &_Input, types::ID _Type);
+ InputAction(const llvm::opt::Arg &_Input, types::ID _Type);
- const Arg &getInputArg() const { return Input; }
+ const llvm::opt::Arg &getInputArg() const { return Input; }
static bool classof(const Action *A) {
return A->getKind() == InputClass;
diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h
deleted file mode 100644
index 662a2e2c618b..000000000000
--- a/include/clang/Driver/Arg.h
+++ /dev/null
@@ -1,133 +0,0 @@
-//===--- Arg.h - Parsed Argument Classes ------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines the clang::driver::Arg class for parsed arguments.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_ARG_H_
-#define CLANG_DRIVER_ARG_H_
-
-#include "Util.h"
-#include "clang/Driver/Option.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include <string>
-
-namespace clang {
-namespace driver {
- class ArgList;
-
- /// \brief A concrete instance of a particular driver option.
- ///
- /// The Arg class encodes just enough information to be able to
- /// derive the argument values efficiently. In addition, Arg
- /// instances have an intrusive double linked list which is used by
- /// ArgList to provide efficient iteration over all instances of a
- /// particular option.
- class Arg {
- Arg(const Arg &) LLVM_DELETED_FUNCTION;
- void operator=(const Arg &) LLVM_DELETED_FUNCTION;
-
- private:
- /// \brief The option this argument is an instance of.
- const Option Opt;
-
- /// \brief The argument this argument was derived from (during tool chain
- /// argument translation), if any.
- const Arg *BaseArg;
-
- /// \brief How this instance of the option was spelled.
- StringRef Spelling;
-
- /// \brief The index at which this argument appears in the containing
- /// ArgList.
- unsigned Index;
-
- /// \brief Was this argument used to affect compilation?
- ///
- /// This is used for generating "argument unused" diagnostics.
- mutable unsigned Claimed : 1;
-
- /// \brief Does this argument own its values?
- mutable unsigned OwnsValues : 1;
-
- /// \brief The argument values, as C strings.
- SmallVector<const char *, 2> Values;
-
- public:
- Arg(const Option Opt, StringRef Spelling, unsigned Index,
- const Arg *BaseArg = 0);
- Arg(const Option Opt, StringRef Spelling, unsigned Index,
- const char *Value0, const Arg *BaseArg = 0);
- Arg(const Option Opt, StringRef Spelling, unsigned Index,
- const char *Value0, const char *Value1, const Arg *BaseArg = 0);
- ~Arg();
-
- Option getOption() const { return Opt; }
- StringRef getSpelling() const { return Spelling; }
- unsigned getIndex() const { return Index; }
-
- /// \brief Return the base argument which generated this arg.
- ///
- /// This is either the argument itself or the argument it was
- /// derived from during tool chain specific argument translation.
- const Arg &getBaseArg() const {
- return BaseArg ? *BaseArg : *this;
- }
- void setBaseArg(const Arg *_BaseArg) {
- BaseArg = _BaseArg;
- }
-
- bool getOwnsValues() const { return OwnsValues; }
- void setOwnsValues(bool Value) const { OwnsValues = Value; }
-
- bool isClaimed() const { return getBaseArg().Claimed; }
-
- /// \brief Set the Arg claimed bit.
- void claim() const { getBaseArg().Claimed = true; }
-
- unsigned getNumValues() const { return Values.size(); }
- const char *getValue(unsigned N = 0) const {
- return Values[N];
- }
-
- SmallVectorImpl<const char*> &getValues() {
- return Values;
- }
-
- bool containsValue(StringRef Value) const {
- for (unsigned i = 0, e = getNumValues(); i != e; ++i)
- if (Values[i] == Value)
- return true;
- return false;
- }
-
- /// \brief Append the argument onto the given array as strings.
- void render(const ArgList &Args, ArgStringList &Output) const;
-
- /// \brief Append the argument, render as an input, onto the given
- /// array as strings.
- ///
- /// The distinction is that some options only render their values
- /// when rendered as a input (e.g., Xlinker).
- void renderAsInput(const ArgList &Args, ArgStringList &Output) const;
-
- void dump() const;
-
- /// \brief Return a formatted version of the argument and
- /// its values, for debugging and diagnostics.
- std::string getAsString(const ArgList &Args) const;
- };
-
-} // end namespace driver
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h
deleted file mode 100644
index 9db170c4a254..000000000000
--- a/include/clang/Driver/ArgList.h
+++ /dev/null
@@ -1,442 +0,0 @@
-//===--- ArgList.h - Argument List Management ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_ARGLIST_H_
-#define CLANG_DRIVER_ARGLIST_H_
-
-#include "clang/Basic/LLVM.h"
-#include "clang/Driver/OptSpecifier.h"
-#include "clang/Driver/Option.h"
-#include "clang/Driver/Util.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include <list>
-#include <string>
-#include <vector>
-
-namespace clang {
- class DiagnosticsEngine;
-
-namespace driver {
- class Arg;
- class ArgList;
- class Option;
-
- /// arg_iterator - Iterates through arguments stored inside an ArgList.
- class arg_iterator {
- /// The current argument.
- SmallVectorImpl<Arg*>::const_iterator Current;
-
- /// The argument list we are iterating over.
- const ArgList &Args;
-
- /// Optional filters on the arguments which will be match. Most clients
- /// should never want to iterate over arguments without filters, so we won't
- /// bother to factor this into two separate iterator implementations.
- //
- // FIXME: Make efficient; the idea is to provide efficient iteration over
- // all arguments which match a particular id and then just provide an
- // iterator combinator which takes multiple iterators which can be
- // efficiently compared and returns them in order.
- OptSpecifier Id0, Id1, Id2;
-
- void SkipToNextArg();
-
- public:
- typedef Arg * const * value_type;
- typedef Arg * const & reference;
- typedef Arg * const * pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
-
- arg_iterator(SmallVectorImpl<Arg*>::const_iterator it,
- const ArgList &_Args, OptSpecifier _Id0 = 0U,
- OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
- : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
- SkipToNextArg();
- }
-
- operator const Arg*() { return *Current; }
- reference operator*() const { return *Current; }
- pointer operator->() const { return Current; }
-
- arg_iterator &operator++() {
- ++Current;
- SkipToNextArg();
- return *this;
- }
-
- arg_iterator operator++(int) {
- arg_iterator tmp(*this);
- ++(*this);
- return tmp;
- }
-
- friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
- return LHS.Current == RHS.Current;
- }
- friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
- return !(LHS == RHS);
- }
- };
-
- /// ArgList - Ordered collection of driver arguments.
- ///
- /// The ArgList class manages a list of Arg instances as well as
- /// auxiliary data and convenience methods to allow Tools to quickly
- /// check for the presence of Arg instances for a particular Option
- /// and to iterate over groups of arguments.
- class ArgList {
- private:
- ArgList(const ArgList &) LLVM_DELETED_FUNCTION;
- void operator=(const ArgList &) LLVM_DELETED_FUNCTION;
-
- public:
- typedef SmallVector<Arg*, 16> arglist_type;
- typedef arglist_type::iterator iterator;
- typedef arglist_type::const_iterator const_iterator;
- typedef arglist_type::reverse_iterator reverse_iterator;
- typedef arglist_type::const_reverse_iterator const_reverse_iterator;
-
- private:
- /// The internal list of arguments.
- arglist_type Args;
-
- protected:
- ArgList();
-
- public:
- virtual ~ArgList();
-
- /// @name Arg Access
- /// @{
-
- /// append - Append \p A to the arg list.
- void append(Arg *A);
-
- arglist_type &getArgs() { return Args; }
- const arglist_type &getArgs() const { return Args; }
-
- unsigned size() const { return Args.size(); }
-
- /// @}
- /// @name Arg Iteration
- /// @{
-
- iterator begin() { return Args.begin(); }
- iterator end() { return Args.end(); }
-
- reverse_iterator rbegin() { return Args.rbegin(); }
- reverse_iterator rend() { return Args.rend(); }
-
- const_iterator begin() const { return Args.begin(); }
- const_iterator end() const { return Args.end(); }
-
- const_reverse_iterator rbegin() const { return Args.rbegin(); }
- const_reverse_iterator rend() const { return Args.rend(); }
-
- arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
- OptSpecifier Id2 = 0U) const {
- return arg_iterator(Args.begin(), *this, Id0, Id1, Id2);
- }
- arg_iterator filtered_end() const {
- return arg_iterator(Args.end(), *this);
- }
-
- /// @}
- /// @name Arg Removal
- /// @{
-
- /// eraseArg - Remove any option matching \p Id.
- void eraseArg(OptSpecifier Id);
-
- /// @}
- /// @name Arg Access
- /// @{
-
- /// hasArg - Does the arg list contain any option matching \p Id.
- ///
- /// \p Claim Whether the argument should be claimed, if it exists.
- bool hasArgNoClaim(OptSpecifier Id) const {
- return getLastArgNoClaim(Id) != 0;
- }
- bool hasArg(OptSpecifier Id) const {
- return getLastArg(Id) != 0;
- }
- bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const {
- return getLastArg(Id0, Id1) != 0;
- }
- bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const {
- return getLastArg(Id0, Id1, Id2) != 0;
- }
-
- /// getLastArg - Return the last argument matching \p Id, or null.
- ///
- /// \p Claim Whether the argument should be claimed, if it exists.
- Arg *getLastArgNoClaim(OptSpecifier Id) const;
- Arg *getLastArg(OptSpecifier Id) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
- OptSpecifier Id6) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
- OptSpecifier Id6, OptSpecifier Id7) const;
-
- /// getArgString - Return the input argument string at \p Index.
- virtual const char *getArgString(unsigned Index) const = 0;
-
- /// getNumInputArgStrings - Return the number of original argument strings,
- /// which are guaranteed to be the first strings in the argument string
- /// list.
- virtual unsigned getNumInputArgStrings() const = 0;
-
- /// @}
- /// @name Argument Lookup Utilities
- /// @{
-
- /// getLastArgValue - Return the value of the last argument, or a default.
- StringRef getLastArgValue(OptSpecifier Id,
- StringRef Default = "") const;
-
- /// getLastArgValue - Return the value of the last argument as an integer,
- /// or a default. If Diags is non-null, emits an error if the argument
- /// is given, but non-integral.
- int getLastArgIntValue(OptSpecifier Id, int Default,
- DiagnosticsEngine *Diags = 0) const;
-
- /// getLastArgValue - Return the value of the last argument as an integer,
- /// or a default. Emits an error if the argument is given, but non-integral.
- int getLastArgIntValue(OptSpecifier Id, int Default,
- DiagnosticsEngine &Diags) const {
- return getLastArgIntValue(Id, Default, &Diags);
- }
-
- /// getAllArgValues - Get the values of all instances of the given argument
- /// as strings.
- std::vector<std::string> getAllArgValues(OptSpecifier Id) const;
-
- /// @}
- /// @name Translation Utilities
- /// @{
-
- /// hasFlag - Given an option \p Pos and its negative form \p Neg, return
- /// true if the option is present, false if the negation is present, and
- /// \p Default if neither option is given. If both the option and its
- /// negation are present, the last one wins.
- bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default = true) const;
-
- /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative
- /// form \p Neg, return true if the option or its alias is present, false if
- /// the negation is present, and \p Default if none of the options are
- /// given. If multiple options are present, the last one wins.
- bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
- bool Default = true) const;
-
- /// AddLastArg - Render only the last argument match \p Id0, if present.
- void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;
- void AddLastArg(ArgStringList &Output, OptSpecifier Id0,
- OptSpecifier Id1) const;
-
- /// AddAllArgs - Render all arguments matching the given ids.
- void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
- OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
-
- /// AddAllArgValues - Render the argument values of all arguments
- /// matching the given ids.
- void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
- OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
-
- /// AddAllArgsTranslated - Render all the arguments matching the
- /// given ids, but forced to separate args and using the provided
- /// name instead of the first option value.
- ///
- /// \param Joined - If true, render the argument as joined with
- /// the option specifier.
- void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
- const char *Translation,
- bool Joined = false) const;
-
- /// ClaimAllArgs - Claim all arguments which match the given
- /// option id.
- void ClaimAllArgs(OptSpecifier Id0) const;
-
- /// ClaimAllArgs - Claim all arguments.
- ///
- void ClaimAllArgs() const;
-
- /// @}
- /// @name Arg Synthesis
- /// @{
-
- /// MakeArgString - Construct a constant string pointer whose
- /// lifetime will match that of the ArgList.
- virtual const char *MakeArgString(StringRef Str) const = 0;
- const char *MakeArgString(const char *Str) const {
- return MakeArgString(StringRef(Str));
- }
- const char *MakeArgString(std::string Str) const {
- return MakeArgString(StringRef(Str));
- }
- const char *MakeArgString(const Twine &Str) const;
-
- /// \brief Create an arg string for (\p LHS + \p RHS), reusing the
- /// string at \p Index if possible.
- const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS,
- StringRef RHS) const;
-
- /// @}
-
- void dump();
- };
-
- class InputArgList : public ArgList {
- private:
- /// List of argument strings used by the contained Args.
- ///
- /// This is mutable since we treat the ArgList as being the list
- /// of Args, and allow routines to add new strings (to have a
- /// convenient place to store the memory) via MakeIndex.
- mutable ArgStringList ArgStrings;
-
- /// Strings for synthesized arguments.
- ///
- /// This is mutable since we treat the ArgList as being the list
- /// of Args, and allow routines to add new strings (to have a
- /// convenient place to store the memory) via MakeIndex.
- mutable std::list<std::string> SynthesizedStrings;
-
- /// The number of original input argument strings.
- unsigned NumInputArgStrings;
-
- public:
- InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
- ~InputArgList();
-
- virtual const char *getArgString(unsigned Index) const {
- return ArgStrings[Index];
- }
-
- virtual unsigned getNumInputArgStrings() const {
- return NumInputArgStrings;
- }
-
- /// @name Arg Synthesis
- /// @{
-
- public:
- /// MakeIndex - Get an index for the given string(s).
- unsigned MakeIndex(StringRef String0) const;
- unsigned MakeIndex(StringRef String0, StringRef String1) const;
-
- virtual const char *MakeArgString(StringRef Str) const;
-
- /// @}
- };
-
- /// DerivedArgList - An ordered collection of driver arguments,
- /// whose storage may be in another argument list.
- class DerivedArgList : public ArgList {
- const InputArgList &BaseArgs;
-
- /// The list of arguments we synthesized.
- mutable arglist_type SynthesizedArgs;
-
- public:
- /// Construct a new derived arg list from \p BaseArgs.
- DerivedArgList(const InputArgList &BaseArgs);
- ~DerivedArgList();
-
- virtual const char *getArgString(unsigned Index) const {
- return BaseArgs.getArgString(Index);
- }
-
- virtual unsigned getNumInputArgStrings() const {
- return BaseArgs.getNumInputArgStrings();
- }
-
- const InputArgList &getBaseArgs() const {
- return BaseArgs;
- }
-
- /// @name Arg Synthesis
- /// @{
-
- /// AddSynthesizedArg - Add a argument to the list of synthesized arguments
- /// (to be freed).
- void AddSynthesizedArg(Arg *A) {
- SynthesizedArgs.push_back(A);
- }
-
- virtual const char *MakeArgString(StringRef Str) const;
-
- /// AddFlagArg - Construct a new FlagArg for the given option \p Id and
- /// append it to the argument list.
- void AddFlagArg(const Arg *BaseArg, const Option Opt) {
- append(MakeFlagArg(BaseArg, Opt));
- }
-
- /// AddPositionalArg - Construct a new Positional arg for the given option
- /// \p Id, with the provided \p Value and append it to the argument
- /// list.
- void AddPositionalArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) {
- append(MakePositionalArg(BaseArg, Opt, Value));
- }
-
-
- /// AddSeparateArg - Construct a new Positional arg for the given option
- /// \p Id, with the provided \p Value and append it to the argument
- /// list.
- void AddSeparateArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) {
- append(MakeSeparateArg(BaseArg, Opt, Value));
- }
-
-
- /// AddJoinedArg - Construct a new Positional arg for the given option
- /// \p Id, with the provided \p Value and append it to the argument list.
- void AddJoinedArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) {
- append(MakeJoinedArg(BaseArg, Opt, Value));
- }
-
-
- /// MakeFlagArg - Construct a new FlagArg for the given option \p Id.
- Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const;
-
- /// MakePositionalArg - Construct a new Positional arg for the
- /// given option \p Id, with the provided \p Value.
- Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) const;
-
- /// MakeSeparateArg - Construct a new Positional arg for the
- /// given option \p Id, with the provided \p Value.
- Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) const;
-
- /// MakeJoinedArg - Construct a new Positional arg for the
- /// given option \p Id, with the provided \p Value.
- Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) const;
-
- /// @}
- };
-
-} // end namespace driver
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Driver/CC1AsOptions.h b/include/clang/Driver/CC1AsOptions.h
index 420a10138cba..345f50a57d5f 100644
--- a/include/clang/Driver/CC1AsOptions.h
+++ b/include/clang/Driver/CC1AsOptions.h
@@ -10,24 +10,27 @@
#ifndef CLANG_DRIVER_CC1ASOPTIONS_H
#define CLANG_DRIVER_CC1ASOPTIONS_H
+namespace llvm {
+namespace opt {
+ class OptTable;
+}
+}
+
namespace clang {
namespace driver {
- class OptTable;
namespace cc1asoptions {
enum ID {
OPT_INVALID = 0, // This is not an option ID.
-#define PREFIX(NAME, VALUE)
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR) OPT_##ID,
#include "clang/Driver/CC1AsOptions.inc"
LastOption
#undef OPTION
-#undef PREFIX
};
}
- OptTable *createCC1AsOptTable();
+llvm::opt::OptTable *createCC1AsOptTable();
}
}
diff --git a/include/clang/Driver/CC1AsOptions.td b/include/clang/Driver/CC1AsOptions.td
index 2749bcd7779c..b536724f2425 100644
--- a/include/clang/Driver/CC1AsOptions.td
+++ b/include/clang/Driver/CC1AsOptions.td
@@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
// Include the common option parsing interfaces.
-include "OptParser.td"
+include "llvm/Option/OptParser.td"
//===----------------------------------------------------------------------===//
// Target Options
@@ -33,7 +33,7 @@ def I : JoinedOrSeparate<["-"], "I">, MetaVarName<"<directory>">,
HelpText<"Add directory to include search path">;
def n : Flag<["-"], "n">,
HelpText<"Don't automatically start assembly file with a text section">;
-def L : Flag<["-"], "L">,
+def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
HelpText<"Save temporary labels in the symbol table. "
"Note this may change .s semantics, it should almost never be used "
"on compiler generated code!">;
@@ -77,15 +77,12 @@ def show_inst : Flag<["-"], "show-inst">,
// Assemble Options
//===----------------------------------------------------------------------===//
-def relax_all : Flag<["-"], "relax-all">,
+def mrelax_all : Flag<["-"], "mrelax-all">,
HelpText<"Relax all fixups (for performance testing)">;
-def no_exec_stack : Flag<["--"], "noexecstack">,
+def mno_exec_stack : Flag<["-"], "mnoexecstack">,
HelpText<"Mark the file as not needing an executable stack">;
-def fatal_warnings : Flag<["--"], "fatal-warnings">,
- HelpText<"Consider warnings as errors">;
-
def g : Flag<["-"], "g">, HelpText<"Generate source level debug information">;
def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 96a50fc5c66a..85cfdcf3946b 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -23,6 +23,8 @@ def target_abi : Separate<["-"], "target-abi">,
HelpText<"Target a particular ABI type">;
def target_cpu : Separate<["-"], "target-cpu">,
HelpText<"Target a specific cpu type">;
+def mfpmath : Separate<["-"], "mfpmath">,
+ HelpText<"Which unit to use for fp math">;
def target_feature : Separate<["-"], "target-feature">,
HelpText<"Target specific attributes">;
def target_linker_version : Separate<["-"], "target-linker-version">,
@@ -136,6 +138,8 @@ def dwarf_column_info : Flag<["-"], "dwarf-column-info">,
HelpText<"Turn on column location information.">;
def split_dwarf : Flag<["-"], "split-dwarf">,
HelpText<"Split out the dwarf .dwo sections">;
+def gnu_pubnames : Flag<["-"], "gnu-pubnames">,
+ HelpText<"Emit newer GNU style pubnames">;
def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">,
HelpText<"Emit an error if a C++ static local initializer would need a guard variable">;
def no_implicit_float : Flag<["-"], "no-implicit-float">,
@@ -161,8 +165,8 @@ def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfie
HelpText<"Use register sized accesses to bit-fields, when possible.">;
def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">,
HelpText<"Turn off Type Based Alias Analysis">;
-def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">,
- HelpText<"Turn on struct-path aware Type Based Alias Analysis">;
+def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">,
+ HelpText<"Turn off struct-path aware Type Based Alias Analysis">;
def masm_verbose : Flag<["-"], "masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<["-"], "mcode-model">,
@@ -204,6 +208,14 @@ def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">,
HelpText<"Emit complete constructors and destructors as aliases when possible">;
def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
HelpText<"Link the given bitcode file before performing optimizations.">;
+def vectorize_loops : Flag<["-"], "vectorize-loops">,
+ HelpText<"Run the Loop vectorization passes">;
+def vectorize_slp : Flag<["-"], "vectorize-slp">,
+ HelpText<"Run the SLP vectorization passes">;
+def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">,
+ HelpText<"Run the BB vectorization passes">;
+def dependent_lib : Joined<["--"], "dependent-lib=">,
+ HelpText<"Add dependent library">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
@@ -213,6 +225,8 @@ 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 show_includes : Flag<["--"], "show-includes">,
+ HelpText<"Print cl.exe style /showIncludes to stderr">;
//===----------------------------------------------------------------------===//
// Diagnostic Options
@@ -290,6 +304,8 @@ def ast_dump_filter : Separate<["-"], "ast-dump-filter">,
HelpText<"Use with -ast-dump or -ast-print to dump/print only AST declaration"
" nodes having a certain substring in a qualified name. Use"
" -ast-list to list all filterable declaration node names.">;
+def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">,
+ HelpText<"Include name lookup table dumps in AST dumps">;
def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">,
HelpText<"Do not automatically generate or update the global module index">;
@@ -320,8 +336,6 @@ def ast_list : Flag<["-"], "ast-list">,
HelpText<"Build ASTs and print the list of declaration node qualified names">;
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 print_decl_contexts : Flag<["-"], "print-decl-contexts">,
@@ -357,8 +371,6 @@ def arcmt_modify : Flag<["-"], "arcmt-modify">,
def arcmt_migrate : Flag<["-"], "arcmt-migrate">,
HelpText<"Apply modifications and produces temporary files that conform to ARC">;
-def relocatable_pch : Flag<["-", "--"], "relocatable-pch">,
- HelpText<"Whether to build a relocatable precompiled header">;
def print_stats : Flag<["-"], "print-stats">,
HelpText<"Print performance metrics and statistics">;
def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">,
@@ -391,8 +403,6 @@ def main_file_name : Separate<["-"], "main-file-name">,
HelpText<"Main file name to use for debug info">;
def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
HelpText<"File name to use for split dwarf debug info output">;
-def fno_signed_char : Flag<["-"], "fno-signed-char">,
- HelpText<"Char is unsigned">;
def fno_wchar : Flag<["-"], "fno-wchar">,
HelpText<"Disable C++ builtin type wchar_t">;
def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
@@ -404,8 +414,8 @@ def fobjc_runtime_has_weak : Flag<["-"], "fobjc-runtime-has-weak">,
HelpText<"The target Objective-C runtime supports ARC weak operations">;
def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">,
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 disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-default-synthesize-properties">,
+ HelpText<"disable the default synthesis of Objective-C properties">;
def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">,
HelpText<"enable extended encoding of block type signature">;
def pic_level : Separate<["-"], "pic-level">,
@@ -432,8 +442,12 @@ def ftype_visibility : Separate<["-"], "ftype-visibility">,
HelpText<"Default type visibility">;
def ftemplate_depth : Separate<["-"], "ftemplate-depth">,
HelpText<"Maximum depth of recursive template instantiation">;
+def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">,
+ HelpText<"Maximum number of 'operator->'s to call for a member access">;
def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">,
HelpText<"Maximum depth of recursive constexpr function calls">;
+def fconstexpr_steps : Separate<["-"], "fconstexpr-steps">,
+ HelpText<"Maximum number of steps in constexpr function evaluation">;
def fbracket_depth : Separate<["-"], "fbracket-depth">,
HelpText<"Maximum nesting level for parentheses, brackets, and braces">;
def fconst_strings : Flag<["-"], "fconst-strings">,
@@ -444,6 +458,8 @@ def fno_bitfield_type_align : Flag<["-"], "fno-bitfield-type-align">,
HelpText<"Ignore bit-field types when aligning structures">;
def ffake_address_space_map : Flag<["-"], "ffake-address-space-map">,
HelpText<"Use a fake address space map; OpenCL testing purposes only">;
+def faddress_space_map_mangling_EQ : Joined<["-"], "faddress-space-map-mangling=">, MetaVarName<"<yes|no|target>">,
+ HelpText<"Set the mode for address space map based mangling; OpenCL testing purposes only">;
def funknown_anytype : Flag<["-"], "funknown-anytype">,
HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">;
def fdebugger_support : Flag<["-"], "fdebugger-support">,
@@ -456,6 +472,10 @@ def fdeprecated_macro : Flag<["-"], "fdeprecated-macro">,
HelpText<"Defines the __DEPRECATED macro">;
def fno_deprecated_macro : Flag<["-"], "fno-deprecated-macro">,
HelpText<"Undefines the __DEPRECATED macro">;
+def fsized_deallocation : Flag<["-"], "fsized-deallocation">,
+ HelpText<"Enable C++1y sized global deallocation functions">;
+def fobjc_subscripting_legacy_runtime : Flag<["-"], "fobjc-subscripting-legacy-runtime">,
+ HelpText<"Allow Objective-C array and dictionary subscripting in legacy runtime">;
//===----------------------------------------------------------------------===//
// Header Search Options
@@ -463,9 +483,6 @@ def fno_deprecated_macro : Flag<["-"], "fno-deprecated-macro">,
def nostdsysteminc : Flag<["-"], "nostdsysteminc">,
HelpText<"Disable standard system #include directories">;
-def fmodule_name : Joined<["-"], "fmodule-name=">,
- MetaVarName<"<name>">,
- HelpText<"Specify the name of the module to build">;
def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">,
HelpText<"Disable the module hash">;
def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">,
diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
new file mode 100644
index 000000000000..d17a63c62c92
--- /dev/null
+++ b/include/clang/Driver/CLCompatOptions.td
@@ -0,0 +1,255 @@
+//===--- CLCompatOptions.td - Options for clang-cl ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the options accepted by clang-cl.
+//
+//===----------------------------------------------------------------------===//
+
+def cl_Group : OptionGroup<"<clang-cl options>">,
+ HelpText<"CL.EXE COMPATIBILITY OPTIONS">;
+
+def cl_compile_Group : OptionGroup<"<clang-cl compile-only options>">,
+ Group<cl_Group>;
+
+def cl_ignored_Group : OptionGroup<"<clang-cl ignored options>">,
+ Group<cl_Group>;
+
+class CLFlag<string name> : Option<["/", "-"], name, KIND_FLAG>,
+ Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLCompileFlag<string name> : Option<["/", "-"], name, KIND_FLAG>,
+ Group<cl_compile_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLIgnoredFlag<string name> : Option<["/", "-"], name, KIND_FLAG>,
+ Group<cl_ignored_Group>, Flags<[CLOption, DriverOption, HelpHidden]>;
+
+class CLJoined<string name> : Option<["/", "-"], name, KIND_JOINED>,
+ Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLCompileJoined<string name> : Option<["/", "-"], name, KIND_JOINED>,
+ Group<cl_compile_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLIgnoredJoined<string name> : Option<["/", "-"], name, KIND_JOINED>,
+ Group<cl_ignored_Group>, Flags<[CLOption, DriverOption, HelpHidden]>;
+
+class CLJoinedOrSeparate<string name> : Option<["/", "-"], name,
+ KIND_JOINED_OR_SEPARATE>, Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLCompileJoinedOrSeparate<string name> : Option<["/", "-"], name,
+ KIND_JOINED_OR_SEPARATE>, Group<cl_compile_Group>,
+ Flags<[CLOption, DriverOption]>;
+
+class CLRemainingArgs<string name> : Option<["/", "-"], name,
+ KIND_REMAINING_ARGS>, Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+// Aliases:
+// (We don't put any of these in cl_compile_Group as the options they alias are
+// already in the right group.)
+
+def _SLASH_C : CLFlag<"C">, HelpText<"Don't discard comments when preprocessing">,
+ Alias<C>;
+def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>;
+def _SLASH_D : CLJoinedOrSeparate<"D">, HelpText<"Define macro">,
+ MetaVarName<"<macro[=value]>">, Alias<D>;
+def _SLASH_GR : CLFlag<"GR">, HelpText<"Enable RTTI">, Alias<frtti>;
+def _SLASH_GR_ : CLFlag<"GR-">, HelpText<"Disable RTTI">, Alias<fno_rtti>;
+def _SLASH_GF_ : CLFlag<"GF-">, HelpText<"Disable string pooling">,
+ Alias<fwritable_strings>;
+def _SLASH_help : CLFlag<"help">, Alias<help>,
+ HelpText<"Display available options">;
+def _SLASH_HELP : CLFlag<"HELP">, Alias<help>;
+def _SLASH_I : CLJoinedOrSeparate<"I">,
+ HelpText<"Add directory to include search path">, MetaVarName<"<dir>">,
+ Alias<I>;
+def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">,
+ Alias<funsigned_char>;
+def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">,
+ MetaVarName<"<n>">, Alias<O>;
+def _SLASH_Ob0 : CLFlag<"Ob0">, HelpText<"Disable inlining">,
+ Alias<fno_inline>;
+def _SLASH_Od : CLFlag<"Od">, HelpText<"Disable optimization">, Alias<O0>;
+def _SLASH_Oi : CLFlag<"Oi">, HelpText<"Enable use of builtin functions">,
+ Alias<fbuiltin>;
+def _SLASH_Oi_ : CLFlag<"Oi-">, HelpText<"Disable use of builtin functions">,
+ Alias<fno_builtin>;
+def _SLASH_Os : CLFlag<"Os">, HelpText<"Optimize for size">, Alias<O>,
+ AliasArgs<["s"]>;
+def _SLASH_Ot : CLFlag<"Ot">, HelpText<"Optimize for speed">, Alias<O>,
+ AliasArgs<["2"]>;
+def _SLASH_Ox : CLFlag<"Ox">, HelpText<"Maximum optimization">, Alias<O>,
+ AliasArgs<["3"]>;
+def _SLASH_Oy : CLFlag<"Oy">, HelpText<"Enable frame pointer omission">,
+ Alias<fomit_frame_pointer>;
+def _SLASH_Oy_ : CLFlag<"Oy-">, HelpText<"Disable frame pointer omission">,
+ Alias<fno_omit_frame_pointer>;
+def _SLASH_P : CLFlag<"P">, HelpText<"Only run the preprocessor">, Alias<E>;
+def _SLASH_QUESTION : CLFlag<"?">, Alias<help>,
+ HelpText<"Display available options">;
+def _SLASH_showIncludes : CLFlag<"showIncludes">,
+ HelpText<"Print info about included files to stderr">,
+ Alias<show_includes>;
+def _SLASH_U : CLJoinedOrSeparate<"U">, HelpText<"Undefine macro">,
+ MetaVarName<"<macro>">, Alias<U>;
+def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias<w>;
+def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_W3 : CLFlag<"W3">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_W4 : CLFlag<"W4">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_WX : CLFlag<"WX">, HelpText<"Treat warnings as errors">,
+ Alias<W_Joined>, AliasArgs<["error"]>;
+def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">,
+ Alias<W_Joined>, AliasArgs<["no-error"]>;
+def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>;
+def _SLASH_Zs : CLFlag<"Zs">, HelpText<"Syntax-check only">,
+ Alias<fsyntax_only>;
+
+
+// Non-aliases:
+
+def _SLASH_M_Group : OptionGroup<"</M group>">, Group<cl_compile_Group>;
+
+def _SLASH_FA : CLFlag<"FA">,
+ HelpText<"Output assembly code file during compilation">;
+def _SLASH_Fa : CLJoined<"Fa">,
+ HelpText<"Output assembly code to this file during compilation">,
+ MetaVarName<"<file or directory>">;
+def _SLASH_fallback : CLCompileFlag<"fallback">,
+ HelpText<"Fall back to cl.exe if clang-cl fails to compile">;
+def _SLASH_FI : CLJoinedOrSeparate<"FI">,
+ HelpText<"Include file before parsing">, Alias<include_>;
+def _SLASH_Fe : CLJoined<"Fe">,
+ HelpText<"Set output executable file or directory (ends in / or \\)">,
+ MetaVarName<"<file or directory>">;
+def _SLASH_Fo : CLCompileJoined<"Fo">,
+ HelpText<"Set output object file, or directory (ends in / or \\)">,
+ MetaVarName<"<file or directory>">;
+def _SLASH_LD : CLFlag<"LD">, HelpText<"Create DLL">;
+def _SLASH_LDd : CLFlag<"LDd">, HelpText<"Create debug DLL">;
+def _SLASH_link : CLRemainingArgs<"link">,
+ HelpText<"Forward options to the linker">, MetaVarName<"<options>">;
+def _SLASH_MD : Option<["/", "-"], "MD", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use DLL run-time">;
+def _SLASH_MDd : Option<["/", "-"], "MDd", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use DLL debug run-time">;
+def _SLASH_MT : Option<["/", "-"], "MT", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use static run-time">;
+def _SLASH_MTd : Option<["/", "-"], "MTd", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use static debug run-time">;
+def _SLASH_Tc : CLCompileJoinedOrSeparate<"Tc">,
+ HelpText<"Specify a C source file">, MetaVarName<"<filename>">;
+def _SLASH_TC : CLCompileFlag<"TC">, HelpText<"Treat all source files as C">;
+def _SLASH_Tp : CLCompileJoinedOrSeparate<"Tp">,
+ HelpText<"Specify a C++ source file">, MetaVarName<"<filename>">;
+def _SLASH_TP : CLCompileFlag<"TP">, HelpText<"Treat all source files as C++">;
+
+
+// Ignored:
+
+def _SLASH_analyze_ : CLIgnoredFlag<"analyze-">;
+def _SLASH_errorReport : CLIgnoredJoined<"errorReport">;
+def _SLASH_FS : CLIgnoredFlag<"FS">, HelpText<"Force synchronous PDB writes">;
+def _SLASH_GF : CLIgnoredFlag<"GF">;
+def _SLASH_GS_ : CLIgnoredFlag<"GS-">;
+def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
+def _SLASH_nologo : CLIgnoredFlag<"nologo">;
+def _SLASH_Ob1 : CLIgnoredFlag<"Ob1">;
+def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">;
+def _SLASH_RTC : CLIgnoredJoined<"RTC">;
+def _SLASH_sdl : CLIgnoredFlag<"sdl">;
+def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">;
+def _SLASH_vmg : CLIgnoredFlag<"vmg">;
+def _SLASH_w : CLIgnoredJoined<"w">;
+def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">;
+def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">;
+def _SLASH_Zm : CLIgnoredJoined<"Zm">;
+
+
+// Unsupported:
+
+def _SLASH_AI : CLJoined<"AI">;
+def _SLASH_arch : CLJoined<"arch:">;
+def _SLASH_bigobj : CLFlag<"bigobj">;
+def _SLASH_clr : CLJoined<"clr">;
+def _SLASH_doc : CLJoined<"doc">;
+def _SLASH_E : CLFlag<"E">;
+def _SLASH_EH : CLJoined<"EH">;
+def _SLASH_EP : CLFlag<"EP">;
+def _SLASH_FA_joined : CLJoined<"FA">;
+def _SLASH_favor : CLJoined<"favor">;
+def _SLASH_FC : CLFlag<"FC">;
+def _SLASH_F : CLFlag<"F">;
+def _SLASH_Fd : CLJoined<"Fd">;
+def _SLASH_Fi : CLJoined<"Fi">;
+def _SLASH_Fm : CLJoined<"Fm">;
+def _SLASH_fp : CLJoined<"fp">;
+def _SLASH_Fp : CLJoined<"Fp">;
+def _SLASH_Fr : CLJoined<"Fr">;
+def _SLASH_FR : CLJoined<"FR">;
+def _SLASH_FU : CLJoinedOrSeparate<"FU">;
+def _SLASH_Fx : CLFlag<"Fx">;
+def _SLASH_G1 : CLFlag<"G1">;
+def _SLASH_G2 : CLFlag<"G2">;
+def _SLASH_GA : CLFlag<"GA">;
+def _SLASH_Gd : CLFlag<"Gd">;
+def _SLASH_Ge : CLFlag<"Ge">;
+def _SLASH_Gh : CLFlag<"Gh">;
+def _SLASH_GH : CLFlag<"GH">;
+def _SLASH_GL : CLFlag<"GL">;
+def _SLASH_GL_ : CLFlag<"GL-">;
+def _SLASH_Gm : CLFlag<"Gm">;
+def _SLASH_Gm_ : CLFlag<"Gm-">;
+def _SLASH_Gr : CLFlag<"Gr">;
+def _SLASH_GS : CLFlag<"GS">;
+def _SLASH_Gs : CLJoined<"Gs">;
+def _SLASH_GT : CLFlag<"GT">;
+def _SLASH_GX : CLFlag<"GX">;
+def _SLASH_Gy : CLFlag<"Gy">;
+def _SLASH_Gy_ : CLFlag<"Gy-">;
+def _SLASH_Gz : CLFlag<"Gz">;
+def _SLASH_GZ : CLFlag<"GZ">;
+def _SLASH_H : CLFlag<"H">;
+def _SLASH_homeparams : CLFlag<"homeparams">;
+def _SLASH_hotpatch : CLFlag<"hotpatch">;
+def _SLASH_kernel : CLFlag<"kernel">;
+def _SLASH_LN : CLFlag<"LN">;
+def _SLASH_MP : CLJoined<"MP">;
+def _SLASH_o : CLJoinedOrSeparate<"o">;
+def _SLASH_openmp : CLFlag<"openmp">;
+def _SLASH_Qfast_transcendentals : CLFlag<"Qfast_transcendentals">;
+def _SLASH_QIfist : CLFlag<"QIfist">;
+def _SLASH_Qimprecise_fwaits : CLFlag<"Qimprecise_fwaits">;
+def _SLASH_Qpar : CLFlag<"Qpar">;
+def _SLASH_Qvec_report : CLJoined<"Qvec-report">;
+def _SLASH_u : CLFlag<"u">;
+def _SLASH_V : CLFlag<"V">;
+def _SLASH_vd : CLJoined<"vd">;
+def _SLASH_vmb : CLFlag<"vmb">;
+def _SLASH_vmm : CLFlag<"vmm">;
+def _SLASH_vms : CLFlag<"vms">;
+def _SLASH_vmv : CLFlag<"vmv">;
+def _SLASH_volatile : CLFlag<"volatile">;
+def _SLASH_WL : CLFlag<"WL">;
+def _SLASH_Wp64 : CLFlag<"Wp64">;
+def _SLASH_X : CLFlag<"X">;
+def _SLASH_Yc : CLJoined<"Yc">;
+def _SLASH_Y_ : CLFlag<"Y-">;
+def _SLASH_Yd : CLFlag<"Yd">;
+def _SLASH_Yl : CLJoined<"Yl">;
+def _SLASH_Yu : CLJoined<"Yu">;
+def _SLASH_Z7 : CLFlag<"Z7">;
+def _SLASH_Za : CLFlag<"Za">;
+def _SLASH_Zc : CLJoined<"Zc:">;
+def _SLASH_Ze : CLFlag<"Ze">;
+def _SLASH_Zg : CLFlag<"Zg">;
+def _SLASH_Zi : CLFlag<"Zi">;
+def _SLASH_ZI : CLFlag<"ZI">;
+def _SLASH_Zl : CLFlag<"Zl">;
+def _SLASH_Zp : CLFlag<"Zp">;
+def _SLASH_ZW : CLJoined<"ZW">;
diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt
index 1277d51edb82..5961cac20ccf 100644
--- a/include/clang/Driver/CMakeLists.txt
+++ b/include/clang/Driver/CMakeLists.txt
@@ -1,7 +1,7 @@
-clang_tablegen(Options.inc -gen-opt-parser-defs
- SOURCE Options.td
- TARGET ClangDriverOptions)
+set(LLVM_TARGET_DEFINITIONS Options.td)
+tablegen(LLVM Options.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ClangDriverOptions)
-clang_tablegen(CC1AsOptions.inc -gen-opt-parser-defs
- SOURCE CC1AsOptions.td
- TARGET ClangCC1AsOptions)
+set(LLVM_TARGET_DEFINITIONS CC1AsOptions.td)
+tablegen(LLVM CC1AsOptions.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ClangCC1AsOptions)
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 15c5e40e495a..3493e4f1509b 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -15,11 +15,16 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Path.h"
+namespace llvm {
+namespace opt {
+ class DerivedArgList;
+ class InputArgList;
+}
+}
+
namespace clang {
namespace driver {
- class DerivedArgList;
class Driver;
- class InputArgList;
class JobAction;
class JobList;
class ToolChain;
@@ -34,11 +39,11 @@ class Compilation {
const ToolChain &DefaultToolChain;
/// The original (untranslated) input argument list.
- InputArgList *Args;
+ llvm::opt::InputArgList *Args;
/// The driver translated arguments. Note that toolchains may perform their
/// own argument translation.
- DerivedArgList *TranslatedArgs;
+ llvm::opt::DerivedArgList *TranslatedArgs;
/// The list of actions.
ActionList Actions;
@@ -48,11 +53,11 @@ class Compilation {
/// Cache of translated arguments for a particular tool chain and bound
/// architecture.
- llvm::DenseMap<std::pair<const ToolChain*, const char*>,
- DerivedArgList*> TCArgs;
+ llvm::DenseMap<std::pair<const ToolChain *, const char *>,
+ llvm::opt::DerivedArgList *> TCArgs;
/// Temporary files which should be removed on exit.
- ArgStringList TempFiles;
+ llvm::opt::ArgStringList TempFiles;
/// Result files which should be removed on failure.
ArgStringMap ResultFiles;
@@ -62,22 +67,23 @@ class Compilation {
ArgStringMap FailureResultFiles;
/// Redirection for stdout, stderr, etc.
- const llvm::sys::Path **Redirects;
+ const StringRef **Redirects;
public:
Compilation(const Driver &D, const ToolChain &DefaultToolChain,
- InputArgList *Args, DerivedArgList *TranslatedArgs);
+ llvm::opt::InputArgList *Args,
+ llvm::opt::DerivedArgList *TranslatedArgs);
~Compilation();
const Driver &getDriver() const { return TheDriver; }
const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
- const InputArgList &getInputArgs() const { return *Args; }
+ const llvm::opt::InputArgList &getInputArgs() const { return *Args; }
- const DerivedArgList &getArgs() const { return *TranslatedArgs; }
+ const llvm::opt::DerivedArgList &getArgs() const { return *TranslatedArgs; }
- DerivedArgList &getArgs() { return *TranslatedArgs; }
+ llvm::opt::DerivedArgList &getArgs() { return *TranslatedArgs; }
ActionList &getActions() { return Actions; }
const ActionList &getActions() const { return Actions; }
@@ -87,7 +93,7 @@ public:
void addCommand(Command *C) { Jobs.addJob(C); }
- const ArgStringList &getTempFiles() const { return TempFiles; }
+ const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
const ArgStringMap &getResultFiles() const { return ResultFiles; }
@@ -102,8 +108,8 @@ public:
/// tool chain \p TC (or the default tool chain, if TC is not specified).
///
/// \param BoundArch - The bound architecture name, or 0.
- const DerivedArgList &getArgsForToolChain(const ToolChain *TC,
- const char *BoundArch);
+ const llvm::opt::DerivedArgList &getArgsForToolChain(const ToolChain *TC,
+ const char *BoundArch);
/// addTempFile - Add a file to remove on exit, and returns its
/// argument.
@@ -136,7 +142,7 @@ public:
///
/// \param IssueErrors - Report failures as errors.
/// \return Whether all files were removed successfully.
- bool CleanupFileList(const ArgStringList &Files,
+ bool CleanupFileList(const llvm::opt::ArgStringList &Files,
bool IssueErrors = false) const;
/// CleanupFileMap - Remove the files in the given map.
@@ -149,23 +155,6 @@ public:
const JobAction *JA,
bool IssueErrors = false) const;
- /// PrintJob - Print one job in -### format.
- ///
- /// \param OS - The stream to print on.
- /// \param J - The job to print.
- /// \param Terminator - A string to print at the end of the line.
- /// \param Quote - Should separate arguments be quoted.
- void PrintJob(raw_ostream &OS, const Job &J,
- const char *Terminator, bool Quote) const;
-
- /// PrintDiagnosticJob - Print one job in -### format, but with the
- /// superfluous options removed, which are not necessary for
- /// reproducing the crash.
- ///
- /// \param OS - The stream to print on.
- /// \param J - The job to print.
- void PrintDiagnosticJob(raw_ostream &OS, const Job &J) const;
-
/// ExecuteCommand - Execute an actual command.
///
/// \param FailingCommand - For non-zero results, this will be set to the
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index d9053d1972aa..867444ea4e13 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -15,6 +15,7 @@
#include "clang/Driver/Phases.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
@@ -24,27 +25,41 @@
#include <set>
#include <string>
+namespace llvm {
+namespace opt {
+ class Arg;
+ class ArgList;
+ class DerivedArgList;
+ class InputArgList;
+ class OptTable;
+}
+}
+
namespace clang {
namespace driver {
+
class Action;
- class Arg;
- class ArgList;
class Command;
class Compilation;
- class DerivedArgList;
- class InputArgList;
class InputInfo;
class JobAction;
- class OptTable;
+ class SanitizerArgs;
class ToolChain;
/// Driver - Encapsulate logic for constructing compilation processes
/// from a set of gcc-driver-like command line arguments.
class Driver {
- OptTable *Opts;
+ llvm::opt::OptTable *Opts;
DiagnosticsEngine &Diags;
+ enum DriverMode {
+ GCCMode,
+ GXXMode,
+ CPPMode,
+ CLMode
+ } Mode;
+
public:
// Diag - Forwarding function for diagnostics.
DiagnosticBuilder Diag(unsigned DiagID) const {
@@ -79,6 +94,9 @@ public:
/// sysroot, if present
std::string SysRoot;
+ /// Dynamic loader prefix, if present
+ std::string DyldPrefix;
+
/// If the standard library is used
bool UseStdLib;
@@ -104,16 +122,17 @@ public:
const char *CCLogDiagnosticsFilename;
/// A list of inputs and their types for the given arguments.
- typedef SmallVector<std::pair<types::ID, const Arg*>, 16> InputList;
+ typedef SmallVector<std::pair<types::ID, const llvm::opt::Arg *>, 16>
+ InputList;
/// Whether the driver should follow g++ like behavior.
- unsigned CCCIsCXX : 1;
+ bool CCCIsCXX() const { return Mode == GXXMode; }
/// Whether the driver is just the preprocessor.
- unsigned CCCIsCPP : 1;
+ bool CCCIsCPP() const { return Mode == CPPMode; }
- /// Echo commands while executing (in -v style).
- unsigned CCCEcho : 1;
+ /// Whether the driver should follow cl.exe like behavior.
+ bool IsCLMode() const { return Mode == CLMode; }
/// Only print tool bindings, don't build any jobs.
unsigned CCCPrintBindings : 1;
@@ -163,12 +182,13 @@ private:
private:
/// TranslateInputArgs - Create a new derived argument list from the input
/// arguments, after applying the standard argument translations.
- DerivedArgList *TranslateInputArgs(const InputArgList &Args) const;
+ llvm::opt::DerivedArgList *
+ TranslateInputArgs(const llvm::opt::InputArgList &Args) const;
// getFinalPhase - Determine which compilation mode we are in and record
// which option we used to determine the final phase.
- phases::ID getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg = 0)
- const;
+ phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
+ llvm::opt::Arg **FinalPhaseArg = 0) const;
public:
Driver(StringRef _ClangExecutable,
@@ -183,8 +203,7 @@ public:
/// Name to use when invoking gcc/g++.
const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }
-
- const OptTable &getOpts() const { return *Opts; }
+ const llvm::opt::OptTable &getOpts() const { return *Opts; }
const DiagnosticsEngine &getDiags() const { return Diags; }
@@ -226,9 +245,12 @@ public:
/// @name Driver Steps
/// @{
+ /// ParseDriverMode - Look for and handle the driver mode option in Args.
+ void ParseDriverMode(ArrayRef<const char *> Args);
+
/// ParseArgStrings - Parse the given list of strings into an
/// ArgList.
- InputArgList *ParseArgStrings(ArrayRef<const char *> Args);
+ llvm::opt::InputArgList *ParseArgStrings(ArrayRef<const char *> Args);
/// BuildInputs - Construct the list of inputs and their types from
/// the given arguments.
@@ -237,7 +259,7 @@ public:
/// \param Args - The input arguments.
/// \param Inputs - The list to store the resulting compilation
/// inputs onto.
- void BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
+ void BuildInputs(const ToolChain &TC, const llvm::opt::DerivedArgList &Args,
InputList &Inputs) const;
/// BuildActions - Construct the list of actions to perform for the
@@ -246,7 +268,7 @@ public:
/// \param TC - The default host tool chain.
/// \param Args - The input arguments.
/// \param Actions - The list to store the resulting actions onto.
- void BuildActions(const ToolChain &TC, const DerivedArgList &Args,
+ void BuildActions(const ToolChain &TC, llvm::opt::DerivedArgList &Args,
const InputList &Inputs, ActionList &Actions) const;
/// BuildUniversalActions - Construct the list of actions to perform
@@ -255,7 +277,8 @@ public:
/// \param TC - The default host tool chain.
/// \param Args - The input arguments.
/// \param Actions - The list to store the resulting actions onto.
- void BuildUniversalActions(const ToolChain &TC, const DerivedArgList &Args,
+ void BuildUniversalActions(const ToolChain &TC,
+ llvm::opt::DerivedArgList &Args,
const InputList &BAInputs,
ActionList &Actions) const;
@@ -292,9 +315,6 @@ public:
/// \param ShowHidden - Show hidden options.
void PrintHelp(bool ShowHidden) const;
- /// PrintOptions - Print the list of arguments.
- void PrintOptions(const ArgList &Args) const;
-
/// PrintVersion - Print the driver version.
void PrintVersion(const Compilation &C, raw_ostream &OS) const;
@@ -324,10 +344,9 @@ public:
/// ConstructAction - Construct the appropriate action to do for
/// \p Phase on the \p Input, taking in to account arguments
/// like -fsyntax-only or --analyze.
- Action *ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+ Action *ConstructPhaseAction(const llvm::opt::ArgList &Args, phases::ID Phase,
Action *Input) const;
-
/// BuildJobsForAction - Construct the jobs to perform for the
/// action \p A.
void BuildJobsForAction(Compilation &C,
@@ -367,18 +386,22 @@ public:
/// handle this action.
bool ShouldUseClangCompiler(const JobAction &JA) const;
- bool IsUsingLTO(const ArgList &Args) const;
+ bool IsUsingLTO(const llvm::opt::ArgList &Args) const;
private:
/// \brief Retrieves a ToolChain for a particular target triple.
///
/// Will cache ToolChains for the life of the driver object, and create them
/// on-demand.
- const ToolChain &getToolChain(const ArgList &Args,
+ const ToolChain &getToolChain(const llvm::opt::ArgList &Args,
StringRef DarwinArchName = "") const;
/// @}
+ /// \brief Get bitmasks for which option flags to include and exclude based on
+ /// the driver mode.
+ std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks() const;
+
public:
/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
/// return the grouped values as integers. Numbers which are not
diff --git a/include/clang/Driver/DriverDiagnostic.h b/include/clang/Driver/DriverDiagnostic.h
index ea7b52f9cb72..f3c33aeccb42 100644
--- a/include/clang/Driver/DriverDiagnostic.h
+++ b/include/clang/Driver/DriverDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
#define DRIVERSTART
#include "clang/Basic/DiagnosticDriverKinds.inc"
#undef DIAG
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index 045b5d89ded3..1dd49a792356 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -11,18 +11,28 @@
#define CLANG_DRIVER_JOB_H_
#include "clang/Basic/LLVM.h"
-#include "clang/Driver/Util.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Option/Option.h"
+
+namespace llvm {
+ class raw_ostream;
+}
namespace clang {
namespace driver {
+class Action;
class Command;
class Tool;
+// Re-export this as clang::driver::ArgStringList.
+using llvm::opt::ArgStringList;
+
class Job {
public:
enum JobClass {
CommandClass,
+ FallbackCommandClass,
JobListClass
};
@@ -36,16 +46,19 @@ public:
JobClass getKind() const { return Kind; }
- /// addCommand - Append a command to the current job, which must be
- /// either a piped job or a job list.
- void addCommand(Command *C);
+ /// Print - Print this Job in -### format.
+ ///
+ /// \param OS - The stream to print on.
+ /// \param Terminator - A string to print at the end of the line.
+ /// \param Quote - Should separate arguments be quoted.
+ /// \param CrashReport - Whether to print for inclusion in a crash report.
+ virtual void Print(llvm::raw_ostream &OS, const char *Terminator,
+ bool Quote, bool CrashReport = false) const = 0;
};
- /// Command - An executable path/name and argument vector to
- /// execute.
+/// Command - An executable path/name and argument vector to
+/// execute.
class Command : public Job {
- virtual void anchor();
-
/// Source - The action which caused the creation of this job.
const Action &Source;
@@ -57,11 +70,17 @@ class Command : public Job {
/// The list of program arguments (not including the implicit first
/// argument, which will be the executable).
- ArgStringList Arguments;
+ llvm::opt::ArgStringList Arguments;
public:
Command(const Action &_Source, const Tool &_Creator, const char *_Executable,
- const ArgStringList &_Arguments);
+ const llvm::opt::ArgStringList &_Arguments);
+
+ virtual void Print(llvm::raw_ostream &OS, const char *Terminator,
+ bool Quote, bool CrashReport = false) const;
+
+ virtual int Execute(const StringRef **Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const;
/// getSource - Return the Action which caused the creation of this job.
const Action &getSource() const { return Source; }
@@ -69,16 +88,37 @@ public:
/// getCreator - Return the Tool which caused the creation of this job.
const Tool &getCreator() const { return Creator; }
- const char *getExecutable() const { return Executable; }
+ const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
- const ArgStringList &getArguments() const { return Arguments; }
+ static bool classof(const Job *J) {
+ return J->getKind() == CommandClass ||
+ J->getKind() == FallbackCommandClass;
+ }
+};
+
+/// Like Command, but with a fallback which is executed in case
+/// the primary command crashes.
+class FallbackCommand : public Command {
+public:
+ FallbackCommand(const Action &Source_, const Tool &Creator_,
+ const char *Executable_, const ArgStringList &Arguments_,
+ Command *Fallback_);
+
+ virtual void Print(llvm::raw_ostream &OS, const char *Terminator,
+ bool Quote, bool CrashReport = false) const;
+
+ virtual int Execute(const StringRef **Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const;
static bool classof(const Job *J) {
- return J->getKind() == CommandClass;
+ return J->getKind() == FallbackCommandClass;
}
+
+private:
+ OwningPtr<Command> Fallback;
};
- /// JobList - A sequence of jobs to perform.
+/// JobList - A sequence of jobs to perform.
class JobList : public Job {
public:
typedef SmallVector<Job*, 4> list_type;
@@ -93,6 +133,9 @@ public:
JobList();
virtual ~JobList();
+ virtual void Print(llvm::raw_ostream &OS, const char *Terminator,
+ bool Quote, bool CrashReport = false) const;
+
/// Add a job to the list (taking ownership).
void addJob(Job *J) { Jobs.push_back(J); }
diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile
index 7d066c77b377..77cf6ff8d938 100644
--- a/include/clang/Driver/Makefile
+++ b/include/clang/Driver/Makefile
@@ -5,10 +5,10 @@ TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
-$(ObjDir)/Options.inc.tmp : Options.td CC1Options.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir
+$(ObjDir)/Options.inc.tmp : Options.td CC1Options.td CLCompatOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang Driver Option tables with tblgen"
- $(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-$(ObjDir)/CC1AsOptions.inc.tmp : CC1AsOptions.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir
+$(ObjDir)/CC1AsOptions.inc.tmp : CC1AsOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang CC1 Assembler Option tables with tblgen"
- $(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td
deleted file mode 100644
index d16a2a779324..000000000000
--- a/include/clang/Driver/OptParser.td
+++ /dev/null
@@ -1,152 +0,0 @@
-//===--- OptParser.td - Common Option Parsing Interfaces ------------------===//
-//
-// 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 common interfaces used by the option parsing TableGen
-// backend.
-//
-//===----------------------------------------------------------------------===//
-
-// Define the kinds of options.
-
-class OptionKind<string name, int predecence = 0, bit sentinel = 0> {
- string Name = name;
- // The kind precedence, kinds with lower precedence are matched first.
- int Precedence = predecence;
- // Indicate a sentinel option.
- bit Sentinel = sentinel;
-}
-
-// An option group.
-def KIND_GROUP : OptionKind<"Group">;
-// The input option kind.
-def KIND_INPUT : OptionKind<"Input", 1, 1>;
-// The unknown option kind.
-def KIND_UNKNOWN : OptionKind<"Unknown", 2, 1>;
-// A flag with no values.
-def KIND_FLAG : OptionKind<"Flag">;
-// An option which prefixes its (single) value.
-def KIND_JOINED : OptionKind<"Joined", 1>;
-// An option which is followed by its value.
-def KIND_SEPARATE : OptionKind<"Separate">;
-// An option followed by its values, which are separated by commas.
-def KIND_COMMAJOINED : OptionKind<"CommaJoined">;
-// An option which is which takes multiple (separate) arguments.
-def KIND_MULTIARG : OptionKind<"MultiArg">;
-// An option which is either joined to its (non-empty) value, or followed by its
-// value.
-def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">;
-// An option which is both joined to its (first) value, and followed by its
-// (second) value.
-def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">;
-
-// Define the option flags.
-
-class OptionFlag {}
-
-// DriverOption - The option is a "driver" option, and should not be forwarded
-// to gcc.
-def DriverOption : OptionFlag;
-
-// LinkerInput - The option is a linker input.
-def LinkerInput : OptionFlag;
-
-// NoArgumentUnused - Don't report argument unused warnings for this option; this
-// is useful for options like -static or -dynamic which a user may always end up
-// passing, even if the platform defaults to (or only supports) that option.
-def NoArgumentUnused : OptionFlag;
-
-// RenderAsInput - The option should not render the name when rendered as an
-// input (i.e., the option is rendered as values).
-def RenderAsInput : OptionFlag;
-
-// RenderJoined - The option should be rendered joined, even if separate (only
-// sensible on single value separate options).
-def RenderJoined : OptionFlag;
-
-// RenderSeparate - The option should be rendered separately, even if joined
-// (only sensible on joined options).
-def RenderSeparate : OptionFlag;
-
-// Unsupported - The option is unsupported, and the driver will reject command
-// lines that use it.
-def Unsupported : OptionFlag;
-
-// HelpHidden - The option should not be displayed in --help, even if it has
-// help text. Clients *can* use this in conjunction with the OptTable::PrintHelp
-// arguments to implement hidden help groups.
-def HelpHidden : OptionFlag;
-
-// NoForward - The option should not be implicitly forwarded to other tools.
-def NoForward : OptionFlag;
-
-// CC1Option - This option should be accepted by clang -cc1.
-def CC1Option : OptionFlag;
-
-// NoDriverOption - This option should not be accepted by the driver.
-def NoDriverOption : OptionFlag;
-
-// Define the option group class.
-
-class OptionGroup<string name> {
- string EnumName = ?; // Uses the def name if undefined.
- string Name = name;
- string HelpText = ?;
- OptionGroup Group = ?;
-}
-
-// Define the option class.
-
-class Option<list<string> prefixes, string name, OptionKind kind> {
- string EnumName = ?; // Uses the def name if undefined.
- list<string> Prefixes = prefixes;
- string Name = name;
- OptionKind Kind = kind;
- // Used by MultiArg option kind.
- int NumArgs = 0;
- string HelpText = ?;
- string MetaVarName = ?;
- list<OptionFlag> Flags = [];
- OptionGroup Group = ?;
- Option Alias = ?;
-}
-
-// Helpers for defining options.
-
-class Flag<list<string> prefixes, string name>
- : Option<prefixes, name, KIND_FLAG>;
-class Joined<list<string> prefixes, string name>
- : Option<prefixes, name, KIND_JOINED>;
-class Separate<list<string> prefixes, string name>
- : Option<prefixes, name, KIND_SEPARATE>;
-class CommaJoined<list<string> prefixes, string name>
- : Option<prefixes, name, KIND_COMMAJOINED>;
-class MultiArg<list<string> prefixes, string name, int numargs>
- : Option<prefixes, name, KIND_MULTIARG> {
- int NumArgs = numargs;
-}
-class JoinedOrSeparate<list<string> prefixes, string name>
- : Option<prefixes, name, KIND_JOINED_OR_SEPARATE>;
-class JoinedAndSeparate<list<string> prefixes, string name>
- : Option<prefixes, name, KIND_JOINED_AND_SEPARATE>;
-
-// Mix-ins for adding optional attributes.
-
-class Alias<Option alias> { Option Alias = alias; }
-class EnumName<string name> { string EnumName = name; }
-class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
-class Group<OptionGroup group> { OptionGroup Group = group; }
-class HelpText<string text> { string HelpText = text; }
-class MetaVarName<string name> { string MetaVarName = name; }
-
-// Predefined options.
-
-// FIXME: Have generator validate that these appear in correct position (and
-// aren't duplicated).
-def INPUT : Option<[], "<input>", KIND_INPUT>, Flags<[DriverOption,CC1Option]>;
-def UNKNOWN : Option<[], "<unknown>", KIND_UNKNOWN>;
diff --git a/include/clang/Driver/OptSpecifier.h b/include/clang/Driver/OptSpecifier.h
deleted file mode 100644
index e683ef325b8e..000000000000
--- a/include/clang/Driver/OptSpecifier.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===--- OptSpecifier.h - Option Specifiers ---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_OPTSPECIFIER_H
-#define CLANG_DRIVER_OPTSPECIFIER_H
-
-#include "llvm/Support/Compiler.h"
-
-namespace clang {
-namespace driver {
- class Option;
-
- /// OptSpecifier - Wrapper class for abstracting references to option IDs.
- class OptSpecifier {
- unsigned ID;
-
- private:
- explicit OptSpecifier(bool) LLVM_DELETED_FUNCTION;
-
- public:
- OptSpecifier() : ID(0) {}
- /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {}
- /*implicit*/ OptSpecifier(const Option *Opt);
-
- bool isValid() const { return ID != 0; }
-
- unsigned getID() const { return ID; }
-
- bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); }
- bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); }
- };
-}
-}
-
-#endif
diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h
deleted file mode 100644
index 53d83a0f38aa..000000000000
--- a/include/clang/Driver/OptTable.h
+++ /dev/null
@@ -1,161 +0,0 @@
-//===--- OptTable.h - Option Table ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_OPTTABLE_H
-#define CLANG_DRIVER_OPTTABLE_H
-
-#include "clang/Basic/LLVM.h"
-#include "clang/Driver/OptSpecifier.h"
-#include "llvm/ADT/StringSet.h"
-
-namespace clang {
-namespace driver {
- class Arg;
- class ArgList;
- class InputArgList;
- class Option;
-
- /// \brief Provide access to the Option info table.
- ///
- /// The OptTable class provides a layer of indirection which allows Option
- /// instance to be created lazily. In the common case, only a few options will
- /// be needed at runtime; the OptTable class maintains enough information to
- /// parse command lines without instantiating Options, while letting other
- /// parts of the driver still use Option instances where convenient.
- class OptTable {
- public:
- /// \brief Entry for a single option instance in the option data table.
- struct Info {
- /// A null terminated array of prefix strings to apply to name while
- /// matching.
- const char *const *Prefixes;
- const char *Name;
- const char *HelpText;
- const char *MetaVar;
- unsigned ID;
- unsigned char Kind;
- unsigned char Param;
- unsigned short Flags;
- unsigned short GroupID;
- unsigned short AliasID;
- };
-
- private:
- /// \brief The static option information table.
- const Info *OptionInfos;
- unsigned NumOptionInfos;
-
- unsigned TheInputOptionID;
- unsigned TheUnknownOptionID;
-
- /// The index of the first option which can be parsed (i.e., is not a
- /// special option like 'input' or 'unknown', and is not an option group).
- unsigned FirstSearchableIndex;
-
- /// The union of all option prefixes. If an argument does not begin with
- /// one of these, it is an input.
- llvm::StringSet<> PrefixesUnion;
- std::string PrefixChars;
-
- private:
- const Info &getInfo(OptSpecifier Opt) const {
- unsigned id = Opt.getID();
- assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID.");
- return OptionInfos[id - 1];
- }
-
- protected:
- OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos);
- public:
- ~OptTable();
-
- /// \brief Return the total number of option classes.
- unsigned getNumOptions() const { return NumOptionInfos; }
-
- /// \brief Get the given Opt's Option instance, lazily creating it
- /// if necessary.
- ///
- /// \return The option, or null for the INVALID option id.
- const Option getOption(OptSpecifier Opt) const;
-
- /// \brief Lookup the name of the given option.
- const char *getOptionName(OptSpecifier id) const {
- return getInfo(id).Name;
- }
-
- /// \brief Get the kind of the given option.
- unsigned getOptionKind(OptSpecifier id) const {
- return getInfo(id).Kind;
- }
-
- /// \brief Get the group id for the given option.
- unsigned getOptionGroupID(OptSpecifier id) const {
- return getInfo(id).GroupID;
- }
-
- /// \brief Get the help text to use to describe this option.
- const char *getOptionHelpText(OptSpecifier id) const {
- return getInfo(id).HelpText;
- }
-
- /// \brief Get the meta-variable name to use when describing
- /// this options values in the help text.
- const char *getOptionMetaVar(OptSpecifier id) const {
- return getInfo(id).MetaVar;
- }
-
- /// \brief Parse a single argument; returning the new argument and
- /// updating Index.
- ///
- /// \param [in,out] Index - The current parsing position in the argument
- /// string list; on return this will be the index of the next argument
- /// string to parse.
- ///
- /// \return The parsed argument, or 0 if the argument is missing values
- /// (in which case Index still points at the conceptual next argument string
- /// to parse).
- Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const;
-
- /// \brief Parse an list of arguments into an InputArgList.
- ///
- /// The resulting InputArgList will reference the strings in [\p ArgBegin,
- /// \p ArgEnd), and their lifetime should extend past that of the returned
- /// InputArgList.
- ///
- /// The only error that can occur in this routine is if an argument is
- /// missing values; in this case \p MissingArgCount will be non-zero.
- ///
- /// \param ArgBegin - The beginning of the argument vector.
- /// \param ArgEnd - The end of the argument vector.
- /// \param MissingArgIndex - On error, the index of the option which could
- /// not be parsed.
- /// \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* const *ArgBegin,
- const char* const *ArgEnd,
- unsigned &MissingArgIndex,
- unsigned &MissingArgCount) const;
-
- /// \brief Render the help text for an option table.
- ///
- /// \param OS - The stream to write the help text to.
- /// \param Name - The name to use in the usage line.
- /// \param Title - The title to use in the usage line.
- /// \param FlagsToInclude - If non-zero, only include options with any
- /// of these flags set.
- /// \param FlagsToExclude - Exclude options with any of these flags set.
- void PrintHelp(raw_ostream &OS, const char *Name,
- const char *Title, unsigned short FlagsToInclude = 0,
- unsigned short FlagsToExclude = 0) const;
- };
-}
-}
-
-#endif
diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h
deleted file mode 100644
index 764934fdf810..000000000000
--- a/include/clang/Driver/Option.h
+++ /dev/null
@@ -1,204 +0,0 @@
-//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_OPTION_H_
-#define CLANG_DRIVER_OPTION_H_
-
-#include "clang/Basic/LLVM.h"
-#include "clang/Driver/OptTable.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/ErrorHandling.h"
-
-namespace clang {
-namespace driver {
- class Arg;
- class ArgList;
-
-namespace options {
- /// Base flags for all options. Custom flags may be added after.
- enum DriverFlag {
- HelpHidden = (1 << 0),
- RenderAsInput = (1 << 1),
- RenderJoined = (1 << 2),
- RenderSeparate = (1 << 3)
- };
-
- /// Flags specifically for clang options.
- enum ClangFlags {
- DriverOption = (1 << 4),
- LinkerInput = (1 << 5),
- NoArgumentUnused = (1 << 6),
- NoForward = (1 << 7),
- Unsupported = (1 << 8),
- CC1Option = (1 << 9),
- NoDriverOption = (1 << 10)
- };
-}
-
- /// Option - Abstract representation for a single form of driver
- /// argument.
- ///
- /// An Option class represents a form of option that the driver
- /// takes, for example how many arguments the option has and how
- /// they can be provided. Individual option instances store
- /// additional information about what group the option is a member
- /// of (if any), if the option is an alias, and a number of
- /// flags. At runtime the driver parses the command line into
- /// concrete Arg instances, each of which corresponds to a
- /// particular Option instance.
- class Option {
- public:
- enum OptionClass {
- GroupClass = 0,
- InputClass,
- UnknownClass,
- FlagClass,
- JoinedClass,
- SeparateClass,
- CommaJoinedClass,
- MultiArgClass,
- JoinedOrSeparateClass,
- JoinedAndSeparateClass
- };
-
- enum RenderStyleKind {
- RenderCommaJoinedStyle,
- RenderJoinedStyle,
- RenderSeparateStyle,
- RenderValuesStyle
- };
-
- protected:
- const OptTable::Info *Info;
- const OptTable *Owner;
-
- public:
- Option(const OptTable::Info *Info, const OptTable *Owner);
- ~Option();
-
- bool isValid() const {
- return Info != 0;
- }
-
- unsigned getID() const {
- assert(Info && "Must have a valid info!");
- return Info->ID;
- }
-
- OptionClass getKind() const {
- assert(Info && "Must have a valid info!");
- return OptionClass(Info->Kind);
- }
-
- /// \brief Get the name of this option without any prefix.
- StringRef getName() const {
- assert(Info && "Must have a valid info!");
- return Info->Name;
- }
-
- const Option getGroup() const {
- assert(Info && "Must have a valid info!");
- assert(Owner && "Must have a valid owner!");
- return Owner->getOption(Info->GroupID);
- }
-
- const Option getAlias() const {
- assert(Info && "Must have a valid info!");
- assert(Owner && "Must have a valid owner!");
- return Owner->getOption(Info->AliasID);
- }
-
- /// \brief Get the default prefix for this option.
- StringRef getPrefix() const {
- const char *Prefix = *Info->Prefixes;
- return Prefix ? Prefix : StringRef();
- }
-
- /// \brief Get the name of this option with the default prefix.
- std::string getPrefixedName() const {
- std::string Ret = getPrefix();
- Ret += getName();
- return Ret;
- }
-
- unsigned getNumArgs() const { return Info->Param; }
-
- bool hasNoOptAsInput() const { return Info->Flags & options::RenderAsInput;}
-
- RenderStyleKind getRenderStyle() const {
- if (Info->Flags & options::RenderJoined)
- return RenderJoinedStyle;
- if (Info->Flags & options::RenderSeparate)
- return RenderSeparateStyle;
- switch (getKind()) {
- case GroupClass:
- case InputClass:
- case UnknownClass:
- return RenderValuesStyle;
- case JoinedClass:
- case JoinedAndSeparateClass:
- return RenderJoinedStyle;
- case CommaJoinedClass:
- return RenderCommaJoinedStyle;
- case FlagClass:
- case SeparateClass:
- case MultiArgClass:
- case JoinedOrSeparateClass:
- return RenderSeparateStyle;
- }
- llvm_unreachable("Unexpected kind!");
- }
-
- /// Test if this option has the flag \a Val.
- bool hasFlag(unsigned Val) const {
- return Info->Flags & Val;
- }
-
- /// getUnaliasedOption - Return the final option this option
- /// aliases (itself, if the option has no alias).
- const Option getUnaliasedOption() const {
- const Option Alias = getAlias();
- if (Alias.isValid()) return Alias.getUnaliasedOption();
- return *this;
- }
-
- /// getRenderName - Return the name to use when rendering this
- /// option.
- StringRef getRenderName() const {
- return getUnaliasedOption().getName();
- }
-
- /// matches - Predicate for whether this option is part of the
- /// given option (which may be a group).
- ///
- /// Note that matches against options which are an alias should never be
- /// done -- aliases do not participate in matching and so such a query will
- /// always be false.
- bool matches(OptSpecifier ID) const;
-
- /// accept - Potentially accept the current argument, returning a
- /// new Arg instance, or 0 if the option does not accept this
- /// argument (or the argument is missing values).
- ///
- /// If the option accepts the current argument, accept() sets
- /// Index to the position where argument parsing should resume
- /// (even if the argument is missing values).
- ///
- /// \parm ArgSize The number of bytes taken up by the matched Option prefix
- /// and name. This is used to determine where joined values
- /// start.
- Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const;
-
- void dump() const;
- };
-
-} // end namespace driver
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h
index 6c114e252d3c..28948be96dec 100644
--- a/include/clang/Driver/Options.h
+++ b/include/clang/Driver/Options.h
@@ -10,24 +10,40 @@
#ifndef CLANG_DRIVER_OPTIONS_H
#define CLANG_DRIVER_OPTIONS_H
+namespace llvm {
+namespace opt {
+class OptTable;
+}
+}
+
namespace clang {
namespace driver {
- class OptTable;
namespace options {
- enum ID {
+/// Flags specifically for clang options. Must not overlap with
+/// llvm::opt::DriverFlag.
+enum ClangFlags {
+ DriverOption = (1 << 4),
+ LinkerInput = (1 << 5),
+ NoArgumentUnused = (1 << 6),
+ Unsupported = (1 << 7),
+ CoreOption = (1 << 8),
+ CLOption = (1 << 9),
+ CC1Option = (1 << 10),
+ NoDriverOption = (1 << 11)
+};
+
+enum ID {
OPT_INVALID = 0, // This is not an option ID.
-#define PREFIX(NAME, VALUE)
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR) OPT_##ID,
#include "clang/Driver/Options.inc"
LastOption
#undef OPTION
-#undef PREFIX
};
}
- OptTable *createDriverOptTable();
+llvm::opt::OptTable *createDriverOptTable();
}
}
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 3a5358a7e355..9e7dc78d63cf 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -12,23 +12,55 @@
//===----------------------------------------------------------------------===//
// Include the common option parsing interfaces.
-include "OptParser.td"
+include "llvm/Option/OptParser.td"
+
+/////////
+// Flags
+
+// DriverOption - The option is a "driver" option, and should not be forwarded
+// to other tools.
+def DriverOption : OptionFlag;
+
+// LinkerInput - The option is a linker input.
+def LinkerInput : OptionFlag;
+
+// NoArgumentUnused - Don't report argument unused warnings for this option; this
+// is useful for options like -static or -dynamic which a user may always end up
+// passing, even if the platform defaults to (or only supports) that option.
+def NoArgumentUnused : OptionFlag;
+
+// Unsupported - The option is unsupported, and the driver will reject command
+// lines that use it.
+def Unsupported : OptionFlag;
+
+// CoreOption - This is considered a "core" Clang option, available in both
+// clang and clang-cl modes.
+def CoreOption : OptionFlag;
+
+// CLOption - This is a cl.exe compatibility option. Options with this flag
+// are made available when the driver is running in CL compatibility mode.
+def CLOption : OptionFlag;
+
+// CC1Option - This option should be accepted by clang -cc1.
+def CC1Option : OptionFlag;
+
+// NoDriverOption - This option should not be accepted by the driver.
+def NoDriverOption : OptionFlag;
/////////
// Groups
-// Meta-group which defines
+// Meta-group for options which are only used for compilation,
+// and not linking etc.
def CompileOnly_Group : OptionGroup<"<CompileOnly group>">;
+
def Action_Group : OptionGroup<"<action group>">;
def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>;
-def L_Group : OptionGroup<"<L group>">, Group<CompileOnly_Group>;
def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>;
def T_Group : OptionGroup<"<T group>">;
def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>;
def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>;
-def X_Group : OptionGroup<"<X group>">;
-def a_Group : OptionGroup<"<a group>">;
def d_Group : OptionGroup<"<d group>">;
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>;
@@ -39,10 +71,10 @@ def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>;
def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>;
def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>;
def m_hexagon_Features_Group : OptionGroup<"<m hexagon features group>">, Group<m_Group>;
+def m_arm_Features_Group : OptionGroup<"<m arm features group>">, Group<m_Group>;
+def m_ppc_Features_Group : OptionGroup<"<m ppc features group>">, Group<m_Group>;
def opencl_Group : OptionGroup<"<opencl group>">;
def u_Group : OptionGroup<"<u group>">;
-def mips_CPUs_Group : OptionGroup<"<MIPS CPU aliases group>">,
- Group<CompileOnly_Group>;
def pedantic_Group : OptionGroup<"<pedantic group>">,
Group<CompileOnly_Group>;
@@ -69,7 +101,9 @@ def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">,
// substitutions:
// _ => __
// - => _
+// / => _SLASH
// # => _HASH
+// ? => _QUESTION
// , => _COMMA
// = => _EQ
// C++ => CXX
@@ -77,45 +111,40 @@ def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">,
// Developer Driver Options
-def ccc_Group : OptionGroup<"<clang internal options>">;
-def ccc_driver_Group : OptionGroup<"<clang driver internal options>">,
- Group<ccc_Group>, HelpText<"DRIVER OPTIONS">;
-def ccc_debug_Group : OptionGroup<"<clang debug/development internal options>">,
- Group<ccc_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">;
-
-class CCCDriverOpt : Group<ccc_driver_Group>, Flags<[DriverOption, HelpHidden]>;
-def ccc_cxx : Flag<["-"], "ccc-cxx">, CCCDriverOpt,
- HelpText<"Act as a C++ driver">;
-def ccc_echo : Flag<["-"], "ccc-echo">, CCCDriverOpt,
- HelpText<"Echo commands before running them">;
-def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, CCCDriverOpt,
+def internal_Group : OptionGroup<"<clang internal options>">;
+def internal_driver_Group : OptionGroup<"<clang driver internal options>">,
+ Group<internal_Group>, HelpText<"DRIVER OPTIONS">;
+def internal_debug_Group :
+ OptionGroup<"<clang debug/development internal options>">,
+ Group<internal_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">;
+
+class InternalDriverOpt : Group<internal_driver_Group>,
+ Flags<[DriverOption, HelpHidden]>;
+def driver_mode : Joined<["--"], "driver-mode=">, Group<internal_driver_Group>,
+ Flags<[CoreOption, DriverOption, HelpHidden]>,
+ HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">;
+def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, InternalDriverOpt,
HelpText<"Name for native GCC compiler">,
MetaVarName<"<gcc-path>">;
-def ccc_clang_archs : Separate<["-"], "ccc-clang-archs">, CCCDriverOpt,
- HelpText<"Comma separate list of architectures to use the clang compiler for">,
- MetaVarName<"<arch-list>">;
-def ccc_pch_is_pch : Flag<["-"], "ccc-pch-is-pch">, CCCDriverOpt,
+def ccc_pch_is_pch : Flag<["-"], "ccc-pch-is-pch">, InternalDriverOpt,
HelpText<"Use lazy PCH for precompiled headers">;
-def ccc_pch_is_pth : Flag<["-"], "ccc-pch-is-pth">, CCCDriverOpt,
+def ccc_pch_is_pth : Flag<["-"], "ccc-pch-is-pth">, InternalDriverOpt,
HelpText<"Use pretokenized headers for precompiled headers">;
-class CCCDebugOpt : Group<ccc_debug_Group>, Flags<[DriverOption, HelpHidden]>;
-def ccc_install_dir : Separate<["-"], "ccc-install-dir">, CCCDebugOpt,
+class InternalDebugOpt : Group<internal_debug_Group>,
+ Flags<[DriverOption, HelpHidden]>;
+def ccc_install_dir : Separate<["-"], "ccc-install-dir">, InternalDebugOpt,
HelpText<"Simulate installation in the given directory">;
-def ccc_print_options : Flag<["-"], "ccc-print-options">, CCCDebugOpt,
- HelpText<"Dump parsed command line arguments">;
-def ccc_print_phases : Flag<["-"], "ccc-print-phases">, CCCDebugOpt,
+def ccc_print_phases : Flag<["-"], "ccc-print-phases">, InternalDebugOpt,
HelpText<"Dump list of actions to perform">;
-def ccc_print_bindings : Flag<["-"], "ccc-print-bindings">, CCCDebugOpt,
+def ccc_print_bindings : Flag<["-"], "ccc-print-bindings">, InternalDebugOpt,
HelpText<"Show bindings of tools to actions">;
-def ccc_arcmt_check : Flag<["-"], "ccc-arcmt-check">, CCCDriverOpt,
+def ccc_arcmt_check : Flag<["-"], "ccc-arcmt-check">, InternalDriverOpt,
HelpText<"Check for ARC migration issues that need manual handling">;
-def ccc_arcmt_modify : Flag<["-"], "ccc-arcmt-modify">, CCCDriverOpt,
+def ccc_arcmt_modify : Flag<["-"], "ccc-arcmt-modify">, InternalDriverOpt,
HelpText<"Apply modifications to files to conform to ARC">;
-def ccc_arrmt_check : Flag<["-"], "ccc-arrmt-check">, Alias<ccc_arcmt_check>;
-def ccc_arrmt_modify : Flag<["-"], "ccc-arrmt-modify">, Alias<ccc_arcmt_modify>;
-def ccc_arcmt_migrate : Separate<["-"], "ccc-arcmt-migrate">, CCCDriverOpt,
+def ccc_arcmt_migrate : Separate<["-"], "ccc-arcmt-migrate">, InternalDriverOpt,
HelpText<"Apply modifications and produces temporary files that conform to ARC">;
def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output">,
HelpText<"Output path for the plist report">, Flags<[CC1Option]>;
@@ -125,25 +154,49 @@ def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">,
def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>,
HelpText<"Run the migrator">;
-def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">, CCCDriverOpt,
+def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">,
+ InternalDriverOpt,
HelpText<"Apply modifications and produces temporary files to migrate to "
"modern ObjC syntax">;
def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC literals">;
def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC subscripting">;
+def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC property">;
+def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC">;
+def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC readonly property">;
+def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC readwrite property">;
+def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to property and method annotations">;
+def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to infer instancetype for method result type">;
+def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">;
+def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to add protocol conformance on classes">;
+def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
+ HelpText<"Make migration to 'atomic' properties">;
+def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">;
+def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">;
+def objcmt_white_list_dir_path: Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>,
+ HelpText<"Only modify files with a filename contained in the provided directory path">;
// Make sure all other -ccc- options are rejected.
-def ccc_ : Joined<["-"], "ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
+def ccc_ : Joined<["-"], "ccc-">, Group<internal_Group>, Flags<[Unsupported]>;
// Standard Options
-def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption]>,
+def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption, CoreOption]>,
HelpText<"Print the commands to run for this compilation">;
-// The '--' option is here for the sake of compatibility with gcc, but is
-// being ignored by the driver.
-def _DASH_DASH : Flag<["--"], "">, Flags<[DriverOption]>;
-def A : JoinedOrSeparate<["-"], "A">;
+def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>,
+ Flags<[DriverOption, CoreOption]>;
+def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>;
def B : JoinedOrSeparate<["-"], "B">;
def CC : Flag<["-"], "CC">, Flags<[CC1Option]>;
def C : Flag<["-"], "C">, Flags<[CC1Option]>;
@@ -174,18 +227,19 @@ def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Specify target for dependency">;
def Mach : Flag<["-"], "Mach">;
def M : Flag<["-"], "M">, Group<M_Group>;
-def O0 : Joined<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>;
-def O4 : Joined<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>;
+def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>;
+def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>;
def ObjCXX : Flag<["-"], "ObjC++">, Flags<[DriverOption]>,
HelpText<"Treat source input files as Objective-C++ inputs">;
def ObjC : Flag<["-"], "ObjC">, Flags<[DriverOption]>,
HelpText<"Treat source input files as Objective-C inputs">;
def O : Joined<["-"], "O">, Group<O_Group>, Flags<[CC1Option]>;
+def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["2"]>;
def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>;
def P : Flag<["-"], "P">, Flags<[CC1Option]>,
HelpText<"Disable linemarker output in -E mode">;
def Qn : Flag<["-"], "Qn">;
-def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption]>,
+def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>,
HelpText<"Don't emit warning for unused driver arguments">;
def Q : Flag<["-"], "Q">;
def R : Flag<["-"], "R">;
@@ -214,9 +268,7 @@ def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Gr
def Wp_COMMA : CommaJoined<["-"], "Wp,">,
HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">,
MetaVarName<"<arg>">;
-def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>, Flags<[CC1Option]>;
-def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>, Flags<[CC1Option]>;
-def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option]>,
+def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option, CoreOption]>,
MetaVarName<"<warning>">, HelpText<"Enable the specified warning">;
def Xanalyzer : Separate<["-"], "Xanalyzer">,
HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">;
@@ -225,7 +277,7 @@ def Xassembler : Separate<["-"], "Xassembler">,
HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">;
def Xclang : Separate<["-"], "Xclang">,
HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">,
- Flags<[NoForward]>;
+ Flags<[DriverOption, CoreOption]>;
def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">;
def Xpreprocessor : Separate<["-"], "Xpreprocessor">,
@@ -236,11 +288,11 @@ def Z_Flag : Flag<["-"], "Z">;
def Z_Joined : Joined<["-"], "Z">;
def all__load : Flag<["-"], "all_load">;
def allowable__client : Separate<["-"], "allowable_client">;
-def ansi : Flag<["-", "--"], "ansi">, Group<a_Group>;
+def ansi : Flag<["-", "--"], "ansi">;
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 a : Joined<["-"], "a">;
def bind__at__load : Flag<["-"], "bind_at_load">;
def bundle__loader : Separate<["-"], "bundle_loader">;
def bundle : Flag<["-"], "bundle">;
@@ -290,9 +342,6 @@ 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 faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Enable AltiVec vector initializer syntax">;
-def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[CC1Option]>;
def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use Apple's kernel extensions ABI">;
def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
@@ -313,9 +362,14 @@ def fast : Flag<["-"], "fast">, Group<f_Group>;
def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group<f_Group>;
def fautolink : Flag <["-"], "fautolink">, Group<f_Group>;
-def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>, Flags<[NoForward, CC1Option]>,
+def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
HelpText<"Disable generation of linker directives for automatic library linking">;
+def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">,
+ Group<f_Group>, Flags<[DriverOption, CC1Option]>,
+ HelpText<"Enable sample-based profile guided optimizations">;
+
def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable the 'blocks' language feature">;
def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group<f_Group>;
@@ -325,8 +379,6 @@ def fbounds_checking : Flag<["-"], "fbounds-checking">, Group<f_Group>,
HelpText<"Enable run-time bounds checks">;
def fbounds_checking_EQ : Joined<["-"], "fbounds-checking=">, Flags<[CC1Option]>,
Group<f_Group>;
-def fbuiltin_strcat : Flag<["-"], "fbuiltin-strcat">, Group<f_Group>;
-def fbuiltin_strcpy : Flag<["-"], "fbuiltin-strcpy">, Group<f_Group>;
def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>;
def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>;
def fcatch_undefined_behavior : Flag<["-"], "fcatch-undefined-behavior">, Group<f_Group>;
@@ -335,6 +387,8 @@ def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>, Flag
HelpText<"Use colors in diagnostics">;
def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group<f_Group>;
def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<f_Group>;
+def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use ANSI escape codes for diagnostics">;
def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Treat each comma separated argument in <arg> as a documentation comment block command">,
MetaVarName<"<arg>">;
@@ -344,13 +398,15 @@ def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>;
def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>;
def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group<f_Group>;
def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
+def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">,
Group<f_Group>;
def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>;
def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>,
HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
-def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>, Flags<[NoForward]>;
+def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>,
+ Flags<[DriverOption]>;
def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>;
def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group<f_Group>;
def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group<f_clang_Group>;
@@ -387,6 +443,10 @@ def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>;
def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>;
def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable support for exception handling">;
+def fexpensive_optimizations : Flag<["-"], "fexpensive-optimizations">,
+ Group<clang_ignored_f_Group>;
+def fno_expensive_optimizations : Flag<["-"], "fno-expensive-optimizations">,
+ Group<clang_ignored_f_Group>;
def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group<f_Group>;
def fextended_identifiers : Flag<["-"], "fextended-identifiers">,
Group<clang_ignored_f_Group>;
@@ -405,7 +465,7 @@ def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group<f_Group>;
def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>;
def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>;
def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
- Flags<[CC1Option]>, MetaVarName<"<check>">,
+ Flags<[CC1Option, CoreOption]>, MetaVarName<"<check>">,
HelpText<"Enable runtime instrumentation for bug detection: "
"address (memory errors) | thread (race detection) | "
"undefined (miscellaneous undefined behavior)">;
@@ -500,13 +560,13 @@ def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Op
HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable Microsoft compatibility mode">;
-def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[CC1Option]>,
+def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">;
def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group<f_Group>,
HelpText<"Parse templated function definitions at the end of the "
"translation unit ">, Flags<[CC1Option]>;
def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>,
- Flags<[NoForward,CC1Option]>, MetaVarName<"<directory>">,
+ Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
HelpText<"Specify the module cache path">;
def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>,
Flags<[CC1Option]>, MetaVarName<"<seconds>">,
@@ -514,10 +574,23 @@ def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i
def fmodules_prune_after : Joined<["-"], "fmodules-prune-after=">, Group<i_Group>,
Flags<[CC1Option]>, MetaVarName<"<seconds>">,
HelpText<"Specify the interval (in seconds) after which a module file will be considered unused">;
-def fmodules : Flag <["-"], "fmodules">, Group<f_Group>, Flags<[NoForward,CC1Option]>,
+def fmodules : Flag <["-"], "fmodules">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
HelpText<"Enable the 'modules' language feature">;
+def fmodule_maps : Flag <["-"], "fmodule-maps">, Group<f_Group>,
+ Flags<[DriverOption,CC1Option]>,
+ HelpText<"Read module maps to understand the structure of library headers">;
+def fmodule_name : JoinedOrSeparate<["-"], "fmodule-name=">, Group<f_Group>,
+ Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">,
+ HelpText<"Specify the name of the module to build">;
+def fmodule_map_file : JoinedOrSeparate<["-"], "fmodule-map-file=">,
+ Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<file>">,
+ HelpText<"Load this module map file">;
def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Ignore the definition of the given macro when building and loading modules">;
+def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>,
+ Flags<[DriverOption,CC1Option]>,
+ HelpText<"Require declaration of modules used within a module">;
def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>;
def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>;
@@ -534,10 +607,12 @@ def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">,
Flags<[CC1Option]>;
def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>;
def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group<f_Group>;
-def fno_builtin_strcat : Flag<["-"], "fno-builtin-strcat">, Group<f_Group>;
-def fno_builtin_strcpy : Flag<["-"], "fno-builtin-strcpy">, Group<f_Group>;
def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable implicit builtin knowledge of functions">;
+def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<clang_ignored_f_Group>,
+ HelpText<"Disable implicit builtin knowledge of a specific function">;
+def fno_math_builtin : Flag<["-"], "fno-math-builtin">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable implicit builtin knowledge of math functions">;
def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group<f_Group>,
Flags<[CC1Option]>;
def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group<f_Group>;
@@ -548,13 +623,14 @@ def fno_constant_cfstrings : Flag<["-"], "fno-constant-cfstrings">, Group<f_Grou
Flags<[CC1Option]>,
HelpText<"Disable creation of CodeFoundation-type constant strings">;
def fno_cxx_exceptions: Flag<["-"], "fno-cxx-exceptions">, Group<f_Group>;
-def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>, Flags<[NoForward]>;
+def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>,
+ Flags<[DriverOption]>;
def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">;
def fno_diagnostics_show_name : Flag<["-"], "fno-diagnostics-show-name">, Group<f_Group>;
def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
- Flags<[CC1Option]>, Group<f_Group>, HelpText<"Display include stacks for diagnostic notes">;
+ Flags<[CC1Option]>, Group<f_Group>;
def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group<f_Group>,
HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>;
def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group<f_Group>,
@@ -571,7 +647,12 @@ def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Group<f_Group>,
HelpText<"Do not limit debug information produced to reduce size of debug binary">;
def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Disallow merging of constants">;
-def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>, Flags<[NoForward]>;
+def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_module_maps : Flag <["-"], "fno-module-maps">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>,
+ Flags<[DriverOption]>;
def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>;
def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>;
def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>;
@@ -594,6 +675,7 @@ 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<f_Group>;
def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;
+def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>;
def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;
def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;
def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,
@@ -643,7 +725,6 @@ def fobjc_nonfragile_abi : Flag<["-"], "fobjc-nonfragile-abi">, 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>;
def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option]>;
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
@@ -658,6 +739,8 @@ def fpack_struct_EQ : Joined<["-"], "fpack-struct=">, Group<f_Group>, Flags<[CC1
HelpText<"Specify the default maximum struct packing alignment">;
def fpascal_strings : Flag<["-"], "fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Recognize and construct Pascal-style string literals">;
+def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Override the default ABI to return all structs on the stack">;
def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group<f_Group>;
def fpic : Flag<["-"], "fpic">, Group<f_Group>;
def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>;
@@ -667,6 +750,8 @@ def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>;
def fprofile_generate : Flag<["-"], "fprofile-generate">, Group<f_Group>;
def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Group>;
+def freg_struct_return : Flag<["-"], "freg-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Override the default ABI to return small structs in registers">;
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<f_Group>, Flags<[CC1Option]>,
@@ -682,6 +767,8 @@ def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group>
def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>;
def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group<f_Group>;
def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>;
+def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>,
+ Group<clang_ignored_f_Group>, HelpText<"Char is unsigned">;
def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>;
def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>;
@@ -696,6 +783,8 @@ def ftemplate_depth_EQ : Joined<["-"], "ftemplate-depth=">, Group<f_Group>;
def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">, Group<f_Group>;
def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">,
Group<f_Group>;
+def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">,
+ Group<f_Group>;
def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>;
def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
HelpText<"Enable the loop vectorization passes">;
@@ -737,12 +826,21 @@ def ftrap_function_EQ : Joined<["-"], "ftrap-function=">, Group<f_Group>, Flags<
def funit_at_a_time : Flag<["-"], "funit-at-a-time">, Group<f_Group>;
def funroll_loops : Flag<["-"], "funroll-loops">, Group<f_Group>,
HelpText<"Turn on loop unroller">, Flags<[CC1Option]>;
+def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group<f_Group>,
+ HelpText<"Turn off loop unroller">, Flags<[CC1Option]>;
+def freroll_loops : Flag<["-"], "freroll-loops">, Group<f_Group>,
+ HelpText<"Turn on loop reroller">, Flags<[CC1Option]>;
+def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<f_Group>,
+ HelpText<"Turn off loop reroller">;
def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>;
def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>;
+def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">, Group<clang_ignored_f_Group>;
def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>;
def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use .init_array instead of .ctors">;
+def fno_var_tracking : Flag<["-"], "fno-var-tracking">,
+ Group<clang_ignored_f_Group>;
def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
HelpText<"Set the default symbol visibility for all global declarations">;
@@ -757,11 +855,17 @@ def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Store string literals as writable data">;
def fzero_initialized_in_bss : Flag<["-"], "fzero-initialized-in-bss">, Group<f_Group>;
-def ffunction_sections: Flag <["-"], "ffunction-sections">, Group<f_Group>,
- Flags<[CC1Option]>, HelpText<"Place each function in its own section (ELF Only)">;
-def fdata_sections : Flag <["-"], "fdata-sections">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Place each data in its own section (ELF Only)">;
-def f : Joined<["-"], "f">, Group<f_Group>;
+def ffunction_sections : Flag<["-"], "ffunction-sections">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Place each function in its own section (ELF Only)">;
+def fno_function_sections : Flag<["-"], "fno-function-sections">,
+ Group<f_Group>, Flags<[CC1Option]>;
+def fdata_sections : Flag <["-"], "fdata-sections">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">;
+def fno_data_sections : Flag <["-"], "fno-data-sections">, Group<f_Group>,
+ Flags<[CC1Option]>;
+def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
def g_Flag : Flag<["-"], "g">, Group<g_Group>,
HelpText<"Generate source level debug information">, Flags<[CC1Option]>;
def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<g_Group>,
@@ -775,9 +879,12 @@ def ggdb0 : Flag<["-"], "ggdb0">, Group<g_Group>;
def ggdb1 : Flag<["-"], "ggdb1">, Group<g_Group>;
def ggdb2 : Flag<["-"], "ggdb2">, Group<g_Group>;
def ggdb3 : Flag<["-"], "ggdb3">, Group<g_Group>;
-def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group<g_Group>;
-def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group<g_Group>;
-def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>;
+def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group<g_Group>,
+ HelpText<"Generate source level debug information with dwarf version 2">, Flags<[CC1Option]>;
+def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group<g_Group>,
+ HelpText<"Generate source level debug information with dwarf version 3">, Flags<[CC1Option]>;
+def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>,
+ HelpText<"Generate source level debug information with dwarf version 4">, Flags<[CC1Option]>;
def gfull : Flag<["-"], "gfull">, Group<g_Group>;
def gused : Flag<["-"], "gused">, Group<g_Group>;
def gstabs : Joined<["-"], "gstabs">, Group<g_Group>, Flags<[Unsupported]>;
@@ -792,6 +899,7 @@ def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>;
def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
+def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>;
def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
def help : Flag<["-", "--"], "help">, Flags<[CC1Option]>,
HelpText<"Display available options">;
@@ -808,6 +916,8 @@ def include_ : JoinedOrSeparate<["-", "--"], "include">, Group<clang_i_Group>, E
MetaVarName<"<file>">, HelpText<"Include file before parsing">, Flags<[CC1Option]>;
def include_pch : Separate<["-"], "include-pch">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Include precompiled header file">, MetaVarName<"<file>">;
+def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>,
+ HelpText<"Whether to build a relocatable precompiled header">;
def init : Separate<["-"], "init">;
def install__name : Separate<["-"], "install_name">;
def integrated_as : Flag<["-"], "integrated-as">, Flags<[DriverOption]>;
@@ -835,39 +945,34 @@ def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>;
def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>;
def EL : Flag<["-"], "EL">, Flags<[DriverOption]>;
def EB : Flag<["-"], "EB">, Flags<[DriverOption]>;
-def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption]>;
+def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>,
HelpText<"Enable hexagon-qdsp6 backward compatibility">;
def m3dnowa : Flag<["-"], "m3dnowa">, Group<m_x86_Features_Group>;
def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>;
-def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption]>;
+def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>;
def march_EQ : Joined<["-"], "march=">, Group<m_Group>;
-def maltivec : Flag<["-"], "maltivec">, Alias<faltivec>;
-def mno_altivec : Flag<["-"], "mno-altivec">, Alias<fno_altivec>;
-def mfprnd : Flag<["-"], "mfprnd">, Group<m_Group>;
-def mno_fprnd : Flag<["-"], "mno-fprnd">, Group<m_Group>;
-def mmfcrf : Flag<["-"], "mmfcrf">, Group<m_Group>;
-def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Group<m_Group>;
-def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_Group>;
-def mno_popcntd : Flag<["-"], "mno-popcntd">, Group<m_Group>;
-def mqpx : Flag<["-"], "mqpx">, Group<m_Group>;
-def mno_qpx : Flag<["-"], "mno-qpx">, Group<m_Group>;
def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>;
def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group<clang_ignored_m_Group>;
def mcpu_EQ : Joined<["-"], "mcpu=">, Group<m_Group>;
def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group<m_Group>;
def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group<clang_ignored_m_Group>;
+def mieee_fp : Flag<["-"], "mieee-fp">, Group<clang_ignored_m_Group>;
+def minline_all_stringops : Flag<["-"], "minline-all-stringops">, Group<clang_ignored_m_Group>;
+def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group<clang_ignored_m_Group>;
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>;
def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
+def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>;
def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>;
def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group<m_Group>;
def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, Alias<miphoneos_version_min_EQ>;
def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Group<m_Group>;
def mkernel : Flag<["-"], "mkernel">, Group<m_Group>;
-def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Flags<[NoForward]>;
+def mlinker_version_EQ : Joined<["-"], "mlinker-version=">,
+ Flags<[DriverOption]>;
def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option]>,
HelpText<"Additional arguments to forward to LLVM's option processing">;
def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">, Group<m_Group>;
@@ -877,8 +982,6 @@ def mstackrealign : Flag<["-"], "mstackrealign">, Group<m_Group>, Flags<[CC1Opti
HelpText<"Force realign the stack at entry to every function">;
def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the stack alignment">;
-def mstrict_align : Flag<["-"], "mstrict-align">, Group<m_Group>, Flags<[CC1Option]>,
- HelpText<"Force all memory accesses to be aligned (ARM only)">;
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>;
@@ -886,7 +989,8 @@ def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group<m_Grou
def mno_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Disable merging of globals">;
def mno_mmx : Flag<["-"], "mno-mmx">, Group<m_x86_Features_Group>;
-def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">, Group<m_Group>;
+def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">,
+ Alias<fno_pascal_strings>;
def mno_red_zone : Flag<["-"], "mno-red-zone">, Group<m_Group>;
def mno_relax_all : Flag<["-"], "mno-relax-all">, Group<m_Group>;
def mno_rtd: Flag<["-"], "mno-rtd">, Group<m_Group>;
@@ -903,12 +1007,17 @@ def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group<m_x86_Features_Group>;
def mno_aes : Flag<["-"], "mno-aes">, Group<m_x86_Features_Group>;
def mno_avx : Flag<["-"], "mno-avx">, Group<m_x86_Features_Group>;
def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
+def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>;
+def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>;
+def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>;
+def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>;
def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>;
def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>;
def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>;
def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>;
def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>;
def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>;
+def mno_tbm : Flag<["-"], "mno-tbm">, Group<m_x86_Features_Group>;
def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>;
def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>;
def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>;
@@ -916,16 +1025,50 @@ def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>;
def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>;
def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>;
def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
+def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>;
-def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_Group>;
+def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
+ HelpText<"Allow memory accesses to be unaligned (ARM only)">;
+def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_arm_Features_Group>,
+ HelpText<"Force all memory accesses to be aligned (ARM only)">;
+def mstrict_align : Flag<["-"], "mstrict-align">, Alias<mno_unaligned_access>, Flags<[CC1Option,HelpHidden]>,
+ HelpText<"Force all memory accesses to be aligned (ARM only, same as mno-unaligned-access)">;
+def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>;
+def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
+ HelpText<"Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.">;
+def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group<m_arm_Features_Group>,
+ HelpText<"Allow generation of deprecated IT blocks for ARMv8. It is off by default for ARMv8 Thumb mode">;
def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
+def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
+ HelpText<"Reserve the r9 register (ARM only)">;
+def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>,
+ HelpText<"Allow use of CRC instructions (ARM only)">;
+def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>,
+ HelpText<"Disallow use of CRC instructions (ARM only)">;
+
+def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>;
+def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>;
+def mfprnd : Flag<["-"], "mfprnd">, Group<m_ppc_Features_Group>;
+def mno_fprnd : Flag<["-"], "mno-fprnd">, Group<m_ppc_Features_Group>;
+def mmfcrf : Flag<["-"], "mmfcrf">, Group<m_ppc_Features_Group>;
+def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Group<m_ppc_Features_Group>;
+def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_ppc_Features_Group>;
+def mno_popcntd : Flag<["-"], "mno-popcntd">, Group<m_ppc_Features_Group>;
+def mqpx : Flag<["-"], "mqpx">, Group<m_ppc_Features_Group>;
+def mno_qpx : Flag<["-"], "mno-qpx">, Group<m_ppc_Features_Group>;
+
+def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable AltiVec vector initializer syntax">;
+def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[CC1Option]>;
+def maltivec : Flag<["-"], "maltivec">, Alias<faltivec>;
+def mno_altivec : Flag<["-"], "mno-altivec">, Alias<fno_altivec>;
def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings">, Group<m_Group>;
def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group<m_Group>;
def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group<m_Group>,
HelpText<"Omit frame pointer setup for leaf functions">, Flags<[CC1Option]>;
def moslib_EQ : Joined<["-"], "moslib=">, Group<m_Group>;
-def mpascal_strings : Flag<["-"], "mpascal-strings">, Group<m_Group>;
+def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias<fpascal_strings>;
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>, Flags<[CC1Option]>,
@@ -949,12 +1092,17 @@ def mssse3 : Flag<["-"], "mssse3">, Group<m_x86_Features_Group>;
def maes : Flag<["-"], "maes">, Group<m_x86_Features_Group>;
def mavx : Flag<["-"], "mavx">, Group<m_x86_Features_Group>;
def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
+def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
+def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>;
+def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>;
+def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>;
def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>;
def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>;
def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>;
def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>;
def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>;
def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>;
+def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>;
def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>;
def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>;
def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>;
@@ -962,25 +1110,45 @@ def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>;
def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>;
def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>;
def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>;
+def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>;
+def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>;
def mips16 : Flag<["-"], "mips16">, Group<m_Group>;
def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>;
def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>;
def mno_micromips : Flag<["-"], "mno-micromips">, Group<m_Group>;
def mxgot : Flag<["-"], "mxgot">, Group<m_Group>;
def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_Group>;
+def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_Group>;
+def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_Group>;
+def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, Group<m_Group>;
+def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">,
+ Group<m_Group>;
def mdsp : Flag<["-"], "mdsp">, Group<m_Group>;
def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_Group>;
def mdspr2 : Flag<["-"], "mdspr2">, Group<m_Group>;
def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_Group>;
def msingle_float : Flag<["-"], "msingle-float">, Group<m_Group>;
def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_Group>;
-def mips32 : Flag<["-"], "mips32">, Group<mips_CPUs_Group>,
+def mmsa : Flag<["-"], "mmsa">, Group<m_Group>,
+ HelpText<"Enable MSA ASE (MIPS only)">;
+def mno_msa : Flag<["-"], "mno-msa">, Group<m_Group>,
+ HelpText<"Disable MSA ASE (MIPS only)">;
+def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>,
+ HelpText<"Use 64-bit floating point registers (MIPS only)">;
+def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>,
+ HelpText<"Use 32-bit floating point registers (MIPS only)">;
+def mnan_EQ : Joined<["-"], "mnan=">, Group<m_Group>;
+def mips32 : Flag<["-"], "mips32">,
+ Alias<march_EQ>, AliasArgs<["mips32"]>,
HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>;
-def mips32r2 : Flag<["-"], "mips32r2">, Group<mips_CPUs_Group>,
+def mips32r2 : Flag<["-"], "mips32r2">,
+ Alias<march_EQ>, AliasArgs<["mips32r2"]>,
HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>;
-def mips64 : Flag<["-"], "mips64">, Group<mips_CPUs_Group>,
+def mips64 : Flag<["-"], "mips64">,
+ Alias<march_EQ>, AliasArgs<["mips64"]>,
HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>;
-def mips64r2 : Flag<["-"], "mips64r2">, Group<mips_CPUs_Group>,
+def mips64r2 : Flag<["-"], "mips64r2">,
+ Alias<march_EQ>, AliasArgs<["mips64r2"]>,
HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>;
def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>;
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
@@ -989,8 +1157,6 @@ def multi__module : Flag<["-"], "multi_module">;
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
def multiply__defined : Separate<["-"], "multiply_defined">;
def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Group<m_Group>;
-def m_Separate : Separate<["-"], "m">, Group<m_Group>;
-def m_Joined : Joined<["-"], "m">, Group<m_Group>;
def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden]>,
HelpText<"Use relative instead of canonical paths">;
def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group<clang_ignored_f_Group>;
@@ -1004,6 +1170,7 @@ def nodefaultlibs : Flag<["-"], "nodefaultlibs">;
def nofixprebinding : Flag<["-"], "nofixprebinding">;
def nolibc : Flag<["-"], "nolibc">;
def nomultidefs : Flag<["-"], "nomultidefs">;
+def nopie : Flag<["-"], "nopie">;
def noprebind : Flag<["-"], "noprebind">;
def noseglinkedit : Flag<["-"], "noseglinkedit">;
def nostartfiles : Flag<["-"], "nostartfiles">;
@@ -1084,16 +1251,16 @@ def static_libgcc : Flag<["-"], "static-libgcc">;
def static_libstdcxx : Flag<["-"], "static-libstdc++">;
def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>;
def std_default_EQ : Joined<["-"], "std-default=">;
-def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, Group<L_Group>,
- HelpText<"Language standard to compile for">;
+def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,
+ Group<CompileOnly_Group>, HelpText<"Language standard to compile for">;
def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>,
HelpText<"C++ standard library to use">;
def sub__library : JoinedOrSeparate<["-"], "sub_library">;
def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">;
def s : Flag<["-"], "s">;
-def target : Separate<["-"], "target">, Flags<[DriverOption]>,
+def target : Joined<["--"], "target=">, Flags<[DriverOption]>,
HelpText<"Generate code for the given target">;
-def gcc_toolchain : Separate<["-"], "gcc-toolchain">, Flags<[DriverOption]>,
+def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>,
HelpText<"Use the gcc toolchain at the given directory">;
def time : Flag<["-"], "time">,
HelpText<"Time individual commands">;
@@ -1111,7 +1278,6 @@ def undef : Flag<["-"], "undef">, Group<u_Group>, Flags<[CC1Option]>,
HelpText<"undef all system defines">;
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">, Flags<[CC1Option]>,
HelpText<"Show commands to run and use verbose output">;
def verify : Flag<["-"], "verify">, Flags<[DriverOption,CC1Option]>,
@@ -1136,6 +1302,7 @@ def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option
// Double dash options, which are usually an alias for one of the previous
// options.
+def _mhwdiv_EQ : Separate<["--"], "mhwdiv">, Alias<mhwdiv_EQ>;
def _CLASSPATH_EQ : Joined<["--"], "CLASSPATH=">, Alias<fclasspath_EQ>;
def _CLASSPATH : Separate<["--"], "CLASSPATH">, Alias<fclasspath_EQ>;
def _all_warnings : Flag<["--"], "all-warnings">, Alias<Wall>;
@@ -1160,6 +1327,8 @@ def _debug : Flag<["--"], "debug">, Alias<g_Flag>;
def _define_macro_EQ : Joined<["--"], "define-macro=">, Alias<D>;
def _define_macro : Separate<["--"], "define-macro">, Alias<D>;
def _dependencies : Flag<["--"], "dependencies">, Alias<M>;
+def _dyld_prefix_EQ : Joined<["--"], "dyld-prefix=">;
+def _dyld_prefix : Separate<["--"], "dyld-prefix">, Alias<_dyld_prefix_EQ>;
def _encoding_EQ : Joined<["--"], "encoding=">, Alias<fencoding_EQ>;
def _encoding : Separate<["--"], "encoding">, Alias<fencoding_EQ>;
def _entry : Flag<["--"], "entry">, Alias<e>;
@@ -1190,10 +1359,6 @@ def _language_EQ : Joined<["--"], "language=">, Alias<x>;
def _language : Separate<["--"], "language">, Alias<x>;
def _library_directory_EQ : Joined<["--"], "library-directory=">, Alias<L>;
def _library_directory : Separate<["--"], "library-directory">, Alias<L>;
-def _machine__EQ : Joined<["--"], "machine-=">, Alias<m_Joined>;
-def _machine_ : Joined<["--"], "machine-">, Alias<m_Joined>;
-def _machine_EQ : Joined<["--"], "machine=">, Alias<m_Joined>;
-def _machine : Separate<["--"], "machine">, Alias<m_Joined>;
def _no_line_commands : Flag<["--"], "no-line-commands">, Alias<P>;
def _no_standard_includes : Flag<["--"], "no-standard-includes">, Alias<nostdinc>;
def _no_standard_libraries : Flag<["--"], "no-standard-libraries">, Alias<nostdlib>;
@@ -1241,6 +1406,22 @@ def _write_dependencies : Flag<["--"], "write-dependencies">, Alias<MD>;
def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias<MMD>;
def _ : Joined<["--"], "">, Flags<[Unsupported]>;
def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>;
+def mv1 : Flag<["-"], "mv1">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
+ AliasArgs<["v1"]>;
+def mv2 : Flag<["-"], "mv2">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
+ AliasArgs<["v2"]>;
+def mv3 : Flag<["-"], "mv3">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
+ AliasArgs<["v3"]>;
+def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
+ AliasArgs<["v4"]>;
+def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
+ AliasArgs<["v5"]>;
+
+// These are legacy user-facing driver-level option spellings. They are always
+// aliases for options that are spelled using the more common Unix / GNU flag
+// style of double-dash and equals-joined flags.
+def gcc_toolchain_legacy_spelling : Separate<["-"], "gcc-toolchain">, Alias<gcc_toolchain>;
+def target_legacy_spelling : Separate<["-"], "target">, Alias<target>;
// Special internal option to handle -Xlinker --no-demangle.
def Z_Xlinker__no_demangle : Flag<["-"], "Z-Xlinker-no-demangle">,
@@ -1256,4 +1437,140 @@ def Z_reserved_lib_stdcxx : Flag<["-"], "Z-reserved-lib-stdc++">,
def Z_reserved_lib_cckext : Flag<["-"], "Z-reserved-lib-cckext">,
Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
+// Ignored options
+// FIXME: multiclasess produce suffixes, not prefixes. This is fine for now
+// since it is only used in ignored options.
+multiclass BooleanFFlag<string name> {
+ def _f : Flag<["-"], "f"#name>;
+ def _fno : Flag<["-"], "fno-"#name>;
+}
+
+def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_f_Group>;
+
+defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_f_Group>;
+def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group<clang_ignored_f_Group>;
+def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<clang_ignored_f_Group>;
+
+defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_f_Group>;
+def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_f_Group>;
+
+// FIXME: This option should be supported and wired up to our diognostics, but
+// ignore it for now to avoid breaking builds that use it.
+def fdiagnostics_show_location_EQ : Joined<["-"], "fdiagnostics-show-location=">, Group<clang_ignored_f_Group>;
+
+defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>;
+defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_f_Group>;
+defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group<clang_ignored_f_Group>;
+defm gcse : BooleanFFlag<"gcse">, Group<clang_ignored_f_Group>;
+defm gnu : BooleanFFlag<"gnu">, Group<clang_ignored_f_Group>;
+defm ident : BooleanFFlag<"ident">, Group<clang_ignored_f_Group>;
+defm implicit_templates : BooleanFFlag<"implicit-templates">, Group<clang_ignored_f_Group>;
+defm inline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_f_Group>;
+defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_f_Group>;
+defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>;
+defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_Group>;
+defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group<clang_ignored_f_Group>;
+defm printf : BooleanFFlag<"printf">, Group<clang_ignored_f_Group>;
+defm profile : BooleanFFlag<"profile">, Group<clang_ignored_f_Group>;
+defm profile_correction : BooleanFFlag<"profile-correction">, Group<clang_ignored_f_Group>;
+defm profile_generate_sampling : BooleanFFlag<"profile-generate-sampling">, Group<clang_ignored_f_Group>;
+defm profile_reusedist : BooleanFFlag<"profile-reusedist">, Group<clang_ignored_f_Group>;
+defm profile_values : BooleanFFlag<"profile-values">, Group<clang_ignored_f_Group>;
+defm regs_graph : BooleanFFlag<"regs-graph">, Group<clang_ignored_f_Group>;
+defm ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>;
+defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_f_Group>;
+defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_f_Group>;
+defm see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>;
+defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_f_Group>;
+defm spec_constr_count : BooleanFFlag<"spec-constr-count">, Group<clang_ignored_f_Group>;
+defm strength_reduce :
+ BooleanFFlag<"strength-reduce">, Group<clang_ignored_f_Group>;
+defm tls_model : BooleanFFlag<"tls-model">, Group<clang_ignored_f_Group>;
+defm tracer : BooleanFFlag<"tracer">, Group<clang_ignored_f_Group>;
+defm tree_salias : BooleanFFlag<"tree-salias">, Group<clang_ignored_f_Group>;
+defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group<clang_ignored_f_Group>;
+defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_f_Group>;
+defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_f_Group>;
+
+
+// gfortran options that we recognize in the driver and pass along when
+// invoking GCC to compile Fortran code.
+def gfortran_Group : OptionGroup<"gfortran Group">;
+
+// Generic gfortran options.
+def A_DASH : Joined<["-"], "A-">, Group<gfortran_Group>;
+def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined]>, Group<gfortran_Group>;
+def cpp : Flag<["-"], "cpp">, Group<gfortran_Group>;
+def nocpp : Flag<["-"], "nocpp">, Group<gfortran_Group>;
+def static_libgfortran : Flag<["-"], "static-libgfortran">, Group<gfortran_Group>;
+
+// "f" options with values for gfortran.
+def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, Group<gfortran_Group>;
+def fcheck_EQ : Joined<["-"], "fcheck=">, Group<gfortran_Group>;
+def fcoarray_EQ : Joined<["-"], "fcoarray=">, Group<gfortran_Group>;
+def fconvert_EQ : Joined<["-"], "fconvert=">, Group<gfortran_Group>;
+def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group<gfortran_Group>;
+def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<gfortran_Group>;
+def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, Group<gfortran_Group>;
+def finit_character_EQ : Joined<["-"], "finit-character=">, Group<gfortran_Group>;
+def finit_integer_EQ : Joined<["-"], "finit-integer=">, Group<gfortran_Group>;
+def finit_logical_EQ : Joined<["-"], "finit-logical=">, Group<gfortran_Group>;
+def finit_real_EQ : Joined<["-"], "finit-real=">, Group<gfortran_Group>;
+def fmax_array_constructor_EQ : Joined<["-"], "fmax-array-constructor=">, Group<gfortran_Group>;
+def fmax_errors_EQ : Joined<["-"], "fmax-errors=">, Group<gfortran_Group>;
+def fmax_stack_var_size_EQ : Joined<["-"], "fmax-stack-var-size=">, Group<gfortran_Group>;
+def fmax_subrecord_length_EQ : Joined<["-"], "fmax-subrecord-length=">, Group<gfortran_Group>;
+def frecord_marker_EQ : Joined<["-"], "frecord-marker=">, Group<gfortran_Group>;
+
+// "f" flags for gfortran.
+defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group<gfortran_Group>;
+defm align_commons : BooleanFFlag<"align-commons">, Group<gfortran_Group>;
+defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group<gfortran_Group>;
+defm automatic : BooleanFFlag<"automatic">, Group<gfortran_Group>;
+defm backslash : BooleanFFlag<"backslash">, Group<gfortran_Group>;
+defm backtrace : BooleanFFlag<"backtrace">, Group<gfortran_Group>;
+defm bounds_check : BooleanFFlag<"bounds-check">, Group<gfortran_Group>;
+defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group<gfortran_Group>;
+defm cray_pointer : BooleanFFlag<"cray-pointer">, Group<gfortran_Group>;
+defm d_lines_as_code : BooleanFFlag<"d-lines-as-code">, Group<gfortran_Group>;
+defm d_lines_as_comments : BooleanFFlag<"d-lines-as-comments">, Group<gfortran_Group>;
+defm default_double_8 : BooleanFFlag<"default-double-8">, Group<gfortran_Group>;
+defm default_integer_8 : BooleanFFlag<"default-integer-8">, Group<gfortran_Group>;
+defm default_real_8 : BooleanFFlag<"default-real-8">, Group<gfortran_Group>;
+defm dollar_ok : BooleanFFlag<"dollar-ok">, Group<gfortran_Group>;
+defm dump_fortran_optimized : BooleanFFlag<"dump-fortran-optimized">, Group<gfortran_Group>;
+defm dump_fortran_original : BooleanFFlag<"dump-fortran-original">, Group<gfortran_Group>;
+defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, Group<gfortran_Group>;
+defm external_blas : BooleanFFlag<"external-blas">, Group<gfortran_Group>;
+defm f2c : BooleanFFlag<"f2c">, Group<gfortran_Group>;
+defm fixed_form : BooleanFFlag<"fixed-form">, Group<gfortran_Group>;
+defm free_form : BooleanFFlag<"free-form">, Group<gfortran_Group>;
+defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group<gfortran_Group>;
+defm implicit_none : BooleanFFlag<"implicit-none">, Group<gfortran_Group>;
+defm init_local_zero : BooleanFFlag<"init-local-zero">, Group<gfortran_Group>;
+defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, Group<gfortran_Group>;
+defm intrinsic_modules_path : BooleanFFlag<"intrinsic-modules-path">, Group<gfortran_Group>;
+defm max_identifier_length : BooleanFFlag<"max-identifier-length">, Group<gfortran_Group>;
+defm module_private : BooleanFFlag<"module-private">, Group<gfortran_Group>;
+defm pack_derived : BooleanFFlag<"pack-derived">, Group<gfortran_Group>;
+defm protect_parens : BooleanFFlag<"protect-parens">, Group<gfortran_Group>;
+defm range_check : BooleanFFlag<"range-check">, Group<gfortran_Group>;
+defm real_4_real_10 : BooleanFFlag<"real-4-real-10">, Group<gfortran_Group>;
+defm real_4_real_16 : BooleanFFlag<"real-4-real-16">, Group<gfortran_Group>;
+defm real_4_real_8 : BooleanFFlag<"real-4-real-8">, Group<gfortran_Group>;
+defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group<gfortran_Group>;
+defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group<gfortran_Group>;
+defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group<gfortran_Group>;
+defm realloc_lhs : BooleanFFlag<"realloc-lhs">, Group<gfortran_Group>;
+defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>;
+defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>;
+defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>;
+defm sign_zero : BooleanFFlag<"sign-zero">, Group<gfortran_Group>;
+defm stack_arrays : BooleanFFlag<"stack-arrays">, Group<gfortran_Group>;
+defm underscoring : BooleanFFlag<"underscoring">, Group<gfortran_Group>;
+defm whole_file : BooleanFFlag<"whole-file">, Group<gfortran_Group>;
+
+
include "CC1Options.td"
+
+include "CLCompatOptions.td"
diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h
new file mode 100644
index 000000000000..35b8f89a88a7
--- /dev/null
+++ b/include/clang/Driver/SanitizerArgs.h
@@ -0,0 +1,147 @@
+//===--- SanitizerArgs.h - Arguments for sanitizer tools -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_
+#define CLANG_LIB_DRIVER_SANITIZERARGS_H_
+
+#include <string>
+
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+
+namespace clang {
+namespace driver {
+
+class Driver;
+class ToolChain;
+
+class SanitizerArgs {
+ /// Assign ordinals to sanitizer flags. We'll use the ordinal values as
+ /// bit positions within \c Kind.
+ enum SanitizeOrdinal {
+#define SANITIZER(NAME, ID) SO_##ID,
+#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
+#include "clang/Basic/Sanitizers.def"
+ SO_Count
+ };
+
+ /// Bugs to catch at runtime.
+ enum SanitizeKind {
+#define SANITIZER(NAME, ID) ID = 1 << SO_##ID,
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ ID = ALIAS, ID##Group = 1 << SO_##ID##Group,
+#include "clang/Basic/Sanitizers.def"
+ NeedsAsanRt = Address,
+ NeedsTsanRt = Thread,
+ NeedsMsanRt = Memory,
+ NeedsDfsanRt = DataFlow,
+ NeedsLeakDetection = Leak,
+ NeedsUbsanRt = Undefined | Integer,
+ NotAllowedWithTrap = Vptr,
+ HasZeroBaseShadow = Thread | Memory | DataFlow
+ };
+ unsigned Kind;
+
+ std::string BlacklistFile;
+ bool MsanTrackOrigins;
+ bool AsanZeroBaseShadow;
+ bool UbsanTrapOnError;
+
+ public:
+ SanitizerArgs();
+ /// Parses the sanitizer arguments from an argument list.
+ SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
+
+ bool needsAsanRt() const { return Kind & NeedsAsanRt; }
+ bool needsTsanRt() const { return Kind & NeedsTsanRt; }
+ bool needsMsanRt() const { return Kind & NeedsMsanRt; }
+ bool needsLeakDetection() const { return Kind & NeedsLeakDetection; }
+ bool needsLsanRt() const {
+ return needsLeakDetection() && !needsAsanRt();
+ }
+ bool needsUbsanRt() const {
+ return !UbsanTrapOnError && (Kind & NeedsUbsanRt);
+ }
+ bool needsDfsanRt() const { return Kind & NeedsDfsanRt; }
+
+ bool sanitizesVptr() const { return Kind & Vptr; }
+ bool notAllowedWithTrap() const { return Kind & NotAllowedWithTrap; }
+ bool hasZeroBaseShadow() const {
+ return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow;
+ }
+ void addArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ private:
+ void clear();
+
+ /// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
+ /// Returns OR of members of the \c SanitizeKind enumeration, or \c 0
+ /// if \p Value is not known.
+ static unsigned parse(const char *Value);
+
+ /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
+ /// invalid components.
+ static unsigned parse(const Driver &D, const llvm::opt::Arg *A,
+ bool DiagnoseErrors);
+
+ /// Parse a single flag of the form -f[no]sanitize=, or
+ /// -f*-sanitizer. Sets the masks defining required change of Kind value.
+ /// Returns true if the flag was parsed successfully.
+ static bool parse(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A, unsigned &Add, unsigned &Remove,
+ bool DiagnoseErrors);
+
+ /// Produce an argument string from ArgList \p Args, which shows how it
+ /// provides a sanitizer kind in \p Mask. For example, the argument list
+ /// "-fsanitize=thread,vptr -faddress-sanitizer" with mask \c NeedsUbsanRt
+ /// would produce "-fsanitize=vptr".
+ static std::string lastArgumentForKind(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ unsigned Kind);
+
+ /// Produce an argument string from argument \p A, which shows how it provides
+ /// a value in \p Mask. For instance, the argument
+ /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
+ /// "-fsanitize=alignment".
+ static std::string describeSanitizeArg(const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A,
+ unsigned Mask);
+
+ static bool getDefaultBlacklistForKind(const Driver &D, unsigned Kind,
+ std::string &BLPath);
+
+ /// Return the smallest superset of sanitizer set \p Kinds such that each
+ /// member of each group whose flag is set in \p Kinds has its flag set in the
+ /// result.
+ static unsigned expandGroups(unsigned Kinds);
+
+ /// Return the subset of \p Kinds supported by toolchain \p TC. If
+ /// \p DiagnoseErrors is true, produce an error diagnostic for each sanitizer
+ /// removed from \p Kinds.
+ static unsigned filterUnsupportedKinds(const ToolChain &TC, unsigned Kinds,
+ const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A,
+ bool DiagnoseErrors,
+ unsigned &DiagnosedKinds);
+
+ /// The flags in \p Mask are unsupported by \p TC. If present in \p Kinds,
+ /// remove them and produce an error diagnostic referring to \p A if
+ /// \p DiagnoseErrors is true.
+ static void filterUnsupportedMask(const ToolChain &TC, unsigned &Kinds,
+ unsigned Mask,
+ const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A,
+ bool DiagnoseErrors,
+ unsigned &DiagnosedKinds);
+};
+
+} // namespace driver
+} // namespace clang
+
+#endif // CLANG_LIB_DRIVER_SANITIZERARGS_H_
diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h
index 4c05d0a743bc..015dcf513e0a 100644
--- a/include/clang/Driver/Tool.h
+++ b/include/clang/Driver/Tool.h
@@ -12,9 +12,15 @@
#include "clang/Basic/LLVM.h"
+namespace llvm {
+namespace opt {
+ class ArgList;
+}
+}
+
namespace clang {
namespace driver {
- class ArgList;
+
class Compilation;
class InputInfo;
class Job;
@@ -57,7 +63,8 @@ public:
virtual bool hasGoodDiagnostics() const { return false; }
/// ConstructJob - Construct jobs to perform the action \p JA,
- /// writing to \p Output and with \p Inputs.
+ /// writing to \p Output and with \p Inputs, and add the jobs to
+ /// \p C.
///
/// \param TCArgs - The argument list for this toolchain, with any
/// tool chain specific translations applied.
@@ -66,7 +73,7 @@ public:
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const = 0;
};
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index aae3d79936b6..84e0b55ba5af 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -19,16 +19,22 @@
#include "llvm/Support/Path.h"
#include <string>
+namespace llvm {
+namespace opt {
+ class ArgList;
+ class DerivedArgList;
+ class InputArgList;
+}
+}
+
namespace clang {
class ObjCRuntime;
namespace driver {
- class ArgList;
class Compilation;
- class DerivedArgList;
class Driver;
- class InputArgList;
class JobAction;
+ class SanitizerArgs;
class Tool;
/// ToolChain - Access to tools for a single platform.
@@ -49,7 +55,7 @@ public:
private:
const Driver &D;
const llvm::Triple Triple;
- const ArgList &Args;
+ const llvm::opt::ArgList &Args;
/// The list of toolchain specific path prefixes to search for
/// files.
@@ -67,8 +73,11 @@ private:
Tool *getLink() const;
Tool *getClangAs() const;
+ mutable OwningPtr<SanitizerArgs> SanitizerArguments;
+
protected:
- ToolChain(const Driver &D, const llvm::Triple &T, const ArgList &Args);
+ ToolChain(const Driver &D, const llvm::Triple &T,
+ const llvm::opt::ArgList &Args);
virtual Tool *buildAssembler() const;
virtual Tool *buildLinker() const;
@@ -76,17 +85,18 @@ protected:
/// \name Utilities for implementing subclasses.
///@{
- static void addSystemInclude(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
+ static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
- static void addExternCSystemInclude(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
+ static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ const Twine &Path);
+ static void
+ addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
- static void addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
- const Twine &Path);
- static void addSystemIncludes(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
+ static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
ArrayRef<StringRef> Paths);
///@}
@@ -117,6 +127,8 @@ public:
path_list &getProgramPaths() { return ProgramPaths; }
const path_list &getProgramPaths() const { return ProgramPaths; }
+ const SanitizerArgs& getSanitizerArgs() const;
+
// Tool access.
/// TranslateArgs - Create a new derived argument list for any argument
@@ -124,8 +136,9 @@ public:
/// specific translations are needed.
///
/// \param BoundArch - The bound architecture name, or 0.
- virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
- const char *BoundArch) const {
+ virtual llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const {
return 0;
}
@@ -137,6 +150,13 @@ public:
std::string GetFilePath(const char *Name) const;
std::string GetProgramPath(const char *Name) const;
+ /// \brief Dispatch to the specific toolchain for verbose printing.
+ ///
+ /// This is used when handling the verbose option to print detailed,
+ /// toolchain-specific information useful for understanding the behavior of
+ /// the driver on a specific platform.
+ virtual void printVerboseInfo(raw_ostream &OS) const {};
+
// Platform defaults information
/// HasNativeLTOLinker - Check whether the linker and related tools have
@@ -157,17 +177,9 @@ public:
/// \brief Check if the toolchain should use the integrated assembler.
bool useIntegratedAs() const;
- /// IsStrictAliasingDefault - Does this tool chain use -fstrict-aliasing by
- /// default.
- virtual bool IsStrictAliasingDefault() const { return true; }
-
/// IsMathErrnoDefault - Does this tool chain use -fmath-errno by default.
virtual bool IsMathErrnoDefault() const { return true; }
- /// IsObjCDefaultSynthPropertiesDefault - Does this tool chain enable
- /// -fobjc-default-synthesize-properties by default.
- virtual bool IsObjCDefaultSynthPropertiesDefault() const { return true; }
-
/// IsEncodeExtendedBlockSignatureDefault - Does this tool chain enable
/// -fencode-extended-block-signature by default.
virtual bool IsEncodeExtendedBlockSignatureDefault() const { return false; }
@@ -225,16 +237,18 @@ public:
/// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
/// command line arguments into account.
- virtual std::string ComputeLLVMTriple(const ArgList &Args,
- types::ID InputType = types::TY_INVALID) const;
+ virtual std::string
+ ComputeLLVMTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType = types::TY_INVALID) const;
/// ComputeEffectiveClangTriple - Return the Clang triple to use for this
/// target, which may take into account the command line arguments. For
/// example, on Darwin the -mmacosx-version-min= command line argument (which
/// sets the deployment target) determines the version in the triple passed to
/// Clang.
- virtual std::string ComputeEffectiveClangTriple(const ArgList &Args,
- types::ID InputType = types::TY_INVALID) const;
+ virtual std::string ComputeEffectiveClangTriple(
+ const llvm::opt::ArgList &Args,
+ types::ID InputType = types::TY_INVALID) const;
/// getDefaultObjCRuntime - Return the default Objective-C runtime
/// for this platform.
@@ -253,42 +267,46 @@ public:
///
/// This routine is responsible for adding the necessary cc1 arguments to
/// include headers from standard system header directories.
- virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
+ virtual void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
/// \brief Add options that need to be passed to cc1 for this target.
- virtual void addClangTargetOptions(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
+ virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
// GetRuntimeLibType - Determine the runtime library type to use with the
// given compilation arguments.
- virtual RuntimeLibType GetRuntimeLibType(const ArgList &Args) const;
+ virtual RuntimeLibType
+ GetRuntimeLibType(const llvm::opt::ArgList &Args) const;
// GetCXXStdlibType - Determine the C++ standard library type to use with the
// given compilation arguments.
- virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
+ virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::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 &DriverArgs,
- ArgStringList &CC1Args) const;
+ virtual void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) 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;
+ virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::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;
+ virtual void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
/// AddFastMathRuntimeIfAvailable - If a runtime library exists that sets
/// global flags for unsafe floating point math, add it and return true.
///
/// This checks for presence of the -ffast-math or -funsafe-math flags.
- virtual bool AddFastMathRuntimeIfAvailable(const ArgList &Args,
- ArgStringList &CmdArgs) const;
+ virtual bool
+ AddFastMathRuntimeIfAvailable(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
};
} // end namespace driver
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index 42f0709cf17a..d4f52d3220c8 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -66,7 +66,7 @@ TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, 0, "pu")
// Other languages.
TYPE("ada", Ada, INVALID, 0, "u")
TYPE("assembler", PP_Asm, INVALID, "s", "au")
-TYPE("assembler-with-cpp", Asm, PP_Asm, 0, "au")
+TYPE("assembler-with-cpp", Asm, PP_Asm, "S", "au")
TYPE("f95", PP_Fortran, INVALID, 0, "u")
TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u")
TYPE("java", Java, INVALID, 0, "u")
diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
index 18cd2d5102cf..cca576a054aa 100644
--- a/include/clang/Driver/Types.h
+++ b/include/clang/Driver/Types.h
@@ -34,7 +34,7 @@ namespace types {
/// getTypeTempSuffix - Return the suffix to use when creating a
/// temp file of this type, or null if unspecified.
- const char *getTypeTempSuffix(ID Id);
+ const char *getTypeTempSuffix(ID Id, bool CLMode = false);
/// onlyAssembleType - Should this type only be assembled.
bool onlyAssembleType(ID Id);
@@ -78,7 +78,7 @@ namespace types {
/// done for type 'Id'.
void getCompilationPhases(
ID Id,
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &Phases);
+ llvm::SmallVectorImpl<phases::ID> &Phases);
/// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given
/// C type (used for clang++ emulation of g++ behaviour)
diff --git a/include/clang/Driver/Util.h b/include/clang/Driver/Util.h
index 06b82b977fe0..b24b9904f2b5 100644
--- a/include/clang/Driver/Util.h
+++ b/include/clang/Driver/Util.h
@@ -14,13 +14,12 @@
#include "llvm/ADT/DenseMap.h"
namespace clang {
+class DiagnosticsEngine;
+
namespace driver {
class Action;
class JobAction;
- /// ArgStringList - Type used for constructing argv lists for subprocesses.
- typedef SmallVector<const char*, 16> ArgStringList;
-
/// ArgStringMap - Type used to map a JobAction to its result file.
typedef llvm::DenseMap<const JobAction*, const char*> ArgStringMap;
diff --git a/include/clang/Edit/Commit.h b/include/clang/Edit/Commit.h
index 48e3d593aa54..626b1dd6305e 100644
--- a/include/clang/Edit/Commit.h
+++ b/include/clang/Edit/Commit.h
@@ -13,6 +13,7 @@
#include "clang/Edit/FileOffset.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
namespace clang {
class LangOptions;
@@ -48,16 +49,19 @@ private:
const LangOptions &LangOpts;
const PPConditionalDirectiveRecord *PPRec;
EditedSource *Editor;
-
+
+ const bool ForceCommitInSystemHeader;
bool IsCommitable;
SmallVector<Edit, 8> CachedEdits;
+
+ llvm::BumpPtrAllocator StrAlloc;
public:
explicit Commit(EditedSource &Editor);
Commit(const SourceManager &SM, const LangOptions &LangOpts,
const PPConditionalDirectiveRecord *PPRec = 0)
: SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0),
- IsCommitable(true) { }
+ ForceCommitInSystemHeader(true), IsCommitable(true) { }
bool isCommitable() const { return IsCommitable; }
@@ -103,7 +107,7 @@ public:
CharSourceRange::getTokenRange(TokenInnerRange));
}
- typedef SmallVector<Edit, 8>::const_iterator edit_iterator;
+ typedef SmallVectorImpl<Edit>::const_iterator edit_iterator;
edit_iterator edit_begin() const { return CachedEdits.begin(); }
edit_iterator edit_end() const { return CachedEdits.end(); }
@@ -131,6 +135,12 @@ private:
SourceLocation *MacroBegin = 0) const;
bool isAtEndOfMacroExpansion(SourceLocation loc,
SourceLocation *MacroEnd = 0) const;
+
+ StringRef copyString(StringRef str) {
+ char *buf = StrAlloc.Allocate<char>(str.size());
+ std::memcpy(buf, str.data(), str.size());
+ return StringRef(buf, str.size());
+ }
};
}
diff --git a/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h
index 733ad400c934..3ad5a6be1464 100644
--- a/include/clang/Edit/EditedSource.h
+++ b/include/clang/Edit/EditedSource.h
@@ -28,6 +28,7 @@ class EditedSource {
const SourceManager &SourceMgr;
const LangOptions &LangOpts;
const PPConditionalDirectiveRecord *PPRec;
+ const bool ForceCommitInSystemHeader;
struct FileEdit {
StringRef Text;
@@ -45,8 +46,10 @@ class EditedSource {
public:
EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
- const PPConditionalDirectiveRecord *PPRec = 0)
+ const PPConditionalDirectiveRecord *PPRec = 0,
+ const bool FCommitInSystemHeader = true)
: SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec),
+ ForceCommitInSystemHeader(FCommitInSystemHeader),
StrAlloc(/*size=*/512) { }
const SourceManager &getSourceManager() const { return SourceMgr; }
@@ -54,6 +57,10 @@ public:
const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const {
return PPRec;
}
+
+ bool getForceCommitInSystemHeader() const {
+ return ForceCommitInSystemHeader;
+ }
bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
diff --git a/include/clang/Edit/Rewriters.h b/include/clang/Edit/Rewriters.h
index 292878e75695..5e3425f56f73 100644
--- a/include/clang/Edit/Rewriters.h
+++ b/include/clang/Edit/Rewriters.h
@@ -9,10 +9,16 @@
#ifndef LLVM_CLANG_EDIT_REWRITERS_H
#define LLVM_CLANG_EDIT_REWRITERS_H
+#include "llvm/ADT/SmallVector.h"
namespace clang {
class ObjCMessageExpr;
+ class ObjCMethodDecl;
+ class ObjCInterfaceDecl;
+ class ObjCProtocolDecl;
class NSAPI;
+ class EnumDecl;
+ class TypedefDecl;
class ParentMap;
namespace edit {
@@ -24,7 +30,7 @@ bool rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit,
const ParentMap *PMap);
-
+
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit);
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 5304dc7ba228..0f2746712a69 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -17,6 +17,7 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Refactoring.h"
+#include "llvm/Support/system_error.h"
namespace clang {
@@ -30,13 +31,29 @@ namespace format {
/// specific guidelines.
struct FormatStyle {
/// \brief The column limit.
+ ///
+ /// A column limit of \c 0 means that there is no column limit. In this case,
+ /// clang-format will respect the input's line breaking decisions within
+ /// statements.
unsigned ColumnLimit;
+ /// \brief The maximum number of consecutive empty lines to keep.
+ unsigned MaxEmptyLinesToKeep;
+
+ /// \brief The penalty for each line break introduced inside a comment.
+ unsigned PenaltyBreakComment;
+
+ /// \brief The penalty for each line break introduced inside a string literal.
+ unsigned PenaltyBreakString;
+
/// \brief The penalty for each character outside of the column limit.
unsigned PenaltyExcessCharacter;
- /// \brief The maximum number of consecutive empty lines to keep.
- unsigned MaxEmptyLinesToKeep;
+ /// \brief The penalty for breaking before the first \c <<.
+ unsigned PenaltyBreakFirstLessLess;
+
+ /// \brief The penalty for breaking a function call after "call(".
+ unsigned PenaltyBreakBeforeFirstCallParameter;
/// \brief Set whether & and * bind to the type as opposed to the variable.
bool PointerBindsToType;
@@ -44,32 +61,62 @@ struct FormatStyle {
/// \brief If \c true, analyze the formatted file for the most common binding.
bool DerivePointerBinding;
- /// \brief The extra indent or outdent of access modifiers (e.g.: public:).
+ /// \brief The extra indent or outdent of access modifiers, e.g. \c public:.
int AccessModifierOffset;
+ /// \brief Supported language standards.
enum LanguageStandard {
+ /// Use C++03-compatible syntax.
LS_Cpp03,
+ /// Use features of C++11 (e.g. \c A<A<int>> instead of
+ /// <tt>A<A<int> ></tt>).
LS_Cpp11,
+ /// Automatic detection based on the input.
LS_Auto
};
- /// \brief Format compatible with this standard, e.g. use \c A<A<int> >
- /// instead of \c A<A<int>> for LS_Cpp03.
+ /// \brief Format compatible with this standard, e.g. use
+ /// <tt>A<A<int> ></tt> instead of \c A<A<int>> for LS_Cpp03.
LanguageStandard Standard;
/// \brief Indent case labels one level from the switch statement.
///
- /// When false, use the same indentation level as for the switch statement.
+ /// When \c false, use the same indentation level as for the switch statement.
/// Switch statement body is always indented one level more than case labels.
bool IndentCaseLabels;
+ /// \brief Different ways to indent namespace contents.
+ enum NamespaceIndentationKind {
+ /// Don't indent in namespaces.
+ NI_None,
+ /// Indent only in inner namespaces (nested in other namespaces).
+ NI_Inner,
+ /// Indent in all namespaces.
+ NI_All
+ };
+
+ /// \brief The indentation used for namespaces.
+ NamespaceIndentationKind NamespaceIndentation;
+
/// \brief The number of spaces to before trailing line comments.
unsigned SpacesBeforeTrailingComments;
- /// \brief If false, a function call's or function definition's parameters
+ /// \brief If \c false, a function call's or function definition's parameters
/// will either all be on the same line or will have one line each.
bool BinPackParameters;
+ /// \brief If \c true, clang-format detects whether function calls and
+ /// definitions are formatted with one parameter per line.
+ ///
+ /// Each call can be bin-packed, one-per-line or inconclusive. If it is
+ /// inconclusive, e.g. completely on one line, but a decision needs to be
+ /// made, clang-format analyzes whether there are other bin-packed cases in
+ /// the input file and act accordingly.
+ ///
+ /// NOTE: This is an experimental flag, that might go away or be renamed. Do
+ /// not use this in config files, etc. Use at your own risk.
+ bool ExperimentalAutoDetectBinPacking;
+
/// \brief Allow putting all parameters of a function declaration onto
/// the next line even if \c BinPackParameters is \c false.
bool AllowAllParametersOfDeclarationOnNextLine;
@@ -82,16 +129,176 @@ struct FormatStyle {
/// initializer on its own line.
bool ConstructorInitializerAllOnOneLineOrOnePerLine;
- /// \brief If true, "if (a) return;" can be put on a single line.
+ /// \brief Always break constructor initializers before commas and align
+ /// the commas with the colon.
+ bool BreakConstructorInitializersBeforeComma;
+
+ /// \brief If \c true, <tt>if (a) return;</tt> can be put on a single
+ /// line.
bool AllowShortIfStatementsOnASingleLine;
+ /// \brief If \c true, <tt>while (true) continue;</tt> can be put on a
+ /// single line.
+ bool AllowShortLoopsOnASingleLine;
+
/// \brief Add a space in front of an Objective-C protocol list, i.e. use
- /// Foo <Protocol> instead of Foo<Protocol>.
+ /// <tt>Foo <Protocol></tt> instead of \c Foo<Protocol>.
bool ObjCSpaceBeforeProtocolList;
+ /// \brief If \c true, aligns trailing comments.
+ bool AlignTrailingComments;
+
/// \brief If \c true, aligns escaped newlines as far left as possible.
/// Otherwise puts them into the right-most column.
bool AlignEscapedNewlinesLeft;
+
+ /// \brief The number of columns to use for indentation.
+ unsigned IndentWidth;
+
+ /// \brief The number of columns used for tab stops.
+ unsigned TabWidth;
+
+ /// \brief The number of characters to use for indentation of constructor
+ /// initializer lists.
+ unsigned ConstructorInitializerIndentWidth;
+
+ /// \brief If \c true, always break after the <tt>template<...></tt> of a
+ /// template declaration.
+ bool AlwaysBreakTemplateDeclarations;
+
+ /// \brief If \c true, always break before multiline string literals.
+ bool AlwaysBreakBeforeMultilineStrings;
+
+ /// \brief Different ways to use tab in formatting.
+ enum UseTabStyle {
+ /// Never use tab.
+ UT_Never,
+ /// Use tabs only for indentation.
+ UT_ForIndentation,
+ /// Use tabs whenever we need to fill whitespace that spans at least from
+ /// one tab stop to the next one.
+ UT_Always
+ };
+
+ /// \brief The way to use tab characters in the resulting file.
+ UseTabStyle UseTab;
+
+ /// \brief If \c true, binary operators will be placed after line breaks.
+ bool BreakBeforeBinaryOperators;
+
+ /// \brief If \c true, ternary operators will be placed after line breaks.
+ bool BreakBeforeTernaryOperators;
+
+ /// \brief Different ways to attach braces to their surrounding context.
+ enum BraceBreakingStyle {
+ /// Always attach braces to surrounding context.
+ BS_Attach,
+ /// Like \c Attach, but break before braces on function, namespace and
+ /// class definitions.
+ BS_Linux,
+ /// Like \c Attach, but break before function definitions.
+ BS_Stroustrup,
+ /// Always break before braces.
+ BS_Allman
+ };
+
+ /// \brief The brace breaking style to use.
+ BraceBreakingStyle BreakBeforeBraces;
+
+ /// \brief If \c true, format braced lists as best suited for C++11 braced
+ /// lists.
+ ///
+ /// Important differences:
+ /// - No spaces inside the braced list.
+ /// - No line break before the closing brace.
+ /// - Indentation with the continuation indent, not with the block indent.
+ ///
+ /// Fundamentally, C++11 braced lists are formatted exactly like function
+ /// calls would be formatted in their place. If the braced list follows a name
+ /// (e.g. a type or variable name), clang-format formats as if the \c {} were
+ /// the parentheses of a function call with that name. If there is no name,
+ /// a zero-length name is assumed.
+ bool Cpp11BracedListStyle;
+
+ /// \brief If \c true, indent when breaking function declarations which
+ /// are not also definitions after the type.
+ bool IndentFunctionDeclarationAfterType;
+
+ /// \brief If \c true, spaces will be inserted after '(' and before ')'.
+ bool SpacesInParentheses;
+
+ /// \brief If \c true, spaces will be inserted after '<' and before '>' in
+ /// template argument lists
+ bool SpacesInAngles;
+
+ /// \brief If \c false, spaces may be inserted into '()'.
+ bool SpaceInEmptyParentheses;
+
+ /// \brief If \c false, spaces may be inserted into C style casts.
+ bool SpacesInCStyleCastParentheses;
+
+ /// \brief If \c true, spaces will be inserted between 'for'/'if'/'while'/...
+ /// and '('.
+ bool SpaceAfterControlStatementKeyword;
+
+ /// \brief If \c false, spaces will be removed before assignment operators.
+ bool SpaceBeforeAssignmentOperators;
+
+ /// \brief Indent width for line continuations.
+ unsigned ContinuationIndentWidth;
+
+ bool operator==(const FormatStyle &R) const {
+ return AccessModifierOffset == R.AccessModifierOffset &&
+ ConstructorInitializerIndentWidth ==
+ R.ConstructorInitializerIndentWidth &&
+ AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
+ AlignTrailingComments == R.AlignTrailingComments &&
+ AllowAllParametersOfDeclarationOnNextLine ==
+ R.AllowAllParametersOfDeclarationOnNextLine &&
+ AllowShortIfStatementsOnASingleLine ==
+ R.AllowShortIfStatementsOnASingleLine &&
+ AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine &&
+ AlwaysBreakTemplateDeclarations ==
+ R.AlwaysBreakTemplateDeclarations &&
+ AlwaysBreakBeforeMultilineStrings ==
+ R.AlwaysBreakBeforeMultilineStrings &&
+ BinPackParameters == R.BinPackParameters &&
+ BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators &&
+ BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
+ BreakBeforeBraces == R.BreakBeforeBraces &&
+ BreakConstructorInitializersBeforeComma ==
+ R.BreakConstructorInitializersBeforeComma &&
+ ColumnLimit == R.ColumnLimit &&
+ ConstructorInitializerAllOnOneLineOrOnePerLine ==
+ R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
+ DerivePointerBinding == R.DerivePointerBinding &&
+ ExperimentalAutoDetectBinPacking ==
+ R.ExperimentalAutoDetectBinPacking &&
+ IndentCaseLabels == R.IndentCaseLabels &&
+ IndentFunctionDeclarationAfterType ==
+ R.IndentFunctionDeclarationAfterType &&
+ IndentWidth == R.IndentWidth &&
+ MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
+ NamespaceIndentation == R.NamespaceIndentation &&
+ ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
+ PenaltyBreakComment == R.PenaltyBreakComment &&
+ PenaltyBreakFirstLessLess == R.PenaltyBreakFirstLessLess &&
+ PenaltyBreakString == R.PenaltyBreakString &&
+ PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
+ PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
+ PointerBindsToType == R.PointerBindsToType &&
+ SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
+ Cpp11BracedListStyle == R.Cpp11BracedListStyle &&
+ Standard == R.Standard && TabWidth == R.TabWidth &&
+ UseTab == R.UseTab && SpacesInParentheses == R.SpacesInParentheses &&
+ SpacesInAngles == R.SpacesInAngles &&
+ SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
+ SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
+ SpaceAfterControlStatementKeyword ==
+ R.SpaceAfterControlStatementKeyword &&
+ SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
+ ContinuationIndentWidth == R.ContinuationIndentWidth;
+ }
};
/// \brief Returns a format style complying with the LLVM coding standards:
@@ -110,6 +317,24 @@ FormatStyle getChromiumStyle();
/// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style.
FormatStyle getMozillaStyle();
+/// \brief Returns a format style complying with Webkit's style guide:
+/// http://www.webkit.org/coding/coding-style.html
+FormatStyle getWebKitStyle();
+
+/// \brief Gets a predefined style by name.
+///
+/// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are
+/// compared case-insensitively.
+///
+/// Returns \c true if the Style has been set.
+bool getPredefinedStyle(StringRef Name, FormatStyle *Style);
+
+/// \brief Parse configuration from YAML-formatted text.
+llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
+
+/// \brief Gets configuration in a YAML string.
+std::string configurationAsText(const FormatStyle &Style);
+
/// \brief Reformats the given \p Ranges in the token stream coming out of
/// \c Lex.
///
@@ -117,18 +342,49 @@ FormatStyle getMozillaStyle();
/// everything that might influence its formatting or might be influenced by its
/// formatting.
///
-/// \param DiagClient A custom DiagnosticConsumer. Can be 0, in this case
-/// diagnostic is output to llvm::errs().
-///
/// Returns the \c Replacements necessary to make all \p Ranges comply with
/// \p Style.
tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
SourceManager &SourceMgr,
- std::vector<CharSourceRange> Ranges,
- DiagnosticConsumer *DiagClient = 0);
+ std::vector<CharSourceRange> Ranges);
+
+/// \brief Reformats the given \p Ranges in \p Code.
+///
+/// Otherwise identical to the reformat() function consuming a \c Lexer.
+tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
+ std::vector<tooling::Range> Ranges,
+ StringRef FileName = "<stdin>");
/// \brief Returns the \c LangOpts that the formatter expects you to set.
-LangOptions getFormattingLangOpts();
+///
+/// \param Standard determines lexing mode: LC_Cpp11 and LS_Auto turn on C++11
+/// lexing mode, LS_Cpp03 - C++03 mode.
+LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard =
+ FormatStyle::LS_Cpp11);
+
+/// \brief Description to be used for help text for a llvm::cl option for
+/// specifying format style. The description is closely related to the operation
+/// of getStyle().
+extern const char *StyleOptionHelpDescription;
+
+/// \brief Construct a FormatStyle based on \c StyleName.
+///
+/// \c StyleName can take several forms:
+/// \li "{<key>: <value>, ...}" - Set specic style parameters.
+/// \li "<style name>" - One of the style names supported by
+/// getPredefinedStyle().
+/// \li "file" - Load style configuration from a file called '.clang-format'
+/// located in one of the parent directories of \c FileName or the current
+/// directory if \c FileName is empty.
+///
+/// \param[in] StyleName Style name to interpret according to the description
+/// above.
+/// \param[in] FileName Path to start search for .clang-format if \c StyleName
+/// == "file".
+///
+/// \returns FormatStyle as specified by \c StyleName. If no style could be
+/// determined, the default is LLVM Style (see getLLVMStyle()).
+FormatStyle getStyle(StringRef StyleName, StringRef FileName);
} // end namespace format
} // end namespace clang
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index 3731478403ef..366c499b67f5 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -16,9 +16,6 @@
#include "clang/Basic/LLVM.h"
-namespace llvm {
- namespace sys { class Path; }
-}
namespace clang {
class ASTConsumer;
@@ -37,16 +34,12 @@ ASTConsumer *CreateASTPrinter(raw_ostream *OS, StringRef FilterString);
// AST dumper: dumps the raw AST in human-readable form to stderr; this is
// intended for debugging.
-ASTConsumer *CreateASTDumper(StringRef FilterString);
+ASTConsumer *CreateASTDumper(StringRef FilterString, bool DumpLookups = false);
// AST Decl node lister: prints qualified names of all filterable AST Decl
// nodes.
ASTConsumer *CreateASTDeclNodeLister();
-// AST XML-dumper: dumps out the AST to stderr in a very detailed XML
-// format; this is intended for particularly intense debugging.
-ASTConsumer *CreateASTDumperXML(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.
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 02c57d7472a5..43d77f0171e9 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -25,7 +25,6 @@
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Sema/CodeCompleteConsumer.h"
-#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
@@ -44,6 +43,7 @@ namespace llvm {
}
namespace clang {
+class Sema;
class ASTContext;
class ASTReader;
class CodeCompleteConsumer;
@@ -75,6 +75,7 @@ private:
IntrusiveRefCntPtr<TargetOptions> TargetOpts;
IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts;
ASTReader *Reader;
+ bool HadModuleLoaderFatalFailure;
struct ASTWriterData;
OwningPtr<ASTWriterData> WriterData;
@@ -456,7 +457,7 @@ public:
void setASTContext(ASTContext *ctx) { Ctx = ctx; }
void setPreprocessor(Preprocessor *pp);
- bool hasSema() const { return TheSema; }
+ bool hasSema() const { return TheSema.isValid(); }
Sema &getSema() const {
assert(TheSema && "ASTUnit does not have a Sema object!");
return *TheSema;
@@ -471,13 +472,14 @@ public:
return OriginalSourceFile;
}
+ ASTMutationListener *getASTMutationListener();
ASTDeserializationListener *getDeserializationListener();
/// \brief Add a temporary file that the ASTUnit depends on.
///
/// This file will be erased when the ASTUnit is destroyed.
- void addTemporaryFile(const llvm::sys::Path &TempFile);
-
+ void addTemporaryFile(StringRef TempFile);
+
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; }
@@ -697,10 +699,10 @@ public:
/// lifetime is expected to extend past that of the returned ASTUnit.
///
/// \param Action - The ASTFrontendAction to invoke. Its ownership is not
- /// transfered.
+ /// transferred.
///
/// \param Unit - optionally an already created ASTUnit. Its ownership is not
- /// transfered.
+ /// transferred.
///
/// \param Persistent - if true the returned ASTUnit will be complete.
/// false means the caller is only interested in getting info through the
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index f6e2472cb9b7..78b825dc14ff 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -39,11 +39,12 @@ CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker
///< aliases to base ctors when possible.
CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled.
CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled.
+CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
+CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use in
///< getting .bc files that correspond to the
///< internal state before optimizations are
///< done.
-CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
@@ -85,6 +86,10 @@ CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer
///< enabled.
VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified.
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
+
+ /// If -fpcc-struct-return or -freg-struct-return is specified.
+ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)
+
CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions.
CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled.
CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA.
@@ -102,8 +107,12 @@ CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization
///< selection.
CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled.
+CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns.
CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables.
+CODEGENOPT(VectorizeBB , 1, 0) ///< Run basic block vectorizer.
+CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer.
+CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
/// Attempt to use register sized accesses to bit-fields in structures, when
/// possible.
@@ -131,6 +140,9 @@ VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
/// The kind of generated debug info.
ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 2, NoDebugInfo)
+/// Dwarf version.
+VALUE_CODEGENOPT(DwarfVersion, 3, 0)
+
/// The kind of inlining to perform.
ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining)
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index db6b4186731c..86aabf7b95ec 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -71,6 +71,12 @@ public:
FPC_Fast // Aggressively fuse FP ops (E.g. FMA).
};
+ enum StructReturnConventionKind {
+ SRCK_Default, // No special option was passed.
+ SRCK_OnStack, // Small structs on the stack (-fpcc-struct-return).
+ SRCK_InRegs // Small structs in registers (-freg-struct-return).
+ };
+
/// The code model to use (-mcmodel).
std::string CodeModel;
@@ -122,6 +128,12 @@ public:
/// A list of command-line options to forward to the LLVM backend.
std::vector<std::string> BackendOptions;
+ /// A list of dependent libraries.
+ std::vector<std::string> DependentLibraries;
+
+ /// Name of the profile file to use with -fprofile-sample-use.
+ std::string SampleProfileFile;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index dbd76066b94e..5673c5908d78 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -395,7 +395,7 @@ public:
/// @name ASTConsumer
/// {
- bool hasASTConsumer() const { return Consumer != 0; }
+ bool hasASTConsumer() const { return Consumer.isValid(); }
ASTConsumer &getASTConsumer() const {
assert(Consumer && "Compiler instance has no AST consumer!");
@@ -413,7 +413,7 @@ public:
/// }
/// @name Semantic analysis
/// {
- bool hasSema() const { return TheSema != 0; }
+ bool hasSema() const { return TheSema.isValid(); }
Sema &getSema() const {
assert(TheSema && "Compiler instance has no Sema object!");
@@ -433,7 +433,9 @@ public:
/// @name Code Completion
/// {
- bool hasCodeCompletionConsumer() const { return CompletionConsumer != 0; }
+ bool hasCodeCompletionConsumer() const {
+ return CompletionConsumer.isValid();
+ }
CodeCompleteConsumer &getCodeCompletionConsumer() const {
assert(CompletionConsumer &&
@@ -455,7 +457,7 @@ public:
/// @name Frontend timer
/// {
- bool hasFrontendTimer() const { return FrontendTimer != 0; }
+ bool hasFrontendTimer() const { return FrontendTimer.isValid(); }
llvm::Timer &getFrontendTimer() const {
assert(FrontendTimer && "Compiler instance has no frontend timer!");
@@ -589,10 +591,10 @@ public:
/// \return - Null on error.
llvm::raw_fd_ostream *
createOutputFile(StringRef OutputPath,
- bool Binary = true, bool RemoveFileOnSignal = true,
- StringRef BaseInput = "",
- StringRef Extension = "",
- bool UseTemporary = false,
+ bool Binary, bool RemoveFileOnSignal,
+ StringRef BaseInput,
+ StringRef Extension,
+ bool UseTemporary,
bool CreateMissingDirectories = false);
/// Create a new output file, optionally deriving the output path name.
@@ -622,13 +624,13 @@ public:
/// will be stored here on success.
static llvm::raw_fd_ostream *
createOutputFile(StringRef OutputPath, std::string &Error,
- bool Binary = true, bool RemoveFileOnSignal = true,
- StringRef BaseInput = "",
- StringRef Extension = "",
- bool UseTemporary = false,
- bool CreateMissingDirectories = false,
- std::string *ResultPathName = 0,
- std::string *TempPathName = 0);
+ bool Binary, bool RemoveFileOnSignal,
+ StringRef BaseInput,
+ StringRef Extension,
+ bool UseTemporary,
+ bool CreateMissingDirectories,
+ std::string *ResultPathName,
+ std::string *TempPathName);
/// }
/// @name Initialization Utility Methods
@@ -662,6 +664,10 @@ public:
SourceLocation ImportLoc,
bool Complain);
+ bool hadModuleLoaderFatalFailure() const {
+ return ModuleLoader::HadFatalFailure;
+ }
+
};
} // end namespace clang
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index fac05c55fbb1..f64773c2c4bd 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -29,15 +29,16 @@
#include <string>
#include <vector>
-namespace clang {
+namespace llvm {
+namespace opt {
+class ArgList;
+}
+}
+namespace clang {
class CompilerInvocation;
class DiagnosticsEngine;
-namespace driver {
-class ArgList;
-}
-
/// \brief Fill out Opts based on the options given in Args.
///
/// Args must have been created from the OptTable returned by
@@ -45,9 +46,9 @@ class ArgList;
///
/// When errors are encountered, return false and, if Diags is non-null,
/// report the error(s).
-bool ParseDiagnosticArgs(DiagnosticOptions &Opts, driver::ArgList &Args,
+bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args,
DiagnosticsEngine *Diags = 0);
-
+
class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
protected:
/// Options controlling the language variant.
diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h
index 83976c36048f..fefb6f3eda84 100644
--- a/include/clang/Frontend/DependencyOutputOptions.h
+++ b/include/clang/Frontend/DependencyOutputOptions.h
@@ -25,6 +25,7 @@ public:
/// dependency, which can avoid some 'make'
/// problems.
unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
+ unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
/// The file to write dependency output to.
std::string OutputFile;
@@ -48,6 +49,7 @@ public:
ShowHeaderIncludes = 0;
UsePhonyTargets = 0;
AddMissingHeaderDeps = 0;
+ PrintShowIncludes = 0;
}
};
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index c67be924720c..a568ba02d2a0 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -94,6 +94,14 @@ protected:
/// BeginSourceFileAction (and BeginSourceFile).
virtual void EndSourceFileAction() {}
+ /// \brief Callback at the end of processing a single input, to determine
+ /// if the output files should be erased or not.
+ ///
+ /// By default it returns true if a compiler error occurred.
+ /// This is guaranteed to only be called following a successful call to
+ /// BeginSourceFileAction (and BeginSourceFile).
+ virtual bool shouldEraseOutputFiles();
+
/// @}
public:
@@ -116,7 +124,7 @@ public:
bool isCurrentFileAST() const {
assert(!CurrentInput.isEmpty() && "No current file!");
- return CurrentASTUnit != 0;
+ return CurrentASTUnit.isValid();
}
const FrontendInputFile &getCurrentInput() const {
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 178619047a38..f3d12769f143 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -56,12 +56,6 @@ protected:
StringRef InFile);
};
-class ASTDumpXMLAction : public ASTFrontendAction {
-protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
-};
-
class ASTViewAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
@@ -99,6 +93,7 @@ public:
class GenerateModuleAction : public ASTFrontendAction {
clang::Module *Module;
+ bool IsSystem;
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
@@ -111,6 +106,9 @@ protected:
virtual bool hasASTFileSupport() const { return false; }
public:
+ explicit GenerateModuleAction(bool IsSystem = false)
+ : ASTFrontendAction(), IsSystem(IsSystem) { }
+
virtual bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename);
/// \brief Compute the AST consumer arguments that will be used to
diff --git a/include/clang/Frontend/FrontendDiagnostic.h b/include/clang/Frontend/FrontendDiagnostic.h
index 0b05b74b9cce..312dbf14115b 100644
--- a/include/clang/Frontend/FrontendDiagnostic.h
+++ b/include/clang/Frontend/FrontendDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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 234e3446c809..4b321e86d29c 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -26,7 +26,6 @@ namespace frontend {
enum ActionKind {
ASTDeclList, ///< Parse ASTs and list Decl nodes.
ASTDump, ///< Parse ASTs and dump them.
- ASTDumpXML, ///< Parse ASTs and dump them in XML.
ASTPrint, ///< Parse ASTs and print them.
ASTView, ///< Parse ASTs and view them in Graphviz.
DumpRawTokens, ///< Dump out raw tokens.
@@ -142,6 +141,8 @@ public:
///< global module index if available.
unsigned GenerateGlobalModuleIndex : 1; ///< Whether we can generate the
///< global module index if needed.
+ unsigned ASTDumpLookups : 1; ///< Whether we include lookup table
+ ///< dumps in AST dumps.
CodeCompleteOptions CodeCompleteOpts;
@@ -157,9 +158,35 @@ public:
/// \brief Enable migration to modern ObjC literals.
ObjCMT_Literals = 0x1,
/// \brief Enable migration to modern ObjC subscripting.
- ObjCMT_Subscripting = 0x2
+ ObjCMT_Subscripting = 0x2,
+ /// \brief Enable migration to modern ObjC readonly property.
+ ObjCMT_ReadonlyProperty = 0x4,
+ /// \brief Enable migration to modern ObjC readwrite property.
+ ObjCMT_ReadwriteProperty = 0x8,
+ /// \brief Enable migration to modern ObjC property.
+ ObjCMT_Property = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty),
+ /// \brief Enable annotation of ObjCMethods of all kinds.
+ ObjCMT_Annotation = 0x10,
+ /// \brief Enable migration of ObjC methods to 'instancetype'.
+ ObjCMT_Instancetype = 0x20,
+ /// \brief Enable migration to NS_ENUM/NS_OPTIONS macros.
+ ObjCMT_NsMacros = 0x40,
+ /// \brief Enable migration to add conforming protocols.
+ ObjCMT_ProtocolConformance = 0x80,
+ /// \brief prefer 'atomic' property over 'nonatomic'.
+ ObjCMT_AtomicProperty = 0x100,
+ /// \brief annotate property with NS_RETURNS_INNER_POINTER
+ ObjCMT_ReturnsInnerPointerProperty = 0x200,
+ /// \brief use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
+ ObjCMT_NsAtomicIOSOnlyProperty = 0x400,
+ ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty |
+ ObjCMT_Annotation | ObjCMT_Instancetype |
+ ObjCMT_NsMacros | ObjCMT_ProtocolConformance |
+ ObjCMT_NsAtomicIOSOnlyProperty),
+ ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | ObjCMT_MigrateDecls)
};
unsigned ObjCMTAction;
+ std::string ObjCMTWhiteListPath;
std::string MTMigrateDir;
std::string ARCMTMigrateReportOut;
@@ -215,7 +242,7 @@ public:
FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false),
FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
SkipFunctionBodies(false), UseGlobalModuleIndex(true),
- GenerateGlobalModuleIndex(true),
+ GenerateGlobalModuleIndex(true), ASTDumpLookups(false),
ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None),
ProgramAction(frontend::ParseSyntaxOnly)
{}
diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h
index 656aa57e6e5a..c8d01b0b15eb 100644
--- a/include/clang/Frontend/TextDiagnostic.h
+++ b/include/clang/Frontend/TextDiagnostic.h
@@ -51,7 +51,8 @@ public:
/// TextDiagnostic logic requires.
static void printDiagnosticLevel(raw_ostream &OS,
DiagnosticsEngine::Level Level,
- bool ShowColors);
+ bool ShowColors,
+ bool CLFallbackMode = false);
/// \brief Pretty-print a diagnostic message to a raw_ostream.
///
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 8830dced3cc2..dff56c3a8a4e 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -17,10 +17,15 @@
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/OptSpecifier.h"
namespace llvm {
class raw_fd_ostream;
class Triple;
+
+namespace opt {
+class ArgList;
+}
}
namespace clang {
@@ -86,9 +91,11 @@ void AttachDependencyFileGen(Preprocessor &PP,
/// 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.
+/// \param ShowDepth - Whether to indent to show the nesting of the includes.
+/// \param MSStyle - Whether to print in cl.exe /showIncludes style.
void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false,
StringRef OutputPath = "",
- bool ShowDepth = true);
+ bool ShowDepth = true, bool MSStyle = false);
/// CacheTokens - Cache tokens for use with PCH. Note that this requires
/// a seekable stream.
@@ -104,6 +111,18 @@ createInvocationFromCommandLine(ArrayRef<const char *> Args,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
IntrusiveRefCntPtr<DiagnosticsEngine>());
-} // end namespace clang
+/// Return the value of the last argument as an integer, or a default. If Diags
+/// is non-null, emits an error if the argument is given, but non-integral.
+int getLastArgIntValue(const llvm::opt::ArgList &Args,
+ llvm::opt::OptSpecifier Id, int Default,
+ DiagnosticsEngine *Diags = 0);
+
+inline int getLastArgIntValue(const llvm::opt::ArgList &Args,
+ llvm::opt::OptSpecifier Id, int Default,
+ DiagnosticsEngine &Diags) {
+ return getLastArgIntValue(Args, Id, Default, &Diags);
+}
+
+} // end namespace clang
#endif
diff --git a/include/clang/Index/CommentToXML.h b/include/clang/Index/CommentToXML.h
new file mode 100644
index 000000000000..8444b145343f
--- /dev/null
+++ b/include/clang/Index/CommentToXML.h
@@ -0,0 +1,50 @@
+//===--- CommentToXML.h - Convert comments to XML representation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_COMMENTTOXML_H
+#define LLVM_CLANG_INDEX_COMMENTTOXML_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+class ASTContext;
+
+namespace comments {
+class FullComment;
+class HTMLTagComment;
+}
+
+namespace index {
+class SimpleFormatContext;
+
+class CommentToXMLConverter {
+ SimpleFormatContext *FormatContext;
+ unsigned FormatInMemoryUniqueId;
+
+public:
+ CommentToXMLConverter() : FormatContext(0), FormatInMemoryUniqueId(0) {}
+
+ void convertCommentToHTML(const comments::FullComment *FC,
+ SmallVectorImpl<char> &HTML,
+ const ASTContext &Context);
+
+ void convertHTMLTagNodeToText(const comments::HTMLTagComment *HTC,
+ SmallVectorImpl<char> &Text,
+ const ASTContext &Context);
+
+ void convertCommentToXML(const comments::FullComment *FC,
+ SmallVectorImpl<char> &XML,
+ const ASTContext &Context);
+};
+
+} // namespace index
+} // namespace clang
+
+#endif // LLVM_CLANG_INDEX_COMMENTTOXML_H
+
diff --git a/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h
new file mode 100644
index 000000000000..7b0fd5063ac6
--- /dev/null
+++ b/include/clang/Index/USRGeneration.h
@@ -0,0 +1,54 @@
+//===- USRGeneration.h - Routines for USR generation ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_USRGENERATION_H
+#define LLVM_CLANG_INDEX_USRGENERATION_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ class Decl;
+
+namespace index {
+
+static inline StringRef getUSRSpacePrefix() {
+ return "c:";
+}
+
+/// \brief Generate a USR for a Decl, including the prefix.
+/// \returns true if the results should be ignored, false otherwise.
+bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf);
+
+/// \brief Generate a USR fragment for an Objective-C class.
+void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C class category.
+void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C instance variable. The
+/// complete USR can be created by concatenating the USR for the
+/// encompassing class with this USR fragment.
+void generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C method.
+void generateUSRForObjCMethod(StringRef Sel, bool IsInstanceMethod,
+ raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C property.
+void generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C protocol.
+void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS);
+
+} // namespace index
+} // namespace clang
+
+#endif // LLVM_CLANG_IDE_USRGENERATION_H
+
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index 261dfabc0fd2..dff3e8c3608d 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -16,6 +16,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/ModuleMap.h"
namespace clang {
class HeaderMap;
@@ -129,6 +130,11 @@ public:
return (SrcMgr::CharacteristicKind)DirCharacteristic;
}
+ /// \brief Whether this describes a system header directory.
+ bool isSystemHeaderDirectory() const {
+ return getDirCharacteristic() != SrcMgr::C_User;
+ }
+
/// \brief Whether this header map is building a framework or not.
bool isIndexHeaderMap() const {
return isHeaderMap() && IsIndexHeaderMap;
@@ -158,7 +164,7 @@ public:
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework) const;
private:
@@ -166,7 +172,7 @@ private:
StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemHeader) const;
};
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 8a5a798560de..fb1a86206354 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -53,6 +53,13 @@ struct HeaderFileInfo {
/// \brief Whether this header is part of a module.
unsigned isModuleHeader : 1;
+
+ /// \brief Whether this header is part of the module that we are building.
+ unsigned isCompilingModuleHeader : 1;
+
+ /// \brief Whether this header is part of the module that we are building.
+ /// This is an instance of ModuleMap::ModuleHeaderRole.
+ unsigned HeaderRole : 2;
/// \brief Whether this structure is considered to already have been
/// "resolved", meaning that it was loaded from the external source.
@@ -93,8 +100,9 @@ struct HeaderFileInfo {
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
- External(false), isModuleHeader(false), Resolved(false),
- IndexHeaderMapHeader(false),
+ External(false), isModuleHeader(false), isCompilingModuleHeader(false),
+ HeaderRole(ModuleMap::NormalHeader),
+ Resolved(false), IndexHeaderMapHeader(false),
NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {}
/// \brief Retrieve the controlling macro for this header file, if
@@ -107,6 +115,16 @@ struct HeaderFileInfo {
return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
ControllingMacroID;
}
+
+ /// \brief Get the HeaderRole properly typed.
+ ModuleMap::ModuleHeaderRole getHeaderRole() const {
+ return static_cast<ModuleMap::ModuleHeaderRole>(HeaderRole);
+ }
+
+ /// \brief Set the HeaderRole properly typed.
+ void setHeaderRole(ModuleMap::ModuleHeaderRole Role) {
+ HeaderRole = Role;
+ }
};
/// \brief An external source of header file information, which may supply
@@ -222,7 +240,7 @@ class HeaderSearch {
public:
HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts,
- FileManager &FM, DiagnosticsEngine &Diags,
+ SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target);
~HeaderSearch();
@@ -261,7 +279,7 @@ public:
/// \brief Checks whether the map exists or not.
bool HasIncludeAliasMap() const {
- return IncludeAliases;
+ return IncludeAliases.isValid();
}
/// \brief Map the source include name to the dest include name.
@@ -354,7 +372,7 @@ public:
const FileEntry *CurFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache = false);
/// \brief Look up a subframework for the specified \#include file.
@@ -368,7 +386,7 @@ public:
const FileEntry *RelativeFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule);
+ ModuleMap::KnownHeader *SuggestedModule);
/// \brief Look up the specified framework name in our framework cache.
/// \returns The DirectoryEntry it is in if we know, null otherwise.
@@ -405,7 +423,9 @@ public:
}
/// \brief Mark the specified file as part of a module.
- void MarkFileModuleHeader(const FileEntry *File);
+ void MarkFileModuleHeader(const FileEntry *File,
+ ModuleMap::ModuleHeaderRole Role,
+ bool IsCompiledModuleHeader);
/// \brief Increment the count for the number of times the specified
/// FileEntry has been entered.
@@ -422,6 +442,11 @@ public:
getFileInfo(File).ControllingMacro = ControllingMacro;
}
+ /// \brief Return true if this is the first time encountering this header.
+ bool FirstTimeLexingFile(const FileEntry *File) {
+ return getFileInfo(File).NumIncludes == 1;
+ }
+
/// \brief Determine whether this file is intended to be safe from
/// multiple inclusions, e.g., it has \#pragma once or a controlling
/// macro.
@@ -471,25 +496,33 @@ public:
///
/// \param Root The "root" directory, at which we should stop looking for
/// module maps.
- bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root);
+ ///
+ /// \param IsSystem Whether the directories we're looking at are system
+ /// header directories.
+ bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root,
+ bool IsSystem);
/// \brief Retrieve the module that corresponds to the given file, if any.
///
/// \param File The header that we wish to map to a module.
- Module *findModuleForHeader(const FileEntry *File) const;
+ ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File) const;
/// \brief Read the contents of the given module map file.
///
/// \param File The module map file.
+ /// \param IsSystem Whether this file is in a system header directory.
///
/// \returns true if an error occurred, false otherwise.
- bool loadModuleMapFile(const FileEntry *File);
+ bool loadModuleMapFile(const FileEntry *File, bool IsSystem);
/// \brief Collect the set of all known, top-level modules.
///
/// \param Modules Will be filled with the set of known, top-level modules.
void collectAllModules(SmallVectorImpl<Module *> &Modules);
-
+
+ /// \brief Load all known, top-level system modules.
+ void loadTopLevelSystemModules();
+
private:
/// \brief Retrieve a module with the given name, which may be part of the
/// given framework.
@@ -516,9 +549,6 @@ public:
unsigned header_file_size() const { return FileInfo.size(); }
- // Used by ASTReader.
- void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
-
/// \brief Return the HeaderFileInfo structure for the specified FileEntry.
const HeaderFileInfo &getFileInfo(const FileEntry *FE) const {
return const_cast<HeaderSearch*>(this)->getFileInfo(FE);
@@ -577,18 +607,21 @@ private:
///
/// \param DirName The name of the directory where we will look for a module
/// map file.
+ /// \param IsSystem Whether this is a system header directory.
///
/// \returns The result of attempting to load the module map file from the
/// named directory.
- LoadModuleMapResult loadModuleMapFile(StringRef DirName);
+ LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem);
/// \brief Try to load the module map file in the given directory.
///
/// \param Dir The directory where we will look for a module map file.
+ /// \param IsSystem Whether this is a system header directory.
///
/// \returns The result of attempting to load the module map file from the
/// named directory.
- LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir);
+ LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir,
+ bool IsSystem);
/// \brief Return the HeaderFileInfo structure for the specified FileEntry.
HeaderFileInfo &getFileInfo(const FileEntry *FE);
diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index afce5ba18b3b..0b21c0dd3492 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -95,6 +95,9 @@ public:
/// Note: Only used for testing!
unsigned DisableModuleHash : 1;
+ /// \brief Interpret module maps. This option is implied by full modules.
+ unsigned ModuleMaps : 1;
+
/// \brief The interval (in seconds) between pruning operations.
///
/// This operation is expensive, because it requires Clang to walk through
@@ -117,6 +120,9 @@ public:
/// of computing the module hash.
llvm::SetVector<std::string> ModulesIgnoreMacros;
+ /// \brief The set of user-provided module-map-files.
+ llvm::SetVector<std::string> ModuleMapFiles;
+
/// Include the compiler builtin includes.
unsigned UseBuiltinIncludes : 1;
@@ -134,7 +140,7 @@ public:
public:
HeaderSearchOptions(StringRef _Sysroot = "/")
- : Sysroot(_Sysroot), DisableModuleHash(0),
+ : Sysroot(_Sysroot), DisableModuleHash(0), ModuleMaps(0),
ModuleCachePruneInterval(7*24*60*60),
ModuleCachePruneAfter(31*24*60*60),
UseBuiltinIncludes(true),
diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h
index 41b93963a7ee..85424aa8a10f 100644
--- a/include/clang/Lex/LexDiagnostic.h
+++ b/include/clang/Lex/LexDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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 cb4f57fb9cf4..f456fa9cd51c 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -80,6 +80,12 @@ class Lexer : public PreprocessorLexer {
// line" flag set on it.
bool IsAtStartOfLine;
+ bool IsAtPhysicalStartOfLine;
+
+ bool HasLeadingSpace;
+
+ bool HasLeadingEmptyMacro;
+
// CurrentConflictMarkerState - The kind of conflict marker we are handling.
ConflictMarkerKind CurrentConflictMarkerState;
@@ -127,31 +133,21 @@ public:
/// from. Currently this is only used by _Pragma handling.
SourceLocation getFileLoc() const { return FileLoc; }
+private:
/// Lex - Return the next token in the file. If this is the end of file, it
/// return the tok::eof token. This implicitly involves the preprocessor.
- void Lex(Token &Result) {
- // Start a new token.
- Result.startToken();
-
- // NOTE, any changes here should also change code after calls to
- // Preprocessor::HandleDirective
- if (IsAtStartOfLine) {
- Result.setFlag(Token::StartOfLine);
- IsAtStartOfLine = false;
- }
-
- // Get a token. Note that this may delete the current lexer if the end of
- // file is reached.
- LexTokenInternal(Result);
- }
+ bool Lex(Token &Result);
+public:
/// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma.
bool isPragmaLexer() const { return Is_PragmaLexer; }
+private:
/// IndirectLex - An indirect call to 'Lex' that can be invoked via
/// the PreprocessorLexer interface.
void IndirectLex(Token &Result) { Lex(Result); }
+public:
/// LexFromRawLexer - Lex a token from a designated raw lexer (one with no
/// associated preprocessor object. Return true if the 'next character to
/// read' pointer points at the end of the lexer buffer, false otherwise.
@@ -202,7 +198,10 @@ public:
/// lexer has nothing to reset to.
void resetExtendedTokenMode();
- const char *getBufferStart() const { return BufferStart; }
+ /// Gets source code buffer.
+ StringRef getBuffer() const {
+ return StringRef(BufferStart, BufferEnd - BufferStart);
+ }
/// ReadToEndOfLine - Read the rest of the current preprocessor line as an
/// uninterpreted string. This switches the lexer out of directive mode.
@@ -285,7 +284,8 @@ public:
/// \returns true if there was a failure, false on success.
static bool getRawToken(SourceLocation Loc, Token &Result,
const SourceManager &SM,
- const LangOptions &LangOpts);
+ const LangOptions &LangOpts,
+ bool IgnoreWhiteSpace = false);
/// \brief Given a location any where in a source buffer, find the location
/// that corresponds to the beginning of the token in which the original
@@ -443,12 +443,14 @@ private:
/// LexTokenInternal - Internal interface to lex a preprocessing token. Called
/// by Lex.
///
- void LexTokenInternal(Token &Result);
+ bool LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine);
+
+ bool CheckUnicodeWhitespace(Token &Result, uint32_t C, const char *CurPtr);
/// Given that a token begins with the Unicode character \p C, figure out
/// what kind of token it is and dispatch to the appropriate lexing helper
/// function.
- void LexUnicode(Token &Result, uint32_t C, const char *CurPtr);
+ bool LexUnicode(Token &Result, uint32_t C, const char *CurPtr);
/// FormTokenWithChars - When we lex a token, we have identified a span
/// starting at BufferPtr, going to TokEnd that forms the token. This method
@@ -566,23 +568,28 @@ private:
void SkipBytes(unsigned Bytes, bool StartOfLine);
- const char *LexUDSuffix(Token &Result, const char *CurPtr);
-
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+
+ const char *LexUDSuffix(Token &Result, const char *CurPtr,
+ bool IsStringLiteral);
+
// Helper functions to lex the remainder of a token of the specific type.
- void LexIdentifier (Token &Result, const char *CurPtr);
- void LexNumericConstant (Token &Result, const char *CurPtr);
- void LexStringLiteral (Token &Result, const char *CurPtr,
+ bool LexIdentifier (Token &Result, const char *CurPtr);
+ bool LexNumericConstant (Token &Result, const char *CurPtr);
+ bool LexStringLiteral (Token &Result, const char *CurPtr,
tok::TokenKind Kind);
- void LexRawStringLiteral (Token &Result, const char *CurPtr,
+ bool LexRawStringLiteral (Token &Result, const char *CurPtr,
tok::TokenKind Kind);
- void LexAngledStringLiteral(Token &Result, const char *CurPtr);
- void LexCharConstant (Token &Result, const char *CurPtr,
+ bool LexAngledStringLiteral(Token &Result, const char *CurPtr);
+ bool LexCharConstant (Token &Result, const char *CurPtr,
tok::TokenKind Kind);
bool LexEndOfFile (Token &Result, const char *CurPtr);
-
- bool SkipWhitespace (Token &Result, const char *CurPtr);
- bool SkipLineComment (Token &Result, const char *CurPtr);
- bool SkipBlockComment (Token &Result, const char *CurPtr);
+ bool SkipWhitespace (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SkipLineComment (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SkipBlockComment (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
bool SaveLineComment (Token &Result, const char *CurPtr);
bool IsStartOfConflictMarker(const char *CurPtr);
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index b1430cc80519..64d5aa2d5928 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -79,6 +79,8 @@ public:
return SuffixBegin - ThisTokBegin;
}
+ static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix);
+
unsigned getRadix() const { return radix; }
/// GetIntegerValue - Convert this numeric literal value to an APInt that
@@ -98,10 +100,18 @@ private:
void ParseNumberStartingWithZero(SourceLocation TokLoc);
+ static bool isDigitSeparator(char C) { return C == '\''; }
+
+ enum CheckSeparatorKind { CSK_BeforeDigits, CSK_AfterDigits };
+
+ /// \brief Ensure that we don't have a digit separator here.
+ void checkSeparator(SourceLocation TokLoc, const char *Pos,
+ CheckSeparatorKind IsAfterDigits);
+
/// SkipHexDigits - Read and skip over any hex digits, up to End.
/// Return a pointer to the first non-hex digit or End.
const char *SkipHexDigits(const char *ptr) {
- while (ptr != ThisTokEnd && isHexDigit(*ptr))
+ while (ptr != ThisTokEnd && (isHexDigit(*ptr) || isDigitSeparator(*ptr)))
ptr++;
return ptr;
}
@@ -109,7 +119,8 @@ private:
/// SkipOctalDigits - Read and skip over any octal digits, up to End.
/// Return a pointer to the first non-hex digit or End.
const char *SkipOctalDigits(const char *ptr) {
- while (ptr != ThisTokEnd && ((*ptr >= '0') && (*ptr <= '7')))
+ while (ptr != ThisTokEnd &&
+ ((*ptr >= '0' && *ptr <= '7') || isDigitSeparator(*ptr)))
ptr++;
return ptr;
}
@@ -117,7 +128,7 @@ private:
/// SkipDigits - Read and skip over any digits, up to End.
/// Return a pointer to the first non-hex digit or End.
const char *SkipDigits(const char *ptr) {
- while (ptr != ThisTokEnd && isDigit(*ptr))
+ while (ptr != ThisTokEnd && (isDigit(*ptr) || isDigitSeparator(*ptr)))
ptr++;
return ptr;
}
@@ -125,7 +136,8 @@ private:
/// SkipBinaryDigits - Read and skip over any binary digits, up to End.
/// Return a pointer to the first non-binary digit or End.
const char *SkipBinaryDigits(const char *ptr) {
- while (ptr != ThisTokEnd && (*ptr == '0' || *ptr == '1'))
+ while (ptr != ThisTokEnd &&
+ (*ptr == '0' || *ptr == '1' || isDigitSeparator(*ptr)))
ptr++;
return ptr;
}
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 64323b7c765f..8cb370e6f833 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -251,7 +251,7 @@ public:
return ReplacementTokens[Tok];
}
- typedef SmallVector<Token, 8>::const_iterator tokens_iterator;
+ typedef SmallVectorImpl<Token>::const_iterator tokens_iterator;
tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); }
tokens_iterator tokens_end() const { return ReplacementTokens.end(); }
bool tokens_empty() const { return ReplacementTokens.empty(); }
@@ -421,7 +421,7 @@ public:
bool isValid() const { return DefDirective != 0; }
bool isInvalid() const { return !isValid(); }
- operator bool() const { return isValid(); }
+ LLVM_EXPLICIT operator bool() const { return isValid(); }
inline DefInfo getPreviousDefinition(bool AllowHidden = false);
const DefInfo getPreviousDefinition(bool AllowHidden = false) const {
diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h
index 3acf9151bc52..254ab36fe960 100644
--- a/include/clang/Lex/ModuleLoader.h
+++ b/include/clang/Lex/ModuleLoader.h
@@ -54,6 +54,8 @@ public:
/// then loading that module.
class ModuleLoader {
public:
+ ModuleLoader() : HadFatalFailure(false) {}
+
virtual ~ModuleLoader();
/// \brief Attempt to load the given module.
@@ -85,6 +87,8 @@ public:
Module::NameVisibilityKind Visibility,
SourceLocation ImportLoc,
bool Complain) = 0;
+
+ bool HadFatalFailure;
};
}
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index dc75f1803cb7..3a17157f94d5 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -37,7 +37,7 @@ class HeaderSearch;
class ModuleMapParser;
class ModuleMap {
- SourceManager *SourceMgr;
+ SourceManager &SourceMgr;
IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
const LangOptions &LangOpts;
const TargetInfo *Target;
@@ -52,37 +52,64 @@ class ModuleMap {
/// These are always simple C language options.
LangOptions MMapLangOpts;
+ // The module that we are building; related to \c LangOptions::CurrentModule.
+ Module *CompilingModule;
+
+public:
+ // The module that the .cc source file is associated with.
+ Module *SourceModule;
+ std::string SourceModuleName;
+
+private:
/// \brief The top-level modules that are known.
llvm::StringMap<Module *> Modules;
+public:
+ /// \brief Describes the role of a module header.
+ enum ModuleHeaderRole {
+ /// \brief This header is normally included in the module.
+ NormalHeader,
+ /// \brief This header is included but private.
+ PrivateHeader,
+ /// \brief This header is explicitly excluded from the module.
+ ExcludedHeader
+ // Caution: Adding an enumerator needs other changes.
+ // Adjust the number of bits for KnownHeader::Storage.
+ // Adjust the bitfield HeaderFileInfo::HeaderRole size.
+ // Adjust the HeaderFileInfoTrait::ReadData streaming.
+ // Adjust the HeaderFileInfoTrait::EmitData streaming.
+ };
+
/// \brief A header that is known to reside within a given module,
/// whether it was included or excluded.
class KnownHeader {
- llvm::PointerIntPair<Module *, 1, bool> Storage;
+ llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
public:
- KnownHeader() : Storage(0, false) { }
- KnownHeader(Module *M, bool Excluded) : Storage(M, Excluded) { }
+ KnownHeader() : Storage(0, NormalHeader) { }
+ KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
/// \brief Retrieve the module the header is stored in.
Module *getModule() const { return Storage.getPointer(); }
- /// \brief Whether this header is explicitly excluded from the module.
- bool isExcluded() const { return Storage.getInt(); }
+ /// \brief The role of this header within the module.
+ ModuleHeaderRole getRole() const { return Storage.getInt(); }
/// \brief Whether this header is available in the module.
bool isAvailable() const {
- return !isExcluded() && getModule()->isAvailable();
+ return getRole() != ExcludedHeader && getModule()->isAvailable();
}
// \brief Whether this known header is valid (i.e., it has an
// associated module).
- operator bool() const { return Storage.getPointer() != 0; }
+ LLVM_EXPLICIT operator bool() const { return Storage.getPointer() != 0; }
};
- typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
+private:
+ typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1> >
+ HeadersMap;
- /// \brief Mapping from each header to the module that owns the contents of the
+ /// \brief Mapping from each header to the module that owns the contents of
/// that header.
HeadersMap Headers;
@@ -151,9 +178,9 @@ class ModuleMap {
public:
/// \brief Construct a new module map.
///
- /// \param FileMgr The file manager used to find module files and headers.
- /// This file manager should be shared with the header-search mechanism, since
- /// they will refer to the same headers.
+ /// \param SourceMgr The source manager used to find module files and headers.
+ /// This source manager should be shared with the header-search mechanism,
+ /// since they will refer to the same headers.
///
/// \param DC A diagnostic consumer that will be cloned for use in generating
/// diagnostics.
@@ -161,7 +188,7 @@ public:
/// \param LangOpts Language options for this translation unit.
///
/// \param Target The target for this translation unit.
- ModuleMap(FileManager &FileMgr, DiagnosticConsumer &DC,
+ ModuleMap(SourceManager &SourceMgr, DiagnosticConsumer &DC,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo);
@@ -182,9 +209,15 @@ public:
///
/// \param File The header file that is likely to be included.
///
- /// \returns The module that owns the given header file, or null to indicate
+ /// \param RequestingModule Specifies the module the header is intended to be
+ /// used from. Used to disambiguate if a header is present in multiple
+ /// modules.
+ ///
+ /// \returns The module KnownHeader, which provides the module that owns the
+ /// given header file. The KnownHeader is default constructed to indicate
/// that no module owns this header file.
- Module *findModuleForHeader(const FileEntry *File);
+ KnownHeader findModuleForHeader(const FileEntry *File,
+ Module *RequestingModule = NULL);
/// \brief Determine whether the given header is part of a module
/// marked 'unavailable'.
@@ -278,6 +311,16 @@ public:
/// false otherwise.
bool resolveExports(Module *Mod, bool Complain);
+ /// \brief Resolve all of the unresolved uses in the given module.
+ ///
+ /// \param Mod The module whose uses should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving uses,
+ /// false otherwise.
+ bool resolveUses(Module *Mod, bool Complain);
+
/// \brief Resolve all of the unresolved conflicts in the given module.
///
/// \param Mod The module whose conflicts should be resolved.
@@ -307,17 +350,20 @@ public:
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir);
/// \brief Adds this header to the given module.
- /// \param Excluded Whether this header is explicitly excluded from the
- /// module; otherwise, it's included in the module.
- void addHeader(Module *Mod, const FileEntry *Header, bool Excluded);
+ /// \param Role The role of the header wrt the module.
+ void addHeader(Module *Mod, const FileEntry *Header,
+ ModuleHeaderRole Role);
/// \brief Parse the given module map file, and record any modules we
/// encounter.
///
/// \param File The file to be parsed.
///
+ /// \param IsSystem Whether this module map file is in a system header
+ /// directory, and therefore should be considered a system module.
+ ///
/// \returns true if an error occurred, false otherwise.
- bool parseModuleMapFile(const FileEntry *File);
+ bool parseModuleMapFile(const FileEntry *File, bool IsSystem);
/// \brief Dump the contents of the module map, for debugging purposes.
void dump();
diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h
index a2a5a77c73d7..b532bf82f049 100644
--- a/include/clang/Lex/MultipleIncludeOpt.h
+++ b/include/clang/Lex/MultipleIncludeOpt.h
@@ -15,6 +15,8 @@
#ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H
#define LLVM_CLANG_MULTIPLEINCLUDEOPT_H
+#include "clang/Basic/SourceLocation.h"
+
namespace clang {
class IdentifierInfo;
@@ -32,6 +34,11 @@ class MultipleIncludeOpt {
/// \#endif can be easily detected.
bool ReadAnyTokens;
+ /// ImmediatelyAfterTopLevelIfndef - This is true when the only tokens
+ /// processed in the file so far is an #ifndef and an identifier. Used in
+ /// the detection of header guards in a file.
+ bool ImmediatelyAfterTopLevelIfndef;
+
/// ReadAnyTokens - This is set to false when a file is first opened and true
/// any time a token is returned to the client or a (non-multiple-include)
/// directive is parsed. When the final #endif is parsed this is reset back
@@ -42,11 +49,36 @@ class MultipleIncludeOpt {
/// TheMacro - The controlling macro for a file, if valid.
///
const IdentifierInfo *TheMacro;
+
+ /// DefinedMacro - The macro defined right after TheMacro, if any.
+ const IdentifierInfo *DefinedMacro;
+
+ SourceLocation MacroLoc;
+ SourceLocation DefinedLoc;
public:
MultipleIncludeOpt() {
ReadAnyTokens = false;
+ ImmediatelyAfterTopLevelIfndef = false;
DidMacroExpansion = false;
TheMacro = 0;
+ DefinedMacro = 0;
+ }
+
+ SourceLocation GetMacroLocation() const {
+ return MacroLoc;
+ }
+
+ SourceLocation GetDefinedLocation() const {
+ return DefinedLoc;
+ }
+
+ void resetImmediatelyAfterTopLevelIfndef() {
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
+
+ void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc) {
+ DefinedMacro = M;
+ DefinedLoc = Loc;
}
/// Invalidate - Permanently mark this file as not being suitable for the
@@ -55,6 +87,8 @@ public:
// If we have read tokens but have no controlling macro, the state-machine
// below can never "accept".
ReadAnyTokens = true;
+ ImmediatelyAfterTopLevelIfndef = false;
+ DefinedMacro = 0;
TheMacro = 0;
}
@@ -63,8 +97,17 @@ public:
/// the "ifndef x" would count as reading tokens.
bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
+ /// getImmediatelyAfterTopLevelIfndef - returns true if the last directive
+ /// was an #ifndef at the beginning of the file.
+ bool getImmediatelyAfterTopLevelIfndef() const {
+ return ImmediatelyAfterTopLevelIfndef;
+ }
+
// If a token is read, remember that we have seen a side-effect in this file.
- void ReadToken() { ReadAnyTokens = true; }
+ void ReadToken() {
+ ReadAnyTokens = true;
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
/// ExpandedMacro - When a macro is expanded with this lexer as the current
/// buffer, this method is called to disable the MIOpt if needed.
@@ -77,7 +120,7 @@ public:
/// ensures that this is only called if there are no tokens read before the
/// \#ifndef. The caller is required to do this, because reading the \#if
/// line obviously reads in in tokens.
- void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
+ void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc) {
// If the macro is already set, this is after the top-level #endif.
if (TheMacro)
return Invalidate();
@@ -91,7 +134,9 @@ public:
// Remember that we're in the #if and that we have the macro.
ReadAnyTokens = true;
+ ImmediatelyAfterTopLevelIfndef = true;
TheMacro = M;
+ MacroLoc = Loc;
}
/// \brief Invoked when a top level conditional (except \#ifndef) is found.
@@ -111,6 +156,7 @@ public:
// At this point, we haven't "read any tokens" but we do have a controlling
// macro.
ReadAnyTokens = false;
+ ImmediatelyAfterTopLevelIfndef = false;
}
/// \brief Once the entire file has been lexed, if there is a controlling
@@ -122,6 +168,12 @@ public:
return TheMacro;
return 0;
}
+
+ /// \brief If the ControllingMacro is followed by a macro definition, return
+ /// the macro that was defined.
+ const IdentifierInfo *GetDefinedMacro() const {
+ return DefinedMacro;
+ }
};
} // end namespace clang
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index db2ecd247f40..0e112182794d 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -19,6 +19,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Pragma.h"
#include "llvm/ADT/StringRef.h"
#include <string>
@@ -155,11 +156,23 @@ public:
virtual void Ident(SourceLocation Loc, const std::string &str) {
}
+ /// \brief Callback invoked when start reading any pragma directive.
+ virtual void PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) {
+ }
+
/// \brief Callback invoked when a \#pragma comment directive is read.
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
const std::string &Str) {
}
+ /// \brief Callback invoked when a \#pragma detect_mismatch directive is
+ /// read.
+ virtual void PragmaDetectMismatch(SourceLocation Loc,
+ const std::string &Name,
+ const std::string &Value) {
+ }
+
/// \brief Callback invoked when a \#pragma clang __debug directive is read.
/// \param Loc The location of the debug directive.
/// \param DebugType The identifier following __debug.
@@ -204,6 +217,26 @@ public:
diag::Mapping mapping, StringRef Str) {
}
+ /// \brief Called when an OpenCL extension is either disabled or
+ /// enabled with a pragma.
+ virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
+ const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) {
+ }
+
+ /// \brief Callback invoked when a \#pragma warning directive is read.
+ virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
+ ArrayRef<int> Ids) {
+ }
+
+ /// \brief Callback invoked when a \#pragma warning(push) directive is read.
+ virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
+ }
+
+ /// \brief Callback invoked when a \#pragma warning(pop) directive is read.
+ virtual void PragmaWarningPop(SourceLocation Loc) {
+ }
+
/// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
/// macro invocation is found.
virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
@@ -224,7 +257,8 @@ public:
/// \brief Hook called whenever the 'defined' operator is seen.
/// \param MD The MacroDirective if the name was a macro, null otherwise.
- virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) {
+ virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
+ SourceRange Range) {
}
/// \brief Hook called when a source range is skipped.
@@ -236,18 +270,21 @@ public:
/// \brief Hook called whenever an \#if is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param ConditionValue The evaluated value of the condition.
///
// FIXME: better to pass in a list (or tree!) of Tokens.
- virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
+ virtual void If(SourceLocation Loc, SourceRange ConditionRange,
+ bool ConditionValue) {
}
/// \brief Hook called whenever an \#elif is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param ConditionValue The evaluated value of the condition.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
- SourceLocation IfLoc) {
+ bool ConditionValue, SourceLocation IfLoc) {
}
/// \brief Hook called whenever an \#ifdef is seen.
@@ -352,6 +389,13 @@ public:
Second->PragmaComment(Loc, Kind, Str);
}
+ virtual void PragmaDetectMismatch(SourceLocation Loc,
+ const std::string &Name,
+ const std::string &Value) {
+ First->PragmaDetectMismatch(Loc, Name, Value);
+ Second->PragmaDetectMismatch(Loc, Name, Value);
+ }
+
virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
PragmaMessageKind Kind, StringRef Str) {
First->PragmaMessage(Loc, Namespace, Kind, Str);
@@ -376,6 +420,29 @@ public:
Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
}
+ virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
+ const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) {
+ First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
+ Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
+ }
+
+ virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
+ ArrayRef<int> Ids) {
+ First->PragmaWarning(Loc, WarningSpec, Ids);
+ Second->PragmaWarning(Loc, WarningSpec, Ids);
+ }
+
+ virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
+ First->PragmaWarningPush(Loc, Level);
+ Second->PragmaWarningPush(Loc, Level);
+ }
+
+ virtual void PragmaWarningPop(SourceLocation Loc) {
+ First->PragmaWarningPop(Loc);
+ Second->PragmaWarningPop(Loc);
+ }
+
virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
SourceRange Range, const MacroArgs *Args) {
First->MacroExpands(MacroNameTok, MD, Range, Args);
@@ -393,9 +460,10 @@ public:
Second->MacroUndefined(MacroNameTok, MD);
}
- virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) {
- First->Defined(MacroNameTok, MD);
- Second->Defined(MacroNameTok, MD);
+ virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
+ SourceRange Range) {
+ First->Defined(MacroNameTok, MD, Range);
+ Second->Defined(MacroNameTok, MD, Range);
}
virtual void SourceRangeSkipped(SourceRange Range) {
@@ -404,16 +472,17 @@ public:
}
/// \brief Hook called whenever an \#if is seen.
- virtual void If(SourceLocation Loc, SourceRange ConditionRange) {
- First->If(Loc, ConditionRange);
- Second->If(Loc, ConditionRange);
+ virtual void If(SourceLocation Loc, SourceRange ConditionRange,
+ bool ConditionValue) {
+ First->If(Loc, ConditionRange, ConditionValue);
+ Second->If(Loc, ConditionRange, ConditionValue);
}
- /// \brief Hook called whenever an \#if is seen.
+ /// \brief Hook called whenever an \#elif is seen.
virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
- SourceLocation IfLoc) {
- First->Elif(Loc, ConditionRange, IfLoc);
- Second->Elif(Loc, ConditionRange, IfLoc);
+ bool ConditionValue, SourceLocation IfLoc) {
+ First->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
+ Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
}
/// \brief Hook called whenever an \#ifdef is seen.
diff --git a/include/clang/Lex/PPConditionalDirectiveRecord.h b/include/clang/Lex/PPConditionalDirectiveRecord.h
index b9a22529e205..54a132d586d1 100644
--- a/include/clang/Lex/PPConditionalDirectiveRecord.h
+++ b/include/clang/Lex/PPConditionalDirectiveRecord.h
@@ -86,9 +86,10 @@ public:
SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const;
private:
- virtual void If(SourceLocation Loc, SourceRange ConditionRange);
+ virtual void If(SourceLocation Loc, SourceRange ConditionRange,
+ bool ConditionValue);
virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
- SourceLocation IfLoc);
+ bool ConditionValue, SourceLocation IfLoc);
virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDirective *MD);
virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h
index a9276e86b726..d748bc1f7dff 100644
--- a/include/clang/Lex/PTHLexer.h
+++ b/include/clang/Lex/PTHLexer.h
@@ -68,7 +68,7 @@ public:
~PTHLexer() {}
/// Lex - Return the next token.
- void Lex(Token &Tok);
+ bool Lex(Token &Tok);
void getEOF(Token &Tok);
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index db74352aa81e..2584340f6ec7 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -576,7 +576,8 @@ namespace clang {
virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDirective *MD);
/// \brief Hook called whenever the 'defined' operator is seen.
- virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD);
+ virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
+ SourceRange Range);
void addMacroExpansion(const Token &Id, const MacroInfo *MI,
SourceRange Range);
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index c5981777cd29..223fd470eca1 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -20,6 +20,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/PTHManager.h"
@@ -221,7 +222,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// \brief The module import path that we're currently processing.
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath;
-
+
+ /// \brief Whether the last token we lexed was an '@'.
+ bool LastTokenWasAt;
+
/// \brief Whether the module import expectes an identifier next. Otherwise,
/// it expects a '.' or ';'.
bool ModuleImportExpectsIdentifier;
@@ -457,6 +461,10 @@ public:
/// \brief Retrieve the module loader associated with this preprocessor.
ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
+ bool hadModuleLoaderFatalFailure() const {
+ return TheModuleLoader.HadFatalFailure;
+ }
+
/// \brief True if we are currently preprocessing a #if or #elif directive
bool isParsingIfOrElifDirective() const {
return ParsingIfOrElifDirective;
@@ -711,17 +719,8 @@ public:
/// caching of tokens is on.
bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); }
- /// Lex - To lex a token from the preprocessor, just pull a token from the
- /// current lexer or macro object.
- void Lex(Token &Result) {
- switch (CurLexerKind) {
- case CLK_Lexer: CurLexer->Lex(Result); break;
- case CLK_PTHLexer: CurPTHLexer->Lex(Result); break;
- case CLK_TokenLexer: CurTokenLexer->Lex(Result); break;
- case CLK_CachingLexer: CachingLex(Result); break;
- case CLK_LexAfterModuleImport: LexAfterModuleImport(Result); break;
- }
- }
+ /// Lex - Lex the next token for this preprocessor.
+ void Lex(Token &Result);
void LexAfterModuleImport(Token &Result);
@@ -828,6 +827,13 @@ public:
AnnotatePreviousCachedTokens(Tok);
}
+ /// Get the location of the last cached token, suitable for setting the end
+ /// location of an annotation token.
+ SourceLocation getLastCachedTokenLocation() const {
+ assert(CachedLexPos != 0);
+ return CachedTokens[CachedLexPos-1].getLocation();
+ }
+
/// \brief Replace the last token with an annotation token.
///
/// Like AnnotateCachedTokens(), this routine replaces an
@@ -989,8 +995,9 @@ public:
/// \brief Relex the token at the specified location.
/// \returns true if there was a failure, false on success.
- bool getRawToken(SourceLocation Loc, Token &Result) {
- return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts);
+ bool getRawToken(SourceLocation Loc, Token &Result,
+ bool IgnoreWhiteSpace = false) {
+ return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts, IgnoreWhiteSpace);
}
/// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant
@@ -1155,7 +1162,10 @@ public:
/// identifier and has filled in the tokens IdentifierInfo member. This
/// callback potentially macro expands it or turns it into a named token (like
/// 'for').
- void HandleIdentifier(Token &Identifier);
+ ///
+ /// \returns true if we actually computed a token, false if we need to
+ /// lex again.
+ bool HandleIdentifier(Token &Identifier);
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
@@ -1216,12 +1226,12 @@ public:
///
/// Returns null on failure. \p isAngled indicates whether the file
/// reference is for system \#include's or not (i.e. using <> instead of "").
- const FileEntry *LookupFile(StringRef Filename,
+ const FileEntry *LookupFile(SourceLocation FilenameLoc, StringRef Filename,
bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache = false);
/// GetCurLookup - The DirectoryLookup structure used to find the current
@@ -1273,6 +1283,8 @@ private:
IncludeMacroStack.pop_back();
}
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+
/// \brief Allocate a new MacroInfo object.
MacroInfo *AllocateMacroInfo();
@@ -1329,7 +1341,7 @@ private:
/// HandleMacroExpandedIdentifier - If an identifier token is read that is to
/// be expanded as a macro, handle it and return the next token as 'Tok'. If
- /// the macro should not be expanded return true, otherwise return false.
+ /// we lexed a token, return true; otherwise the caller should lex again.
bool HandleMacroExpandedIdentifier(Token &Tok, MacroDirective *MD);
/// \brief Cache macro expanded tokens for TokenLexers.
@@ -1400,7 +1412,7 @@ private:
bool InCachingLexMode() const {
// If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
// that we are past EOF, not that we are in CachingLex mode.
- return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 &&
+ return !CurPPLexer && !CurTokenLexer && !CurPTHLexer &&
!IncludeMacroStack.empty();
}
void EnterCachingLexMode();
@@ -1432,8 +1444,32 @@ private:
void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
void HandleMicrosoftImportDirective(Token &Tok);
+ // Module inclusion testing.
+ /// \brief Find the module for the source or header file that \p FilenameLoc
+ /// points to.
+ Module *getModuleForLocation(SourceLocation FilenameLoc);
+
+ /// \brief Verify that a private header is included only from within its
+ /// module.
+ bool violatesPrivateInclude(Module *RequestingModule,
+ const FileEntry *IncFileEnt,
+ ModuleMap::ModuleHeaderRole Role,
+ Module *RequestedModule);
+
+ /// \brief Verify that a module includes headers only from modules that it
+ /// has declared that it uses.
+ bool violatesUseDeclarations(Module *RequestingModule,
+ Module *RequestedModule);
+
+ /// \brief Verify that it is legal for the source file that \p FilenameLoc
+ /// points to to include the file \p Filename.
+ ///
+ /// Tries to reuse \p IncFileEnt.
+ void verifyModuleInclude(SourceLocation FilenameLoc, StringRef Filename,
+ const FileEntry *IncFileEnt);
+
// Macro handling.
- void HandleDefineDirective(Token &Tok);
+ void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
void HandleUndefDirective(Token &Tok);
// Conditional Inclusion.
@@ -1445,7 +1481,8 @@ private:
void HandleElifDirective(Token &Tok);
// Pragmas.
- void HandlePragmaDirective(unsigned Introducer);
+ void HandlePragmaDirective(SourceLocation IntroducerLoc,
+ PragmaIntroducerKind Introducer);
public:
void HandlePragmaOnce(Token &OnceTok);
void HandlePragmaMark();
diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h
index 20fb8a0c4804..27a8df43a274 100644
--- a/include/clang/Lex/PreprocessorLexer.h
+++ b/include/clang/Lex/PreprocessorLexer.h
@@ -111,9 +111,9 @@ protected:
/// stack, returning information about it. If the conditional stack is empty,
/// this returns true and does not fill in the arguments.
bool popConditionalLevel(PPConditionalInfo &CI) {
- if (ConditionalStack.empty()) return true;
- CI = ConditionalStack.back();
- ConditionalStack.pop_back();
+ if (ConditionalStack.empty())
+ return true;
+ CI = ConditionalStack.pop_back_val();
return false;
}
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index bcbe9c913be1..4f6391d6502d 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -71,13 +71,16 @@ public:
// Various flags set per token:
enum TokenFlags {
- StartOfLine = 0x01, // At start of line or only after whitespace.
- LeadingSpace = 0x02, // Whitespace exists before this token.
+ StartOfLine = 0x01, // At start of line or only after whitespace
+ // (considering the line after macro expansion).
+ LeadingSpace = 0x02, // Whitespace exists before this token (considering
+ // whitespace after macro expansion).
DisableExpand = 0x04, // This identifier may never be macro expanded.
NeedsCleaning = 0x08, // Contained an escaped newline or trigraph.
LeadingEmptyMacro = 0x10, // Empty macro exists before this token.
HasUDSuffix = 0x20, // This string or character literal has a ud-suffix.
- HasUCN = 0x40 // This identifier contains a UCN.
+ HasUCN = 0x40, // This identifier contains a UCN.
+ IgnoredComma = 0x80 // This comma is not a macro argument separator (MS).
};
tok::TokenKind getKind() const { return (tok::TokenKind)Kind; }
diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h
index 090402a811e2..7c8cfd028a28 100644
--- a/include/clang/Lex/TokenLexer.h
+++ b/include/clang/Lex/TokenLexer.h
@@ -136,7 +136,7 @@ public:
unsigned isNextTokenLParen() const;
/// Lex - Lex and return a token from this macro stream.
- void Lex(Token &Tok);
+ bool Lex(Token &Tok);
/// isParsingPreprocessorDirective - Return true if we are in the middle of a
/// preprocessor directive.
@@ -181,6 +181,8 @@ private:
/// macro definition.
void updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc,
Token *begin_tokens, Token *end_tokens);
+
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
};
} // end namespace clang
diff --git a/include/clang/Parse/CMakeLists.txt b/include/clang/Parse/CMakeLists.txt
index d20708e58c55..ed80c1889c7d 100644
--- a/include/clang/Parse/CMakeLists.txt
+++ b/include/clang/Parse/CMakeLists.txt
@@ -1,7 +1,12 @@
-clang_tablegen(AttrExprArgs.inc -gen-clang-attr-expr-args-list
+clang_tablegen(AttrIdentifierArg.inc -gen-clang-attr-identifier-arg-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
- TARGET ClangAttrExprArgs)
+ TARGET ClangAttrIdentifierArg)
+
+clang_tablegen(AttrTypeArg.inc -gen-clang-attr-type-arg-list
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE ../Basic/Attr.td
+ TARGET ClangAttrTypeArg)
clang_tablegen(AttrLateParsed.inc -gen-clang-attr-late-parsed-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
diff --git a/include/clang/Parse/Makefile b/include/clang/Parse/Makefile
index fb63175ba9b3..00d41fafddeb 100644
--- a/include/clang/Parse/Makefile
+++ b/include/clang/Parse/Makefile
@@ -1,19 +1,25 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = AttrExprArgs.inc AttrLateParsed.inc
+BUILT_SOURCES = AttrIdentifierArg.inc AttrLateParsed.inc AttrTypeArg.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
-$(ObjDir)/AttrExprArgs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
+$(ObjDir)/AttrIdentifierArg.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
- $(Echo) "Building Clang attribute expression arguments table with tblgen"
- $(Verb) $(ClangTableGen) -gen-clang-attr-expr-args-list -o $(call SYSPATH, $@) \
+ $(Echo) "Building Clang attribute identifier argument table with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-identifier-arg-list -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
+$(ObjDir)/AttrTypeArg.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang attribute type argument table with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-type-arg-list -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/AttrLateParsed.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute late-parsed table with tblgen"
$(Verb) $(ClangTableGen) -gen-clang-attr-late-parsed-list -o $(call SYSPATH, $@) \
- -I $(PROJ_SRC_DIR)/../../ $< \ No newline at end of file
+ -I $(PROJ_SRC_DIR)/../../ $<
diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h
index 0d4729297057..b593806ff391 100644
--- a/include/clang/Parse/ParseDiagnostic.h
+++ b/include/clang/Parse/ParseDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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 1029a90c55c8..bd49988c5b00 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -45,6 +45,7 @@ namespace clang {
class InMessageExpressionRAIIObject;
class PoisonSEHIdentifiersRAIIObject;
class VersionTuple;
+ class OMPClause;
/// Parser - This implements a parser for the C family of languages. After
/// parsing units of the grammar, productions are invoked to handle whatever has
@@ -101,15 +102,17 @@ class Parser : public CodeCompletionHandler {
/// Contextual keywords for Microsoft extensions.
IdentifierInfo *Ident__except;
+ mutable IdentifierInfo *Ident_sealed;
/// Ident_super - IdentifierInfo for "super", to support fast
/// comparison.
IdentifierInfo *Ident_super;
- /// Ident_vector and Ident_pixel - cached IdentifierInfo's for
- /// "vector" and "pixel" fast comparison. Only present if
- /// AltiVec enabled.
+ /// Ident_vector, Ident_pixel, Ident_bool - cached IdentifierInfo's
+ /// for "vector", "pixel", and "bool" fast comparison. Only present
+ /// if AltiVec enabled.
IdentifierInfo *Ident_vector;
IdentifierInfo *Ident_pixel;
+ IdentifierInfo *Ident_bool;
/// Objective-C contextual keywords.
mutable IdentifierInfo *Ident_instancetype;
@@ -150,6 +153,7 @@ class Parser : public CodeCompletionHandler {
OwningPtr<CommentHandler> CommentSemaHandler;
OwningPtr<PragmaHandler> OpenMPHandler;
OwningPtr<PragmaHandler> MSCommentHandler;
+ OwningPtr<PragmaHandler> MSDetectMismatchHandler;
/// Whether the '>' token acts as an operator or not. This will be
/// true except when we are parsing an expression within a C++
@@ -398,7 +402,8 @@ private:
/// \brief Abruptly cut off parsing; mainly used when we have reached the
/// code-completion point.
void cutOffParsing() {
- PP.setCodeCompletionReached();
+ if (PP.isCodeCompletionEnabled())
+ PP.setCodeCompletionReached();
// Cut off parsing by acting as if we reached the end-of-file.
Tok.setKind(tok::eof);
}
@@ -419,6 +424,10 @@ private:
void HandlePragmaMSStruct();
/// \brief Handle the annotation token produced for
+ /// #pragma comment...
+ void HandlePragmaMSComment();
+
+ /// \brief Handle the annotation token produced for
/// #pragma align...
void HandlePragmaAlign();
@@ -525,7 +534,8 @@ private:
bool &isInvalid) {
if (!getLangOpts().AltiVec ||
(Tok.getIdentifierInfo() != Ident_vector &&
- Tok.getIdentifierInfo() != Ident_pixel))
+ Tok.getIdentifierInfo() != Ident_pixel &&
+ Tok.getIdentifierInfo() != Ident_bool))
return false;
return TryAltiVecTokenOutOfLine(DS, Loc, PrevSpec, DiagID, isInvalid);
@@ -545,6 +555,13 @@ private:
const char *&PrevSpec, unsigned &DiagID,
bool &isInvalid);
+ /// TryKeywordIdentFallback - For compatibility with system headers using
+ /// keywords as identifiers, attempt to convert the current token to an
+ /// identifier and optionally disable the keyword for the remainder of the
+ /// translation unit. This returns false if the token was not replaced,
+ /// otherwise emits a diagnostic and returns true.
+ bool TryKeywordIdentFallback(bool DisableKeyword);
+
/// \brief Get the TemplateIdAnnotation from the token.
TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
@@ -599,6 +616,7 @@ private:
assert(!isActive && "Forgot to call Commit or Revert!");
}
};
+ class UnannotatedTentativeParsingAction;
/// ObjCDeclContextSwitch - An object used to switch context from
/// an objective-c decl context to its enclosing decl context and
@@ -725,32 +743,45 @@ private:
void CheckNestedObjCContexts(SourceLocation AtLoc);
public:
+
+ /// \brief Control flags for SkipUntil functions.
+ enum SkipUntilFlags {
+ StopAtSemi = 1 << 0, ///< Stop skipping at semicolon
+ /// \brief Stop skipping at specified token, but don't skip the token itself
+ StopBeforeMatch = 1 << 1,
+ StopAtCodeCompletion = 1 << 2 ///< Stop at code completion
+ };
+
+ friend LLVM_CONSTEXPR SkipUntilFlags operator|(SkipUntilFlags L,
+ SkipUntilFlags R) {
+ return static_cast<SkipUntilFlags>(static_cast<unsigned>(L) |
+ static_cast<unsigned>(R));
+ }
+
/// SkipUntil - Read tokens until we get to the specified token, then consume
- /// it (unless DontConsume is true). Because we cannot guarantee that the
- /// token will ever occur, this skips to the next token, or to some likely
- /// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
- /// character.
+ /// it (unless StopBeforeMatch is specified). Because we cannot guarantee
+ /// that the token will ever occur, this skips to the next token, or to some
+ /// likely good stopping point. If Flags has StopAtSemi flag, skipping will
+ /// stop at a ';' character.
///
/// If SkipUntil finds the specified token, it returns true, otherwise it
/// returns false.
- bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true,
- bool DontConsume = false, bool StopAtCodeCompletion = false) {
- return SkipUntil(llvm::makeArrayRef(T), StopAtSemi, DontConsume,
- StopAtCodeCompletion);
+ bool SkipUntil(tok::TokenKind T,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
+ return SkipUntil(llvm::makeArrayRef(T), Flags);
}
- bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true,
- bool DontConsume = false, bool StopAtCodeCompletion = false) {
+ bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
tok::TokenKind TokArray[] = {T1, T2};
- return SkipUntil(TokArray, StopAtSemi, DontConsume,StopAtCodeCompletion);
+ return SkipUntil(TokArray, Flags);
}
bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, tok::TokenKind T3,
- bool StopAtSemi = true, bool DontConsume = false,
- bool StopAtCodeCompletion = false) {
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
tok::TokenKind TokArray[] = {T1, T2, T3};
- return SkipUntil(TokArray, StopAtSemi, DontConsume,StopAtCodeCompletion);
+ return SkipUntil(TokArray, Flags);
}
- bool SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi = true,
- bool DontConsume = false, bool StopAtCodeCompletion = false);
+ bool SkipUntil(ArrayRef<tok::TokenKind> Toks,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0));
/// SkipMalformedDecl - Read tokens until we get to some likely good stopping
/// point for skipping past a simple-declaration.
@@ -1042,32 +1073,21 @@ private:
SourceRange getSourceRange() const LLVM_READONLY;
};
- /// \brief Contains a late templated function.
- /// Will be parsed at the end of the translation unit.
- struct LateParsedTemplatedFunction {
- explicit LateParsedTemplatedFunction(Decl *MD)
- : D(MD) {}
-
- CachedTokens Toks;
-
- /// \brief The template function declaration to be late parsed.
- Decl *D;
- };
-
void LexTemplateFunctionForLateParsing(CachedTokens &Toks);
- void ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT);
- typedef llvm::DenseMap<const FunctionDecl*, LateParsedTemplatedFunction*>
- LateParsedTemplateMapT;
- LateParsedTemplateMapT LateParsedTemplateMap;
+ void ParseLateTemplatedFuncDef(LateParsedTemplate &LPT);
- static void LateTemplateParserCallback(void *P, const FunctionDecl *FD);
- void LateTemplateParser(const FunctionDecl *FD);
+ static void LateTemplateParserCallback(void *P, LateParsedTemplate &LPT);
Sema::ParsingClassState
PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface);
void DeallocateParsedClasses(ParsingClass *Class);
void PopParsingClass(Sema::ParsingClassState);
+ enum CachedInitKind {
+ CIK_DefaultArgument,
+ CIK_DefaultInitializer
+ };
+
NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS,
AttributeList *AccessAttrs,
ParsingDeclarator &D,
@@ -1089,6 +1109,8 @@ private:
void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod);
bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks);
+ bool ConsumeAndStoreInitializer(CachedTokens &Toks, CachedInitKind CIK);
+ bool ConsumeAndStoreConditional(CachedTokens &Toks);
bool ConsumeAndStoreUntil(tok::TokenKind T1,
CachedTokens &Toks,
bool StopAtSemi = true,
@@ -1274,6 +1296,12 @@ private:
ArrayRef<Expr *> Args) = 0,
Expr *Data = 0);
+ /// ParseSimpleExpressionList - A simple comma-separated list of expressions,
+ /// used for misc language extensions.
+ bool ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs);
+
+
/// ParenParseOption - Control what ParseParenExpression will parse.
enum ParenParseOption {
SimpleExpr, // Only parse '(' expression ')'
@@ -1325,7 +1353,8 @@ private:
// [...] () -> type {...}
ExprResult ParseLambdaExpression();
ExprResult TryParseLambdaExpression();
- Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro);
+ Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro,
+ bool *SkippedInits = 0);
bool TryParseLambdaIntroducer(LambdaIntroducer &Intro);
ExprResult ParseLambdaExpressionAfterIntroducer(
LambdaIntroducer &Intro);
@@ -1461,10 +1490,7 @@ private:
/// A SmallVector of types.
typedef SmallVector<ParsedType, 12> TypeVector;
- StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0) {
- StmtVector Stmts;
- return ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc);
- }
+ StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0);
StmtResult ParseStatementOrDeclaration(StmtVector &Stmts,
bool OnlyStatement,
SourceLocation *TrailingElseLoc = 0);
@@ -1628,6 +1654,9 @@ private:
AccessSpecifier AS = AS_none,
DeclSpecContext DSC = DSC_normal,
LateParsedAttrList *LateAttrs = 0);
+ bool DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
+ DeclSpecContext DSContext,
+ LateParsedAttrList *LateAttrs = 0);
void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none,
DeclSpecContext DSC = DSC_normal);
@@ -1800,6 +1829,11 @@ private:
isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False(),
bool *HasMissingTypename = 0);
+ /// Given that isCXXDeclarationSpecifier returns \c TPResult::True or
+ /// \c TPResult::Ambiguous, determine whether the decl-specifier would be
+ /// a type-specifier other than a cv-qualifier.
+ bool isCXXDeclarationSpecifierAType();
+
/// \brief Determine whether an identifier has been tentatively declared as a
/// non-type. Such tentative declarations should not be found to name a type
/// during a tentative parse, but also should not be annotated as a non-type.
@@ -1812,15 +1846,18 @@ private:
// that more tentative parsing is necessary for disambiguation.
// They all consume tokens, so backtracking should be used after calling them.
- TPResult TryParseDeclarationSpecifier(bool *HasMissingTypename = 0);
TPResult TryParseSimpleDeclaration(bool AllowForRangeDecl);
TPResult TryParseTypeofSpecifier();
TPResult TryParseProtocolQualifiers();
+ TPResult TryParsePtrOperatorSeq();
+ TPResult TryParseOperatorId();
TPResult TryParseInitDeclaratorList();
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
- TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = 0);
+ TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = 0,
+ bool VersusTemplateArg = false);
TPResult TryParseFunctionDeclarator();
TPResult TryParseBracketDeclarator();
+ TPResult TryConsumeDeclarationSpecifier();
public:
TypeResult ParseTypeName(SourceRange *Range = 0,
@@ -1866,6 +1903,10 @@ private:
// for example, attributes appertain to decl specifiers.
void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs);
+ /// \brief Diagnose and skip C++11 attributes that appear in syntactic
+ /// locations where attributes are not allowed.
+ void DiagnoseAndSkipCXX11Attributes();
+
void MaybeParseGNUAttributes(Declarator &D,
LateParsedAttrList *LateAttrs = 0) {
if (Tok.is(tok::kw___attribute)) {
@@ -1891,6 +1932,7 @@ private:
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc,
AttributeList::Syntax Syntax);
+ IdentifierLoc *ParseIdentifierLoc();
void MaybeParseCXX11Attributes(Declarator &D) {
if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
@@ -1961,6 +2003,11 @@ private:
ParsedAttributes &Attrs,
SourceLocation *EndLoc);
+ void ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc);
+
void ParseTypeofSpecifier(DeclSpec &DS);
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
@@ -2024,7 +2071,8 @@ private:
void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
bool CXX11AttributesAllowed = true,
- bool AtomicAllowed = true);
+ bool AtomicAllowed = true,
+ bool IdentifierRequired = false);
void ParseDirectDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseFunctionDeclarator(Declarator &D,
@@ -2035,11 +2083,11 @@ private:
bool isFunctionDeclaratorIdentifierList();
void ParseFunctionDeclaratorIdentifierList(
Declarator &D,
- SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo);
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo);
void ParseParameterDeclarationClause(
Declarator &D,
ParsedAttributes &attrs,
- SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo,
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc);
void ParseBracketDeclarator(Declarator &D);
@@ -2060,6 +2108,8 @@ private:
isCXX11AttributeSpecifier(bool Disambiguate = false,
bool OuterMightBeMessageSend = false);
+ void DiagnoseUnexpectedNamespace(NamedDecl *Context);
+
Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
SourceLocation InlineLoc = SourceLocation());
void ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
@@ -2134,9 +2184,44 @@ private:
//===--------------------------------------------------------------------===//
// OpenMP: Directives and clauses.
+ /// \brief Parses declarative OpenMP directives.
DeclGroupPtrTy ParseOpenMPDeclarativeDirective();
+ /// \brief Parses simple list of variables.
+ ///
+ /// \param Kind Kind of the directive.
+ /// \param [out] VarList List of referenced variables.
+ /// \param AllowScopeSpecifier true, if the variables can have fully
+ /// qualified names.
+ ///
bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
- SmallVectorImpl<DeclarationNameInfo> &IdList);
+ SmallVectorImpl<Expr *> &VarList,
+ bool AllowScopeSpecifier);
+ /// \brief Parses declarative or executable directive.
+ StmtResult ParseOpenMPDeclarativeOrExecutableDirective();
+ /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
+ ///
+ /// \param DKind Kind of current directive.
+ /// \param CKind Kind of current clause.
+ /// \param FirstClause true, if this is the first clause of a kind \a CKind
+ /// in current directive.
+ ///
+ OMPClause *ParseOpenMPClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind, bool FirstClause);
+ /// \brief Parses clause with a single expression of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind);
+ /// \brief Parses simple clause of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind);
+ /// \brief Parses clause with the list of variables of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPVarListClause(OpenMPClauseKind Kind);
public:
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowDestructorName,
diff --git a/include/clang/Rewrite/Core/HTMLRewrite.h b/include/clang/Rewrite/Core/HTMLRewrite.h
index 88caf85e6010..3cd04615d826 100644
--- a/include/clang/Rewrite/Core/HTMLRewrite.h
+++ b/include/clang/Rewrite/Core/HTMLRewrite.h
@@ -57,7 +57,7 @@ namespace html {
/// in 's' are not interpreted as HTML tags. Unlike the version of
/// EscapeText that rewrites a file, this version by default replaces tabs
/// with spaces.
- std::string EscapeText(const std::string& s,
+ std::string EscapeText(StringRef s,
bool EscapeSpaces = false, bool ReplaceTabs = false);
void AddLineNumbers(Rewriter& R, FileID FID);
diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h
index cb044aef23fe..2d2917b910b9 100644
--- a/include/clang/Rewrite/Core/Rewriter.h
+++ b/include/clang/Rewrite/Core/Rewriter.h
@@ -40,20 +40,18 @@ class RewriteBuffer {
/// Deltas - Keep track of all the deltas in the source code due to insertions
/// and deletions.
DeltaTree Deltas;
-
- /// Buffer - This is the actual buffer itself. Note that using a vector or
- /// string is a horribly inefficient way to do this, we should use a rope
- /// instead.
- typedef RewriteRope BufferTy;
- BufferTy Buffer;
+ RewriteRope Buffer;
public:
- typedef BufferTy::const_iterator iterator;
+ typedef RewriteRope::const_iterator iterator;
iterator begin() const { return Buffer.begin(); }
iterator end() const { return Buffer.end(); }
unsigned size() const { return Buffer.size(); }
/// \brief Write to \p Stream the result of applying all changes to the
/// original buffer.
+ /// Note that it isn't safe to use this function to overwrite memory mapped
+ /// files in-place (PR17960). Consider using a higher-level utility such as
+ /// Rewriter::overwriteChangedFiles() instead.
///
/// The original buffer is not actually changed.
raw_ostream &write(raw_ostream &Stream) const;
@@ -149,6 +147,7 @@ public:
};
typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator;
+ typedef std::map<FileID, RewriteBuffer>::const_iterator const_buffer_iterator;
explicit Rewriter(SourceManager &SM, const LangOptions &LO)
: SourceMgr(&SM), LangOpts(&LO) {}
@@ -282,10 +281,12 @@ public:
// Iterators over rewrite buffers.
buffer_iterator buffer_begin() { return RewriteBuffers.begin(); }
buffer_iterator buffer_end() { return RewriteBuffers.end(); }
+ const_buffer_iterator buffer_begin() const { return RewriteBuffers.begin(); }
+ const_buffer_iterator buffer_end() const { return RewriteBuffers.end(); }
/// overwriteChangedFiles - Save all changed files to disk.
///
- /// Returns whether not all changes were saved successfully.
+ /// Returns true if any files were not saved successfully.
/// Outputs diagnostics via the source manager's diagnostic engine
/// in case of an error.
bool overwriteChangedFiles();
diff --git a/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h
index eeac97332dfb..432c4e23a993 100644
--- a/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/include/clang/Sema/AnalysisBasedWarnings.h
@@ -38,6 +38,7 @@ public:
unsigned enableCheckFallThrough : 1;
unsigned enableCheckUnreachable : 1;
unsigned enableThreadSafetyAnalysis : 1;
+ unsigned enableConsumedAnalysis : 1;
public:
Policy();
void disableCheckFallThrough() { enableCheckFallThrough = 0; }
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h
index d5f31779a635..508064def2ca 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -19,6 +19,7 @@
#include "clang/Basic/VersionTuple.h"
#include "clang/Sema/Ownership.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Allocator.h"
#include <cassert>
@@ -44,6 +45,20 @@ struct AvailabilityChange {
bool isValid() const { return !Version.empty(); }
};
+/// \brief Wraps an identifier and optional source location for the identifier.
+struct IdentifierLoc {
+ SourceLocation Loc;
+ IdentifierInfo *Ident;
+
+ static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
+ IdentifierInfo *Ident);
+};
+
+/// \brief A union of the various pointer types that can be passed to an
+/// AttributeList as an argument.
+typedef llvm::PointerUnion<Expr*, IdentifierLoc*> ArgsUnion;
+typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector;
+
/// AttributeList - Represents a syntactic attribute.
///
/// For a GNU attribute, there are four forms of this construct:
@@ -66,13 +81,12 @@ public:
/// __ptr16, alignas(...), etc.
AS_Keyword
};
+
private:
IdentifierInfo *AttrName;
IdentifierInfo *ScopeName;
- IdentifierInfo *ParmName;
SourceRange AttrRange;
SourceLocation ScopeLoc;
- SourceLocation ParmLoc;
SourceLocation EllipsisLoc;
/// The number of expression arguments this attribute has.
@@ -100,6 +114,9 @@ private:
/// Microsoft __delcspec(property) attribute.
unsigned IsProperty : 1;
+ /// True if this has a ParsedType
+ unsigned HasParsedType : 1;
+
unsigned AttrKind : 8;
/// \brief The location of the 'unavailable' keyword in an
@@ -114,22 +131,27 @@ private:
/// The next attribute allocated in the current Pool.
AttributeList *NextInPool;
- Expr **getArgsBuffer() {
- return reinterpret_cast<Expr**>(this+1);
+ /// Arguments, if any, are stored immediately following the object.
+ ArgsUnion *getArgsBuffer() {
+ return reinterpret_cast<ArgsUnion*>(this+1);
}
- Expr * const *getArgsBuffer() const {
- return reinterpret_cast<Expr* const *>(this+1);
+ ArgsUnion const *getArgsBuffer() const {
+ return reinterpret_cast<ArgsUnion const *>(this+1);
}
enum AvailabilitySlot {
IntroducedSlot, DeprecatedSlot, ObsoletedSlot
};
- AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
- return reinterpret_cast<AvailabilityChange*>(this+1)[index];
+ /// Availability information is stored immediately following the arguments,
+ /// if any, at the end of the object.
+ AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
+ return reinterpret_cast<AvailabilityChange*>(getArgsBuffer()
+ + NumArgs)[index];
}
const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
- return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
+ return reinterpret_cast<const AvailabilityChange*>(getArgsBuffer()
+ + NumArgs)[index];
}
public:
@@ -145,14 +167,20 @@ public:
};
private:
+ /// Type tag information is stored immediately following the arguments, if
+ /// any, at the end of the object. They are mutually exlusive with
+ /// availability slots.
TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
- return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1);
+ return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
}
const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
- return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
+ return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
+ + NumArgs);
}
+ /// The type buffer immediately follows the object and are mutually exclusive
+ /// with arguments.
ParsedType &getTypeBuffer() {
return *reinterpret_cast<ParsedType *>(this + 1);
}
@@ -161,6 +189,8 @@ private:
return *reinterpret_cast<const ParsedType *>(this + 1);
}
+ /// The property data immediately follows the object is is mutually exclusive
+ /// with arguments.
PropertyData &getPropertyDataBuffer() {
assert(IsProperty);
return *reinterpret_cast<PropertyData*>(this + 1);
@@ -181,36 +211,34 @@ private:
/// Constructor for attributes with expression arguments.
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
- Expr **args, unsigned numArgs,
+ ArgsUnion *args, unsigned numArgs,
Syntax syntaxUsed, SourceLocation ellipsisLoc)
- : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
- AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
- EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed),
- Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0),
- NextInPool(0) {
- if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
+ SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(false), NextInPosition(0), NextInPool(0) {
+ if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Constructor for availability attributes.
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
- const AvailabilityChange &introduced,
+ IdentifierLoc *Parm, const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
SourceLocation unavailable,
const Expr *messageExpr,
Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
- AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(),
- NumArgs(0), SyntaxUsed(syntaxUsed),
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
- IsTypeTagForDatatype(false), IsProperty(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
UnavailableLoc(unavailable), MessageExpr(messageExpr),
NextInPosition(0), NextInPool(0) {
+ ArgsUnion PVal(Parm);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
@@ -220,16 +248,15 @@ private:
/// Constructor for type_tag_for_datatype attribute.
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *argumentKindName,
- SourceLocation argumentKindLoc,
- ParsedType matchingCType, bool layoutCompatible,
- bool mustBeNull, Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName),
- AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc),
- EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
+ IdentifierLoc *ArgKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(true), IsProperty(false), NextInPosition(NULL),
- NextInPool(NULL) {
+ IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
+ NextInPosition(NULL), NextInPool(NULL) {
+ ArgsUnion PVal(ArgKind);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
new (&ExtraData.MatchingCType) ParsedType(matchingCType);
ExtraData.LayoutCompatible = layoutCompatible;
@@ -240,14 +267,12 @@ private:
/// Constructor for attributes with a single type argument.
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
ParsedType typeArg, Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
- AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
- EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
- UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(false), NextInPosition(0),
- NextInPool(0) {
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
+ NextInPosition(0), NextInPool(0) {
new (&getTypeBuffer()) ParsedType(typeArg);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
@@ -255,15 +280,13 @@ private:
/// Constructor for microsoft __declspec(property) attribute.
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
IdentifierInfo *getterId, IdentifierInfo *setterId,
Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
- AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
- SyntaxUsed(syntaxUsed),
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(true), NextInPosition(0),
- NextInPool(0) {
+ IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
+ NextInPosition(0), NextInPool(0) {
new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
@@ -288,8 +311,7 @@ public:
IdentifierInfo *getScopeName() const { return ScopeName; }
SourceLocation getScopeLoc() const { return ScopeLoc; }
- IdentifierInfo *getParameterName() const { return ParmName; }
- SourceLocation getParameterLoc() const { return ParmLoc; }
+ bool hasParsedType() const { return HasParsedType; }
/// Is this the Microsoft __declspec(property) attribute?
bool isDeclspecPropertyAttribute() const {
@@ -326,21 +348,31 @@ public:
/// getNumArgs - Return the number of actual arguments to this attribute.
unsigned getNumArgs() const { return NumArgs; }
- /// hasParameterOrArguments - Return true if this attribute has a parameter,
- /// or has a non empty argument expression list.
- bool hasParameterOrArguments() const { return ParmName || NumArgs; }
-
/// getArg - Return the specified argument.
- Expr *getArg(unsigned Arg) const {
+ ArgsUnion getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
return getArgsBuffer()[Arg];
}
+ bool isArgExpr(unsigned Arg) const {
+ return Arg < NumArgs && getArg(Arg).is<Expr*>();
+ }
+ Expr *getArgAsExpr(unsigned Arg) const {
+ return getArg(Arg).get<Expr*>();
+ }
+
+ bool isArgIdent(unsigned Arg) const {
+ return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
+ }
+ IdentifierLoc *getArgAsIdent(unsigned Arg) const {
+ return getArg(Arg).get<IdentifierLoc*>();
+ }
+
class arg_iterator {
- Expr * const *X;
+ ArgsUnion const *X;
unsigned Idx;
public:
- arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {}
+ arg_iterator(ArgsUnion const *x, unsigned idx) : X(x), Idx(idx) {}
arg_iterator& operator++() {
++Idx;
@@ -357,7 +389,7 @@ public:
return !operator==(I);
}
- Expr* operator*() const {
+ ArgsUnion operator*() const {
return X[Idx];
}
@@ -418,7 +450,7 @@ public:
}
const ParsedType &getTypeArg() const {
- assert(getKind() == AT_VecTypeHint && "Not a type attribute");
+ assert(HasParsedType && "Not a type attribute");
return getTypeBuffer();
}
@@ -431,6 +463,10 @@ public:
/// defined in Attr.td. This index is used by an attribute
/// to pretty print itself.
unsigned getAttributeSpellingListIndex() const;
+
+ bool hasCustomParsing() const;
+ unsigned getMinArgs() const;
+ unsigned getMaxArgs() const;
};
/// A factory, from which one makes pools, from which one creates
@@ -445,11 +481,13 @@ public:
/// which we want to ensure is a multiple of sizeof(void*).
AvailabilityAllocSize =
sizeof(AttributeList)
- + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1)
+ + ((3 * sizeof(AvailabilityChange) + sizeof(void*) +
+ sizeof(ArgsUnion) - 1)
/ sizeof(void*) * sizeof(void*)),
TypeTagForDatatypeAllocSize =
sizeof(AttributeList)
- + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
+ + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) +
+ sizeof(ArgsUnion) - 1)
/ sizeof(void*) * sizeof(void*),
PropertyAllocSize =
sizeof(AttributeList)
@@ -541,22 +579,20 @@ public:
AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
- Expr **args, unsigned numArgs,
+ ArgsUnion *args, unsigned numArgs,
AttributeList::Syntax syntax,
SourceLocation ellipsisLoc = SourceLocation()) {
void *memory = allocate(sizeof(AttributeList)
- + numArgs * sizeof(Expr*));
+ + numArgs * sizeof(ArgsUnion));
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
- parmName, parmLoc,
args, numArgs, syntax,
ellipsisLoc));
}
AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
+ IdentifierLoc *Param,
const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
@@ -566,9 +602,9 @@ public:
void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
- parmName, parmLoc,
- introduced, deprecated, obsoleted,
- unavailable, MessageExpr, syntax));
+ Param, introduced, deprecated,
+ obsoleted, unavailable, MessageExpr,
+ syntax));
}
AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
@@ -577,40 +613,35 @@ public:
AttributeList *createTypeTagForDatatype(
IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *argumentKindName,
- SourceLocation argumentKindLoc,
- ParsedType matchingCType, bool layoutCompatible,
- bool mustBeNull, AttributeList::Syntax syntax) {
+ IdentifierLoc *argumentKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull,
+ AttributeList::Syntax syntax) {
void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
- argumentKindName, argumentKindLoc,
- matchingCType, layoutCompatible,
- mustBeNull, syntax));
+ argumentKind, matchingCType,
+ layoutCompatible, mustBeNull,
+ syntax));
}
AttributeList *createTypeAttribute(
IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
- parmName, parmLoc,
typeArg, syntaxUsed));
}
AttributeList *createPropertyAttribute(
IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
IdentifierInfo *getterId, IdentifierInfo *setterId,
AttributeList::Syntax syntaxUsed) {
void *memory = allocate(AttributeFactory::PropertyAllocSize);
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
- parmName, parmLoc,
getterId, setterId,
syntaxUsed));
}
@@ -709,13 +740,12 @@ public:
/// Add attribute with expression arguments.
AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
- Expr **args, unsigned numArgs,
+ ArgsUnion *args, unsigned numArgs,
AttributeList::Syntax syntax,
SourceLocation ellipsisLoc = SourceLocation()) {
AttributeList *attr =
- pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
- args, numArgs, syntax, ellipsisLoc);
+ pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs,
+ syntax, ellipsisLoc);
add(attr);
return attr;
}
@@ -723,7 +753,7 @@ public:
/// Add availability attribute.
AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
+ IdentifierLoc *Param,
const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
@@ -731,9 +761,8 @@ public:
const Expr *MessageExpr,
AttributeList::Syntax syntax) {
AttributeList *attr =
- pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
- introduced, deprecated, obsoleted, unavailable,
- MessageExpr, syntax);
+ pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
+ deprecated, obsoleted, unavailable, MessageExpr, syntax);
add(attr);
return attr;
}
@@ -742,16 +771,14 @@ public:
AttributeList *addNewTypeTagForDatatype(
IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *argumentKindName,
- SourceLocation argumentKindLoc,
- ParsedType matchingCType, bool layoutCompatible,
- bool mustBeNull, AttributeList::Syntax syntax) {
+ IdentifierLoc *argumentKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull,
+ AttributeList::Syntax syntax) {
AttributeList *attr =
pool.createTypeTagForDatatype(attrName, attrRange,
scopeName, scopeLoc,
- argumentKindName, argumentKindLoc,
- matchingCType, layoutCompatible,
- mustBeNull, syntax);
+ argumentKind, matchingCType,
+ layoutCompatible, mustBeNull, syntax);
add(attr);
return attr;
}
@@ -760,11 +787,10 @@ public:
AttributeList *
addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
AttributeList *attr =
pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
- parmName, parmLoc, typeArg, syntaxUsed);
+ typeArg, syntaxUsed);
add(attr);
return attr;
}
@@ -773,13 +799,11 @@ public:
AttributeList *
addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
- IdentifierInfo *parmName, SourceLocation parmLoc,
IdentifierInfo *getterId, IdentifierInfo *setterId,
AttributeList::Syntax syntaxUsed) {
AttributeList *attr =
pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
- parmName, parmLoc, getterId, setterId,
- syntaxUsed);
+ getterId, setterId, syntaxUsed);
add(attr);
return attr;
}
@@ -798,6 +822,15 @@ private:
AttributeList *list;
};
+/// These constants match the enumerated choices of
+/// err_attribute_argument_n_type and err_attribute_argument_type.
+enum AttributeArgumentNType {
+ AANT_ArgumentIntOrBool,
+ AANT_ArgumentIntegerConstant,
+ AANT_ArgumentString,
+ AANT_ArgumentIdentifier
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Sema/CMakeLists.txt b/include/clang/Sema/CMakeLists.txt
index 6b5d222b5d56..5a48b901d2bf 100644
--- a/include/clang/Sema/CMakeLists.txt
+++ b/include/clang/Sema/CMakeLists.txt
@@ -17,3 +17,8 @@ clang_tablegen(AttrSpellingListIndex.inc -gen-clang-attr-spelling-index
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
TARGET ClangAttrSpellingListIndex)
+
+clang_tablegen(AttrParsedAttrImpl.inc -gen-clang-attr-parsed-attr-impl
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE ../Basic/Attr.td
+ TARGET ClangAttrParsedAttrImpl)
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index a1ddec7520ad..64de82c6b05f 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -271,22 +271,17 @@ private:
QualType BaseType;
/// \brief The identifiers for Objective-C selector parts.
- IdentifierInfo **SelIdents;
-
- /// \brief The number of Objective-C selector parts.
- unsigned NumSelIdents;
+ ArrayRef<IdentifierInfo *> SelIdents;
public:
/// \brief Construct a new code-completion context of the given kind.
- CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(NULL),
- NumSelIdents(0) { }
+ CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { }
/// \brief Construct a new code-completion context of the given kind.
CodeCompletionContext(enum Kind Kind, QualType T,
- IdentifierInfo **SelIdents = NULL,
- unsigned NumSelIdents = 0) : Kind(Kind),
- SelIdents(SelIdents),
- NumSelIdents(NumSelIdents) {
+ ArrayRef<IdentifierInfo *> SelIdents = None)
+ : Kind(Kind),
+ SelIdents(SelIdents) {
if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess ||
Kind == CCC_ObjCPropertyAccess || Kind == CCC_ObjCClassMessage ||
Kind == CCC_ObjCInstanceMessage)
@@ -308,10 +303,7 @@ public:
QualType getBaseType() const { return BaseType; }
/// \brief Retrieve the Objective-C selector identifiers.
- IdentifierInfo **getSelIdents() const { return SelIdents; }
-
- /// \brief Retrieve the number of Objective-C selector identifiers.
- unsigned getNumSelIdents() const { return NumSelIdents; }
+ ArrayRef<IdentifierInfo *> getSelIdents() const { return SelIdents; }
/// \brief Determines whether we want C++ constructors as results within this
/// context.
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 059919a35bb0..8f6bd186a7dc 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -337,6 +337,7 @@ private:
// function-specifier
unsigned FS_inline_specified : 1;
+ unsigned FS_forceinline_specified: 1;
unsigned FS_virtual_specified : 1;
unsigned FS_explicit_specified : 1;
unsigned FS_noreturn_specified : 1;
@@ -381,6 +382,7 @@ private:
SourceRange TypeofParensRange;
SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc;
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
+ SourceLocation FS_forceinlineLoc;
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
WrittenBuiltinSpecs writtenBS;
@@ -419,6 +421,7 @@ public:
TypeSpecOwned(false),
TypeQualifiers(TQ_unspecified),
FS_inline_specified(false),
+ FS_forceinline_specified(false),
FS_virtual_specified(false),
FS_explicit_specified(false),
FS_noreturn_specified(false),
@@ -458,6 +461,12 @@ public:
ThreadStorageClassSpecLoc = SourceLocation();
}
+ void ClearTypeSpecType() {
+ TypeSpecType = DeclSpec::TST_unspecified;
+ TypeSpecOwned = false;
+ TSTLoc = SourceLocation();
+ }
+
// type-specifier
TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; }
TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; }
@@ -504,6 +513,8 @@ public:
return TypeSpecType == TST_auto || TypeSpecType == TST_decltype_auto;
}
+ bool hasTagDefinition() const;
+
/// \brief Turn a type-specifier-type into a string like "_Bool" or "union".
static const char *getSpecifierName(DeclSpec::TST T);
static const char *getSpecifierName(DeclSpec::TQ Q);
@@ -532,8 +543,12 @@ public:
}
// function-specifier
- bool isInlineSpecified() const { return FS_inline_specified; }
- SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }
+ bool isInlineSpecified() const {
+ return FS_inline_specified | FS_forceinline_specified;
+ }
+ SourceLocation getInlineSpecLoc() const {
+ return FS_inline_specified ? FS_inlineLoc : FS_forceinlineLoc;
+ }
bool isVirtualSpecified() const { return FS_virtual_specified; }
SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
@@ -547,6 +562,8 @@ public:
void ClearFunctionSpecs() {
FS_inline_specified = false;
FS_inlineLoc = SourceLocation();
+ FS_forceinline_specified = false;
+ FS_forceinlineLoc = SourceLocation();
FS_virtual_specified = false;
FS_virtualLoc = SourceLocation();
FS_explicit_specified = false;
@@ -615,6 +632,8 @@ public:
const char *&PrevSpec, unsigned &DiagID);
bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID);
+ bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID);
bool SetTypeSpecError();
void UpdateDeclRep(Decl *Rep) {
assert(isDeclRep((TST) TypeSpecType));
@@ -632,10 +651,16 @@ public:
bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, const LangOptions &Lang);
- bool setFunctionSpecInline(SourceLocation Loc);
- bool setFunctionSpecVirtual(SourceLocation Loc);
- bool setFunctionSpecExplicit(SourceLocation Loc);
- bool setFunctionSpecNoreturn(SourceLocation Loc);
+ bool setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
@@ -1500,6 +1525,7 @@ public:
ObjCCatchContext, // Objective-C catch exception-declaration
BlockLiteralContext, // Block literal declarator.
LambdaExprContext, // Lambda-expression declarator.
+ LambdaExprParameterContext, // Lambda-expression parameter declarator.
ConversionIdContext, // C++ conversion-type-id.
TrailingReturnContext, // C++11 trailing-type-specifier.
TemplateTypeArgContext, // Template type argument.
@@ -1575,7 +1601,6 @@ public:
~Declarator() {
clear();
}
-
/// getDeclSpec - Return the declaration-specifier that this declarator was
/// declared with.
const DeclSpec &getDeclSpec() const { return DS; }
@@ -1604,7 +1629,8 @@ public:
bool isPrototypeContext() const {
return (Context == PrototypeContext ||
Context == ObjCParameterContext ||
- Context == ObjCResultContext);
+ Context == ObjCResultContext ||
+ Context == LambdaExprParameterContext);
}
/// \brief Get the source range that spans this declarator.
@@ -1668,6 +1694,7 @@ public:
case AliasDeclContext:
case AliasTemplateContext:
case PrototypeContext:
+ case LambdaExprParameterContext:
case ObjCParameterContext:
case ObjCResultContext:
case TemplateParamContext:
@@ -1696,6 +1723,7 @@ public:
case ForContext:
case ConditionContext:
case PrototypeContext:
+ case LambdaExprParameterContext:
case TemplateParamContext:
case CXXCatchContext:
case ObjCCatchContext:
@@ -1717,6 +1745,39 @@ public:
llvm_unreachable("unknown context kind!");
}
+ /// diagnoseIdentifier - Return true if the identifier is prohibited and
+ /// should be diagnosed (because it cannot be anything else).
+ bool diagnoseIdentifier() const {
+ switch (Context) {
+ case FileContext:
+ case KNRTypeListContext:
+ case MemberContext:
+ case BlockContext:
+ case ForContext:
+ case ConditionContext:
+ case PrototypeContext:
+ case LambdaExprParameterContext:
+ case TemplateParamContext:
+ case CXXCatchContext:
+ case ObjCCatchContext:
+ case TypeNameContext:
+ case ConversionIdContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
+ case BlockLiteralContext:
+ case CXXNewContext:
+ case LambdaExprContext:
+ return false;
+
+ case AliasDeclContext:
+ case AliasTemplateContext:
+ case TemplateTypeArgContext:
+ case TrailingReturnContext:
+ return true;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
/// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
/// followed by a C++ direct initializer, e.g. "int x(1);".
bool mayBeFollowedByCXXDirectInit() const {
@@ -1748,6 +1809,7 @@ public:
case KNRTypeListContext:
case MemberContext:
case PrototypeContext:
+ case LambdaExprParameterContext:
case ObjCParameterContext:
case ObjCResultContext:
case TemplateParamContext:
@@ -1934,6 +1996,7 @@ public:
case AliasDeclContext:
case AliasTemplateContext:
case PrototypeContext:
+ case LambdaExprParameterContext:
case ObjCParameterContext:
case ObjCResultContext:
case TemplateParamContext:
@@ -1995,7 +2058,7 @@ public:
/// \brief Return a source range list of C++11 attributes associated
/// with the declarator.
- void getCXX11AttributeRanges(SmallVector<SourceRange, 4> &Ranges) {
+ void getCXX11AttributeRanges(SmallVectorImpl<SourceRange> &Ranges) {
AttributeList *AttrList = Attrs.getList();
while (AttrList) {
if (AttrList->isCXX11Attribute())
@@ -2038,6 +2101,16 @@ public:
return (FunctionDefinitionKind)FunctionDefinition;
}
+ /// Returns true if this declares a real member and not a friend.
+ bool isFirstDeclarationOfMember() {
+ return getContext() == MemberContext && !getDeclSpec().isFriendSpecified();
+ }
+
+ /// Returns true if this declares a static member. This cannot be called on a
+ /// declarator outside of a MemberContext because we won't know until
+ /// redeclaration time if the decl is static.
+ bool isStaticMember();
+
void setRedeclaration(bool Val) { Redeclaration = Val; }
bool isRedeclaration() const { return Redeclaration; }
};
@@ -2057,7 +2130,8 @@ public:
enum Specifier {
VS_None = 0,
VS_Override = 1,
- VS_Final = 2
+ VS_Final = 2,
+ VS_Sealed = 4
};
VirtSpecifiers() : Specifiers(0) { }
@@ -2068,7 +2142,8 @@ public:
bool isOverrideSpecified() const { return Specifiers & VS_Override; }
SourceLocation getOverrideLoc() const { return VS_overrideLoc; }
- bool isFinalSpecified() const { return Specifiers & VS_Final; }
+ bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed); }
+ bool isFinalSpelledSealed() const { return Specifiers & VS_Sealed; }
SourceLocation getFinalLoc() const { return VS_finalLoc; }
void clear() { Specifiers = 0; }
@@ -2088,13 +2163,16 @@ private:
struct LambdaCapture {
LambdaCaptureKind Kind;
SourceLocation Loc;
- IdentifierInfo* Id;
+ IdentifierInfo *Id;
SourceLocation EllipsisLoc;
-
+ ExprResult Init;
+ ParsedType InitCaptureType;
LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
- IdentifierInfo* Id = 0,
- SourceLocation EllipsisLoc = SourceLocation())
- : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc)
+ IdentifierInfo* Id,
+ SourceLocation EllipsisLoc,
+ ExprResult Init, ParsedType InitCaptureType)
+ : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init),
+ InitCaptureType(InitCaptureType)
{}
};
@@ -2111,11 +2189,13 @@ struct LambdaIntroducer {
/// \brief Append a capture in a lambda introducer.
void addCapture(LambdaCaptureKind Kind,
SourceLocation Loc,
- IdentifierInfo* Id = 0,
- SourceLocation EllipsisLoc = SourceLocation()) {
- Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc));
+ IdentifierInfo* Id,
+ SourceLocation EllipsisLoc,
+ ExprResult Init,
+ ParsedType InitCaptureType) {
+ Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, Init,
+ InitCaptureType));
}
-
};
} // end namespace clang
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index 3704e095c74f..4f4a87fe11f2 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -6,16 +6,17 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the DelayedDiagnostic class, which is used to
-// record diagnostics that are being conditionally produced during
-// declarator parsing. Certain kinds of diagnostics --- notably
-// deprecation and access control --- are suppressed based on
-// semantic properties of the parsed declaration that aren't known
-// until it is fully parsed.
-//
-// This file also defines AccessedEntity.
-//
+///
+/// \file
+/// \brief Defines the classes clang::DelayedDiagnostic and
+/// clang::AccessedEntity.
+///
+/// DelayedDiangostic is used to record diagnostics that are being
+/// conditionally produced during declarator parsing. Certain kinds of
+/// diagnostics -- notably deprecation and access control -- are suppressed
+/// based on semantic properties of the parsed declaration that aren't known
+/// until it is fully parsed.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
@@ -224,8 +225,7 @@ private:
};
};
-/// DelayedDiagnosticPool - A collection of diagnostics which were
-/// delayed.
+/// \brief A collection of diagnostics which were delayed.
class DelayedDiagnosticPool {
const DelayedDiagnosticPool *Parent;
SmallVector<DelayedDiagnostic, 4> Diagnostics;
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index cbce757ea7d0..325abdf8e517 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -14,6 +14,8 @@
#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Type.h"
+#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/MapVector.h"
#include <utility>
@@ -30,7 +32,8 @@ class Sema;
class TypedefNameDecl;
class ValueDecl;
class VarDecl;
-
+struct LateParsedTemplate;
+
/// \brief A simple structure that captures a vtable use for the purposes of
/// the \c ExternalSemaSource.
struct ExternalVTableUse {
@@ -177,6 +180,45 @@ public:
SmallVectorImpl<std::pair<ValueDecl *,
SourceLocation> > &Pending) {}
+ /// \brief Read the set of late parsed template functions for this source.
+ ///
+ /// The external source should insert its own late parsed template functions
+ /// into the map. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same map entries
+ /// repeatedly.
+ virtual void ReadLateParsedTemplates(
+ llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {}
+
+ /// \copydoc Sema::CorrectTypo
+ /// \note LookupKind must correspond to a valid Sema::LookupNameKind
+ ///
+ /// ExternalSemaSource::CorrectTypo is always given the first chance to
+ /// correct a typo (really, to offer suggestions to repair a failed lookup).
+ /// It will even be called when SpellChecking is turned off or after a
+ /// fatal error has already been detected.
+ virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ int LookupKind, Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT) {
+ return TypoCorrection();
+ }
+
+ /// \brief Produces a diagnostic note if the external source contains a
+ /// complete definition for \p T.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the \c QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
+ QualType T) {
+ return false;
+ }
+
// isa/cast/dyn_cast support
static bool classof(const ExternalASTSource *Source) {
return Source->SemaSource;
diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h
index 0b1b74a0d8cc..99d94a1fed85 100644
--- a/include/clang/Sema/IdentifierResolver.h
+++ b/include/clang/Sema/IdentifierResolver.h
@@ -51,11 +51,6 @@ class IdentifierResolver {
/// The decl must already be part of the decl chain.
void RemoveDecl(NamedDecl *D);
- /// Replaces the Old declaration with the New declaration. If the
- /// replacement is successful, returns true. If the old
- /// declaration was not found, returns false.
- bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
-
/// \brief Insert the given declaration at the given position in the list.
void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) {
Decls.insert(Pos, D);
@@ -168,11 +163,6 @@ public:
/// The decl must already be part of the decl chain.
void RemoveDecl(NamedDecl *D);
- /// Replace the decl Old with the new declaration New on its
- /// identifier chain. Returns true if the old declaration was found
- /// (and, therefore, replaced).
- bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
-
/// \brief Insert the given declaration after the given iterator
/// position.
void InsertDeclAfter(iterator Pos, NamedDecl *D);
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 58781ac628c4..83fb2be5f15f 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -35,6 +35,7 @@ class ParmVarDecl;
class Sema;
class TypeLoc;
class VarDecl;
+class ObjCMethodDecl;
/// \brief Describes an entity that is being initialized.
class InitializedEntity {
@@ -78,7 +79,17 @@ public:
EK_LambdaCapture,
/// \brief The entity being initialized is the initializer for a compound
/// literal.
- EK_CompoundLiteralInit
+ EK_CompoundLiteralInit,
+ /// \brief The entity being implicitly initialized back to the formal
+ /// result type.
+ EK_RelatedResult,
+ /// \brief The entity being initialized is a function parameter; function
+ /// is member of group of audited CF APIs.
+ EK_Parameter_CF_Audited
+
+ // Note: err_init_conversion_failed in DiagnosticSemaKinds.td uses this
+ // enum as an index for its first %select. When modifying this list,
+ // that diagnostic text needs to be updated as well.
};
private:
@@ -105,8 +116,8 @@ private:
};
struct C {
- /// \brief The variable being captured by an EK_LambdaCapture.
- VarDecl *Var;
+ /// \brief The name of the variable being captured by an EK_LambdaCapture.
+ IdentifierInfo *VarID;
/// \brief The source location at which the capture occurs.
unsigned Location;
@@ -116,6 +127,10 @@ private:
/// \brief When Kind == EK_Variable, or EK_Member, the VarDecl or
/// FieldDecl, respectively.
DeclaratorDecl *VariableOrMember;
+
+ /// \brief When Kind == EK_RelatedResult, the ObjectiveC method where
+ /// result type was implicitly changed to accommodate ARC semantics.
+ ObjCMethodDecl *MethodDecl;
/// \brief When Kind == EK_Parameter, the ParmVarDecl, with the
/// low bit indicating whether the parameter is "consumed".
@@ -168,10 +183,10 @@ private:
const InitializedEntity &Parent);
/// \brief Create the initialization entity for a lambda capture.
- InitializedEntity(VarDecl *Var, FieldDecl *Field, SourceLocation Loc)
- : Kind(EK_LambdaCapture), Parent(0), Type(Field->getType())
+ InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
+ : Kind(EK_LambdaCapture), Parent(0), Type(FieldType)
{
- Capture.Var = Var;
+ Capture.VarID = VarID;
Capture.Location = Loc.getRawEncoding();
}
@@ -254,10 +269,19 @@ public:
Result.TypeInfo = TypeInfo;
return Result;
}
+
+ /// \brief Create the initialization entity for a related result.
+ static InitializedEntity InitializeRelatedResult(ObjCMethodDecl *MD,
+ QualType Type) {
+ InitializedEntity Result(EK_RelatedResult, SourceLocation(), Type);
+ Result.MethodDecl = MD;
+ return Result;
+ }
+
/// \brief Create the initialization entity for a base class subobject.
static InitializedEntity InitializeBase(ASTContext &Context,
- CXXBaseSpecifier *Base,
+ const CXXBaseSpecifier *Base,
bool IsInheritedVirtualBase);
/// \brief Create the initialization entity for a delegated constructor.
@@ -285,10 +309,10 @@ public:
}
/// \brief Create the initialization entity for a lambda capture.
- static InitializedEntity InitializeLambdaCapture(VarDecl *Var,
- FieldDecl *Field,
+ static InitializedEntity InitializeLambdaCapture(IdentifierInfo *VarID,
+ QualType FieldType,
SourceLocation Loc) {
- return InitializedEntity(Var, Field, Loc);
+ return InitializedEntity(VarID, FieldType, Loc);
}
/// \brief Create the entity for a compound literal initializer.
@@ -326,22 +350,29 @@ public:
/// \brief Retrieve the variable, parameter, or field being
/// initialized.
DeclaratorDecl *getDecl() const;
+
+ /// \brief Retrieve the ObjectiveC method being initialized.
+ ObjCMethodDecl *getMethodDecl() const { return MethodDecl; }
/// \brief Determine whether this initialization allows the named return
/// value optimization, which also applies to thrown objects.
bool allowsNRVO() const;
+ bool isParameterKind() const {
+ return (getKind() == EK_Parameter ||
+ getKind() == EK_Parameter_CF_Audited);
+ }
/// \brief Determine whether this initialization consumes the
/// parameter.
bool isParameterConsumed() const {
- assert(getKind() == EK_Parameter && "Not a parameter");
+ assert(isParameterKind() && "Not a parameter");
return (Parameter & 1);
}
/// \brief Retrieve the base specifier.
- CXXBaseSpecifier *getBaseSpecifier() const {
+ const CXXBaseSpecifier *getBaseSpecifier() const {
assert(getKind() == EK_Base && "Not a base specifier");
- return reinterpret_cast<CXXBaseSpecifier *>(Base & ~0x1);
+ return reinterpret_cast<const CXXBaseSpecifier *>(Base & ~0x1);
}
/// \brief Return whether the base is an inherited virtual base.
@@ -371,19 +402,28 @@ public:
getKind() == EK_ComplexElement);
this->Index = Index;
}
-
- /// \brief Retrieve the variable for a captured variable in a lambda.
- VarDecl *getCapturedVar() const {
+ /// \brief For a lambda capture, return the capture's name.
+ StringRef getCapturedVarName() const {
assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
- return Capture.Var;
+ return Capture.VarID->getName();
}
-
/// \brief Determine the location of the capture when initializing
/// field from a captured variable in a lambda.
SourceLocation getCaptureLoc() const {
assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
return SourceLocation::getFromRawEncoding(Capture.Location);
}
+
+ void setParameterCFAudited() {
+ Kind = EK_Parameter_CF_Audited;
+ }
+
+ /// Dump a representation of the initialized entity to standard error,
+ /// for debugging purposes.
+ void dump() const;
+
+private:
+ unsigned dumpImpl(raw_ostream &OS) const;
};
/// \brief Describes the kind of initialization being performed, along with
@@ -544,8 +584,10 @@ public:
bool AllowExplicit() const { return !isCopyInit(); }
/// \brief Retrieve whether this initialization allows the use of explicit
- /// conversion functions.
- bool allowExplicitConversionFunctions() const {
+ /// conversion functions when binding a reference. If the reference is the
+ /// first parameter in a copy or move constructor, such conversions are
+ /// permitted even though we are performing copy-initialization.
+ bool allowExplicitConversionFunctionsInRefBinding() const {
return !isCopyInit() || Context == IC_ExplicitConvs;
}
@@ -610,6 +652,8 @@ public:
SK_LValueToRValue,
/// \brief Perform an implicit conversion sequence.
SK_ConversionSequence,
+ /// \brief Perform an implicit conversion sequence without narrowing.
+ SK_ConversionSequenceNoNarrowing,
/// \brief Perform list-initialization without a constructor
SK_ListInitialization,
/// \brief Perform list-initialization with a constructor.
@@ -706,6 +750,16 @@ public:
/// \brief Array must be initialized with an initializer list or a
/// string literal.
FK_ArrayNeedsInitListOrStringLiteral,
+ /// \brief Array must be initialized with an initializer list or a
+ /// wide string literal.
+ FK_ArrayNeedsInitListOrWideStringLiteral,
+ /// \brief Initializing a wide char array with narrow string literal.
+ FK_NarrowStringIntoWideCharArray,
+ /// \brief Initializing char array with wide string literal.
+ FK_WideStringIntoCharArray,
+ /// \brief Initializing wide char array with incompatible wide string
+ /// literal.
+ FK_IncompatWideStringIntoWideChar,
/// \brief Array type mismatch.
FK_ArrayTypeMismatch,
/// \brief Non-constant array initializer
@@ -753,9 +807,6 @@ public:
/// \brief Initializer has a placeholder type which cannot be
/// resolved by initialization.
FK_PlaceholderType,
- /// \brief Failed to initialize a std::initializer_list because copy
- /// construction of some element failed.
- FK_InitListElementCopyFailure,
/// \brief List-copy-initialization chose an explicit constructor.
FK_ExplicitConstructor
};
@@ -791,11 +842,19 @@ public:
/// \param Kind the kind of initialization being performed.
///
/// \param Args the argument(s) provided for initialization.
+ ///
+ /// \param InInitList true if we are initializing from an expression within
+ /// an initializer list. This disallows narrowing conversions in C++11
+ /// onwards.
InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
- MultiExprArg Args);
-
+ MultiExprArg Args,
+ bool InInitList = false);
+ void InitializeFrom(Sema &S, const InitializedEntity &Entity,
+ const InitializationKind &Kind, MultiExprArg Args,
+ bool InInitList);
+
~InitializationSequence();
/// \brief Perform the actual initialization of the given entity based on
@@ -841,12 +900,12 @@ public:
void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
/// \brief Determine whether the initialization sequence is valid.
- operator bool() const { return !Failed(); }
+ LLVM_EXPLICIT operator bool() const { return !Failed(); }
/// \brief Determine whether the initialization sequence is invalid.
bool Failed() const { return SequenceKind == FailedSequence; }
-
- typedef SmallVector<Step, 4>::const_iterator step_iterator;
+
+ typedef SmallVectorImpl<Step>::const_iterator step_iterator;
step_iterator step_begin() const { return Steps.begin(); }
step_iterator step_end() const { return Steps.end(); }
@@ -930,7 +989,7 @@ public:
/// \brief Add a new step that applies an implicit conversion sequence.
void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
- QualType T);
+ QualType T, bool TopLevelOfInitList = false);
/// \brief Add a list-initialization step.
void AddListInitializationStep(QualType T);
diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index 3e7e3a16ebc8..105c8791e222 100644
--- a/include/clang/Sema/Lookup.h
+++ b/include/clang/Sema/Lookup.h
@@ -139,7 +139,8 @@ public:
Redecl(Redecl != Sema::NotForRedeclaration),
HideTags(true),
Diagnose(Redecl == Sema::NotForRedeclaration),
- AllowHidden(Redecl == Sema::ForRedeclaration)
+ AllowHidden(Redecl == Sema::ForRedeclaration),
+ Shadowed(false)
{
configure();
}
@@ -160,7 +161,8 @@ public:
Redecl(Redecl != Sema::NotForRedeclaration),
HideTags(true),
Diagnose(Redecl == Sema::NotForRedeclaration),
- AllowHidden(Redecl == Sema::ForRedeclaration)
+ AllowHidden(Redecl == Sema::ForRedeclaration),
+ Shadowed(false)
{
configure();
}
@@ -179,7 +181,8 @@ public:
Redecl(Other.Redecl),
HideTags(Other.HideTags),
Diagnose(false),
- AllowHidden(Other.AllowHidden)
+ AllowHidden(Other.AllowHidden),
+ Shadowed(false)
{}
~LookupResult() {
@@ -283,33 +286,36 @@ public:
/// \brief Determine whether the given declaration is visible to the
/// program.
- static bool isVisible(NamedDecl *D) {
+ static bool isVisible(Sema &SemaRef, NamedDecl *D) {
// If this declaration is not hidden, it's visible.
if (!D->isHidden())
return true;
-
- // FIXME: We should be allowed to refer to a module-private name from
- // within the same module, e.g., during template instantiation.
- // This requires us know which module a particular declaration came from.
- return false;
+
+ if (SemaRef.ActiveTemplateInstantiations.empty())
+ return false;
+
+ // During template instantiation, we can refer to hidden declarations, if
+ // they were visible in any module along the path of instantiation.
+ return isVisibleSlow(SemaRef, D);
}
-
+
/// \brief Retrieve the accepted (re)declaration of the given declaration,
/// if there is one.
NamedDecl *getAcceptableDecl(NamedDecl *D) const {
if (!D->isInIdentifierNamespace(IDNS))
return 0;
-
- if (isHiddenDeclarationVisible() || isVisible(D))
+
+ if (isHiddenDeclarationVisible() || isVisible(SemaRef, D))
return D;
-
+
return getAcceptableDeclSlow(D);
}
-
+
private:
+ static bool isVisibleSlow(Sema &SemaRef, NamedDecl *D);
NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
+
public:
-
/// \brief Returns the identifier namespace mask for this lookup.
unsigned getIdentifierNamespace() const {
return IDNS;
@@ -390,7 +396,15 @@ public:
assert(ResultKind == NotFound && Decls.empty());
ResultKind = NotFoundInCurrentInstantiation;
}
-
+
+ /// \brief Determine whether the lookup result was shadowed by some other
+ /// declaration that lookup ignored.
+ bool isShadowed() const { return Shadowed; }
+
+ /// \brief Note that we found and ignored a declaration while performing
+ /// lookup.
+ void setShadowed() { Shadowed = true; }
+
/// \brief Resolves the result kind of the lookup, possibly hiding
/// decls.
///
@@ -479,6 +493,7 @@ public:
if (Paths) deletePaths(Paths);
Paths = NULL;
NamingClass = 0;
+ Shadowed = false;
}
/// \brief Clears out any current state and re-initializes for a
@@ -598,6 +613,13 @@ public:
return Filter(*this);
}
+ void setFindLocalExtern(bool FindLocalExtern) {
+ if (FindLocalExtern)
+ IDNS |= Decl::IDNS_LocalExtern;
+ else
+ IDNS &= ~Decl::IDNS_LocalExtern;
+ }
+
private:
void diagnose() {
if (isAmbiguous())
@@ -657,34 +679,44 @@ private:
/// \brief True if we should allow hidden declarations to be 'visible'.
bool AllowHidden;
+
+ /// \brief True if the found declarations were shadowed by some other
+ /// declaration that we skipped. This only happens when \c LookupKind
+ /// is \c LookupRedeclarationWithLinkage.
+ bool Shadowed;
};
- /// \brief Consumes visible declarations found when searching for
- /// all visible names within a given scope or context.
+/// \brief Consumes visible declarations found when searching for
+/// all visible names within a given scope or context.
+///
+/// This abstract class is meant to be subclassed by clients of \c
+/// Sema::LookupVisibleDecls(), each of which should override the \c
+/// FoundDecl() function to process declarations as they are found.
+class VisibleDeclConsumer {
+public:
+ /// \brief Destroys the visible declaration consumer.
+ virtual ~VisibleDeclConsumer();
+
+ /// \brief Determine whether hidden declarations (from unimported
+ /// modules) should be given to this consumer. By default, they
+ /// are not included.
+ virtual bool includeHiddenDecls() const;
+
+ /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
+ /// declaration visible from the current scope or context.
///
- /// This abstract class is meant to be subclassed by clients of \c
- /// Sema::LookupVisibleDecls(), each of which should override the \c
- /// FoundDecl() function to process declarations as they are found.
- class VisibleDeclConsumer {
- public:
- /// \brief Destroys the visible declaration consumer.
- virtual ~VisibleDeclConsumer();
-
- /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
- /// declaration visible from the current scope or context.
- ///
- /// \param ND the declaration found.
- ///
- /// \param Hiding a declaration that hides the declaration \p ND,
- /// or NULL if no such declaration exists.
- ///
- /// \param Ctx the original context from which the lookup started.
- ///
- /// \param InBaseClass whether this declaration was found in base
- /// class of the context we searched.
- virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
- bool InBaseClass) = 0;
- };
+ /// \param ND the declaration found.
+ ///
+ /// \param Hiding a declaration that hides the declaration \p ND,
+ /// or NULL if no such declaration exists.
+ ///
+ /// \param Ctx the original context from which the lookup started.
+ ///
+ /// \param InBaseClass whether this declaration was found in base
+ /// class of the context we searched.
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) = 0;
+};
/// \brief A class for storing results from argument-dependent lookup.
class ADLResult {
@@ -701,7 +733,8 @@ public:
Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
}
- class iterator {
+ class iterator
+ : public std::iterator<std::forward_iterator_tag, NamedDecl *> {
typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator;
inner_iterator iter;
@@ -713,7 +746,7 @@ public:
iterator &operator++() { ++iter; return *this; }
iterator operator++(int) { return iterator(iter++); }
- NamedDecl *operator*() const { return iter->second; }
+ value_type operator*() const { return iter->second; }
bool operator==(const iterator &other) const { return iter == other.iter; }
bool operator!=(const iterator &other) const { return iter != other.iter; }
diff --git a/include/clang/Sema/Makefile b/include/clang/Sema/Makefile
index 7d658a7c11ef..799f789e0ead 100644
--- a/include/clang/Sema/Makefile
+++ b/include/clang/Sema/Makefile
@@ -1,7 +1,7 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
BUILT_SOURCES = AttrTemplateInstantiate.inc AttrParsedAttrList.inc AttrParsedAttrKinds.inc \
- AttrSpellingListIndex.inc
+ AttrSpellingListIndex.inc AttrParsedAttrImpl.inc
TABLEGEN_INC_FILES_COMMON = 1
@@ -31,4 +31,9 @@ $(ObjDir)/AttrSpellingListIndex.inc.tmp : $(TD_SRC_DIR)/Attr.td \
$(Verb) $(ClangTableGen) -gen-clang-attr-spelling-index -o \
$(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $<
+$(ObjDir)/AttrParsedAttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td \
+ $(CLANG_TBLGEN) $(ObjDir)/.dir
+ $(Echo) "Building Clang parsed attribute list impl with tablegen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-parsed-attr-impl -o \
+ $(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $<
diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h
index ff87d05c0404..e9ba479d1255 100644
--- a/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -322,6 +322,36 @@ public:
virtual void ReadPendingInstantiations(
SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending);
+ /// \brief Read the set of late parsed template functions for this source.
+ ///
+ /// The external source should insert its own late parsed template functions
+ /// into the map. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same map entries
+ /// repeatedly.
+ virtual void ReadLateParsedTemplates(
+ llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap);
+
+ /// \copydoc ExternalSemaSource::CorrectTypo
+ /// \note Returns the first nonempty correction.
+ virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ int LookupKind, Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT);
+
+ /// \brief Produces a diagnostic note if one of the attached sources
+ /// contains a complete definition for \p T. Queries the sources in list
+ /// order until the first one claims that a diagnostic was produced.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the \c QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, QualType T);
+
// isa/cast/dyn_cast support
static bool classof(const MultiplexExternalSemaSource*) { return true; }
//static bool classof(const ExternalSemaSource*) { return true; }
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index c685843f18cd..b8bd14aa1cd5 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -22,6 +22,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Sema/SemaFixItUtils.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
@@ -241,7 +242,7 @@ namespace clang {
QualType &ConstantType) const;
bool isPointerConversionToBool() const;
bool isPointerConversionToVoidPointer(ASTContext& Context) const;
- void DebugPrint() const;
+ void dump() const;
};
/// UserDefinedConversionSequence - Represents a user-defined
@@ -287,7 +288,7 @@ namespace clang {
/// that refers to \c ConversionFunction.
DeclAccessPair FoundConversionFunction;
- void DebugPrint() const;
+ void dump() const;
};
/// Represents an ambiguous user-defined conversion sequence.
@@ -405,9 +406,6 @@ namespace clang {
/// ConversionKind - The kind of implicit conversion sequence.
unsigned ConversionKind : 30;
- /// \brief Whether the argument is an initializer list.
- bool ListInitializationSequence : 1;
-
/// \brief Whether the target is really a std::initializer_list, and the
/// sequence only represents the worst element conversion.
bool StdInitializerListElement : 1;
@@ -440,16 +438,14 @@ namespace clang {
BadConversionSequence Bad;
};
- ImplicitConversionSequence()
- : ConversionKind(Uninitialized), ListInitializationSequence(false),
- StdInitializerListElement(false)
+ ImplicitConversionSequence()
+ : ConversionKind(Uninitialized), StdInitializerListElement(false)
{}
~ImplicitConversionSequence() {
destruct();
}
ImplicitConversionSequence(const ImplicitConversionSequence &Other)
- : ConversionKind(Other.ConversionKind),
- ListInitializationSequence(Other.ListInitializationSequence),
+ : ConversionKind(Other.ConversionKind),
StdInitializerListElement(Other.StdInitializerListElement)
{
switch (ConversionKind) {
@@ -535,16 +531,6 @@ namespace clang {
Ambiguous.construct();
}
- /// \brief Whether this sequence was created by the rules of
- /// list-initialization sequences.
- bool isListInitializationSequence() const {
- return ListInitializationSequence;
- }
-
- void setListInitializationSequence() {
- ListInitializationSequence = true;
- }
-
/// \brief Whether the target is really a std::initializer_list, and the
/// sequence only represents the worst element conversion.
bool isStdInitializerListElement() const {
@@ -568,7 +554,7 @@ namespace clang {
SourceLocation CaretLoc,
const PartialDiagnostic &PDiag) const;
- void DebugPrint() const;
+ void dump() const;
};
enum OverloadFailureKind {
@@ -656,53 +642,6 @@ namespace clang {
/// \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 {
- /// A Sema::TemplateDeductionResult.
- unsigned Result : 8;
-
- /// \brief Indicates whether a diagnostic is stored in Diagnostic.
- unsigned HasDiagnostic : 1;
-
- /// \brief Opaque pointer containing additional data about
- /// this deduction failure.
- void *Data;
-
- /// \brief A diagnostic indicating why deduction failed.
- union {
- void *Align;
- char Diagnostic[sizeof(PartialDiagnosticAt)];
- };
-
- /// \brief Retrieve the diagnostic which caused this deduction failure,
- /// if any.
- PartialDiagnosticAt *getSFINAEDiagnostic();
-
- /// \brief Retrieve the template parameter this deduction failure
- /// refers to, if any.
- TemplateParameter getTemplateParameter();
-
- /// \brief Retrieve the template argument list associated with this
- /// deduction failure, if any.
- TemplateArgumentList *getTemplateArgumentList();
-
- /// \brief Return the first template argument this deduction failure
- /// refers to, if any.
- const TemplateArgument *getFirstArg();
-
- /// \brief Return the second template argument this deduction failure
- /// refers to, if any.
- const TemplateArgument *getSecondArg();
-
- /// \brief Return the expression this deduction failure refers to,
- /// if any.
- Expr *getExpr();
-
- /// \brief Free any memory associated with this deduction failure.
- void Destroy();
- };
union {
DeductionFailureInfo DeductionFailure;
@@ -773,7 +712,7 @@ namespace clang {
/// \brief Clear out all of the candidates.
void clear();
- typedef SmallVector<OverloadCandidate, 16>::iterator iterator;
+ typedef SmallVectorImpl<OverloadCandidate>::iterator iterator;
iterator begin() { return Candidates.begin(); }
iterator end() { return Candidates.end(); }
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
index c3d1f4e0b7db..b7d7710eb121 100644
--- a/include/clang/Sema/Ownership.h
+++ b/include/clang/Sema/Ownership.h
@@ -33,8 +33,12 @@ namespace clang {
class TemplateName;
class TemplateParameterList;
- /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
- /// Parser doesn't know about but that Sema or another client does. The UID
+ /// \brief Wrapper for void* pointer.
+ /// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like
+ /// a pointer.
+ ///
+ /// This is a very simple POD type that wraps a pointer that the Parser
+ /// doesn't know about but that Sema or another client does. The PtrTy
/// template argument is used to make sure that "Decl" pointers are not
/// compatible with "Type" pointers for example.
template <class PtrTy>
@@ -49,11 +53,21 @@ namespace clang {
static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
- template <typename T> T* getAs() const {
+ /// \brief Returns plain pointer to the entity pointed by this wrapper.
+ /// \tparam PointeeT Type of pointed entity.
+ ///
+ /// It is identical to getPtrAs<PointeeT*>.
+ template <typename PointeeT> PointeeT* getPtrTo() const {
return get();
}
- template <typename T> T getAsVal() const {
+ /// \brief Returns pointer converted to the specified type.
+ /// \tparam PtrT Result pointer type. There must be implicit conversion
+ /// from PtrTy to PtrT.
+ ///
+ /// In contrast to getPtrTo, this method allows the return type to be
+ /// a smart pointer.
+ template <typename PtrT> PtrT getPtrAs() const {
return get();
}
@@ -65,7 +79,7 @@ namespace clang {
Ptr = Traits::getAsVoidPointer(P);
}
- operator bool() const { return Ptr != 0; }
+ LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
void *getAsOpaquePtr() const { return Ptr; }
static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index d016b9b887c5..249a4c74311b 100644
--- a/include/clang/Sema/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -91,7 +91,10 @@ public:
TryScope = 0x2000,
/// \brief This is the scope for a function-level C++ try or catch scope.
- FnTryCatchScope = 0x4000
+ FnTryCatchScope = 0x4000,
+
+ /// \brief This is the scope of OpenMP executable directive
+ OpenMPDirectiveScope = 0x8000
};
private:
/// The parent scope for this scope. This is null for the translation-unit
@@ -143,11 +146,10 @@ private:
typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy;
DeclSetTy DeclsInScope;
- /// Entity - The entity with which this scope is associated. For
+ /// The DeclContext with which this scope is associated. For
/// example, the entity of a class scope is the class itself, the
- /// entity of a function scope is a function, etc. This field is
- /// maintained by the Action implementation.
- void *Entity;
+ /// entity of a function scope is a function, etc.
+ DeclContext *Entity;
typedef SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy;
UsingDirectivesTy UsingDirectives;
@@ -236,8 +238,8 @@ public:
return DeclsInScope.count(D) != 0;
}
- void* getEntity() const { return Entity; }
- void setEntity(void *E) { Entity = E; }
+ DeclContext *getEntity() const { return Entity; }
+ void setEntity(DeclContext *E) { Entity = E; }
bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); }
@@ -301,7 +303,12 @@ public:
}
return false;
}
-
+
+ /// \brief Determines whether this scope is the OpenMP directive scope
+ bool isOpenMPDirectiveScope() const {
+ return (getFlags() & Scope::OpenMPDirectiveScope);
+ }
+
/// \brief Determine whether this scope is a C++ 'try' block.
bool isTryScope() const { return getFlags() & Scope::TryScope; }
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index b232b59d3c17..06afe1a8ae9d 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -18,8 +18,11 @@
#include "clang/AST/Type.h"
#include "clang/Basic/CapturedStmt.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Sema/Ownership.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
namespace clang {
@@ -27,6 +30,7 @@ class Decl;
class BlockDecl;
class CapturedDecl;
class CXXMethodDecl;
+class FieldDecl;
class ObjCPropertyDecl;
class IdentifierInfo;
class ImplicitParamDecl;
@@ -34,8 +38,11 @@ class LabelDecl;
class ReturnStmt;
class Scope;
class SwitchStmt;
+class TemplateTypeParmDecl;
+class TemplateParameterList;
class VarDecl;
class DeclRefExpr;
+class MemberExpr;
class ObjCIvarRefExpr;
class ObjCPropertyRefExpr;
class ObjCMessageExpr;
@@ -330,60 +337,78 @@ public:
ImplicitCaptureStyle ImpCaptureStyle;
class Capture {
- // There are two categories of capture: capturing 'this', and capturing
- // local variables. There are three ways to capture a local variable:
- // capture by copy in the C++11 sense, capture by reference
- // in the C++11 sense, and __block capture. Lambdas explicitly specify
- // capture by copy or capture by reference. For blocks, __block capture
- // applies to variables with that annotation, variables of reference type
- // are captured by reference, and other variables are captured by copy.
+ // There are three categories of capture: capturing 'this', capturing
+ // local variables, and C++1y initialized captures (which can have an
+ // arbitrary initializer, and don't really capture in the traditional
+ // sense at all).
+ //
+ // There are three ways to capture a local variable:
+ // - capture by copy in the C++11 sense,
+ // - capture by reference in the C++11 sense, and
+ // - __block capture.
+ // Lambdas explicitly specify capture by copy or capture by reference.
+ // For blocks, __block capture applies to variables with that annotation,
+ // variables of reference type are captured by reference, and other
+ // variables are captured by copy.
enum CaptureKind {
- Cap_This, Cap_ByCopy, Cap_ByRef, Cap_Block
+ Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_This
};
- // The variable being captured (if we are not capturing 'this'),
- // and misc bits descibing the capture.
- llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind;
+ /// The variable being captured (if we are not capturing 'this') and whether
+ /// this is a nested capture.
+ llvm::PointerIntPair<VarDecl*, 1, bool> VarAndNested;
- // Expression to initialize a field of the given type, and whether this
- // is a nested capture; the expression is only required if we are
- // capturing ByVal and the variable's type has a non-trivial
- // copy constructor.
- llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested;
+ /// Expression to initialize a field of the given type, and the kind of
+ /// capture (if this is a capture and not an init-capture). The expression
+ /// is only required if we are capturing ByVal and the variable's type has
+ /// a non-trivial copy constructor.
+ llvm::PointerIntPair<Expr*, 2, CaptureKind> InitExprAndCaptureKind;
- /// \brief The source location at which the first capture occurred..
+ /// \brief The source location at which the first capture occurred.
SourceLocation Loc;
-
+
/// \brief The location of the ellipsis that expands a parameter pack.
SourceLocation EllipsisLoc;
-
+
/// \brief The type as it was captured, which is in effect the type of the
/// non-static data member that would hold the capture.
QualType CaptureType;
-
+
public:
- Capture(VarDecl *Var, bool block, bool byRef, bool isNested,
- SourceLocation Loc, SourceLocation EllipsisLoc,
+ Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
QualType CaptureType, Expr *Cpy)
- : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy),
- CopyExprAndNested(Cpy, isNested), Loc(Loc), EllipsisLoc(EllipsisLoc),
- CaptureType(CaptureType){}
+ : VarAndNested(Var, IsNested),
+ InitExprAndCaptureKind(Cpy, Block ? Cap_Block :
+ ByRef ? Cap_ByRef : Cap_ByCopy),
+ Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
enum IsThisCapture { ThisCapture };
- Capture(IsThisCapture, bool isNested, SourceLocation Loc,
+ Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
QualType CaptureType, Expr *Cpy)
- : VarAndKind(0, Cap_This), CopyExprAndNested(Cpy, isNested), Loc(Loc),
- EllipsisLoc(), CaptureType(CaptureType) { }
+ : VarAndNested(0, IsNested),
+ InitExprAndCaptureKind(Cpy, Cap_This),
+ Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {}
- bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; }
- bool isVariableCapture() const { return !isThisCapture(); }
- bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; }
- bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; }
- bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; }
- bool isNested() { return CopyExprAndNested.getInt(); }
+ bool isThisCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_This;
+ }
+ bool isVariableCapture() const {
+ return InitExprAndCaptureKind.getInt() != Cap_This;
+ }
+ bool isCopyCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
+ }
+ bool isReferenceCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByRef;
+ }
+ bool isBlockCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_Block;
+ }
+ bool isNested() { return VarAndNested.getInt(); }
VarDecl *getVariable() const {
- return VarAndKind.getPointer();
+ return VarAndNested.getPointer();
}
/// \brief Retrieve the location at which this variable was captured.
@@ -398,8 +423,8 @@ public:
/// that would store this capture.
QualType getCaptureType() const { return CaptureType; }
- Expr *getCopyExpr() const {
- return CopyExprAndNested.getPointer();
+ Expr *getInitExpr() const {
+ return InitExprAndCaptureKind.getPointer();
}
};
@@ -529,6 +554,8 @@ public:
switch (CapRegionKind) {
case CR_Default:
return "default captured statement";
+ case CR_OpenMP:
+ return "OpenMP region";
}
llvm_unreachable("Invalid captured region kind!");
}
@@ -543,19 +570,23 @@ public:
/// \brief The class that describes the lambda.
CXXRecordDecl *Lambda;
- /// \brief The class that describes the lambda.
+ /// \brief The lambda's compiler-generated \c operator().
CXXMethodDecl *CallOperator;
/// \brief Source range covering the lambda introducer [...].
SourceRange IntroducerRange;
- /// \brief The number of captures in the \c Captures list that are
+ /// \brief Source location of the '&' or '=' specifying the default capture
+ /// type, if any.
+ SourceLocation CaptureDefaultLoc;
+
+ /// \brief The number of captures in the \c Captures list that are
/// explicit captures.
unsigned NumExplicitCaptures;
/// \brief Whether this is a mutable lambda.
bool Mutable;
-
+
/// \brief Whether the (empty) parameter list is explicit.
bool ExplicitParams;
@@ -572,25 +603,169 @@ public:
/// its list of array index variables.
SmallVector<unsigned, 4> ArrayIndexStarts;
- LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
- CXXMethodDecl *CallOperator)
- : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
- CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),
- ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)
+ /// \brief If this is a generic lambda, use this as the depth of
+ /// each 'auto' parameter, during initial AST construction.
+ unsigned AutoTemplateParameterDepth;
+
+ /// \brief Store the list of the auto parameters for a generic lambda.
+ /// If this is a generic lambda, store the list of the auto
+ /// parameters converted into TemplateTypeParmDecls into a vector
+ /// that can be used to construct the generic lambda's template
+ /// parameter list, during initial AST construction.
+ SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;
+
+ /// If this is a generic lambda, and the template parameter
+ /// list has been created (from the AutoTemplateParams) then
+ /// store a reference to it (cache it to avoid reconstructing it).
+ TemplateParameterList *GLTemplateParameterList;
+
+ /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs
+ /// or MemberExprs) that refer to local variables in a generic lambda
+ /// or a lambda in a potentially-evaluated-if-used context.
+ ///
+ /// Potentially capturable variables of a nested lambda that might need
+ /// to be captured by the lambda are housed here.
+ /// This is specifically useful for generic lambdas or
+ /// lambdas within a a potentially evaluated-if-used context.
+ /// If an enclosing variable is named in an expression of a lambda nested
+ /// within a generic lambda, we don't always know know whether the variable
+ /// will truly be odr-used (i.e. need to be captured) by that nested lambda,
+ /// until its instantiation. But we still need to capture it in the
+ /// enclosing lambda if all intervening lambdas can capture the variable.
+
+ llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;
+
+ /// \brief Contains all variable-referring-expressions that refer
+ /// to local variables that are usable as constant expressions and
+ /// do not involve an odr-use (they may still need to be captured
+ /// if the enclosing full-expression is instantiation dependent).
+ llvm::SmallSet<Expr*, 8> NonODRUsedCapturingExprs;
+
+ SourceLocation PotentialThisCaptureLocation;
+
+ LambdaScopeInfo(DiagnosticsEngine &Diag)
+ : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0),
+ CallOperator(0), NumExplicitCaptures(0), Mutable(false),
+ ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false),
+ AutoTemplateParameterDepth(0), GLTemplateParameterList(0)
{
Kind = SK_Lambda;
}
virtual ~LambdaScopeInfo();
- /// \brief Note when
+ /// \brief Note when all explicit captures have been added.
void finishedExplicitCaptures() {
NumExplicitCaptures = Captures.size();
}
static bool classof(const FunctionScopeInfo *FSI) {
- return FSI->Kind == SK_Lambda;
+ return FSI->Kind == SK_Lambda;
}
+
+ ///
+ /// \brief Add a variable that might potentially be captured by the
+ /// lambda and therefore the enclosing lambdas.
+ ///
+ /// This is also used by enclosing lambda's to speculatively capture
+ /// variables that nested lambda's - depending on their enclosing
+ /// specialization - might need to capture.
+ /// Consider:
+ /// void f(int, int); <-- don't capture
+ /// void f(const int&, double); <-- capture
+ /// void foo() {
+ /// const int x = 10;
+ /// auto L = [=](auto a) { // capture 'x'
+ /// return [=](auto b) {
+ /// f(x, a); // we may or may not need to capture 'x'
+ /// };
+ /// };
+ /// }
+ void addPotentialCapture(Expr *VarExpr) {
+ assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr));
+ PotentiallyCapturingExprs.push_back(VarExpr);
+ }
+
+ void addPotentialThisCapture(SourceLocation Loc) {
+ PotentialThisCaptureLocation = Loc;
+ }
+ bool hasPotentialThisCapture() const {
+ return PotentialThisCaptureLocation.isValid();
+ }
+
+ /// \brief Mark a variable's reference in a lambda as non-odr using.
+ ///
+ /// For generic lambdas, if a variable is named in a potentially evaluated
+ /// expression, where the enclosing full expression is dependent then we
+ /// must capture the variable (given a default capture).
+ /// This is accomplished by recording all references to variables
+ /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of
+ /// PotentialCaptures. All such variables have to be captured by that lambda,
+ /// except for as described below.
+ /// If that variable is usable as a constant expression and is named in a
+ /// manner that does not involve its odr-use (e.g. undergoes
+ /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the
+ /// act of analyzing the enclosing full expression (ActOnFinishFullExpr)
+ /// if we can determine that the full expression is not instantiation-
+ /// dependent, then we can entirely avoid its capture.
+ ///
+ /// const int n = 0;
+ /// [&] (auto x) {
+ /// (void)+n + x;
+ /// };
+ /// Interestingly, this strategy would involve a capture of n, even though
+ /// it's obviously not odr-used here, because the full-expression is
+ /// instantiation-dependent. It could be useful to avoid capturing such
+ /// variables, even when they are referred to in an instantiation-dependent
+ /// expression, if we can unambiguously determine that they shall never be
+ /// odr-used. This would involve removal of the variable-referring-expression
+ /// from the array of PotentialCaptures during the lvalue-to-rvalue
+ /// conversions. But per the working draft N3797, (post-chicago 2013) we must
+ /// capture such variables.
+ /// Before anyone is tempted to implement a strategy for not-capturing 'n',
+ /// consider the insightful warning in:
+ /// /cfe-commits/Week-of-Mon-20131104/092596.html
+ /// "The problem is that the set of captures for a lambda is part of the ABI
+ /// (since lambda layout can be made visible through inline functions and the
+ /// like), and there are no guarantees as to which cases we'll manage to build
+ /// an lvalue-to-rvalue conversion in, when parsing a template -- some
+ /// seemingly harmless change elsewhere in Sema could cause us to start or stop
+ /// building such a node. So we need a rule that anyone can implement and get
+ /// exactly the same result".
+ ///
+ void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {
+ assert(isa<DeclRefExpr>(CapturingVarExpr)
+ || isa<MemberExpr>(CapturingVarExpr));
+ NonODRUsedCapturingExprs.insert(CapturingVarExpr);
+ }
+ bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) {
+ assert(isa<DeclRefExpr>(CapturingVarExpr)
+ || isa<MemberExpr>(CapturingVarExpr));
+ return NonODRUsedCapturingExprs.count(CapturingVarExpr);
+ }
+ void removePotentialCapture(Expr *E) {
+ PotentiallyCapturingExprs.erase(
+ std::remove(PotentiallyCapturingExprs.begin(),
+ PotentiallyCapturingExprs.end(), E),
+ PotentiallyCapturingExprs.end());
+ }
+ void clearPotentialCaptures() {
+ PotentiallyCapturingExprs.clear();
+ PotentialThisCaptureLocation = SourceLocation();
+ }
+ unsigned getNumPotentialVariableCaptures() const {
+ return PotentiallyCapturingExprs.size();
+ }
+
+ bool hasPotentialCaptures() const {
+ return getNumPotentialVariableCaptures() ||
+ PotentialThisCaptureLocation.isValid();
+ }
+
+ // When passed the index, returns the VarDecl and Expr associated
+ // with the index.
+ void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E);
+
};
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index d7c80f2e4f91..48794d6f02fd 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -20,12 +20,13 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExternalASTSource.h"
-#include "clang/AST/LambdaMangleContext.h"
+#include "clang/AST/MangleNumberingContext.h"
#include "clang/AST/NSAPI.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/ExpressionTraits.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TypeTraits.h"
@@ -49,6 +50,7 @@
#include "llvm/MC/MCParser/MCAsmParser.h"
#include <deque>
#include <string>
+#include <vector>
namespace llvm {
class APSInt;
@@ -85,6 +87,7 @@ namespace clang {
class ClassTemplateDecl;
class ClassTemplatePartialSpecializationDecl;
class ClassTemplateSpecializationDecl;
+ class VarTemplatePartialSpecializationDecl;
class CodeCompleteConsumer;
class CodeCompletionAllocator;
class CodeCompletionTUInfo;
@@ -136,6 +139,7 @@ namespace clang {
class ObjCPropertyDecl;
class ObjCProtocolDecl;
class OMPThreadPrivateDecl;
+ class OMPClause;
class OverloadCandidateSet;
class OverloadExpr;
class ParenListExpr;
@@ -170,9 +174,12 @@ namespace clang {
class UsingShadowDecl;
class ValueDecl;
class VarDecl;
+ class VarTemplateSpecializationDecl;
class VisibilityAttr;
class VisibleDeclConsumer;
class IndirectFieldDecl;
+ struct DeductionFailureInfo;
+ class TemplateSpecCandidateSet;
namespace sema {
class AccessedEntity;
@@ -215,7 +222,7 @@ class Sema {
// it will keep having external linkage. If it has internal linkage, we
// will not link it. Since it has no previous decls, it will remain
// with internal linkage.
- return !Old->isHidden() || New->hasExternalLinkage();
+ return !Old->isHidden() || New->isExternallyVisible();
}
public:
@@ -274,6 +281,12 @@ public:
/// element type here is ExprWithCleanups::Object.
SmallVector<BlockDecl*, 8> ExprCleanupObjects;
+ /// \brief Store a list of either DeclRefExprs or MemberExprs
+ /// that contain a reference to a variable (constant) that may or may not
+ /// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue
+ /// and discarded value conversions have been applied to all subexpressions
+ /// of the enclosing full expression. This is cleared at the end of each
+ /// full expression.
llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
/// \brief Stack containing information about each of the nested
@@ -340,8 +353,7 @@ public:
llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternCDecls;
/// \brief Look for a locally scoped extern "C" declaration by the given name.
- llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
- findLocallyScopedExternCDecl(DeclarationName Name);
+ NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
typedef LazyVector<VarDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadTentativeDefinitions, 2, 2>
@@ -366,11 +378,6 @@ public:
/// cycle detection at the end of the TU.
DelegatingCtorDeclsType DelegatingCtorDecls;
- /// \brief All the destructors seen during a class definition that had their
- /// exception spec computation delayed because it depended on an unparsed
- /// exception spec.
- SmallVector<CXXDestructorDecl*, 2> DelayedDestructorExceptionSpecs;
-
/// \brief All the overriding destructors seen during a class definition
/// (there could be multiple due to nested classes) that had their exception
/// spec checks delayed, plus the overridden destructor.
@@ -388,8 +395,12 @@ public:
SmallVector<std::pair<CXXMethodDecl*, const FunctionProtoType*>, 2>
DelayedDefaultedMemberExceptionSpecs;
+ typedef llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *>
+ LateParsedTemplateMapT;
+ LateParsedTemplateMapT LateParsedTemplateMap;
+
/// \brief Callback to the parser to parse templated functions when needed.
- typedef void LateTemplateParserCB(void *P, const FunctionDecl *FD);
+ typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT);
LateTemplateParserCB *LateTemplateParser;
void *OpaqueParser;
@@ -621,7 +632,7 @@ public:
/// \brief The current context is "potentially evaluated" in C++11 terms,
/// but the expression is evaluated at compile-time (like the values of
- /// cases in a switch statment).
+ /// cases in a switch statement).
ConstantEvaluated,
/// \brief The current expression is potentially evaluated at run time,
@@ -662,17 +673,17 @@ public:
/// is indeed an unevaluated context.
SmallVector<LambdaExpr *, 2> Lambdas;
- /// \brief The declaration that provides context for the lambda expression
- /// if the normal declaration context does not suffice, e.g., in a
- /// default function argument.
- Decl *LambdaContextDecl;
+ /// \brief The declaration that provides context for lambda expressions
+ /// and block literals if the normal declaration context does not
+ /// suffice, e.g., in a default function argument.
+ Decl *ManglingContextDecl;
/// \brief The context information used to mangle lambda expressions
- /// within this context.
+ /// and block literals within this context.
///
/// This mangling information is allocated lazily, since most contexts
- /// do not have lambda expressions.
- IntrusiveRefCntPtr<LambdaMangleContext> LambdaMangle;
+ /// do not have lambda expressions or block literals.
+ IntrusiveRefCntPtr<MangleNumberingContext> MangleNumbering;
/// \brief If we are processing a decltype type, a set of call expressions
/// for which we have deferred checking the completeness of the return type.
@@ -685,19 +696,15 @@ public:
ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
unsigned NumCleanupObjects,
bool ParentNeedsCleanups,
- Decl *LambdaContextDecl,
+ Decl *ManglingContextDecl,
bool IsDecltype)
: Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
- LambdaContextDecl(LambdaContextDecl), LambdaMangle() { }
-
- /// \brief Retrieve the mangling context for lambdas.
- LambdaMangleContext &getLambdaMangleContext() {
- assert(LambdaContextDecl && "Need to have a lambda context declaration");
- if (!LambdaMangle)
- LambdaMangle = new LambdaMangleContext;
- return *LambdaMangle;
- }
+ ManglingContextDecl(ManglingContextDecl), MangleNumbering() { }
+
+ /// \brief Retrieve the mangling numbering context, used to consistently
+ /// number constructs like lambdas for mangling.
+ MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx);
bool isUnevaluated() const {
return Context == Unevaluated || Context == UnevaluatedAbstract;
@@ -707,6 +714,18 @@ public:
/// A stack of expression evaluation contexts.
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+ /// \brief Compute the mangling number context for a lambda expression or
+ /// block literal.
+ ///
+ /// \param DC - The DeclContext containing the lambda expression or
+ /// block literal.
+ /// \param[out] ManglingContextDecl - Returns the ManglingContextDecl
+ /// associated with the context, if relevant.
+ MangleNumberingContext *getCurrentMangleNumberContext(
+ const DeclContext *DC,
+ Decl *&ManglingContextDecl);
+
+
/// SpecialMemberOverloadResult - The overloading result for a special member
/// function.
///
@@ -775,7 +794,7 @@ public:
/// Obtain a sorted list of functions that are undefined but ODR-used.
void getUndefinedButUsed(
- llvm::SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
+ SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
@@ -905,6 +924,15 @@ public:
// Dispatch to Sema to emit the diagnostic.
SemaRef.EmitCurrentDiagnostic(DiagID);
}
+
+ /// Teach operator<< to produce an object of the correct type.
+ template<typename T>
+ friend const SemaDiagnosticBuilder &operator<<(
+ const SemaDiagnosticBuilder &Diag, const T &Value) {
+ const DiagnosticBuilder &BaseDiag = Diag;
+ BaseDiag << Value;
+ return Diag;
+ }
};
/// \brief Emit a diagnostic.
@@ -922,8 +950,9 @@ public:
bool findMacroSpelling(SourceLocation &loc, StringRef name);
/// \brief Get a string to suggest for zero-initialization of a type.
- std::string getFixItZeroInitializerForType(QualType T) const;
- std::string getFixItZeroLiteralForType(QualType T) const;
+ std::string
+ getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const;
+ std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
ExprResult Owned(Expr* E) { return E; }
ExprResult Owned(ExprResult R) { return R; }
@@ -937,7 +966,13 @@ public:
void PushFunctionScope();
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
- void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);
+ sema::LambdaScopeInfo *PushLambdaScope();
+
+ /// \brief This is used to inform Sema what the current TemplateParameterDepth
+ /// is during Parsing. Currently it is used to pass on the depth
+ /// when parsing generic lambda 'auto' parameters.
+ void RecordParsingTemplateParameterDepth(unsigned Depth);
+
void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
RecordDecl *RD,
CapturedRegionKind K);
@@ -947,7 +982,13 @@ public:
sema::FunctionScopeInfo *getCurFunction() const {
return FunctionScopes.back();
}
-
+
+ template <typename ExprT>
+ void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) {
+ if (!isUnevaluatedContext())
+ getCurFunction()->recordUseOfWeak(E, IsRead);
+ }
+
void PushCompoundScope();
void PopCompoundScope();
@@ -958,14 +999,17 @@ public:
/// \brief Retrieve the current block, if any.
sema::BlockScopeInfo *getCurBlock();
- /// \brief Retrieve the current lambda expression, if any.
+ /// \brief Retrieve the current lambda scope info, if any.
sema::LambdaScopeInfo *getCurLambda();
+ /// \brief Retrieve the current generic lambda info, if any.
+ sema::LambdaScopeInfo *getCurGenericLambda();
+
/// \brief Retrieve the current captured region, if any.
sema::CapturedRegionScopeInfo *getCurCapturedRegion();
/// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
- SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+ SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
void ActOnComment(SourceRange Comment);
@@ -987,6 +1031,8 @@ public:
QualType BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc);
+ bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
+
/// \brief Build a function type.
///
/// This routine checks the function type according to C++ rules and
@@ -1152,6 +1198,10 @@ public:
virtual ~BoundTypeDiagnoser3() { }
};
+private:
+ bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser);
+public:
bool RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser);
bool RequireCompleteType(SourceLocation Loc, QualType T,
@@ -1287,6 +1337,7 @@ public:
NC_Expression,
NC_NestedNameSpecifier,
NC_TypeTemplate,
+ NC_VarTemplate,
NC_FunctionTemplate
};
@@ -1325,6 +1376,12 @@ public:
return Result;
}
+ static NameClassification VarTemplate(TemplateName Name) {
+ NameClassification Result(NC_VarTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
static NameClassification FunctionTemplate(TemplateName Name) {
NameClassification Result(NC_FunctionTemplate);
Result.Template = Name;
@@ -1344,13 +1401,22 @@ public:
}
TemplateName getTemplateName() const {
- assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate);
+ assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate ||
+ Kind == NC_VarTemplate);
return Template;
}
TemplateNameKind getTemplateNameKind() const {
- assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate);
- return Kind == NC_TypeTemplate? TNK_Type_template : TNK_Function_template;
+ switch (Kind) {
+ case NC_TypeTemplate:
+ return TNK_Type_template;
+ case NC_FunctionTemplate:
+ return TNK_Function_template;
+ case NC_VarTemplate:
+ return TNK_Var_template;
+ default:
+ llvm_unreachable("unsupported name classification.");
+ }
}
};
@@ -1390,13 +1456,12 @@ public:
NamedDecl *HandleDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists);
- void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
- const LookupResult &Previous,
- Scope *S);
+ void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S);
bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
SourceLocation Loc);
+ static bool adjustContextForLocalExternDecl(DeclContext *&DC);
void DiagnoseFunctionSpecifiers(const DeclSpec &DS);
void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
void CheckShadow(Scope *S, VarDecl *D);
@@ -1407,10 +1472,11 @@ public:
LookupResult &Previous);
NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D,
LookupResult &Previous, bool &Redeclaration);
- NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ NamedDecl *ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo,
LookupResult &Previous,
- MultiTemplateParamsArg TemplateParamLists);
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &AddToScope);
// Returns true if the variable declaration is a redeclaration
bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
void CheckVariableDeclarationType(VarDecl *NewVD);
@@ -1418,6 +1484,7 @@ public:
void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
void ActOnStartFunctionDeclarator();
void ActOnEndFunctionDeclarator();
+
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TypeSourceInfo *TInfo,
LookupResult &Previous,
@@ -1429,12 +1496,17 @@ public:
bool CheckConstexprFunctionDecl(const FunctionDecl *FD);
bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body);
- void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
+ void FindHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
+ void NoteHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
// Returns true if the function declaration is a redeclaration
bool CheckFunctionDeclaration(Scope *S,
FunctionDecl *NewFD, LookupResult &Previous,
bool IsExplicitSpecialization);
void CheckMain(FunctionDecl *FD, const DeclSpec &D);
+ void CheckMSVCRTEntryPoint(FunctionDecl *FD);
Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
@@ -1462,19 +1534,20 @@ public:
void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
void FinalizeDeclaration(Decl *D);
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
- Decl **Group,
- unsigned NumDecls);
- DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
+ ArrayRef<Decl *> Group);
+ DeclGroupPtrTy BuildDeclaratorGroup(llvm::MutableArrayRef<Decl *> Group,
bool TypeMayContainAuto = true);
/// Should be called on all declarations that might have attached
/// documentation comments.
void ActOnDocumentableDecl(Decl *D);
- void ActOnDocumentableDecls(Decl **Group, unsigned NumDecls);
+ void ActOnDocumentableDecls(ArrayRef<Decl *> Group);
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls);
- void CheckForFunctionRedefinition(FunctionDecl *FD);
+ void CheckForFunctionRedefinition(FunctionDecl *FD,
+ const FunctionDecl *EffectiveDefinition =
+ 0);
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
@@ -1533,6 +1606,10 @@ public:
DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc,
ModuleIdPath Path);
+ /// \brief The parser has processed a module import translated from a
+ /// #include or similar preprocessing directive.
+ void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
+
/// \brief Create an implicit import of the given module at the given
/// source location.
///
@@ -1660,6 +1737,7 @@ public:
/// member declarations.
void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl,
SourceLocation FinalLoc,
+ bool IsFinalSpelledSealed,
SourceLocation LBraceLoc);
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
@@ -1748,7 +1826,7 @@ public:
/// \param ExplicitInstantiationOrSpecialization When true, we are checking
/// whether the declaration is in scope for the purposes of explicit template
/// instantiation or specialization. The default is false.
- bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0,
+ bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = 0,
bool ExplicitInstantiationOrSpecialization = false);
/// Finds the scope corresponding to the given decl context, if it
@@ -1780,9 +1858,9 @@ public:
unsigned AttrSpellingListIndex);
DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex);
- FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,
- int FormatIdx, int FirstArg,
- unsigned AttrSpellingListIndex);
+ FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Format, int FormatIdx,
+ int FirstArg, unsigned AttrSpellingListIndex);
SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
unsigned AttrSpellingListIndex);
@@ -1802,13 +1880,13 @@ public:
void mergeDeclAttributes(NamedDecl *New, Decl *Old,
AvailabilityMergeKind AMK = AMK_Redeclaration);
void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
- bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S);
+ bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S,
+ bool MergeTypeWithOld);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
- Scope *S);
+ Scope *S, bool MergeTypeWithOld);
void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
- void MergeVarDecl(VarDecl *New, LookupResult &OldDecls,
- bool OldDeclsWereHidden);
- void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldIsHidden);
+ void MergeVarDecl(VarDecl *New, LookupResult &Previous);
+ void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
@@ -1821,7 +1899,8 @@ public:
AA_Converting,
AA_Initializing,
AA_Sending,
- AA_Casting
+ AA_Casting,
+ AA_Passing_CFAudited
};
/// C++ Overloading.
@@ -1920,65 +1999,91 @@ public:
/// Contexts in which a converted constant expression is required.
enum CCEKind {
- CCEK_CaseValue, ///< Expression in a case label.
- CCEK_Enumerator, ///< Enumerator value with fixed underlying type.
- CCEK_TemplateArg ///< Value of a non-type template parameter.
+ CCEK_CaseValue, ///< Expression in a case label.
+ CCEK_Enumerator, ///< Enumerator value with fixed underlying type.
+ CCEK_TemplateArg, ///< Value of a non-type template parameter.
+ CCEK_NewExpr ///< Constant expression in a noptr-new-declarator.
};
ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
llvm::APSInt &Value, CCEKind CCE);
- /// \brief Abstract base class used to diagnose problems that occur while
- /// trying to convert an expression to integral or enumeration type.
- class ICEConvertDiagnoser {
+ /// \brief Abstract base class used to perform a contextual implicit
+ /// conversion from an expression to any type passing a filter.
+ class ContextualImplicitConverter {
public:
bool Suppress;
bool SuppressConversion;
- ICEConvertDiagnoser(bool Suppress = false,
- bool SuppressConversion = false)
- : Suppress(Suppress), SuppressConversion(SuppressConversion) { }
+ ContextualImplicitConverter(bool Suppress = false,
+ bool SuppressConversion = false)
+ : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
+
+ /// \brief Determine whether the specified type is a valid destination type
+ /// for this conversion.
+ virtual bool match(QualType T) = 0;
/// \brief Emits a diagnostic complaining that the expression does not have
/// integral or enumeration type.
- virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
- QualType T) = 0;
+ virtual SemaDiagnosticBuilder
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
/// \brief Emits a diagnostic when the expression has incomplete class type.
- virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
- QualType T) = 0;
+ virtual SemaDiagnosticBuilder
+ diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
/// \brief Emits a diagnostic when the only matching conversion function
/// is explicit.
- virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
- QualType T,
- QualType ConvTy) = 0;
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
/// \brief Emits a note for the explicit conversion function.
- virtual DiagnosticBuilder
+ virtual SemaDiagnosticBuilder
noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
/// \brief Emits a diagnostic when there are multiple possible conversion
/// functions.
- virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) = 0;
+ virtual SemaDiagnosticBuilder
+ diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
/// \brief Emits a note for one of the candidate conversions.
- virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) = 0;
+ virtual SemaDiagnosticBuilder
+ noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
/// \brief Emits a diagnostic when we picked a conversion function
/// (for cases when we are not allowed to pick a conversion function).
- virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
- QualType T,
- QualType ConvTy) = 0;
+ virtual SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
- virtual ~ICEConvertDiagnoser() {}
+ virtual ~ContextualImplicitConverter() {}
};
- ExprResult
- ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE,
- ICEConvertDiagnoser &Diagnoser,
- bool AllowScopedEnumerations);
+ class ICEConvertDiagnoser : public ContextualImplicitConverter {
+ bool AllowScopedEnumerations;
+
+ public:
+ ICEConvertDiagnoser(bool AllowScopedEnumerations,
+ bool Suppress, bool SuppressConversion)
+ : ContextualImplicitConverter(Suppress, SuppressConversion),
+ AllowScopedEnumerations(AllowScopedEnumerations) {}
+
+ /// Match an integral or (possibly scoped) enumeration type.
+ bool match(QualType T);
+
+ SemaDiagnosticBuilder
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) {
+ return diagnoseNotInt(S, Loc, T);
+ }
+
+ /// \brief Emits a diagnostic complaining that the expression does not have
+ /// integral or enumeration type.
+ virtual SemaDiagnosticBuilder
+ diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
+ };
+
+ /// Perform a contextual implicit conversion.
+ ExprResult PerformContextualImplicitConversion(
+ SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
+
enum ObjCSubscriptKind {
OS_Array,
@@ -2054,12 +2159,14 @@ public:
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
- OverloadCandidateSet& CandidateSet);
+ OverloadCandidateSet& CandidateSet,
+ bool AllowObjCConversionOnExplicit = false);
void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet);
+ OverloadCandidateSet &CandidateSet,
+ bool AllowObjCConversionOnExplicit = false);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
@@ -2159,14 +2266,13 @@ public:
ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
bool AllowTypoCorrection=true);
bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
- Expr **Args, unsigned NumArgs,
- SourceLocation RParenLoc,
+ MultiExprArg Args, SourceLocation RParenLoc,
OverloadCandidateSet *CandidateSet,
ExprResult *Result);
@@ -2186,15 +2292,17 @@ public:
ExprResult
BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
- SourceLocation LParenLoc, Expr **Args,
- unsigned NumArgs, SourceLocation RParenLoc);
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc);
ExprResult
BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ MultiExprArg Args,
SourceLocation RParenLoc);
ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc);
+ SourceLocation OpLoc,
+ bool *NoArrowOperatorFound = 0);
/// CheckCallReturnType - Checks that a call expression's return type is
/// complete. Returns true on failure. The location passed in is the location
@@ -2203,7 +2311,8 @@ public:
CallExpr *CE, FunctionDecl *FD);
/// Helpers for dealing with blocks and functions.
- bool CheckParmsForFunctionDef(ParmVarDecl **Param, ParmVarDecl **ParamEnd,
+ bool CheckParmsForFunctionDef(ParmVarDecl *const *Param,
+ ParmVarDecl *const *ParamEnd,
bool CheckParameterNames);
void CheckCXXDefaultArguments(FunctionDecl *FD);
void CheckExtraCXXDefaultArguments(Declarator &D);
@@ -2271,6 +2380,9 @@ public:
/// are outside of the current scope unless they have linkage. See
/// C99 6.2.2p4-5 and C++ [basic.link]p6.
LookupRedeclarationWithLinkage,
+ /// Look up a friend of a local class. This lookup does not look
+ /// outside the innermost non-class scope. See C++11 [class.friend]p11.
+ LookupLocalFriendName,
/// Look up the name of an Objective-C protocol.
LookupObjCProtocolName,
/// Look up implicit 'self' parameter of an objective-c method.
@@ -2303,7 +2415,11 @@ public:
/// \brief The lookup found an overload set of literal operator templates,
/// which expect the characters of the spelling of the literal token to be
/// passed as a non-type template argument pack.
- LOLR_Template
+ LOLR_Template,
+ /// \brief The lookup found an overload set of literal operator templates,
+ /// which expect the character type and characters of the spelling of the
+ /// string literal token to be passed as template arguments.
+ LOLR_StringTemplate
};
SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D,
@@ -2370,7 +2486,9 @@ public:
LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
ArrayRef<QualType> ArgTys,
- bool AllowRawAndTemplate);
+ bool AllowRaw,
+ bool AllowTemplate,
+ bool AllowStringTemplate);
bool isKnownName(StringRef name);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
@@ -2391,7 +2509,17 @@ public:
CorrectionCandidateCallback &CCC,
DeclContext *MemberContext = 0,
bool EnteringContext = false,
- const ObjCObjectPointerType *OPT = 0);
+ const ObjCObjectPointerType *OPT = 0,
+ bool RecordFailure = true);
+
+ void diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ bool ErrorRecovery = true);
+
+ void diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ const PartialDiagnostic &PrevNote,
+ bool ErrorRecovery = true);
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
ArrayRef<Expr *> Args,
@@ -2402,7 +2530,7 @@ public:
bool ConsiderLinkage,
bool ExplicitInstantiationOrSpecialization);
- bool DiagnoseAmbiguousLookup(LookupResult &Result);
+ void DiagnoseAmbiguousLookup(LookupResult &Result);
//@}
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
@@ -2419,12 +2547,8 @@ public:
void ProcessPragmaWeak(Scope *S, Decl *D);
// Decl attributes - this routine is the top level dispatcher.
- void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
- bool NonInheritable = true,
- bool Inheritable = true);
+ void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
- bool NonInheritable = true,
- bool Inheritable = true,
bool IncludeCXX11Attributes = true);
bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
const AttributeList *AttrList);
@@ -2435,8 +2559,21 @@ public:
bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
const FunctionDecl *FD = 0);
bool CheckNoReturnAttr(const AttributeList &attr);
+ bool checkStringLiteralArgumentAttr(const AttributeList &Attr,
+ unsigned ArgNum, StringRef &Str,
+ SourceLocation *ArgLocation = 0);
+
void CheckAlignasUnderalignment(Decl *D);
+ /// Adjust the calling convention of a method to be the ABI default if it
+ /// wasn't specified explicitly. This handles method types formed from
+ /// function type typedefs and typename template arguments.
+ void adjustMemberFunctionCC(QualType &T, bool IsStatic);
+
+ /// Get the outermost AttributedType node that sets a calling convention.
+ /// Valid types should not have multiple attributes with different CCs.
+ const AttributedType *getCallingConvAttributedType(QualType T) const;
+
/// \brief Stmt attributes - this routine is the top level dispatcher.
StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,
SourceRange Range);
@@ -2457,9 +2594,6 @@ public:
ObjCMethodDecl *MethodDecl,
bool IsProtocolMethodDecl);
- bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
- ObjCInterfaceDecl *IDecl);
-
typedef llvm::SmallPtrSet<Selector, 8> SelectorSet;
typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap;
@@ -2507,6 +2641,16 @@ public:
bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
ObjCMethodDecl *Method, ObjCIvarDecl *IV);
+ /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which
+ /// backs the property is not used in the property's accessor.
+ void DiagnoseUnusedBackingIvarInAccessor(Scope *S);
+
+ /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and
+ /// it property has a backing ivar, returns this ivar; otherwise, returns NULL.
+ /// It also returns ivar's property on success.
+ ObjCIvarDecl *GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
+ const ObjCPropertyDecl *&PDecl) const;
+
/// Called by ActOnProperty to handle \@property declarations in
/// class extensions.
ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S,
@@ -2592,6 +2736,17 @@ private:
bool receiverIdOrClass,
bool warn, bool instance);
+ /// \brief Record the typo correction failure and return an empty correction.
+ TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
+ bool RecordFailure = true,
+ bool IsUnqualifiedLookup = false) {
+ if (IsUnqualifiedLookup)
+ (void)UnqualifiedTyposCorrected[Typo];
+ if (RecordFailure)
+ TypoCorrectionFailures[Typo].insert(TypoLoc);
+ return TypoCorrection();
+ }
+
public:
/// AddInstanceMethodToGlobalPool - All instance methods in a translation
/// unit are added to a global pool. This allows us to efficiently associate
@@ -2628,6 +2783,14 @@ public:
warn, /*instance*/false);
}
+ const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
+ QualType ObjectType=QualType());
+
+ /// DiagnoseMismatchedMethodsInGlobalPool - This routine goes through list of
+ /// methods in global pool and issues diagnostic on identical selectors which
+ /// have mismathched types.
+ void DiagnoseMismatchedMethodsInGlobalPool();
+
/// LookupImplementedMethodInGlobalPool - Returns the method which has an
/// implementation.
ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
@@ -2691,8 +2854,7 @@ public:
void ActOnStartOfCompoundStmt();
void ActOnFinishOfCompoundStmt();
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
- MultiStmtArg Elts,
- bool isStmtExpr);
+ ArrayRef<Stmt *> Elts, bool isStmtExpr);
/// \brief A RAII object to enter scope of a compound statement.
class CompoundScopeRAII {
@@ -2865,11 +3027,10 @@ public:
StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
Decl *ExDecl, Stmt *HandlerBlock);
StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
- MultiStmtArg Handlers);
+ ArrayRef<Stmt *> Handlers);
StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
- SourceLocation TryLoc,
- Stmt *TryBlock,
+ SourceLocation TryLoc, Stmt *TryBlock,
Stmt *Handler);
StmtResult ActOnSEHExceptBlock(SourceLocation Loc,
@@ -2944,7 +3105,7 @@ public:
ObjCMethodDecl *Getter,
SourceLocation Loc);
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
- Expr **Args, unsigned NumArgs);
+ ArrayRef<Expr *> Args);
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
Decl *LambdaContextDecl = 0,
@@ -3006,12 +3167,19 @@ public:
/// from within the current scope. Only valid when the variable can be
/// captured.
///
+ /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
+ /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
+ /// This is useful when enclosing lambdas must speculatively capture
+ /// variables that may or may not be used in certain specializations of
+ /// a nested generic lambda.
+ ///
/// \returns true if an error occurred (i.e., the variable cannot be
/// captured) and false if the capture succeeded.
bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind,
SourceLocation EllipsisLoc, bool BuildAndDiagnose,
QualType &CaptureType,
- QualType &DeclRefType);
+ QualType &DeclRefType,
+ const unsigned *const FunctionScopeIndexToStopAt);
/// \brief Try to capture the given variable.
bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
@@ -3034,8 +3202,8 @@ public:
bool (*IsPlausibleResult)(QualType) = 0);
/// \brief Figure out if an expression could be turned into a call.
- bool isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
- UnresolvedSetImpl &NonTemplateOverloads);
+ bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
+ UnresolvedSetImpl &NonTemplateOverloads);
/// \brief Conditionally issue a diagnostic based on the current
/// evaluation context.
@@ -3054,7 +3222,8 @@ public:
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
bool HasTrailingLParen, bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC = 0);
+ CorrectionCandidateCallback *CCC = 0,
+ bool IsInlineAsmIdentifier = false);
void DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer,
@@ -3080,17 +3249,19 @@ public:
ExprValueKind VK,
SourceLocation Loc,
const CXXScopeSpec *SS = 0);
- ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
- ExprValueKind VK,
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
- const CXXScopeSpec *SS = 0,
- NamedDecl *FoundD = 0);
+ const CXXScopeSpec *SS = 0, NamedDecl *FoundD = 0,
+ const TemplateArgumentListInfo *TemplateArgs = 0);
ExprResult
- BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
- SourceLocation nameLoc,
- IndirectFieldDecl *indirectField,
- Expr *baseObjectExpr = 0,
- SourceLocation opLoc = SourceLocation());
+ BuildAnonymousStructUnionMemberReference(
+ const CXXScopeSpec &SS,
+ SourceLocation nameLoc,
+ IndirectFieldDecl *indirectField,
+ DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_none),
+ Expr *baseObjectExpr = 0,
+ SourceLocation opLoc = SourceLocation());
+
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -3115,9 +3286,9 @@ public:
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
LookupResult &R,
bool NeedsADL);
- ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- NamedDecl *D, NamedDecl *FoundD = 0);
+ ExprResult BuildDeclarationNameExpr(
+ const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+ NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0);
ExprResult BuildLiteralOperatorCall(LookupResult &R,
DeclarationNameInfo &SuffixInfo,
@@ -3125,6 +3296,8 @@ public:
SourceLocation LitEndLoc,
TemplateArgumentListInfo *ExplicitTemplateArgs = 0);
+ ExprResult BuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT);
ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = 0);
@@ -3143,15 +3316,14 @@ public:
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
- MultiTypeArg ArgTypes,
- MultiExprArg ArgExprs);
+ ArrayRef<ParsedType> ArgTypes,
+ ArrayRef<Expr *> ArgExprs);
ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
- TypeSourceInfo **Types,
- Expr **Exprs,
- unsigned NumAssocs);
+ ArrayRef<TypeSourceInfo *> Types,
+ ArrayRef<Expr *> Exprs);
// Binary/Unary Operators. 'Tok' is the token for the operator.
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
@@ -3161,6 +3333,8 @@ public:
ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, Expr *Input);
+ QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+
ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
@@ -3255,7 +3429,7 @@ public:
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
bool ExecConfig = false);
void CheckStaticArrayArgument(SourceLocation CallLoc,
@@ -3270,7 +3444,7 @@ public:
Expr *ExecConfig = 0, bool IsExecConfig = false);
ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Arg,
SourceLocation RParenLoc,
Expr *Config = 0,
bool IsExecConfig = false);
@@ -3431,6 +3605,13 @@ public:
ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
Scope *CurScope);
+ //===---------------------------- Clang Extensions ----------------------===//
+
+ /// __builtin_convertvector(...)
+ ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+
//===---------------------------- OpenCL Features -----------------------===//
/// __builtin_astype(...)
@@ -3488,12 +3669,14 @@ public:
void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
- const LookupResult &PreviousDecls);
+ const LookupResult &PreviousDecls,
+ UsingShadowDecl *&PrevShadow);
UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
- NamedDecl *Target);
+ NamedDecl *Target,
+ UsingShadowDecl *PrevDecl);
bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
- bool isTypeName,
+ bool HasTypenameKeyword,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Previous);
@@ -3507,7 +3690,7 @@ public:
const DeclarationNameInfo &NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc);
bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
@@ -3519,7 +3702,7 @@ public:
CXXScopeSpec &SS,
UnqualifiedId &Name,
AttributeList *AttrList,
- bool IsTypeName,
+ bool HasTypenameKeyword,
SourceLocation TypenameLoc);
Decl *ActOnAliasDeclaration(Scope *CurScope,
AccessSpecifier AS,
@@ -3918,7 +4101,17 @@ public:
///
/// \param Explicit Whether 'this' is explicitly captured in a lambda
/// capture list.
- void CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false);
+ ///
+ /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
+ /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
+ /// This is useful when enclosing lambdas must speculatively capture
+ /// 'this' that may or may not be used in certain specializations of
+ /// a nested generic lambda (depending on whether the name resolves to
+ /// a non-static member function or a static function).
+ /// \return returns 'true' if failed, 'false' if success.
+ bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false,
+ bool BuildAndDiagnose = true,
+ const unsigned *const FunctionScopeIndexToStopAt = 0);
/// \brief Determine whether the given type is the type of *this that is used
/// outside of the body of a member function for a type that is currently
@@ -3979,22 +4172,26 @@ public:
SourceRange R);
bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
bool UseGlobal, QualType AllocType, bool IsArray,
- Expr **PlaceArgs, unsigned NumPlaceArgs,
+ MultiExprArg PlaceArgs,
FunctionDecl *&OperatorNew,
FunctionDecl *&OperatorDelete);
bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
- DeclarationName Name, Expr** Args,
- unsigned NumArgs, DeclContext *Ctx,
+ DeclarationName Name, MultiExprArg Args,
+ DeclContext *Ctx,
bool AllowMissing, FunctionDecl *&Operator,
bool Diagnose = true);
void DeclareGlobalNewDelete();
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
- QualType Argument,
+ QualType Param1,
+ QualType Param2 = QualType(),
bool addMallocAttr = false);
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
DeclarationName Name, FunctionDecl* &Operator,
bool Diagnose = true);
+ FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
+ bool CanProvideSize,
+ DeclarationName Name);
/// ActOnCXXDelete - Parsed a C++ 'delete' expression
ExprResult ActOnCXXDelete(SourceLocation StartLoc,
@@ -4120,7 +4317,8 @@ public:
}
ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
bool DiscardedValue = false,
- bool IsConstexpr = false);
+ bool IsConstexpr = false,
+ bool IsLambdaInitCaptureInitializer = false);
StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type.
@@ -4131,7 +4329,6 @@ public:
bool EnteringContext = false);
bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
- bool isUnknownSpecialization(const CXXScopeSpec &SS);
/// \brief The parser has parsed a global nested-name-specifier '::'.
///
@@ -4296,7 +4493,8 @@ public:
/// \brief Create a new lambda closure type.
CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent);
+ bool KnownDependent,
+ LambdaCaptureDefault CaptureDefault);
/// \brief Start the definition of a lambda expression.
CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
@@ -4305,13 +4503,31 @@ public:
SourceLocation EndLoc,
ArrayRef<ParmVarDecl *> Params);
- /// \brief Introduce the scope for a lambda expression.
- sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
- SourceRange IntroducerRange,
- LambdaCaptureDefault CaptureDefault,
- bool ExplicitParams,
- bool ExplicitResultType,
- bool Mutable);
+ /// \brief Endow the lambda scope info with the relevant properties.
+ void buildLambdaScope(sema::LambdaScopeInfo *LSI,
+ CXXMethodDecl *CallOperator,
+ SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
+ bool ExplicitParams,
+ bool ExplicitResultType,
+ bool Mutable);
+
+ /// \brief Perform initialization analysis of the init-capture and perform
+ /// any implicit conversions such as an lvalue-to-rvalue conversion if
+ /// not being used to initialize a reference.
+ QualType performLambdaInitCaptureInitialization(SourceLocation Loc,
+ bool ByRef, IdentifierInfo *Id, Expr *&Init);
+ /// \brief Create a dummy variable within the declcontext of the lambda's
+ /// call operator, for name lookup purposes for a lambda init capture.
+ ///
+ /// CodeGen handles emission of lambda captures, ignoring these dummy
+ /// variables appropriately.
+ VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
+ QualType InitCaptureType, IdentifierInfo *Id, Expr *Init);
+
+ /// \brief Build the implicit field for an init-capture.
+ FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var);
/// \brief Note that we have finished the explicit captures for the
/// given lambda.
@@ -4444,6 +4660,7 @@ public:
//
bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = 0);
+ bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS);
bool ActOnAccessSpecifier(AccessSpecifier Access,
SourceLocation ASLoc,
@@ -4466,7 +4683,7 @@ public:
const DeclSpec &DS,
SourceLocation IdLoc,
SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
+ ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc);
@@ -4590,7 +4807,9 @@ public:
void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
void ActOnFinishDelayedMemberInitializers(Decl *Record);
- void MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag = true);
+ void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
+ CachedTokens &Toks);
+ void UnmarkAsLateParsedTemplate(FunctionDecl *FD);
bool IsInsideALocalClassWithinATemplateFunction();
Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
@@ -4624,7 +4843,7 @@ public:
void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD);
void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD,
const FunctionProtoType *T);
- void CheckDelayedExplicitlyDefaultedMemberExceptionSpecs();
+ void CheckDelayedMemberExceptionSpecs();
//===--------------------------------------------------------------------===//
// C++ Derived Classes
@@ -4687,7 +4906,7 @@ public:
bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
/// CheckOverrideControl - Check C++11 override control semantics.
- void CheckOverrideControl(Decl *D);
+ void CheckOverrideControl(NamedDecl *D);
/// CheckForFunctionMarkedFinal - Checks whether a virtual member function
/// overrides a virtual member function marked 'final', according to
@@ -4735,6 +4954,9 @@ public:
const PartialDiagnostic &PDiag,
QualType objectType = QualType());
AccessResult CheckFriendAccess(NamedDecl *D);
+ AccessResult CheckMemberAccess(SourceLocation UseLoc,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair Found);
AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
Expr *ObjectExpr,
Expr *ArgExpr,
@@ -4771,6 +4993,7 @@ public:
AbstractVariableType,
AbstractFieldType,
AbstractIvarType,
+ AbstractSynthesizedIvarType,
AbstractArrayType
};
@@ -4878,12 +5101,13 @@ public:
Decl **Params, unsigned NumParams,
SourceLocation RAngleLoc);
- /// \brief The context in which we are checking a template parameter
- /// list.
+ /// \brief The context in which we are checking a template parameter list.
enum TemplateParamListContext {
TPC_ClassTemplate,
+ TPC_VarTemplate,
TPC_FunctionTemplate,
TPC_ClassTemplateMember,
+ TPC_FriendClassTemplate,
TPC_FriendFunctionTemplate,
TPC_FriendFunctionTemplateDefinition,
TPC_TypeAliasTemplate
@@ -4892,15 +5116,10 @@ public:
bool CheckTemplateParameterList(TemplateParameterList *NewParams,
TemplateParameterList *OldParams,
TemplateParamListContext TPC);
- TemplateParameterList *
- MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
- SourceLocation DeclLoc,
- const CXXScopeSpec &SS,
- TemplateParameterList **ParamLists,
- unsigned NumParamLists,
- bool IsFriend,
- bool &IsExplicitSpecialization,
- bool &Invalid);
+ TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
+ SourceLocation DeclStartLoc, SourceLocation DeclLoc,
+ const CXXScopeSpec &SS, ArrayRef<TemplateParameterList *> ParamLists,
+ bool IsFriend, bool &IsExplicitSpecialization, bool &Invalid);
DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
@@ -4942,6 +5161,21 @@ public:
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc);
+ DeclResult ActOnVarTemplateSpecialization(
+ Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI,
+ SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+ StorageClass SC, bool IsPartialSpecialization);
+
+ DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation TemplateNameLoc,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ ExprResult CheckVarTemplateId(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
@@ -5035,7 +5269,9 @@ public:
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
Decl *Param,
- SmallVectorImpl<TemplateArgument> &Converted);
+ SmallVectorImpl<TemplateArgument>
+ &Converted,
+ bool &HasDefaultArg);
/// \brief Specifies the context in which a particular template
/// argument is being checked.
@@ -5289,7 +5525,7 @@ public:
/// \brief Block expression,
UPPC_Block
-};
+ };
/// \brief Diagnose unexpanded parameter packs.
///
@@ -5538,10 +5774,25 @@ public:
/// false otherwise.
bool containsUnexpandedParameterPacks(Declarator &D);
+ /// \brief Returns the pattern of the pack expansion for a template argument.
+ ///
+ /// \param OrigLoc The template argument to expand.
+ ///
+ /// \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 getTemplateArgumentPackExpansionPattern(
+ TemplateArgumentLoc OrigLoc,
+ SourceLocation &Ellipsis,
+ Optional<unsigned> &NumExpansions) const;
+
//===--------------------------------------------------------------------===//
// C++ Template Argument Deduction (C++ [temp.deduct])
//===--------------------------------------------------------------------===//
+ QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType);
+
/// \brief Describes the result of template argument deduction.
///
/// The TemplateDeductionResult enumeration describes the result of
@@ -5598,12 +5849,16 @@ public:
sema::TemplateDeductionInfo &Info);
TemplateDeductionResult
- SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo &ExplicitTemplateArgs,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- SmallVectorImpl<QualType> &ParamTypes,
- QualType *FunctionType,
- sema::TemplateDeductionInfo &Info);
+ DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult SubstituteExplicitTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo &ExplicitTemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
+ sema::TemplateDeductionInfo &Info);
/// brief A function argument from which we performed template argument
// deduction for a call.
@@ -5655,6 +5910,12 @@ public:
sema::TemplateDeductionInfo &Info,
bool InOverloadResolution = false);
+ /// \brief Substitute Replacement for \p auto in \p TypeWithAuto
+ QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
+ /// \brief Substitute Replacement for auto in TypeWithAuto
+ TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ QualType Replacement);
+
/// \brief Result type of DeduceAutoType.
enum DeduceAutoResult {
DAR_Succeeded,
@@ -5666,7 +5927,6 @@ public:
QualType &Result);
DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer,
QualType &Result);
- QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose = true);
@@ -5679,17 +5939,16 @@ public:
FunctionTemplateDecl *FT2,
SourceLocation Loc,
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,
- bool Complain = true,
- QualType TargetType = QualType());
+ unsigned NumCallArguments1,
+ unsigned NumCallArguments2);
+ UnresolvedSetIterator
+ getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
+ TemplateSpecCandidateSet &FailedCandidates,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag,
+ bool Complain = true, QualType TargetType = QualType());
ClassTemplatePartialSpecializationDecl *
getMoreSpecializedPartialSpecialization(
@@ -5697,6 +5956,10 @@ public:
ClassTemplatePartialSpecializationDecl *PS2,
SourceLocation Loc);
+ VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
+ VarTemplatePartialSpecializationDecl *PS1,
+ VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+
void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
bool OnlyDeduced,
unsigned Depth,
@@ -5814,10 +6077,7 @@ public:
case PriorTemplateArgumentSubstitution:
case DefaultTemplateArgumentChecking:
- if (X.Template != Y.Template)
- return false;
-
- // Fall through
+ return X.Template == Y.Template && X.TemplateArgs == Y.TemplateArgs;
case DefaultTemplateArgumentInstantiation:
case ExplicitTemplateArgumentSubstitution:
@@ -5845,6 +6105,20 @@ public:
SmallVector<ActiveTemplateInstantiation, 16>
ActiveTemplateInstantiations;
+ /// \brief Extra modules inspected when performing a lookup during a template
+ /// instantiation. Computed lazily.
+ SmallVector<Module*, 16> ActiveTemplateInstantiationLookupModules;
+
+ /// \brief Cache of additional modules that should be used for name lookup
+ /// within the current template instantiation. Computed lazily; use
+ /// getLookupModules() to get a complete set.
+ llvm::DenseSet<Module*> LookupModulesCache;
+
+ /// \brief Get the set of additional modules that should be checked during
+ /// name lookup. A module and its imports become visible when instanting a
+ /// template defined within it.
+ llvm::DenseSet<Module*> &getLookupModules();
+
/// \brief Whether we are in a SFINAE context that is not associated with
/// template instantiation.
///
@@ -5906,8 +6180,9 @@ public:
/// deduction.
///
/// FIXME: Serialize this structure to the AST file.
- llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >
- SuppressedDiagnostics;
+ typedef llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >
+ SuppressedDiagnosticsMap;
+ SuppressedDiagnosticsMap SuppressedDiagnostics;
/// \brief A stack object to be created when performing template
/// instantiation.
@@ -5959,6 +6234,15 @@ public:
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
+ /// \brief Note that we are instantiating as part of template
+ /// argument deduction for a variable template partial
+ /// specialization.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ VarTemplatePartialSpecializationDecl *PartialSpec,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
+
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
@@ -5994,7 +6278,7 @@ public:
/// \brief Determines whether we have exceeded the maximum
/// recursive template instantiations.
- operator bool() const { return Invalid; }
+ bool isInvalid() const { return Invalid; }
private:
Sema &SemaRef;
@@ -6031,7 +6315,7 @@ public:
/// \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;
@@ -6063,10 +6347,34 @@ public:
}
};
+ /// \brief RAII class used to indicate that we are performing provisional
+ /// semantic analysis to determine the validity of a construct, so
+ /// typo-correction and diagnostics in the immediate context (not within
+ /// implicitly-instantiated templates) should be suppressed.
+ class TentativeAnalysisScope {
+ Sema &SemaRef;
+ // FIXME: Using a SFINAETrap for this is a hack.
+ SFINAETrap Trap;
+ bool PrevDisableTypoCorrection;
+ public:
+ explicit TentativeAnalysisScope(Sema &SemaRef)
+ : SemaRef(SemaRef), Trap(SemaRef, true),
+ PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) {
+ SemaRef.DisableTypoCorrection = true;
+ }
+ ~TentativeAnalysisScope() {
+ SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection;
+ }
+ };
+
/// \brief The current instantiation scope used to store local
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
+ /// \brief Tracks whether we are in a context where typo correction is
+ /// disabled.
+ bool DisableTypoCorrection;
+
/// \brief The number of typos corrected by CorrectTypo.
unsigned TyposCorrected;
@@ -6081,6 +6389,14 @@ public:
/// string represents a keyword.
UnqualifiedTyposCorrectedMap UnqualifiedTyposCorrected;
+ typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet;
+ typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations;
+
+ /// \brief A cache containing identifiers for which typo correction failed and
+ /// their locations, so that repeated attempts to correct an identifier in a
+ /// given location are ignored if typo correction already failed for it.
+ IdentifierSourceLocations TypoCorrectionFailures;
+
/// \brief Worker object for performing CFG-based warnings.
sema::AnalysisBasedWarnings AnalysisWarnings;
@@ -6107,6 +6423,26 @@ public:
/// types, static variables, enumerators, etc.
std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
+ class SavePendingLocalImplicitInstantiationsRAII {
+ public:
+ SavePendingLocalImplicitInstantiationsRAII(Sema &S): S(S) {
+ SavedPendingLocalImplicitInstantiations.swap(
+ S.PendingLocalImplicitInstantiations);
+ }
+
+ ~SavePendingLocalImplicitInstantiationsRAII() {
+ assert(S.PendingLocalImplicitInstantiations.empty() &&
+ "there shouldn't be any pending local implicit instantiations");
+ SavedPendingLocalImplicitInstantiations.swap(
+ S.PendingLocalImplicitInstantiations);
+ }
+
+ private:
+ Sema &S;
+ std::deque<PendingImplicitInstantiation>
+ SavedPendingLocalImplicitInstantiations;
+ };
+
void PerformPendingInstantiations(bool LocalOnly = false);
TypeSourceInfo *SubstType(TypeSourceInfo *T,
@@ -6240,6 +6576,30 @@ public:
FunctionDecl *Function,
bool Recursive = false,
bool DefinitionRequired = false);
+ VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+ const TemplateArgumentList &TemplateArgList,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ SmallVectorImpl<TemplateArgument> &Converted,
+ SourceLocation PointOfInstantiation, void *InsertPos,
+ LateInstantiatedAttrVec *LateAttrs = 0,
+ LocalInstantiationScope *StartingScope = 0);
+ VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl(
+ VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void
+ BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ LateInstantiatedAttrVec *LateAttrs,
+ DeclContext *Owner,
+ LocalInstantiationScope *StartingScope,
+ bool InstantiatingVarTemplate = false);
+ void InstantiateVariableInitializer(
+ VarDecl *Var, VarDecl *OldVar,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
+ VarDecl *Var, bool Recursive = false,
+ bool DefinitionRequired = false);
void InstantiateStaticDataMemberDefinition(
SourceLocation PointOfInstantiation,
VarDecl *Var,
@@ -6277,6 +6637,10 @@ public:
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
+
+ void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc);
Decl *ActOnCompatibilityAlias(
SourceLocation AtCompatibilityAliasLoc,
@@ -6359,18 +6723,15 @@ public:
void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
ObjCPropertyDecl *SuperProperty,
- const IdentifierInfo *Name);
+ const IdentifierInfo *Name,
+ bool OverridingProtocolProperty);
void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
ObjCInterfaceDecl *ID);
- void MatchOneProtocolPropertiesInClass(Decl *CDecl,
- ObjCProtocolDecl *PDecl);
-
Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
- Decl **allMethods = 0, unsigned allNum = 0,
- Decl **allProperties = 0, unsigned pNum = 0,
- DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
+ ArrayRef<Decl *> allMethods = None,
+ ArrayRef<DeclGroupPtrTy> allTUVars = None);
Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
SourceLocation LParenLoc,
@@ -6584,6 +6945,15 @@ public:
PMSST_ON // #pragms ms_struct on
};
+ enum PragmaMSCommentKind {
+ PCK_Unknown,
+ PCK_Linker, // #pragma comment(linker, ...)
+ PCK_Lib, // #pragma comment(lib, ...)
+ PCK_Compiler, // #pragma comment(compiler, ...)
+ PCK_ExeStr, // #pragma comment(exestr, ...)
+ PCK_User // #pragma comment(user, ...)
+ };
+
/// ActOnPragmaPack - Called on well formed \#pragma pack(...).
void ActOnPragmaPack(PragmaPackKind Kind,
IdentifierInfo *Name,
@@ -6595,6 +6965,13 @@ public:
/// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
+ /// ActOnPragmaMSComment - Called on well formed
+ /// \#pragma comment(kind, "arg").
+ void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg);
+
+ /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
+ void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
+
/// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
void ActOnPragmaUnused(const Token &Identifier,
Scope *curScope,
@@ -6670,16 +7047,79 @@ public:
unsigned SpellingListIndex, bool IsPackExpansion);
// OpenMP directives and clauses.
+private:
+ void *VarDataSharingAttributesStack;
+ /// \brief Initialization of data-sharing attributes stack.
+ void InitDataSharingAttributesStack();
+ void DestroyDataSharingAttributesStack();
+public:
+ /// \brief Called on start of new data sharing attribute block.
+ void StartOpenMPDSABlock(OpenMPDirectiveKind K,
+ const DeclarationNameInfo &DirName,
+ Scope *CurScope);
+ /// \brief Called on end of data sharing attribute block.
+ void EndOpenMPDSABlock(Stmt *CurDirective);
+ // OpenMP directives and clauses.
+ /// \brief Called on correct id-expression from the '#pragma omp
+ /// threadprivate'.
+ ExprResult ActOnOpenMPIdExpression(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id);
/// \brief Called on well-formed '#pragma omp threadprivate'.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
- SourceLocation Loc,
- Scope *CurScope,
- ArrayRef<DeclarationNameInfo> IdList);
- /// \brief Build a new OpenMPThreadPrivateDecl and check its correctness.
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
+ // \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(
- SourceLocation Loc,
- ArrayRef<DeclRefExpr *> VarList);
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
+
+ StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp parallel' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
+ unsigned Argument,
+ SourceLocation ArgumentLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'default' clause.
+ OMPClause *ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
+ ArrayRef<Expr *> Vars,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'private' clause.
+ OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'firstprivate' clause.
+ OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'shared' clause.
+ OMPClause *ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
@@ -6753,20 +7193,25 @@ public:
enum VarArgKind {
VAK_Valid,
VAK_ValidInCXX11,
+ VAK_Undefined,
VAK_Invalid
};
// Determines which VarArgKind fits an expression.
VarArgKind isValidVarArgType(const QualType &Ty);
+ /// Check to see if the given expression is a valid argument to a variadic
+ /// function, issuing a diagnostic if not.
+ void checkVariadicArgument(const Expr *E, VariadicCallType CT);
+
/// GatherArgumentsForCall - Collector argument expressions for various
/// form of call prototypes.
bool GatherArgumentsForCall(SourceLocation CallLoc,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
unsigned FirstProtoArg,
- Expr **Args, unsigned NumArgs,
- SmallVector<Expr *, 8> &AllArgs,
+ ArrayRef<Expr *> Args,
+ SmallVectorImpl<Expr *> &AllArgs,
VariadicCallType CallType = VariadicDoesNotApply,
bool AllowExplicit = false,
bool IsListInitialization = false);
@@ -6776,10 +7221,6 @@ public:
ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
FunctionDecl *FDecl);
- /// Checks to see if the given expression is a valid argument to a variadic
- /// function, issuing a diagnostic and returning NULL if not.
- bool variadicArgumentPODCheck(const Expr *E, VariadicCallType CT);
-
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's
// operands and then handles various conversions that are common to binary
// operators (C99 6.3.1.8). If both operands aren't arithmetic, this
@@ -6892,7 +7333,8 @@ public:
// this routine performs the default function/array converions.
AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType,
ExprResult &RHS,
- bool Diagnose = true);
+ bool Diagnose = true,
+ bool DiagnoseCFAudited = false);
// \brief If the lhs type is a transparent union, check whether we
// can initialize the transparent union with the given expression.
@@ -7071,7 +7513,8 @@ public:
/// retainable pointers and other pointer kinds.
ARCConversionResult CheckObjCARCConversion(SourceRange castRange,
QualType castType, Expr *&op,
- CheckedConversionKind CCK);
+ CheckedConversionKind CCK,
+ bool DiagnoseCFAudited = false);
Expr *stripARCUnbridgedCast(Expr *e);
void diagnoseARCUnbridgedCast(Expr *e);
@@ -7098,7 +7541,7 @@ public:
/// \param [out] ReturnType - The return type of the send.
/// \return true iff there were any incompatible types.
bool CheckMessageArgumentTypes(QualType ReceiverType,
- Expr **Args, unsigned NumArgs, Selector Sel,
+ MultiExprArg Args, Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
ObjCMethodDecl *Method, bool isClassMessage,
bool isSuperMessage,
@@ -7186,8 +7629,8 @@ public:
/// Returns false on success.
/// Can optionally return whether the bit-field is of width 0
ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
- QualType FieldTy, Expr *BitWidth,
- bool *ZeroWidth = 0);
+ QualType FieldTy, bool IsMsStruct,
+ Expr *BitWidth, bool *ZeroWidth = 0);
enum CUDAFunctionTarget {
CFT_Device,
@@ -7284,9 +7727,10 @@ public:
void CodeCompleteNamespaceDecl(Scope *S);
void CodeCompleteNamespaceAliasDecl(Scope *S);
void CodeCompleteOperatorName(Scope *S);
- void CodeCompleteConstructorInitializer(Decl *Constructor,
- CXXCtorInitializer** Initializers,
- unsigned NumInitializers);
+ void CodeCompleteConstructorInitializer(
+ Decl *Constructor,
+ ArrayRef<CXXCtorInitializer *> Initializers);
+
void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
bool AfterAmpersand);
@@ -7301,24 +7745,20 @@ public:
bool IsParameter);
void CodeCompleteObjCMessageReceiver(Scope *S);
void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression);
void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
bool IsSuper = false);
void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
+ ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
ObjCInterfaceDecl *Super = 0);
void CodeCompleteObjCForCollection(Scope *S,
DeclGroupPtrTy IterationVar);
void CodeCompleteObjCSelector(Scope *S,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
+ ArrayRef<IdentifierInfo *> SelIdents);
void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
unsigned NumProtocols);
void CodeCompleteObjCProtocolDecl(Scope *S);
@@ -7343,8 +7783,7 @@ public:
bool IsInstanceMethod,
bool AtParameterName,
ParsedType ReturnType,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
+ ArrayRef<IdentifierInfo *> SelIdents);
void CodeCompletePreprocessorDirective(bool InConditional);
void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
void CodeCompletePreprocessorMacroName(bool IsDefinition);
@@ -7385,8 +7824,9 @@ private:
const FunctionProtoType *Proto);
bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
ArrayRef<const Expr *> Args);
- bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto);
+ bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto);
+ bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto);
void CheckConstructorCall(FunctionDecl *FDecl,
ArrayRef<const Expr *> Args,
const FunctionProtoType *Proto,
@@ -7401,7 +7841,10 @@ private:
bool CheckObjCString(Expr *Arg);
ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStart(CallExpr *TheCall);
@@ -7411,6 +7854,9 @@ private:
public:
// Used by C++ template instantiation.
ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+ ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
private:
bool SemaBuiltinPrefetch(CallExpr *TheCall);
@@ -7422,6 +7868,7 @@ private:
bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
llvm::APSInt &Result);
+public:
enum FormatStringType {
FST_Scanf,
FST_Printf,
@@ -7433,37 +7880,26 @@ private:
};
static FormatStringType GetFormatStringType(const FormatAttr *Format);
- enum StringLiteralCheckType {
- SLCT_NotALiteral,
- SLCT_UncheckedLiteral,
- SLCT_CheckedLiteral
- };
-
- StringLiteralCheckType checkFormatStringExpr(const Expr *E,
- ArrayRef<const Expr *> Args,
- bool HasVAListArg,
- unsigned format_idx,
- unsigned firstDataArg,
- FormatStringType Type,
- VariadicCallType CallType,
- bool inFunctionCall = true);
-
void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
ArrayRef<const Expr *> Args, bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg,
FormatStringType Type, bool inFunctionCall,
- VariadicCallType CallType);
+ VariadicCallType CallType,
+ llvm::SmallBitVector &CheckedVarArgs);
+private:
bool CheckFormatArguments(const FormatAttr *Format,
ArrayRef<const Expr *> Args,
bool IsCXXMember,
VariadicCallType CallType,
- SourceLocation Loc, SourceRange Range);
+ SourceLocation Loc, SourceRange Range,
+ llvm::SmallBitVector &CheckedVarArgs);
bool CheckFormatArguments(ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
VariadicCallType CallType,
- SourceLocation Loc, SourceRange range);
+ SourceLocation Loc, SourceRange range,
+ llvm::SmallBitVector &CheckedVarArgs);
void CheckNonNullArguments(const NonNullAttr *NonNull,
const Expr * const *ExprArgs,
@@ -7536,6 +7972,7 @@ private:
Scope *CurScope;
mutable IdentifierInfo *Ident_super;
+ mutable IdentifierInfo *Ident___float128;
protected:
friend class Parser;
@@ -7555,6 +7992,7 @@ public:
Scope *getCurScope() const { return CurScope; }
IdentifierInfo *getSuperIdentifier() const;
+ IdentifierInfo *getFloat128Identifier() const;
Decl *getObjCDeclContext() const;
@@ -7601,6 +8039,18 @@ public:
}
};
-} // end namespace clang
+DeductionFailureInfo
+MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK,
+ sema::TemplateDeductionInfo &Info);
+
+/// \brief Contains a late templated function.
+/// Will be parsed at the end of the translation unit, used by Sema & Parser.
+struct LateParsedTemplate {
+ CachedTokens Toks;
+ /// \brief The template function declaration to be late parsed.
+ Decl *D;
+};
+
+} // end namespace clang
#endif
diff --git a/include/clang/Sema/SemaDiagnostic.h b/include/clang/Sema/SemaDiagnostic.h
index 9605bf889a31..fdf959305151 100644
--- a/include/clang/Sema/SemaDiagnostic.h
+++ b/include/clang/Sema/SemaDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
#define SEMASTART
#include "clang/Basic/DiagnosticSemaKinds.inc"
#undef DIAG
diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
index bbf42721ba6d..01d4cc9679ef 100644
--- a/include/clang/Sema/SemaInternal.h
+++ b/include/clang/Sema/SemaInternal.h
@@ -24,7 +24,44 @@ namespace clang {
inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
return PartialDiagnostic(DiagID, Context.getDiagAllocator());
}
-
+
+
+// This requires the variable to be non-dependent and the initializer
+// to not be value dependent.
+inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
+ const VarDecl *DefVD = 0;
+ return !isa<ParmVarDecl>(Var) &&
+ Var->isUsableInConstantExpressions(Context) &&
+ Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
+}
+
+// Directly mark a variable odr-used. Given a choice, prefer to use
+// MarkVariableReferenced since it does additional checks and then
+// calls MarkVarDeclODRUsed.
+// If the variable must be captured:
+// - if FunctionScopeIndexToStopAt is null, capture it in the CurContext
+// - else capture it in the DeclContext that maps to the
+// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack.
+inline void MarkVarDeclODRUsed(VarDecl *Var,
+ SourceLocation Loc, Sema &SemaRef,
+ const unsigned *const FunctionScopeIndexToStopAt) {
+ // Keep track of used but undefined variables.
+ // FIXME: We shouldn't suppress this warning for static data members.
+ if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
+ !Var->isExternallyVisible() &&
+ !(Var->isStaticDataMember() && Var->hasInit())) {
+ SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
+ QualType CaptureType, DeclRefType;
+ SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/ true,
+ CaptureType, DeclRefType,
+ FunctionScopeIndexToStopAt);
+
+ Var->markUsed(SemaRef.Context);
+}
}
#endif
diff --git a/include/clang/Sema/SemaLambda.h b/include/clang/Sema/SemaLambda.h
new file mode 100644
index 000000000000..cf9fff1f1a2a
--- /dev/null
+++ b/include/clang/Sema/SemaLambda.h
@@ -0,0 +1,39 @@
+//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides some common utility functions for processing
+/// Lambdas.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_LAMBDA_H
+#define LLVM_CLANG_SEMA_LAMBDA_H
+#include "clang/AST/ASTLambda.h"
+#include "clang/Sema/ScopeInfo.h"
+namespace clang {
+
+// Given a lambda's call operator and a variable (or null for 'this'),
+// compute the nearest enclosing lambda that is capture-ready (i.e
+// the enclosing context is not dependent, and all intervening lambdas can
+// either implicitly or explicitly capture Var)
+//
+// Return the CallOperator of the capturable lambda and set function scope
+// index to the correct index within the function scope stack to correspond
+// to the capturable lambda.
+// If VarDecl *VD is null, we check for 'this' capture.
+CXXMethodDecl*
+GetInnermostEnclosingCapturableLambda(
+ ArrayRef<sema::FunctionScopeInfo*> FunctionScopes,
+ unsigned &FunctionScopeIndex,
+ DeclContext *const CurContext, VarDecl *VD, Sema &S);
+
+} // clang
+
+#endif // LLVM_CLANG_SEMA_LAMBDA_H
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index f9481c6c0c20..1af61d5abd61 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -97,13 +97,6 @@ namespace clang {
addOuterTemplateArguments(ArgList(TemplateArgs->data(),
TemplateArgs->size()));
}
-
- /// \brief Add a new outmost level to the multi-level template argument
- /// list.
- void addOuterTemplateArguments(const TemplateArgument *Args,
- unsigned NumArgs) {
- addOuterTemplateArguments(ArgList(Args, NumArgs));
- }
/// \brief Add a new outmost level to the multi-level template argument
/// list.
@@ -385,6 +378,14 @@ namespace clang {
ClassTemplatePartialSpecializationDecl *>, 4>
OutOfLinePartialSpecs;
+ /// \brief A list of out-of-line variable template partial
+ /// specializations that will need to be instantiated after the
+ /// enclosing variable's instantiation is complete.
+ /// FIXME: Verify that this is needed.
+ SmallVector<
+ std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
+ OutOfLineVarPartialSpecs;
+
public:
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs)
@@ -393,62 +394,39 @@ namespace clang {
Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0)
{ }
- // 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 *VisitTypeAliasDecl(TypeAliasDecl *D);
- Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
- Decl *VisitVarDecl(VarDecl *D);
- Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
- Decl *VisitFieldDecl(FieldDecl *D);
- Decl *VisitMSPropertyDecl(MSPropertyDecl *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);
+// Define all the decl visitors using DeclNodes.inc
+#define DECL(DERIVED, BASE) \
+ Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
+#define ABSTRACT_DECL(DECL)
+
+// Decls which never appear inside a class or function.
+#define OBJCCONTAINER(DERIVED, BASE)
+#define FILESCOPEASM(DERIVED, BASE)
+#define IMPORT(DERIVED, BASE)
+#define LINKAGESPEC(DERIVED, BASE)
+#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
+#define OBJCMETHOD(DERIVED, BASE)
+#define OBJCIVAR(DERIVED, BASE)
+#define OBJCPROPERTY(DERIVED, BASE)
+#define OBJCPROPERTYIMPL(DERIVED, BASE)
+#define EMPTY(DERIVED, BASE)
+
+// Decls which use special-case instantiation code.
+#define BLOCK(DERIVED, BASE)
+#define CAPTURED(DERIVED, BASE)
+#define IMPLICITPARAM(DERIVED, BASE)
+
+#include "clang/AST/DeclNodes.inc"
+
+ // A few supplemental visitor functions.
Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
- TemplateParameterList *TemplateParams = 0,
+ TemplateParameterList *TemplateParams,
bool IsClassScopeSpecialization = false);
- 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);
- Decl *VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D);
- Decl *VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
-
- // Base case. FIXME: Remove once we can instantiate everything.
- Decl *VisitDecl(Decl *D) {
- unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
- DiagnosticsEngine::Error,
- "cannot instantiate %0 yet");
- SemaRef.Diag(D->getLocation(), DiagID)
- << D->getDeclKindName();
-
- return 0;
- }
-
+ Decl *VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams);
+ Decl *VisitDecl(Decl *D);
+ Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate);
+
// Enable late instantiation of attributes. Late instantiated attributes
// will be stored in LA.
void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
@@ -470,6 +448,10 @@ namespace clang {
::iterator
delayed_partial_spec_iterator;
+ typedef SmallVectorImpl<std::pair<
+ VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> >::iterator
+ delayed_var_partial_spec_iterator;
+
/// \brief Return an iterator to the beginning of the set of
/// "delayed" partial specializations, which must be passed to
/// InstantiateClassTemplatePartialSpecialization once the class
@@ -478,6 +460,10 @@ namespace clang {
return OutOfLinePartialSpecs.begin();
}
+ delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
+ return OutOfLineVarPartialSpecs.begin();
+ }
+
/// \brief Return an iterator to the end of the set of
/// "delayed" partial specializations, which must be passed to
/// InstantiateClassTemplatePartialSpecialization once the class
@@ -486,6 +472,10 @@ namespace clang {
return OutOfLinePartialSpecs.end();
}
+ delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
+ return OutOfLineVarPartialSpecs.end();
+ }
+
// Helper functions for instantiating methods.
TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
SmallVectorImpl<ParmVarDecl *> &Params);
@@ -499,12 +489,21 @@ namespace clang {
DeclaratorDecl *NewDecl);
bool SubstQualifier(const TagDecl *OldDecl,
TagDecl *NewDecl);
-
+
+ Decl *VisitVarTemplateSpecializationDecl(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar, void *InsertPos,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ llvm::ArrayRef<TemplateArgument> Converted);
+
Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
ClassTemplatePartialSpecializationDecl *
InstantiateClassTemplatePartialSpecialization(
ClassTemplateDecl *ClassTemplate,
ClassTemplatePartialSpecializationDecl *PartialSpec);
+ VarTemplatePartialSpecializationDecl *
+ InstantiateVarTemplatePartialSpecialization(
+ VarTemplateDecl *VarTemplate,
+ VarTemplatePartialSpecializationDecl *PartialSpec);
void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
};
}
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
index 8292045fdb91..1daa6891ed12 100644
--- a/include/clang/Sema/TemplateDeduction.h
+++ b/include/clang/Sema/TemplateDeduction.h
@@ -20,6 +20,7 @@
namespace clang {
class TemplateArgumentList;
+class Sema;
namespace sema {
@@ -162,7 +163,124 @@ public:
Expr *Expression;
};
-}
-}
+} // end namespace sema
+
+/// A structure used to record information about a failed
+/// template argument deduction, for diagnosis.
+struct DeductionFailureInfo {
+ /// A Sema::TemplateDeductionResult.
+ unsigned Result : 8;
+
+ /// \brief Indicates whether a diagnostic is stored in Diagnostic.
+ unsigned HasDiagnostic : 1;
+
+ /// \brief Opaque pointer containing additional data about
+ /// this deduction failure.
+ void *Data;
+
+ /// \brief A diagnostic indicating why deduction failed.
+ union {
+ void *Align;
+ char Diagnostic[sizeof(PartialDiagnosticAt)];
+ };
+
+ /// \brief Retrieve the diagnostic which caused this deduction failure,
+ /// if any.
+ PartialDiagnosticAt *getSFINAEDiagnostic();
+
+ /// \brief Retrieve the template parameter this deduction failure
+ /// refers to, if any.
+ TemplateParameter getTemplateParameter();
+
+ /// \brief Retrieve the template argument list associated with this
+ /// deduction failure, if any.
+ TemplateArgumentList *getTemplateArgumentList();
+
+ /// \brief Return the first template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getFirstArg();
+
+ /// \brief Return the second template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getSecondArg();
+
+ /// \brief Return the expression this deduction failure refers to,
+ /// if any.
+ Expr *getExpr();
+
+ /// \brief Free any memory associated with this deduction failure.
+ void Destroy();
+};
+
+/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
+/// which keeps track of template argument deduction failure info, when
+/// handling explicit specializations (and instantiations) of templates
+/// beyond function overloading.
+/// For now, assume that the candidates are non-matching specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidate.
+struct TemplateSpecCandidate {
+ /// Specialization - The actual specialization that this candidate
+ /// represents. When NULL, this may be a built-in candidate.
+ Decl *Specialization;
+
+ /// Template argument deduction info
+ DeductionFailureInfo DeductionFailure;
+
+ void set(Decl *Spec, DeductionFailureInfo Info) {
+ Specialization = Spec;
+ DeductionFailure = Info;
+ }
+
+ /// Diagnose a template argument deduction failure.
+ void NoteDeductionFailure(Sema &S);
+};
+
+/// TemplateSpecCandidateSet - A set of generalized overload candidates,
+/// used in template specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidateSet.
+class TemplateSpecCandidateSet {
+ SmallVector<TemplateSpecCandidate, 16> Candidates;
+ SourceLocation Loc;
+
+ TemplateSpecCandidateSet(
+ const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
+ void operator=(const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
+
+ void destroyCandidates();
+
+public:
+ TemplateSpecCandidateSet(SourceLocation Loc) : Loc(Loc) {}
+ ~TemplateSpecCandidateSet() { destroyCandidates(); }
+
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Clear out all of the candidates.
+ /// TODO: This may be unnecessary.
+ void clear();
+
+ typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator;
+ iterator begin() { return Candidates.begin(); }
+ iterator end() { return Candidates.end(); }
+
+ size_t size() const { return Candidates.size(); }
+ bool empty() const { return Candidates.empty(); }
+
+ /// \brief Add a new candidate with NumConversions conversion sequence slots
+ /// to the overload set.
+ TemplateSpecCandidate &addCandidate() {
+ Candidates.push_back(TemplateSpecCandidate());
+ return Candidates.back();
+ }
+
+ void NoteCandidates(Sema &S, SourceLocation Loc);
+
+ void NoteCandidates(Sema &S, SourceLocation Loc) const {
+ const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
+ }
+};
+
+} // end namespace clang
#endif
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index cdd71c8fa9aa..f0b772649847 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/include/clang/Sema/TypoCorrection.h
@@ -39,31 +39,35 @@ public:
static const unsigned CallbackDistanceWeight = 150U;
TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
- NestedNameSpecifier *NNS=0, unsigned CharDistance=0,
- unsigned QualifierDistance=0)
+ NestedNameSpecifier *NNS = 0, unsigned CharDistance = 0,
+ unsigned QualifierDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(QualifierDistance),
- CallbackDistance(0) {
+ CharDistance(CharDistance), QualifierDistance(QualifierDistance),
+ CallbackDistance(0), ForceSpecifierReplacement(false),
+ RequiresImport(false) {
if (NameDecl)
CorrectionDecls.push_back(NameDecl);
}
- TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=0,
- unsigned CharDistance=0)
+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = 0,
+ unsigned CharDistance = 0)
: CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0) {
+ CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
+ ForceSpecifierReplacement(false), RequiresImport(false) {
if (Name)
CorrectionDecls.push_back(Name);
}
- TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=0,
- unsigned CharDistance=0)
+ TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = 0,
+ unsigned CharDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0) {}
+ CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
+ ForceSpecifierReplacement(false), RequiresImport(false) {}
TypoCorrection()
: CorrectionNameSpec(0), CharDistance(0), QualifierDistance(0),
- CallbackDistance(0) {}
+ CallbackDistance(0), ForceSpecifierReplacement(false),
+ RequiresImport(false) {}
/// \brief Gets the DeclarationName of the typo correction
DeclarationName getCorrection() const { return CorrectionName; }
@@ -77,6 +81,15 @@ public:
}
void setCorrectionSpecifier(NestedNameSpecifier* NNS) {
CorrectionNameSpec = NNS;
+ ForceSpecifierReplacement = (NNS != 0);
+ }
+
+ void WillReplaceSpecifier(bool ForceReplacement) {
+ ForceSpecifierReplacement = ForceReplacement;
+ }
+
+ bool WillReplaceSpecifier() const {
+ return ForceSpecifierReplacement;
}
void setQualifierDistance(unsigned ED) {
@@ -116,20 +129,31 @@ public:
}
/// \brief Gets the pointer to the declaration of the typo correction
- NamedDecl* getCorrectionDecl() const {
+ NamedDecl *getCorrectionDecl() const {
return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
}
template <class DeclClass>
DeclClass *getCorrectionDeclAs() const {
return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
}
-
+
+ /// \brief Clears the list of NamedDecls.
+ void ClearCorrectionDecls() {
+ CorrectionDecls.clear();
+ }
+
/// \brief Clears the list of NamedDecls before adding the new one.
void setCorrectionDecl(NamedDecl *CDecl) {
CorrectionDecls.clear();
addCorrectionDecl(CDecl);
}
+ /// \brief Clears the list of NamedDecls and adds the given set.
+ void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) {
+ CorrectionDecls.clear();
+ CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end());
+ }
+
/// \brief Add the given NamedDecl to the list of NamedDecls that are the
/// declarations associated with the DeclarationName of this TypoCorrection
void addCorrectionDecl(NamedDecl *CDecl);
@@ -140,7 +164,7 @@ public:
}
/// \brief Returns whether this TypoCorrection has a non-empty DeclarationName
- operator bool() const { return bool(CorrectionName); }
+ LLVM_EXPLICIT operator bool() const { return bool(CorrectionName); }
/// \brief Mark this TypoCorrection as being a keyword.
/// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
@@ -149,6 +173,7 @@ public:
void makeKeyword() {
CorrectionDecls.clear();
CorrectionDecls.push_back(0);
+ ForceSpecifierReplacement = true;
}
// Check if this TypoCorrection is a keyword by checking if the first
@@ -171,10 +196,11 @@ public:
return CorrectionDecls.size() > 1;
}
- void setCorrectionRange(CXXScopeSpec* SS,
+ void setCorrectionRange(CXXScopeSpec *SS,
const DeclarationNameInfo &TypoName) {
- CorrectionRange.setBegin(CorrectionNameSpec && SS ? SS->getBeginLoc()
- : TypoName.getLoc());
+ CorrectionRange.setBegin(ForceSpecifierReplacement && SS && !SS->isEmpty()
+ ? SS->getBeginLoc()
+ : TypoName.getLoc());
CorrectionRange.setEnd(TypoName.getLoc());
}
@@ -182,17 +208,22 @@ public:
return CorrectionRange;
}
- typedef SmallVector<NamedDecl *, 1>::iterator decl_iterator;
+ typedef SmallVectorImpl<NamedDecl *>::iterator decl_iterator;
decl_iterator begin() {
return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
}
decl_iterator end() { return CorrectionDecls.end(); }
- typedef SmallVector<NamedDecl *, 1>::const_iterator const_decl_iterator;
+ typedef SmallVectorImpl<NamedDecl *>::const_iterator const_decl_iterator;
const_decl_iterator begin() const {
return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
}
const_decl_iterator end() const { return CorrectionDecls.end(); }
+ /// \brief Returns whether this typo correction is correcting to a
+ /// declaration that was declared in a module that has not been imported.
+ bool requiresImport() const { return RequiresImport; }
+ void setRequiresImport(bool Req) { RequiresImport = Req; }
+
private:
bool hasCorrectionDecl() const {
return (!isKeyword() && !CorrectionDecls.empty());
@@ -206,12 +237,14 @@ private:
unsigned QualifierDistance;
unsigned CallbackDistance;
SourceRange CorrectionRange;
+ bool ForceSpecifierReplacement;
+ bool RequiresImport;
};
/// @brief Base class for callback objects used by Sema::CorrectTypo to check
/// the validity of a potential typo correction.
class CorrectionCandidateCallback {
- public:
+public:
static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;
CorrectionCandidateCallback()
@@ -260,12 +293,42 @@ class CorrectionCandidateCallback {
/// to ones having a single Decl* of the given type.
template <class C>
class DeclFilterCCC : public CorrectionCandidateCallback {
- public:
+public:
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
return candidate.getCorrectionDeclAs<C>();
}
};
+// @brief Callback class to limit the allowed keywords and to only accept typo
+// corrections that are keywords or whose decls refer to functions (or template
+// functions) that accept the given number of arguments.
+class FunctionCallFilterCCC : public CorrectionCandidateCallback {
+public:
+ FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
+ bool HasExplicitTemplateArgs);
+
+ virtual bool ValidateCandidate(const TypoCorrection &candidate);
+
+ private:
+ unsigned NumArgs;
+ bool HasExplicitTemplateArgs;
+};
+
+// @brief Callback class that effectively disabled typo correction
+class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
+public:
+ NoTypoCorrectionCCC() {
+ WantTypeSpecifiers = false;
+ WantExpressionKeywords = false;
+ WantCXXNamedCasts = false;
+ WantRemainingKeywords = false;
+ }
+
+ virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ return false;
+ }
+};
+
}
#endif
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 81f898042581..03d905054aea 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -535,7 +535,10 @@ namespace clang {
/// \brief Record code for undefined but used functions and variables that
/// need a definition in this TU.
- UNDEFINED_BUT_USED = 49
+ UNDEFINED_BUT_USED = 49,
+
+ /// \brief Record code for late parsed template functions.
+ LATE_PARSED_TEMPLATE = 50
};
/// \brief Record types used within a source manager block.
@@ -623,7 +626,9 @@ namespace clang {
/// \brief Specifies a configuration macro for this module.
SUBMODULE_CONFIG_MACRO = 11,
/// \brief Specifies a conflict with another module.
- SUBMODULE_CONFLICT = 12
+ SUBMODULE_CONFLICT = 12,
+ /// \brief Specifies a header that is private to this submodule.
+ SUBMODULE_PRIVATE_HEADER = 13
};
/// \brief Record types used within a comments block.
@@ -834,7 +839,9 @@ namespace clang {
/// \brief A UnaryTransformType record.
TYPE_UNARY_TRANSFORM = 39,
/// \brief An AtomicType record.
- TYPE_ATOMIC = 40
+ TYPE_ATOMIC = 40,
+ /// \brief A DecayedType record.
+ TYPE_DECAYED = 41
};
/// \brief The type IDs for special types constructed by semantic
@@ -1023,6 +1030,12 @@ namespace clang {
DECL_CLASS_TEMPLATE_SPECIALIZATION,
/// \brief A ClassTemplatePartialSpecializationDecl record.
DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+ /// \brief A VarTemplateDecl record.
+ DECL_VAR_TEMPLATE,
+ /// \brief A VarTemplateSpecializationDecl record.
+ DECL_VAR_TEMPLATE_SPECIALIZATION,
+ /// \brief A VarTemplatePartialSpecializationDecl record.
+ DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION,
/// \brief A FunctionTemplateDecl record.
DECL_FUNCTION_TEMPLATE,
/// \brief A TemplateTypeParmDecl record.
@@ -1050,7 +1063,7 @@ namespace clang {
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
/// \brief An ImportDecl recording a module import.
DECL_IMPORT,
- /// \brief A OMPThreadPrivateDecl record.
+ /// \brief An OMPThreadPrivateDecl record.
DECL_OMP_THREADPRIVATE,
/// \brief An EmptyDecl record.
DECL_EMPTY
@@ -1173,6 +1186,8 @@ namespace clang {
EXPR_GNU_NULL,
/// \brief A ShuffleVectorExpr record.
EXPR_SHUFFLE_VECTOR,
+ /// \brief A ConvertVectorExpr record.
+ EXPR_CONVERT_VECTOR,
/// \brief BlockExpr
EXPR_BLOCK,
/// \brief A GenericSelectionExpr record.
@@ -1259,6 +1274,8 @@ namespace clang {
EXPR_CXX_FUNCTIONAL_CAST,
/// \brief A UserDefinedLiteral record.
EXPR_USER_DEFINED_LITERAL,
+ /// \brief A CXXStdInitializerListExpr record.
+ EXPR_CXX_STD_INITIALIZER_LIST,
/// \brief A CXXBoolLiteralExpr record.
EXPR_CXX_BOOL_LITERAL,
EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
@@ -1313,7 +1330,10 @@ namespace clang {
STMT_SEH_EXCEPT, // SEHExceptStmt
STMT_SEH_FINALLY, // SEHFinallyStmt
STMT_SEH_TRY, // SEHTryStmt
-
+
+ // OpenMP drectives
+ STMT_OMP_PARALLEL_DIRECTIVE,
+
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 2c0102e3410f..d3cca1a84948 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -88,7 +88,7 @@ class TypeLocReader;
struct HeaderFileInfo;
class VersionTuple;
class TargetOptions;
-class ASTUnresolvedSet;
+class LazyASTUnresolvedSet;
/// \brief Abstract interface for callback invocations by the ASTReader.
///
@@ -166,9 +166,6 @@ public:
return false;
}
- /// \brief Receives a HeaderFileInfo entry.
- virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {}
-
/// \brief Receives __COUNTER__ value.
virtual void ReadCounter(const serialization::ModuleFile &M,
unsigned Value) {}
@@ -190,11 +187,9 @@ class PCHValidator : public ASTReaderListener {
Preprocessor &PP;
ASTReader &Reader;
- unsigned NumHeaderInfos;
-
public:
PCHValidator(Preprocessor &PP, ASTReader &Reader)
- : PP(PP), Reader(Reader), NumHeaderInfos(0) {}
+ : PP(PP), Reader(Reader) {}
virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
bool Complain);
@@ -203,7 +198,6 @@ public:
virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
bool Complain,
std::string &SuggestedPredefines);
- virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID);
virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value);
private:
@@ -246,6 +240,7 @@ class ASTReader
{
public:
typedef SmallVector<uint64_t, 64> RecordData;
+ typedef SmallVectorImpl<uint64_t> RecordDataImpl;
/// \brief The result of reading the control block of an AST file, which
/// can fail for various reasons.
@@ -315,6 +310,10 @@ private:
/// \brief The module manager which manages modules and their dependencies
ModuleManager ModuleMgr;
+ /// \brief The location where the module file will be considered as
+ /// imported from. For non-module AST types it should be invalid.
+ SourceLocation CurrentImportLoc;
+
/// \brief The global module index, if loaded.
llvm::OwningPtr<GlobalModuleIndex> GlobalIndex;
@@ -712,6 +711,9 @@ private:
/// SourceLocation of a matching ODR-use.
SmallVector<uint64_t, 8> UndefinedButUsed;
+ // \brief A list of late parsed template function data.
+ SmallVector<uint64_t, 1> LateParsedTemplates;
+
/// \brief A list of modules that were imported by precompiled headers or
/// any other non-module AST file.
SmallVector<serialization::SubmoduleID, 2> ImportedModules;
@@ -873,6 +875,14 @@ private:
/// been completed.
std::deque<PendingDeclContextInfo> PendingDeclContextInfos;
+ /// \brief The set of NamedDecls that have been loaded, but are members of a
+ /// context that has been merged into another context where the corresponding
+ /// declaration is either missing or has not yet been loaded.
+ ///
+ /// We will check whether the corresponding declaration is in fact missing
+ /// once recursing loading has been completed.
+ llvm::SmallVector<NamedDecl *, 16> PendingOdrMergeChecks;
+
/// \brief The set of Objective-C categories that have been deserialized
/// since the last time the declaration chains were linked.
llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized;
@@ -909,16 +919,22 @@ private:
/// the given canonical declaration.
MergedDeclsMap::iterator
combineStoredMergedDecls(Decl *Canon, serialization::GlobalDeclID CanonID);
-
- /// \brief Ready to load the previous declaration of the given Decl.
- void loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID);
+
+ /// \brief A mapping from DeclContexts to the semantic DeclContext that we
+ /// are treating as the definition of the entity. This is used, for instance,
+ /// when merging implicit instantiations of class templates across modules.
+ llvm::DenseMap<DeclContext *, DeclContext *> MergedDeclContexts;
+
+ /// \brief A mapping from canonical declarations of enums to their canonical
+ /// definitions. Only populated when using modules in C++.
+ llvm::DenseMap<EnumDecl *, EnumDecl *> EnumDefinitions;
/// \brief When reading a Stmt tree, Stmt operands are placed in this stack.
SmallVector<Stmt *, 16> StmtStack;
/// \brief What kind of records we are reading.
enum ReadingKind {
- Read_Decl, Read_Type, Read_Stmt
+ Read_None, Read_Decl, Read_Type, Read_Stmt
};
/// \brief What kind of records we are reading.
@@ -1238,7 +1254,7 @@ public:
void setDeserializationListener(ASTDeserializationListener *Listener);
/// \brief Determine whether this AST reader has a global index.
- bool hasGlobalIndex() const { return GlobalIndex; }
+ bool hasGlobalIndex() const { return GlobalIndex.isValid(); }
/// \brief Attempts to load the global index.
///
@@ -1252,6 +1268,9 @@ public:
/// \brief Initializes the ASTContext
void InitializeContext();
+ /// \brief Update the state of Sema after loading some additional modules.
+ void UpdateSema();
+
/// \brief Add in-memory (virtual file) buffer.
void addInMemoryBuffer(StringRef &FileName, llvm::MemoryBuffer *Buffer) {
ModuleMgr.addInMemoryBuffer(FileName, Buffer);
@@ -1386,6 +1405,10 @@ public:
ReadTemplateArgumentLoc(ModuleFile &F,
const RecordData &Record, unsigned &Idx);
+ const ASTTemplateArgumentListInfo*
+ ReadASTTemplateArgumentListInfo(ModuleFile &F,
+ const RecordData &Record, unsigned &Index);
+
/// \brief Reads a declarator info from the given record.
TypeSourceInfo *GetTypeSourceInfo(ModuleFile &F,
const RecordData &Record, unsigned &Idx);
@@ -1612,6 +1635,9 @@ public:
SmallVectorImpl<std::pair<ValueDecl *,
SourceLocation> > &Pending);
+ virtual void ReadLateParsedTemplates(
+ llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap);
+
/// \brief Load a selector from disk, registering its ID if it exists.
void LoadSelector(Selector Sel);
@@ -1734,12 +1760,12 @@ public:
/// \brief Read a template argument array.
void
- ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs,
+ ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
ModuleFile &F, const RecordData &Record,
unsigned &Idx);
/// \brief Read a UnresolvedSet structure.
- void ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set,
+ void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
const RecordData &Record, unsigned &Idx);
/// \brief Read a C++ base specifier.
@@ -1762,7 +1788,8 @@ public:
/// \brief Read a source location.
SourceLocation ReadSourceLocation(ModuleFile &ModuleFile,
- const RecordData &Record, unsigned &Idx) {
+ const RecordDataImpl &Record,
+ unsigned &Idx) {
return ReadSourceLocation(ModuleFile, Record[Idx++]);
}
@@ -1813,7 +1840,7 @@ public:
Expr *ReadSubExpr();
/// \brief Reads a token out of a record.
- Token ReadToken(ModuleFile &M, const RecordData &Record, unsigned &Idx);
+ Token ReadToken(ModuleFile &M, const RecordDataImpl &Record, unsigned &Idx);
/// \brief Reads the macro record located at the given offset.
MacroInfo *ReadMacroRecord(ModuleFile &F, uint64_t Offset);
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 8ac8fde88470..07fdd062ace7 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -424,7 +424,8 @@ private:
StringRef isysroot, const std::string &OutputFile);
void WriteInputFiles(SourceManager &SourceMgr,
HeaderSearchOptions &HSOpts,
- StringRef isysroot);
+ StringRef isysroot,
+ bool Modules);
void WriteSourceManagerBlock(SourceManager &SourceMgr,
const Preprocessor &PP,
StringRef isysroot);
@@ -456,7 +457,8 @@ private:
void WriteObjCCategories();
void WriteRedeclarations();
void WriteMergedDecls();
-
+ void WriteLateParsedTemplates(Sema &SemaRef);
+
unsigned DeclParmVarAbbrev;
unsigned DeclContextLexicalAbbrev;
unsigned DeclContextVisibleLookupAbbrev;
@@ -575,6 +577,11 @@ public:
void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
RecordDataImpl &Record);
+ /// \brief Emits an AST template argument list info.
+ void AddASTTemplateArgumentListInfo(
+ const ASTTemplateArgumentListInfo *ASTTemplArgList,
+ RecordDataImpl &Record);
+
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordDataImpl &Record);
@@ -723,8 +730,12 @@ public:
virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
const ClassTemplateSpecializationDecl *D);
+ virtual void
+ AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
+ const VarTemplateSpecializationDecl *D);
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D);
+ virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
virtual void CompletedImplicitDefinition(const FunctionDecl *D);
virtual void StaticDataMemberInstantiated(const VarDecl *D);
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
@@ -732,6 +743,7 @@ public:
virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
const ObjCPropertyDecl *OrigProp,
const ObjCCategoryDecl *ClassExt);
+ void DeclarationMarkedUsed(const Decl *D) LLVM_OVERRIDE;
};
/// \brief AST and semantic-analysis consumer that generates a
@@ -746,6 +758,8 @@ class PCHGenerator : public SemaConsumer {
SmallVector<char, 128> Buffer;
llvm::BitstreamWriter Stream;
ASTWriter Writer;
+ bool AllowASTWithErrors;
+ bool HasEmittedPCH;
protected:
ASTWriter &getWriter() { return Writer; }
@@ -754,12 +768,15 @@ protected:
public:
PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
clang::Module *Module,
- StringRef isysroot, raw_ostream *Out);
+ StringRef isysroot, raw_ostream *Out,
+ bool AllowASTWithErrors = false);
~PCHGenerator();
virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
virtual void HandleTranslationUnit(ASTContext &Ctx);
virtual ASTMutationListener *GetASTMutationListener();
virtual ASTDeserializationListener *GetASTDeserializationListener();
+
+ bool hasEmittedPCH() const { return HasEmittedPCH; }
};
} // end namespace clang
diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h
index ab91f4009c0b..76414ba634cc 100644
--- a/include/clang/Serialization/GlobalModuleIndex.h
+++ b/include/clang/Serialization/GlobalModuleIndex.h
@@ -34,6 +34,7 @@ namespace clang {
class DirectoryEntry;
class FileEntry;
class FileManager;
+class IdentifierIterator;
namespace serialization {
class ModuleFile;
diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h
index b2c406346a5f..ca643ba45f2e 100644
--- a/include/clang/Serialization/ModuleManager.h
+++ b/include/clang/Serialization/ModuleManager.h
@@ -96,9 +96,9 @@ class ModuleManager {
void returnVisitState(VisitState *State);
public:
- typedef SmallVector<ModuleFile*, 2>::iterator ModuleIterator;
- typedef SmallVector<ModuleFile*, 2>::const_iterator ModuleConstIterator;
- typedef SmallVector<ModuleFile*, 2>::reverse_iterator ModuleReverseIterator;
+ typedef SmallVectorImpl<ModuleFile*>::iterator ModuleIterator;
+ typedef SmallVectorImpl<ModuleFile*>::const_iterator ModuleConstIterator;
+ typedef SmallVectorImpl<ModuleFile*>::reverse_iterator ModuleReverseIterator;
typedef std::pair<uint32_t, StringRef> ModuleOffset;
explicit ModuleManager(FileManager &FileMgr);
diff --git a/include/clang/Serialization/SerializationDiagnostic.h b/include/clang/Serialization/SerializationDiagnostic.h
index e63f814ee6a0..c28cfea25c87 100644
--- a/include/clang/Serialization/SerializationDiagnostic.h
+++ b/include/clang/Serialization/SerializationDiagnostic.h
@@ -16,7 +16,7 @@ namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
- SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
#define SERIALIZATIONSTART
#include "clang/Basic/DiagnosticSerializationKinds.inc"
#undef DIAG
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
new file mode 100644
index 000000000000..5978299701cf
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -0,0 +1,223 @@
+//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- 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 core data structures for retain count "summaries"
+// for Objective-C and Core Foundation APIs. These summaries are used
+// by the static analyzer to summarize the retain/release effects of
+// function and method calls. This drives a path-sensitive typestate
+// analysis in the static analyzer, but can also potentially be used by
+// other clients.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_OBJCRETAINCOUNT_H
+#define LLVM_CLANG_OBJCRETAINCOUNT_H
+
+namespace clang { namespace ento { namespace objc_retain {
+
+/// An ArgEffect summarizes the retain count behavior on an argument or receiver
+/// to a function or method.
+enum ArgEffect {
+ /// There is no effect.
+ DoNothing,
+
+ /// The argument is treated as if an -autorelease message had been sent to
+ /// the referenced object.
+ Autorelease,
+
+ /// The argument is treated as if an -dealloc message had been sent to
+ /// the referenced object.
+ Dealloc,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if CFRelease has been called on the argument.
+ DecRef,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if a -release message has been sent to the argument. This differs
+ /// in behavior from DecRef when GC is enabled.
+ DecRefMsg,
+
+ /// The argument has its reference count decreased by 1 to model
+ /// a transferred bridge cast under ARC.
+ DecRefBridgedTransferred,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if a -retain message has been sent to the argument. This differs
+ /// in behavior from IncRef when GC is enabled.
+ IncRefMsg,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if CFRetain has been called on the argument.
+ IncRef,
+
+ /// The argument acts as if has been passed to CFMakeCollectable, which
+ /// transfers the object to the Garbage Collector under GC.
+ MakeCollectable,
+
+ /// The argument is treated as potentially escaping, meaning that
+ /// even when its reference count hits 0 it should be treated as still
+ /// possibly being alive as someone else *may* be holding onto the object.
+ MayEscape,
+
+ /// All typestate tracking of the object ceases. This is usually employed
+ /// when the effect of the call is completely unknown.
+ StopTracking,
+
+ /// All typestate tracking of the object ceases. Unlike StopTracking,
+ /// this is also enforced when the method body is inlined.
+ ///
+ /// In some cases, we obtain a better summary for this checker
+ /// by looking at the call site than by inlining the function.
+ /// Signifies that we should stop tracking the symbol even if
+ /// the function is inlined.
+ StopTrackingHard,
+
+ /// Performs the combined functionality of DecRef and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefAndStopTrackingHard,
+
+ /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefMsgAndStopTrackingHard
+};
+
+/// RetEffect summarizes a call's retain/release behavior with respect
+/// to its return value.
+class RetEffect {
+public:
+ enum Kind {
+ /// Indicates that no retain count information is tracked for
+ /// the return value.
+ NoRet,
+ /// Indicates that the returned value is an owned (+1) symbol.
+ OwnedSymbol,
+ /// Indicates that the returned value is an owned (+1) symbol and
+ /// that it should be treated as freshly allocated.
+ OwnedAllocatedSymbol,
+ /// Indicates that the returned value is an object with retain count
+ /// semantics but that it is not owned (+0). This is the default
+ /// for getters, etc.
+ NotOwnedSymbol,
+ /// Indicates that the object is not owned and controlled by the
+ /// Garbage collector.
+ GCNotOwnedSymbol,
+ /// Indicates that the object is not owned and controlled by ARC.
+ ARCNotOwnedSymbol,
+ /// Indicates that the return value is an owned object when the
+ /// receiver is also a tracked object.
+ OwnedWhenTrackedReceiver,
+ // Treat this function as returning a non-tracked symbol even if
+ // the function has been inlined. This is used where the call
+ // site summary is more presise than the summary indirectly produced
+ // by inlining the function
+ NoRetHard
+ };
+
+ /// Determines the object kind of a tracked object.
+ enum ObjKind {
+ /// Indicates that the tracked object is a CF object. This is
+ /// important between GC and non-GC code.
+ CF,
+ /// Indicates that the tracked object is an Objective-C object.
+ ObjC,
+ /// Indicates that the tracked object could be a CF or Objective-C object.
+ AnyObj
+ };
+
+private:
+ Kind K;
+ ObjKind O;
+
+ RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
+
+public:
+ Kind getKind() const { return K; }
+
+ ObjKind getObjKind() const { return O; }
+
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
+ K == OwnedWhenTrackedReceiver;
+ }
+
+ bool notOwned() const {
+ return K == NotOwnedSymbol || K == ARCNotOwnedSymbol;
+ }
+
+ bool operator==(const RetEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+
+ static RetEffect MakeOwnedWhenTrackedReceiver() {
+ return RetEffect(OwnedWhenTrackedReceiver, ObjC);
+ }
+
+ static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
+ return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
+ }
+ static RetEffect MakeNotOwned(ObjKind o) {
+ return RetEffect(NotOwnedSymbol, o);
+ }
+ static RetEffect MakeGCNotOwned() {
+ return RetEffect(GCNotOwnedSymbol, ObjC);
+ }
+ static RetEffect MakeARCNotOwned() {
+ return RetEffect(ARCNotOwnedSymbol, ObjC);
+ }
+ static RetEffect MakeNoRet() {
+ return RetEffect(NoRet);
+ }
+ static RetEffect MakeNoRetHard() {
+ return RetEffect(NoRetHard);
+ }
+};
+
+/// Encapsulates the retain count semantics on the arguments, return value,
+/// and receiver (if any) of a function/method call.
+///
+/// Note that construction of these objects is not highly efficient. That
+/// is okay for clients where creating these objects isn't really a bottleneck.
+/// The purpose of the API is to provide something simple. The actual
+/// static analyzer checker that implements retain/release typestate
+/// tracking uses something more efficient.
+class CallEffects {
+ llvm::SmallVector<ArgEffect, 10> Args;
+ RetEffect Ret;
+ ArgEffect Receiver;
+
+ CallEffects(const RetEffect &R) : Ret(R) {}
+
+public:
+ /// Returns the argument effects for a call.
+ llvm::ArrayRef<ArgEffect> getArgs() const { return Args; }
+
+ /// Returns the effects on the receiver.
+ ArgEffect getReceiver() const { return Receiver; }
+
+ /// Returns the effect on the return value.
+ RetEffect getReturnValue() const { return Ret; }
+
+ /// Return the CallEfect for a given Objective-C method.
+ static CallEffects getEffect(const ObjCMethodDecl *MD);
+
+ /// Return the CallEfect for a given C/C++ function.
+ static CallEffects getEffect(const FunctionDecl *FD);
+};
+
+}}}
+
+#endif
+
diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def
index dc7945016b1a..3355f4b6949c 100644
--- a/include/clang/StaticAnalyzer/Core/Analyses.def
+++ b/include/clang/StaticAnalyzer/Core/Analyses.def
@@ -24,14 +24,14 @@ ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateR
ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
#ifndef ANALYSIS_DIAGNOSTICS
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
#endif
-ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer, false)
-ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true)
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
#ifndef ANALYSIS_PURGE
#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index fb35f518ef02..618782e5d78c 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -52,7 +52,7 @@ NumConstraints
/// AnalysisDiagClients - Set of available diagnostic clients for rendering
/// analysis results.
enum AnalysisDiagClients {
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME,
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,
#include "clang/StaticAnalyzer/Core/Analyses.def"
NUM_ANALYSIS_DIAG_CLIENTS
};
@@ -201,6 +201,9 @@ private:
/// \sa mayInlineCXXContainerCtorsAndDtors
Optional<bool> InlineCXXContainerCtorsAndDtors;
+ /// \sa mayInlineCXXSharedPtrDtor
+ Optional<bool> InlineCXXSharedPtrDtor;
+
/// \sa mayInlineObjCMethod
Optional<bool> ObjCInliningMode;
@@ -223,6 +226,9 @@ private:
/// \sa shouldSuppressFromCXXStandardLibrary
Optional<bool> SuppressFromCXXStandardLibrary;
+ /// \sa reportIssuesInMainSourceFile
+ Optional<bool> ReportIssuesInMainSourceFile;
+
/// \sa getGraphTrimInterval
Optional<unsigned> GraphTrimInterval;
@@ -291,6 +297,16 @@ public:
/// accepts the values "true" and "false".
bool mayInlineCXXContainerCtorsAndDtors();
+ /// Returns whether or not the destructor of C++ 'shared_ptr' may be
+ /// considered for inlining.
+ ///
+ /// This covers std::shared_ptr, std::tr1::shared_ptr, and boost::shared_ptr,
+ /// and indeed any destructor named "~shared_ptr".
+ ///
+ /// This is controlled by the 'c++-shared_ptr-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineCXXSharedPtrDtor();
+
/// Returns whether or not paths that go through null returns should be
/// suppressed.
///
@@ -326,6 +342,13 @@ public:
/// which accepts the values "true" and "false".
bool shouldSuppressFromCXXStandardLibrary();
+ /// Returns whether or not the diagnostic report should be always reported
+ /// in the main source file and not the headers.
+ ///
+ /// This is controlled by the 'report-in-main-source-file' config option,
+ /// which accepts the values "true" and "false".
+ bool shouldReportIssuesInMainSourceFile();
+
/// Returns whether irrelevant parts of a bug report path should be pruned
/// out of the final output.
///
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 5c560b2f0ec9..9584b8baf4f1 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_GR_BUGREPORTER
#include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
@@ -375,6 +376,7 @@ public:
virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
virtual ASTContext &getASTContext() = 0;
virtual SourceManager& getSourceManager() = 0;
+ virtual AnalyzerOptions& getAnalyzerOptions() = 0;
};
/// BugReporter is a utility class for generating PathDiagnostics for analysis.
@@ -442,6 +444,8 @@ public:
SourceManager& getSourceManager() { return D.getSourceManager(); }
+ AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
+
virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
PathDiagnosticConsumer &PC,
ArrayRef<BugReport *> &bugReports) {
@@ -462,20 +466,7 @@ public:
void EmitBasicReport(const Decl *DeclWithIssue,
StringRef BugName, StringRef BugCategory,
StringRef BugStr, PathDiagnosticLocation Loc,
- SourceRange* RangeBeg, unsigned NumRanges);
-
- void EmitBasicReport(const Decl *DeclWithIssue,
- StringRef BugName, StringRef BugCategory,
- StringRef BugStr, PathDiagnosticLocation Loc) {
- EmitBasicReport(DeclWithIssue, BugName, BugCategory, BugStr, Loc, 0, 0);
- }
-
- void EmitBasicReport(const Decl *DeclWithIssue,
- StringRef BugName, StringRef Category,
- StringRef BugStr, PathDiagnosticLocation Loc,
- SourceRange R) {
- EmitBasicReport(DeclWithIssue, BugName, Category, BugStr, Loc, &R, 1);
- }
+ ArrayRef<SourceRange> Ranges = None);
private:
llvm::StringMap<BugType *> StrBugTypes;
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 644aa3159301..49f9c83ba950 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
#define LLVM_CLANG_ANALYSIS_BUGTYPE
+#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
#include <string>
@@ -31,10 +32,12 @@ private:
const std::string Name;
const std::string Category;
bool SuppressonSink;
+
+ virtual void anchor();
public:
BugType(StringRef name, StringRef cat)
: Name(name), Category(cat), SuppressonSink(false) {}
- virtual ~BugType();
+ virtual ~BugType() {}
// FIXME: Should these be made strings as well?
StringRef getName() const { return Name; }
@@ -50,14 +53,14 @@ public:
};
class BuiltinBug : public BugType {
- virtual void anchor();
const std::string desc;
+ virtual void anchor();
public:
BuiltinBug(const char *name, const char *description)
- : BugType(name, "Logic error"), desc(description) {}
+ : BugType(name, categories::LogicError), desc(description) {}
BuiltinBug(const char *name)
- : BugType(name, "Logic error"), desc(name) {}
+ : BugType(name, categories::LogicError), desc(name) {}
StringRef getDescription() const { return desc; }
};
diff --git a/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
index 9d4251b1a757..3f0fe968cc11 100644
--- a/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
@@ -7,16 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H
-#define LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H
+#ifndef LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H
+#define LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H
// Common strings used for the "category" of many static analyzer issues.
namespace clang {
namespace ento {
namespace categories {
- extern const char *CoreFoundationObjectiveC;
- extern const char *MemoryCoreFoundationObjectiveC;
- extern const char *UnixAPI;
+ extern const char * const CoreFoundationObjectiveC;
+ extern const char * const LogicError;
+ extern const char * const MemoryCoreFoundationObjectiveC;
+ extern const char * const UnixAPI;
}
}
}
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index a80b5a7a248c..b0670dad240d 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -38,6 +38,7 @@ class ParentMap;
class ProgramPoint;
class SourceManager;
class Stmt;
+class CallExpr;
namespace ento {
@@ -97,7 +98,6 @@ public:
enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
virtual bool supportsLogicalOpControlFlow() const { return false; }
- virtual bool supportsAllBlockEdges() const { return false; }
/// Return true if the PathDiagnosticConsumer supports individual
/// PathDiagnostics that span multiple files.
@@ -285,11 +285,13 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const;
+ void dump() const;
+
/// \brief Given an exploded node, retrieve the statement that should be used
/// for the diagnostic location.
static const Stmt *getStmt(const ExplodedNode *N);
- /// \brief Retrieve the statement corresponding to the sucessor node.
+ /// \brief Retrieve the statement corresponding to the successor node.
static const Stmt *getNextStmt(const ExplodedNode *N);
};
@@ -331,6 +333,10 @@ private:
const std::string str;
const Kind kind;
const DisplayHint Hint;
+
+ /// \brief In the containing bug report, this piece is the last piece from
+ /// the main source file.
+ bool LastInMainSourceFile;
/// A constant string that can be used to tag the PathDiagnosticPiece,
/// typically with the identification of the creator. The actual pointer
@@ -389,6 +395,16 @@ public:
ArrayRef<SourceRange> getRanges() const { return ranges; }
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ void setAsLastInMainSourceFile() {
+ LastInMainSourceFile = true;
+ }
+
+ bool isLastInMainSourceFile() const {
+ return LastInMainSourceFile;
+ }
+
+ virtual void dump() const = 0;
};
@@ -403,6 +419,8 @@ public:
flattenTo(Result, Result, ShouldFlattenMacros);
return Result;
}
+
+ LLVM_ATTRIBUTE_USED void dump() const;
};
class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
@@ -421,7 +439,7 @@ public:
PathDiagnosticLocation getLocation() const { return Pos; }
virtual void flattenLocations() { Pos.flatten(); }
-
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const PathDiagnosticPiece *P) {
@@ -504,7 +522,7 @@ public:
}
bool hasCallStackHint() {
- return (CallStackHint != 0);
+ return CallStackHint.isValid();
}
/// Produce the hint for the given node. The node contains
@@ -515,6 +533,8 @@ public:
return "";
}
+ virtual void dump() const;
+
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Event;
}
@@ -582,6 +602,8 @@ public:
static PathDiagnosticCallPiece *construct(PathPieces &pieces,
const Decl *caller);
+ virtual void dump() const;
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
static inline bool classof(const PathDiagnosticPiece *P) {
@@ -649,7 +671,9 @@ public:
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == ControlFlow;
}
-
+
+ virtual void dump() const;
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
};
@@ -673,7 +697,9 @@ public:
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Macro;
}
-
+
+ virtual void dump() const;
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
};
@@ -687,7 +713,10 @@ class PathDiagnostic : public llvm::FoldingSetNode {
std::string ShortDesc;
std::string Category;
std::deque<std::string> OtherDesc;
+
+ /// \brief Loc The location of the path diagnostic report.
PathDiagnosticLocation Loc;
+
PathPieces pathImpl;
SmallVector<PathPieces *, 3> pathStack;
@@ -735,12 +764,23 @@ public:
getActivePath().push_back(EndPiece);
}
+ void appendToDesc(StringRef S) {
+ if (!ShortDesc.empty())
+ ShortDesc.append(S);
+ VerboseDesc.append(S);
+ }
+
void resetPath() {
pathStack.clear();
pathImpl.clear();
Loc = PathDiagnosticLocation();
}
-
+
+ /// \brief If the last piece of the report point to the header file, resets
+ /// the location of the report to be the last location in the main source
+ /// file.
+ void resetDiagnosticLocationToMainFile();
+
StringRef getVerboseDescription() const { return VerboseDesc; }
StringRef getShortDescription() const {
return ShortDesc.empty() ? VerboseDesc : ShortDesc;
@@ -759,7 +799,7 @@ public:
void addMeta(StringRef s) { OtherDesc.push_back(s); }
PathDiagnosticLocation getLocation() const {
- assert(Loc.isValid() && "No end-of-path location set yet!");
+ assert(Loc.isValid() && "No report location set yet!");
return Loc;
}
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index 0dbaab033d2d..cf7cf051d225 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -320,18 +320,35 @@ public:
class PointerEscape {
template <typename CHECKER>
static ProgramStateRef
- _checkPointerEscape(void *checker,
+ _checkPointerEscape(void *Checker,
ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst) {
- if (!IsConst)
- return ((const CHECKER *)checker)->checkPointerEscape(State,
+ RegionAndSymbolInvalidationTraits *ETraits) {
+
+ if (!ETraits)
+ return ((const CHECKER *)Checker)->checkPointerEscape(State,
Escaped,
Call,
Kind);
- return State;
+
+ InvalidatedSymbols RegularEscape;
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ E = Escaped.end(); I != E; ++I)
+ if (!ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
+ !ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
+ RegularEscape.insert(*I);
+
+ if (RegularEscape.empty())
+ return State;
+
+ return ((const CHECKER *)Checker)->checkPointerEscape(State,
+ RegularEscape,
+ Call,
+ Kind);
}
public:
@@ -346,18 +363,32 @@ public:
class ConstPointerEscape {
template <typename CHECKER>
static ProgramStateRef
- _checkConstPointerEscape(void *checker,
+ _checkConstPointerEscape(void *Checker,
ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst) {
- if (IsConst)
- return ((const CHECKER *)checker)->checkConstPointerEscape(State,
- Escaped,
- Call,
- Kind);
- return State;
+ RegionAndSymbolInvalidationTraits *ETraits) {
+
+ if (!ETraits)
+ return State;
+
+ InvalidatedSymbols ConstEscape;
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ E = Escaped.end(); I != E; ++I)
+ if (ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
+ !ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
+ ConstEscape.insert(*I);
+
+ if (ConstEscape.empty())
+ return State;
+
+ return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
+ ConstEscape,
+ Call,
+ Kind);
}
public:
@@ -502,10 +533,14 @@ struct ImplicitNullDerefEvent {
};
/// \brief A helper class which wraps a boolean value set to false by default.
+///
+/// This class should behave exactly like 'bool' except that it doesn't need to
+/// be explicitly initialized.
struct DefaultBool {
bool val;
DefaultBool() : val(false) {}
- operator bool() const { return val; }
+ /*implicit*/ operator bool&() { return val; }
+ /*implicit*/ operator const bool&() const { return val; }
DefaultBool &operator=(bool b) { val = b; return *this; }
};
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index b2411e6e6544..8ad67c118f01 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -19,7 +19,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
@@ -366,14 +365,16 @@ public:
/// \param Escaped The list of escaped symbols.
/// \param Call The corresponding CallEvent, if the symbols escape as
/// parameters to the given call.
- /// \param IsConst Specifies if the pointer is const.
+ /// \param Kind The reason of pointer escape.
+ /// \param ITraits Information about invalidation for a particular
+ /// region/symbol.
/// \returns Checkers can modify the state by returning a new one.
ProgramStateRef
runCheckersForPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst = false);
+ RegionAndSymbolInvalidationTraits *ITraits);
/// \brief Run checkers for handling assumptions on symbolic values.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
@@ -465,7 +466,7 @@ public:
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst)>
+ RegionAndSymbolInvalidationTraits *ITraits)>
CheckPointerEscapeFunc;
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
@@ -581,35 +582,12 @@ private:
};
std::vector<StmtCheckerInfo> StmtCheckers;
- struct CachedStmtCheckersKey {
- unsigned StmtKind;
- bool IsPreVisit;
-
- CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
- CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
- : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
-
- static CachedStmtCheckersKey getSentinel() {
- return CachedStmtCheckersKey(~0U, 0);
- }
- unsigned getHashValue() const {
- llvm::FoldingSetNodeID ID;
- ID.AddInteger(StmtKind);
- ID.AddBoolean(IsPreVisit);
- return ID.ComputeHash();
- }
- bool operator==(const CachedStmtCheckersKey &RHS) const {
- return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
- }
- };
- friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
-
typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
- typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
- CachedStmtCheckersMapTy;
+ typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
CachedStmtCheckersMapTy CachedStmtCheckersMap;
- CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
+ const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
+ bool isPreVisit);
std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
@@ -659,30 +637,4 @@ private:
} // end clang namespace
-namespace llvm {
- /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
- /// in DenseMap and DenseSets.
- template <>
- struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
- static inline clang::ento::CheckerManager::CachedStmtCheckersKey
- getEmptyKey() {
- return clang::ento::CheckerManager::CachedStmtCheckersKey();
- }
- static inline clang::ento::CheckerManager::CachedStmtCheckersKey
- getTombstoneKey() {
- return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
- }
-
- static unsigned
- getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
- return S.getHashValue();
- }
-
- static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
- clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
- return LHS == RHS;
- }
- };
-} // end namespace llvm
-
#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
index 4557aa40ea80..ca68a74fef96 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
@@ -54,10 +54,6 @@
//
// For a complete working example, see examples/analyzer-plugin.
-
-namespace clang {
-namespace ento {
-
#ifndef CLANG_ANALYZER_API_VERSION_STRING
// FIXME: The Clang version string is not particularly granular;
// the analyzer infrastructure can change a lot between releases.
@@ -67,6 +63,9 @@ namespace ento {
#define CLANG_ANALYZER_API_VERSION_STRING CLANG_VERSION_STRING
#endif
+namespace clang {
+namespace ento {
+
class CheckerOptInfo;
/// Manages a set of available checkers for running a static analysis.
diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index b856de7dc612..43e9166b3cdc 100644
--- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -27,18 +27,12 @@ namespace ento {
class PathDiagnosticConsumer;
typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
-#define CREATE_CONSUMER(NAME)\
-void create ## NAME ## DiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,\
- PathDiagnosticConsumers &C,\
- const std::string& prefix,\
- const Preprocessor &PP);
-
-CREATE_CONSUMER(HTML)
-CREATE_CONSUMER(Plist)
-CREATE_CONSUMER(PlistMultiFile)
-CREATE_CONSUMER(TextPath)
-
-#undef CREATE_CONSUMER
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
+void CREATEFN(AnalyzerOptions &AnalyzerOpts,\
+ PathDiagnosticConsumers &C,\
+ const std::string &Prefix,\
+ const Preprocessor &PP);
+#include "clang/StaticAnalyzer/Core/Analyses.def"
} // end 'ento' namespace
} // end 'clang' namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 458c8966e79e..d7d83ce8b17d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -65,6 +65,10 @@ public:
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
}
+
+ AnalyzerOptions& getAnalyzerOptions() {
+ return options;
+ }
ConstraintManagerCreator getConstraintManagerCreator() {
return CreateConstraintMgr;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index f990b8dcd0ec..cfaf085b5f34 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -228,11 +228,6 @@ public:
return false;
}
- /// \brief Returns true if this is a call to a variadic function or method.
- virtual bool isVariadic() const {
- return false;
- }
-
/// \brief Returns a source range for the entire call, suitable for
/// outputting in diagnostics.
virtual SourceRange getSourceRange() const {
@@ -341,6 +336,11 @@ public:
/// This will return a null QualType if the result type cannot be determined.
static QualType getDeclaredResultType(const Decl *D);
+ /// \brief Returns true if the given decl is known to be variadic.
+ ///
+ /// \p D must not be null.
+ static bool isVariadic(const Decl *D);
+
// Iterator access to formal parameters and their types.
private:
typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
@@ -350,19 +350,13 @@ public:
/// Returns an iterator over the call's formal parameters.
///
- /// If UseDefinitionParams is set, this will return the parameter decls
- /// used in the callee's definition (suitable for inlining). Most of the
- /// time it is better to use the decl found by name lookup, which likely
- /// carries more annotations.
- ///
/// Remember that the number of formal parameters may not match the number
/// of arguments for all calls. However, the first parameter will always
/// correspond with the argument value returned by \c getArgSVal(0).
///
- /// If the call has no accessible declaration (or definition, if
- /// \p UseDefinitionParams is set), \c param_begin() will be equal to
- /// \c param_end().
- virtual param_iterator param_begin() const =0;
+ /// If the call has no accessible declaration, \c param_begin() will be equal
+ /// to \c param_end().
+ virtual param_iterator param_begin() const = 0;
/// \sa param_begin()
virtual param_iterator param_end() const = 0;
@@ -423,10 +417,6 @@ public:
return RuntimeDefinition();
}
- virtual bool isVariadic() const {
- return getDecl()->isVariadic();
- }
-
virtual bool argumentsMayEscape() const;
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
@@ -527,10 +517,6 @@ public:
return RuntimeDefinition(getBlockDecl());
}
- virtual bool isVariadic() const {
- return getBlockDecl()->isVariadic();
- }
-
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const;
@@ -849,9 +835,6 @@ public:
virtual const Expr *getArgExpr(unsigned Index) const {
return getOriginExpr()->getArg(Index);
}
- virtual bool isVariadic() const {
- return getDecl()->isVariadic();
- }
bool isInstanceMessage() const {
return getOriginExpr()->isInstanceMessage();
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index edcfc8a6c097..bf17cd807d65 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -184,7 +184,7 @@ public:
bool isSink() const { return Succs.getFlag(); }
- bool hasSinglePred() const {
+ bool hasSinglePred() const {
return (pred_size() == 1);
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 33e4431eb4be..d89dffe63b0a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -203,6 +203,8 @@ public:
void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void ProcessDeleteDtor(const CFGDeleteDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
void ProcessBaseDtor(const CFGBaseDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
void ProcessMemberDtor(const CFGMemberDtor D,
@@ -476,14 +478,14 @@ protected:
SVal Loc, SVal Val);
/// Call PointerEscape callback when a value escapes as a result of
/// region invalidation.
- /// \param[in] IsConst Specifies that the pointer is const.
+ /// \param[in] ITraits Specifies invalidation traits for regions/symbols.
ProgramStateRef notifyCheckersOfPointerEscape(
ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
- bool IsConst);
+ RegionAndSymbolInvalidationTraits &ITraits);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 9b4f77dd679f..cc790c1b6b39 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -635,12 +635,14 @@ class BlockDataRegion : public TypedRegion {
friend class MemRegionManager;
const BlockTextRegion *BC;
const LocationContext *LC; // Can be null */
+ unsigned BlockCount;
void *ReferencedVars;
void *OriginalVars;
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
- const MemRegion *sreg)
+ unsigned count, const MemRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ BlockCount(count),
ReferencedVars(0), OriginalVars(0) {}
public:
@@ -692,7 +694,8 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
- const LocationContext *, const MemRegion *);
+ const LocationContext *, unsigned,
+ const MemRegion *);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind;
@@ -1270,7 +1273,13 @@ public:
/// argument is allowed to be NULL for cases where we have no known
/// context.
const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
- const LocationContext *lc = NULL);
+ const LocationContext *lc,
+ unsigned blockCount);
+
+ /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
+ /// by static references. This differs from getCXXTempObjectRegion in the
+ /// super-region used.
+ const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
private:
template <typename RegionTy, typename A1>
@@ -1304,6 +1313,39 @@ private:
inline ASTContext &MemRegion::getContext() const {
return getMemRegionManager()->getContext();
}
+
+//===----------------------------------------------------------------------===//
+// Means for storing region/symbol handling traits.
+//===----------------------------------------------------------------------===//
+
+/// Information about invalidation for a particular region/symbol.
+class RegionAndSymbolInvalidationTraits {
+ typedef unsigned char StorageTypeForKinds;
+ llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
+ llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
+
+ typedef llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator
+ const_region_iterator;
+ typedef llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator
+ const_symbol_iterator;
+
+public:
+ /// \brief Describes different invalidation traits.
+ enum InvalidationKinds {
+ /// Tells that a region's contents is not changed.
+ TK_PreserveContents = 0x1,
+ /// Suppress pointer-escaping of a region.
+ TK_SuppressEscape = 0x2
+
+ // Do not forget to extend StorageTypeForKinds if number of traits exceed
+ // the number of bits StorageTypeForKinds can store.
+ };
+
+ void setTrait(SymbolRef Sym, InvalidationKinds IK);
+ void setTrait(const MemRegion *MR, InvalidationKinds IK);
+ bool hasTrait(SymbolRef Sym, InvalidationKinds IK);
+ bool hasTrait(const MemRegion *MR, InvalidationKinds IK);
+};
} // end GR namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 42ef1db45591..03739ed9284d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -232,22 +232,21 @@ public:
/// \param IS the set of invalidated symbols.
/// \param Call if non-null, the invalidated regions represent parameters to
/// the call and should be considered directly invalidated.
- /// \param ConstRegions the set of regions whose contents are accessible,
- /// even though the regions themselves should not be invalidated.
+ /// \param ITraits information about special handling for a particular
+ /// region/symbol.
ProgramStateRef
invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
const CallEvent *Call = 0,
- ArrayRef<const MemRegion *> ConstRegions =
- ArrayRef<const MemRegion *>()) const;
+ RegionAndSymbolInvalidationTraits *ITraits = 0) const;
ProgramStateRef
invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
const CallEvent *Call = 0,
- ArrayRef<SVal> ConstRegions = ArrayRef<SVal>()) const;
+ RegionAndSymbolInvalidationTraits *ITraits = 0) const;
/// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
@@ -425,9 +424,9 @@ private:
const Expr *E, unsigned BlockCount,
const LocationContext *LCtx,
bool ResultsInSymbolEscape,
- InvalidatedSymbols &IS,
- const CallEvent *Call,
- ArrayRef<SVal> ConstValues) const;
+ InvalidatedSymbols *IS,
+ RegionAndSymbolInvalidationTraits *HTraits,
+ const CallEvent *Call) const;
};
//===----------------------------------------------------------------------===//
@@ -516,8 +515,8 @@ public:
public:
- SVal ArrayToPointer(Loc Array) {
- return StoreMgr->ArrayToPointer(Array);
+ SVal ArrayToPointer(Loc Array, QualType ElementTy) {
+ return StoreMgr->ArrayToPointer(Array, ElementTy);
}
// Methods that manipulate the GDM.
@@ -798,7 +797,7 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
/// A Utility class that allows to visit the reachable symbols using a custom
/// SymbolVisitor.
class ScanReachableSymbols {
- typedef llvm::DenseMap<const void*, unsigned> VisitedItems;
+ typedef llvm::DenseSet<const void*> VisitedItems;
VisitedItems visited;
ProgramStateRef state;
@@ -808,6 +807,7 @@ public:
ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v)
: state(st), visitor(v) {}
+ bool scan(nonloc::LazyCompoundVal val);
bool scan(nonloc::CompoundVal val);
bool scan(SVal val);
bool scan(const MemRegion *R);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index bbb56885af04..c5d0a92cabdd 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -200,7 +200,8 @@ public:
DefinedSVal getFunctionPointer(const FunctionDecl *func);
DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
- const LocationContext *locContext);
+ const LocationContext *locContext,
+ unsigned blockCount);
/// Returns the value of \p E, if it can be determined in a non-path-sensitive
/// manner.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 326e784e83d4..5a426ef00197 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -290,7 +290,7 @@ public:
static inline bool isLocType(QualType T) {
return T->isAnyPointerType() || T->isBlockPointerType() ||
- T->isReferenceType();
+ T->isReferenceType() || T->isNullPtrType();
}
private:
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index b219495d5f06..530dae59892a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -111,7 +111,7 @@ public:
/// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
/// conversions between arrays and pointers.
- virtual SVal ArrayToPointer(Loc Array) = 0;
+ virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0;
/// Evaluates a chain of derived-to-base casts through the path specified in
/// \p Cast.
@@ -164,8 +164,6 @@ public:
/// the given regions. Optionally, invalidates non-static globals as well.
/// \param[in] store The initial store
/// \param[in] Values The values to invalidate.
- /// \param[in] ConstValues The values to invalidate; these are known to be
- /// const, so only regions accesible from them should be invalidated.
/// \param[in] E The current statement being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
@@ -174,13 +172,10 @@ public:
/// globals should get invalidated.
/// \param[in,out] IS A set to fill with any symbols that are no longer
/// accessible. Pass \c NULL if this information will not be used.
- /// \param[in,out] ConstIS A set to fill with any symbols corresponding to
- /// the ConstValues.
+ /// \param[in] ITraits Information about invalidation for a particular
+ /// region/symbol.
/// \param[in,out] InvalidatedTopLevel A vector to fill with regions
- //// explicitely being invalidated. Pass \c NULL if this
- /// information will not be used.
- /// \param[in,out] InvalidatedTopLevelConst A vector to fill with const
- //// regions explicitely being invalidated. Pass \c NULL if this
+ //// explicitly being invalidated. Pass \c NULL if this
/// information will not be used.
/// \param[in,out] Invalidated A vector to fill with any regions being
/// invalidated. This should include any regions explicitly invalidated
@@ -188,14 +183,12 @@ public:
/// information will not be used.
virtual StoreRef invalidateRegions(Store store,
ArrayRef<SVal> Values,
- ArrayRef<SVal> ConstValues,
const Expr *E, unsigned Count,
const LocationContext *LCtx,
const CallEvent *Call,
InvalidatedSymbols &IS,
- InvalidatedSymbols &ConstIS,
+ RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *InvalidatedTopLevel,
- InvalidatedRegions *InvalidatedTopLevelConst,
InvalidatedRegions *Invalidated) = 0;
/// enterStackFrame - Let the StoreManager to do something when execution
@@ -231,7 +224,7 @@ public:
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
SVal val);
- operator bool() { return First && Binding; }
+ LLVM_EXPLICIT operator bool() { return First && Binding; }
const MemRegion *getRegion() { return Binding; }
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index d4100634a785..f653c70a30f3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -134,7 +134,7 @@ public:
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
- bool IsConst = false) = 0;
+ RegionAndSymbolInvalidationTraits &HTraits) = 0;
/// printState - Called by ProgramStateManager to print checker-specific data.
virtual void printState(raw_ostream &Out, ProgramStateRef State,
diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h
index 492ddd2b0078..71acef8650fe 100644
--- a/include/clang/Tooling/ArgumentsAdjusters.h
+++ b/include/clang/Tooling/ArgumentsAdjusters.h
@@ -52,6 +52,12 @@ class ClangSyntaxOnlyAdjuster : public ArgumentsAdjuster {
virtual CommandLineArguments Adjust(const CommandLineArguments &Args);
};
+/// \brief An argument adjuster which removes output-related command line
+/// arguments.
+class ClangStripOutputAdjuster : public ArgumentsAdjuster {
+ virtual CommandLineArguments Adjust(const CommandLineArguments &Args);
+};
+
} // end namespace tooling
} // end namespace clang
diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h
index 677593413948..eaffe4363515 100644
--- a/include/clang/Tooling/CommonOptionsParser.h
+++ b/include/clang/Tooling/CommonOptionsParser.h
@@ -64,7 +64,7 @@ public:
/// This constructor can change argc and argv contents, e.g. consume
/// command-line options used for creating FixedCompilationDatabase.
/// This constructor exits program in case of error.
- CommonOptionsParser(int &argc, const char **argv);
+ CommonOptionsParser(int &argc, const char **argv, const char *Overview = 0);
/// Returns a reference to the loaded compilations database.
CompilationDatabase &getCompilations() {
diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index 7a8054ffc3a4..8cca3296f94d 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -50,6 +50,16 @@ struct CompileCommand {
/// \brief The command line that was executed.
std::vector<std::string> CommandLine;
+
+ /// \brief An optional mapping from each file's path to its content for all
+ /// files needed for the compilation that are not available via the file
+ /// system.
+ ///
+ /// Note that a tool implementation is required to fall back to the file
+ /// system if a source file is not provided in the mapped sources, as
+ /// compilation databases will usually not provide all files in mapped sources
+ /// for performance reasons.
+ std::vector<std::pair<std::string, std::string> > MappedSources;
};
/// \brief Interface for compilation databases.
@@ -108,6 +118,10 @@ public:
/// \brief Returns all compile commands for all the files in the compilation
/// database.
+ ///
+ /// FIXME: Add a layer in Tooling that provides an interface to run a tool
+ /// over all files in a compilation database. Not all build systems have the
+ /// ability to provide a feasible implementation for \c getAllCompileCommands.
virtual std::vector<CompileCommand> getAllCompileCommands() const = 0;
};
diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h
index 079ce7420db9..43ec9acdb3bf 100644
--- a/include/clang/Tooling/Refactoring.h
+++ b/include/clang/Tooling/Refactoring.h
@@ -32,6 +32,37 @@ class SourceLocation;
namespace tooling {
+/// \brief A source range independent of the \c SourceManager.
+class Range {
+public:
+ Range() : Offset(0), Length(0) {}
+ Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
+
+ /// \brief Accessors.
+ /// @{
+ unsigned getOffset() const { return Offset; }
+ unsigned getLength() const { return Length; }
+ /// @}
+
+ /// \name Range Predicates
+ /// @{
+ /// \brief Whether this range overlaps with \p RHS or not.
+ bool overlapsWith(Range RHS) const {
+ return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length;
+ }
+
+ /// \brief Whether this range contains \p RHS or not.
+ bool contains(Range RHS) const {
+ return RHS.Offset >= Offset &&
+ (RHS.Offset + RHS.Length) <= (Offset + Length);
+ }
+ /// @}
+
+private:
+ unsigned Offset;
+ unsigned Length;
+};
+
/// \brief A text replacement.
///
/// Represents a SourceManager independent replacement of a range of text in a
@@ -72,8 +103,8 @@ public:
/// \brief Accessors.
/// @{
StringRef getFilePath() const { return FilePath; }
- unsigned getOffset() const { return Offset; }
- unsigned getLength() const { return Length; }
+ unsigned getOffset() const { return ReplacementRange.getOffset(); }
+ unsigned getLength() const { return ReplacementRange.getLength(); }
StringRef getReplacementText() const { return ReplacementText; }
/// @}
@@ -83,12 +114,6 @@ public:
/// \brief Returns a human readable string representation.
std::string toString() const;
- /// \brief Comparator to be able to use Replacement in std::set for uniquing.
- class Less {
- public:
- bool operator()(const Replacement &R1, const Replacement &R2) const;
- };
-
private:
void setFromSourceLocation(SourceManager &Sources, SourceLocation Start,
unsigned Length, StringRef ReplacementText);
@@ -96,14 +121,27 @@ public:
StringRef ReplacementText);
std::string FilePath;
- unsigned Offset;
- unsigned Length;
+ Range ReplacementRange;
std::string ReplacementText;
};
+/// \brief Less-than operator between two Replacements.
+bool operator<(const Replacement &LHS, const Replacement &RHS);
+
+/// \brief Equal-to operator between two Replacements.
+bool operator==(const Replacement &LHS, const Replacement &RHS);
+
/// \brief A set of Replacements.
/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
-typedef std::set<Replacement, Replacement::Less> Replacements;
+typedef std::set<Replacement> Replacements;
+
+/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
+///
+/// Replacement applications happen independently of the success of
+/// other applications.
+///
+/// \returns true if all replacements apply. false otherwise.
+bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
///
@@ -111,7 +149,48 @@ typedef std::set<Replacement, Replacement::Less> Replacements;
/// other applications.
///
/// \returns true if all replacements apply. false otherwise.
-bool applyAllReplacements(Replacements &Replaces, Rewriter &Rewrite);
+bool applyAllReplacements(const std::vector<Replacement> &Replaces,
+ Rewriter &Rewrite);
+
+/// \brief Applies all replacements in \p Replaces to \p Code.
+///
+/// This completely ignores the path stored in each replacement. If one or more
+/// replacements cannot be applied, this returns an empty \c string.
+std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
+
+/// \brief Calculates how a code \p Position is shifted when \p Replaces are
+/// applied.
+unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position);
+
+/// \brief Calculates how a code \p Position is shifted when \p Replaces are
+/// applied.
+///
+/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset().
+unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
+ unsigned Position);
+
+/// \brief Removes duplicate Replacements and reports if Replacements conflict
+/// with one another.
+///
+/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
+///
+/// This function sorts \p Replaces so that conflicts can be reported simply by
+/// offset into \p Replaces and number of elements in the conflict.
+void deduplicate(std::vector<Replacement> &Replaces,
+ std::vector<Range> &Conflicts);
+
+/// \brief Collection of Replacements generated from a single translation unit.
+struct TranslationUnitReplacements {
+ /// Name of the main source for the translation unit.
+ std::string MainSourceFile;
+
+ /// A freeform chunk of text to describe the context of the replacements.
+ /// Will be printed, for example, when detecting conflicts during replacement
+ /// deduplication.
+ std::string Context;
+
+ std::vector<Replacement> Replacements;
+};
/// \brief A tool to run refactorings.
///
diff --git a/include/clang/Tooling/ReplacementsYaml.h b/include/clang/Tooling/ReplacementsYaml.h
new file mode 100644
index 000000000000..18d3259d7058
--- /dev/null
+++ b/include/clang/Tooling/ReplacementsYaml.h
@@ -0,0 +1,88 @@
+//===-- ReplacementsYaml.h -- Serialiazation for Replacements ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the structure of a YAML document for serializing
+/// replacements.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REPLACEMENTS_YAML_H
+#define LLVM_CLANG_TOOLING_REPLACEMENTS_YAML_H
+
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <vector>
+#include <string>
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement)
+
+namespace llvm {
+namespace yaml {
+
+/// \brief ScalarTraits to read/write std::string objects.
+template <> struct ScalarTraits<std::string> {
+ static void output(const std::string &Val, void *, llvm::raw_ostream &Out) {
+ Out << Val;
+ }
+
+ static StringRef input(StringRef Scalar, void *, std::string &Val) {
+ Val = Scalar;
+ return StringRef();
+ }
+};
+
+/// \brief Specialized MappingTraits to describe how a Replacement is
+/// (de)serialized.
+template <> struct MappingTraits<clang::tooling::Replacement> {
+ /// \brief Helper to (de)serialize a Replacement since we don't have direct
+ /// access to its data members.
+ struct NormalizedReplacement {
+ NormalizedReplacement(const IO &)
+ : FilePath(""), Offset(0), Length(0), ReplacementText("") {}
+
+ NormalizedReplacement(const IO &, const clang::tooling::Replacement &R)
+ : FilePath(R.getFilePath()), Offset(R.getOffset()),
+ Length(R.getLength()), ReplacementText(R.getReplacementText()) {}
+
+ clang::tooling::Replacement denormalize(const IO &) {
+ return clang::tooling::Replacement(FilePath, Offset, Length,
+ ReplacementText);
+ }
+
+ std::string FilePath;
+ unsigned int Offset;
+ unsigned int Length;
+ std::string ReplacementText;
+ };
+
+ static void mapping(IO &Io, clang::tooling::Replacement &R) {
+ MappingNormalization<NormalizedReplacement, clang::tooling::Replacement>
+ Keys(Io, R);
+ Io.mapRequired("FilePath", Keys->FilePath);
+ Io.mapRequired("Offset", Keys->Offset);
+ Io.mapRequired("Length", Keys->Length);
+ Io.mapRequired("ReplacementText", Keys->ReplacementText);
+ }
+};
+
+/// \brief Specialized MappingTraits to describe how a
+/// TranslationUnitReplacements is (de)serialized.
+template <> struct MappingTraits<clang::tooling::TranslationUnitReplacements> {
+ static void mapping(IO &Io,
+ clang::tooling::TranslationUnitReplacements &Doc) {
+ Io.mapRequired("MainSourceFile", Doc.MainSourceFile);
+ Io.mapOptional("Context", Doc.Context, std::string());
+ Io.mapRequired("Replacements", Doc.Replacements);
+ }
+};
+} // end namespace yaml
+} // end namespace llvm
+
+#endif // LLVM_CLANG_TOOLING_REPLACEMENTS_YAML_H
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index 27e5a0af2573..de507a7a8b25 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -30,6 +30,7 @@
#ifndef LLVM_CLANG_TOOLING_TOOLING_H
#define LLVM_CLANG_TOOLING_TOOLING_H
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Util.h"
@@ -53,11 +54,34 @@ class FrontendAction;
namespace tooling {
+/// \brief Interface to process a clang::CompilerInvocation.
+///
+/// If your tool is based on FrontendAction, you should be deriving from
+/// FrontendActionFactory instead.
+class ToolAction {
+public:
+ virtual ~ToolAction();
+
+ /// \brief Perform an action for an invocation.
+ virtual bool runInvocation(clang::CompilerInvocation *Invocation,
+ FileManager *Files,
+ DiagnosticConsumer *DiagConsumer) = 0;
+};
+
/// \brief Interface to generate clang::FrontendActions.
-class FrontendActionFactory {
+///
+/// Having a factory interface allows, for example, a new FrontendAction to be
+/// created for each translation unit processed by ClangTool. This class is
+/// also a ToolAction which uses the FrontendActions created by create() to
+/// process each translation unit.
+class FrontendActionFactory : public ToolAction {
public:
virtual ~FrontendActionFactory();
+ /// \brief Invokes the compiler with a FrontendAction created by create().
+ bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files,
+ DiagnosticConsumer *DiagConsumer);
+
/// \brief Returns a new clang::FrontendAction.
///
/// The caller takes ownership of the returned action.
@@ -66,7 +90,7 @@ public:
/// \brief Returns a new FrontendActionFactory for a given type.
///
-/// T must extend clang::FrontendAction.
+/// T must derive from clang::FrontendAction.
///
/// Example:
/// FrontendActionFactory *Factory =
@@ -74,12 +98,22 @@ public:
template <typename T>
FrontendActionFactory *newFrontendActionFactory();
-/// \brief Called at the end of each source file when used with
-/// \c newFrontendActionFactory.
-class EndOfSourceFileCallback {
+/// \brief Callbacks called before and after each source file processed by a
+/// FrontendAction created by the FrontedActionFactory returned by \c
+/// newFrontendActionFactory.
+class SourceFileCallbacks {
public:
- virtual ~EndOfSourceFileCallback() {}
- virtual void run() = 0;
+ virtual ~SourceFileCallbacks() {}
+
+ /// \brief Called before a source file is processed by a FrontEndAction.
+ /// \see clang::FrontendAction::BeginSourceFileAction
+ virtual bool handleBeginSource(CompilerInstance &CI, StringRef Filename) {
+ return true;
+ }
+
+ /// \brief Called after a source file is processed by a FrontendAction.
+ /// \see clang::FrontendAction::EndSourceFileAction
+ virtual void handleEndSource() {}
};
/// \brief Returns a new FrontendActionFactory for any type that provides an
@@ -95,7 +129,7 @@ public:
/// newFrontendActionFactory(&Factory);
template <typename FactoryT>
inline FrontendActionFactory *newFrontendActionFactory(
- FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback = NULL);
+ FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = NULL);
/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
///
@@ -120,6 +154,26 @@ bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
const std::vector<std::string> &Args,
const Twine &FileName = "input.cc");
+/// \brief Builds an AST for 'Code'.
+///
+/// \param Code C++ code.
+/// \param FileName The file name which 'Code' will be mapped as.
+///
+/// \return The resulting AST or null if an error occurred.
+ASTUnit *buildASTFromCode(const Twine &Code,
+ const Twine &FileName = "input.cc");
+
+/// \brief Builds an AST for 'Code' with additional flags.
+///
+/// \param Code C++ code.
+/// \param Args Additional flags to pass on.
+/// \param FileName The file name which 'Code' will be mapped as.
+///
+/// \return The resulting AST or null if an error occurred.
+ASTUnit *buildASTFromCodeWithArgs(const Twine &Code,
+ const std::vector<std::string> &Args,
+ const Twine &FileName = "input.cc");
+
/// \brief Utility to run a FrontendAction in a single clang invocation.
class ToolInvocation {
public:
@@ -129,12 +183,25 @@ class ToolInvocation {
/// uses its binary name (CommandLine[0]) to locate its builtin headers.
/// Callers have to ensure that they are installed in a compatible location
/// (see clang driver implementation) or mapped in via mapVirtualFile.
- /// \param ToolAction The action to be executed. Class takes ownership.
+ /// \param FAction The action to be executed. Class takes ownership.
/// \param Files The FileManager used for the execution. Class does not take
/// ownership.
- ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
+ ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *FAction,
+ FileManager *Files);
+
+ /// \brief Create a tool invocation.
+ ///
+ /// \param CommandLine The command line arguments to clang.
+ /// \param Action The action to be executed.
+ /// \param Files The FileManager used for the execution.
+ ToolInvocation(ArrayRef<std::string> CommandLine, ToolAction *Action,
FileManager *Files);
+ ~ToolInvocation();
+
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer);
+
/// \brief Map a virtual file to be used while running the tool.
///
/// \param FilePath The path at which the content will be mapped.
@@ -154,10 +221,12 @@ class ToolInvocation {
clang::CompilerInvocation *Invocation);
std::vector<std::string> CommandLine;
- OwningPtr<FrontendAction> ToolAction;
+ ToolAction *Action;
+ bool OwnsAction;
FileManager *Files;
// Maps <file name> -> <file content>.
llvm::StringMap<StringRef> MappedFileContents;
+ DiagnosticConsumer *DiagConsumer;
};
/// \brief Utility to run a FrontendAction over a set of files.
@@ -165,8 +234,8 @@ class ToolInvocation {
/// This class is written to be usable for command line utilities.
/// By default the class uses ClangSyntaxOnlyAdjuster to modify
/// command line arguments before the arguments are used to run
-/// a frontend action. One could install another command line
-/// arguments adjuster by call setArgumentsAdjuster() method.
+/// a frontend action. One could install an additional command line
+/// arguments adjuster by calling the appendArgumentsAdjuster() method.
class ClangTool {
public:
/// \brief Constructs a clang tool to run over a list of files.
@@ -178,7 +247,10 @@ class ClangTool {
ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths);
- virtual ~ClangTool() {}
+ virtual ~ClangTool() { clearArgumentsAdjusters(); }
+
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer);
/// \brief Map a virtual file to be used while running the tool.
///
@@ -189,29 +261,45 @@ class ClangTool {
/// \brief Install command line arguments adjuster.
///
/// \param Adjuster Command line arguments adjuster.
+ //
+ /// FIXME: Function is deprecated. Use (clear/append)ArgumentsAdjuster instead.
+ /// Remove it once all callers are gone.
void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
- /// Runs a frontend action over all files specified in the command line.
+ /// \brief Append a command line arguments adjuster to the adjuster chain.
+ ///
+ /// \param Adjuster An argument adjuster, which will be run on the output of
+ /// previous argument adjusters.
+ void appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
+
+ /// \brief Clear the command line arguments adjuster chain.
+ void clearArgumentsAdjusters();
+
+ /// Runs an action over all files specified in the command line.
///
- /// \param ActionFactory Factory generating the frontend actions. The function
- /// takes ownership of this parameter. A new action is generated for every
- /// processed translation unit.
- virtual int run(FrontendActionFactory *ActionFactory);
+ /// \param Action Tool action.
+ int run(ToolAction *Action);
+
+ /// \brief Create an AST for each file specified in the command line and
+ /// append them to ASTs.
+ int buildASTs(std::vector<ASTUnit *> &ASTs);
/// \brief Returns the file manager used in the tool.
///
/// The file manager is shared between all translation units.
- FileManager &getFiles() { return Files; }
+ FileManager &getFiles() { return *Files; }
private:
// We store compile commands as pair (file name, compile command).
std::vector< std::pair<std::string, CompileCommand> > CompileCommands;
- FileManager Files;
+ llvm::IntrusiveRefCntPtr<FileManager> Files;
// Contains a list of pairs (<file name>, <file content>).
std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
- OwningPtr<ArgumentsAdjuster> ArgsAdjuster;
+ SmallVector<ArgumentsAdjuster *, 2> ArgsAdjusters;
+
+ DiagnosticConsumer *DiagConsumer;
};
template <typename T>
@@ -226,23 +314,23 @@ FrontendActionFactory *newFrontendActionFactory() {
template <typename FactoryT>
inline FrontendActionFactory *newFrontendActionFactory(
- FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback) {
+ FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) {
class FrontendActionFactoryAdapter : public FrontendActionFactory {
public:
explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
- EndOfSourceFileCallback *EndCallback)
- : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {}
+ SourceFileCallbacks *Callbacks)
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
virtual clang::FrontendAction *create() {
- return new ConsumerFactoryAdaptor(ConsumerFactory, EndCallback);
+ return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
}
private:
class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
public:
ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
- EndOfSourceFileCallback *EndCallback)
- : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {}
+ SourceFileCallbacks *Callbacks)
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &,
StringRef) {
@@ -250,21 +338,29 @@ inline FrontendActionFactory *newFrontendActionFactory(
}
protected:
- virtual void EndSourceFileAction() {
- if (EndCallback != NULL)
- EndCallback->run();
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) LLVM_OVERRIDE {
+ if (!clang::ASTFrontendAction::BeginSourceFileAction(CI, Filename))
+ return false;
+ if (Callbacks != NULL)
+ return Callbacks->handleBeginSource(CI, Filename);
+ return true;
+ }
+ virtual void EndSourceFileAction() LLVM_OVERRIDE {
+ if (Callbacks != NULL)
+ Callbacks->handleEndSource();
clang::ASTFrontendAction::EndSourceFileAction();
}
private:
FactoryT *ConsumerFactory;
- EndOfSourceFileCallback *EndCallback;
+ SourceFileCallbacks *Callbacks;
};
FactoryT *ConsumerFactory;
- EndOfSourceFileCallback *EndCallback;
+ SourceFileCallbacks *Callbacks;
};
- return new FrontendActionFactoryAdapter(ConsumerFactory, EndCallback);
+ return new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks);
}
/// \brief Returns the absolute path of \c File, by prepending it with
@@ -275,10 +371,8 @@ inline FrontendActionFactory *newFrontendActionFactory(
/// Otherwise, the returned path will contain the literal path-concatenation of
/// the current directory and \c File.
///
-/// The difference to llvm::sys::fs::make_absolute is that we prefer
-/// ::getenv("PWD") if available.
-/// FIXME: Make this functionality available from llvm::sys::fs and delete
-/// this function.
+/// The difference to llvm::sys::fs::make_absolute is the canonicalization this
+/// does by removing "./" and computing native paths.
///
/// \param File Either an absolute or relative path.
std::string getAbsolutePath(StringRef File);