aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/APValue.h46
-rw-r--r--include/clang/AST/ASTContext.h136
-rw-r--r--include/clang/AST/ASTFwd.h2
-rw-r--r--include/clang/AST/ASTImporter.h43
-rw-r--r--include/clang/AST/ASTImporterSharedState.h2
-rw-r--r--include/clang/AST/ASTNodeTraverser.h3
-rw-r--r--include/clang/AST/ASTStructuralEquivalence.h19
-rw-r--r--include/clang/AST/ASTTypeTraits.h4
-rw-r--r--include/clang/AST/Attr.h151
-rw-r--r--include/clang/AST/CXXRecordDeclDefinitionBits.def236
-rw-r--r--include/clang/AST/CharUnits.h5
-rw-r--r--include/clang/AST/CommentCommands.td1
-rw-r--r--include/clang/AST/CommentLexer.h3
-rw-r--r--include/clang/AST/Decl.h52
-rw-r--r--include/clang/AST/DeclBase.h2
-rw-r--r--include/clang/AST/DeclCXX.h343
-rw-r--r--include/clang/AST/DeclTemplate.h178
-rw-r--r--include/clang/AST/Expr.h16
-rw-r--r--include/clang/AST/ExprCXX.h235
-rw-r--r--include/clang/AST/ExternalASTMerger.h38
-rw-r--r--include/clang/AST/FormatString.h22
-rw-r--r--include/clang/AST/GlobalDecl.h1
-rw-r--r--include/clang/AST/JSONNodeDumper.h2
-rw-r--r--include/clang/AST/Mangle.h18
-rw-r--r--include/clang/AST/NSAPI.h3
-rw-r--r--include/clang/AST/OpenMPClause.h157
-rw-r--r--include/clang/AST/OperationKinds.def5
-rw-r--r--include/clang/AST/OptionalDiagnostic.h78
-rw-r--r--include/clang/AST/RawCommentList.h23
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h100
-rw-r--r--include/clang/AST/Stmt.h10
-rw-r--r--include/clang/AST/StmtOpenMP.h302
-rw-r--r--include/clang/AST/TextNodeDumper.h2
-rw-r--r--include/clang/AST/Type.h105
-rw-r--r--include/clang/AST/TypeLoc.h2
-rw-r--r--include/clang/AST/TypeLocNodes.def2
-rw-r--r--include/clang/AST/TypeNodes.def135
-rw-r--r--include/clang/AST/TypeVisitor.h4
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h186
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h25
-rw-r--r--include/clang/Analysis/AnalysisDeclContext.h51
-rw-r--r--include/clang/Analysis/CFG.h195
-rw-r--r--include/clang/Analysis/CallGraph.h1
-rw-r--r--include/clang/Analysis/PathDiagnostic.h (renamed from include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h)145
-rw-r--r--include/clang/Basic/AArch64SVEACLETypes.def70
-rw-r--r--include/clang/Basic/Attr.td182
-rw-r--r--include/clang/Basic/AttrDocs.td210
-rw-r--r--include/clang/Basic/AttributeCommonInfo.h190
-rw-r--r--include/clang/Basic/Builtins.def27
-rw-r--r--include/clang/Basic/BuiltinsAArch64.def56
-rw-r--r--include/clang/Basic/BuiltinsAMDGPU.def9
-rw-r--r--include/clang/Basic/BuiltinsARM.def48
-rw-r--r--include/clang/Basic/BuiltinsBPF.def24
-rw-r--r--include/clang/Basic/BuiltinsPPC.def14
-rw-r--r--include/clang/Basic/BuiltinsWebAssembly.def33
-rw-r--r--include/clang/Basic/BuiltinsX86.def4
-rw-r--r--include/clang/Basic/BuiltinsX86_64.def4
-rw-r--r--include/clang/Basic/CodeGenOptions.def14
-rw-r--r--include/clang/Basic/CodeGenOptions.h6
-rw-r--r--include/clang/Basic/Diagnostic.h17
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td139
-rw-r--r--include/clang/Basic/DiagnosticCommentKinds.td6
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td26
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td9
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td13
-rw-r--r--include/clang/Basic/DiagnosticGroups.td50
-rw-r--r--include/clang/Basic/DiagnosticOptions.def1
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td55
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td388
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td15
-rw-r--r--include/clang/Basic/Features.def4
-rw-r--r--include/clang/Basic/FileManager.h204
-rw-r--r--include/clang/Basic/IdentifierTable.h6
-rw-r--r--include/clang/Basic/LangOptions.def11
-rw-r--r--include/clang/Basic/LangOptions.h16
-rw-r--r--include/clang/Basic/LangStandard.h (renamed from include/clang/Frontend/LangStandard.h)69
-rw-r--r--include/clang/Basic/LangStandards.def (renamed from include/clang/Frontend/LangStandards.def)5
-rw-r--r--include/clang/Basic/Linkage.h6
-rw-r--r--include/clang/Basic/OpenCLOptions.h6
-rw-r--r--include/clang/Basic/OpenMPKinds.def103
-rw-r--r--include/clang/Basic/OpenMPKinds.h13
-rw-r--r--include/clang/Basic/OperatorKinds.h19
-rw-r--r--include/clang/Basic/SourceManager.h83
-rw-r--r--include/clang/Basic/Specifiers.h3
-rw-r--r--include/clang/Basic/Stack.h29
-rw-r--r--include/clang/Basic/StmtNodes.td7
-rw-r--r--include/clang/Basic/SyncScope.h2
-rw-r--r--include/clang/Basic/TargetBuiltins.h10
-rw-r--r--include/clang/Basic/TargetInfo.h23
-rw-r--r--include/clang/Basic/TokenKinds.def72
-rw-r--r--include/clang/Basic/TokenKinds.h11
-rw-r--r--include/clang/Basic/TypeNodes.td106
-rw-r--r--include/clang/Basic/X86Target.def5
-rw-r--r--include/clang/Basic/arm_neon.td8
-rw-r--r--include/clang/CodeGen/CGFunctionInfo.h10
-rw-r--r--include/clang/CrossTU/CrossTranslationUnit.h143
-rw-r--r--include/clang/DirectoryWatcher/DirectoryWatcher.h10
-rw-r--r--include/clang/Driver/Action.h26
-rw-r--r--include/clang/Driver/CC1Options.td16
-rw-r--r--include/clang/Driver/CLCompatOptions.td14
-rw-r--r--include/clang/Driver/Driver.h14
-rw-r--r--include/clang/Driver/Options.h2
-rw-r--r--include/clang/Driver/Options.td136
-rw-r--r--include/clang/Driver/Phases.h3
-rw-r--r--include/clang/Driver/SanitizerArgs.h7
-rw-r--r--include/clang/Driver/ToolChain.h9
-rw-r--r--include/clang/Driver/Types.def123
-rw-r--r--include/clang/Driver/Types.h7
-rw-r--r--include/clang/Format/Format.h240
-rw-r--r--include/clang/Frontend/ASTUnit.h5
-rw-r--r--include/clang/Frontend/CompilerInstance.h24
-rw-r--r--include/clang/Frontend/CompilerInvocation.h14
-rw-r--r--include/clang/Frontend/FrontendActions.h9
-rw-r--r--include/clang/Frontend/FrontendOptions.h51
-rw-r--r--include/clang/Frontend/Utils.h13
-rw-r--r--include/clang/Index/CodegenNameGenerator.h52
-rw-r--r--include/clang/Index/IndexDataConsumer.h16
-rw-r--r--include/clang/Index/IndexingAction.h37
-rw-r--r--include/clang/Index/IndexingOptions.h42
-rw-r--r--include/clang/Lex/DependencyDirectivesSourceMinimizer.h22
-rw-r--r--include/clang/Lex/DirectoryLookup.h68
-rw-r--r--include/clang/Lex/HeaderMap.h5
-rw-r--r--include/clang/Lex/HeaderSearch.h14
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h27
-rw-r--r--include/clang/Lex/Lexer.h15
-rw-r--r--include/clang/Lex/MacroArgs.h10
-rw-r--r--include/clang/Lex/PPCallbacks.h12
-rw-r--r--include/clang/Lex/Preprocessor.h55
-rw-r--r--include/clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h31
-rw-r--r--include/clang/Lex/PreprocessorOptions.h16
-rw-r--r--include/clang/Parse/Parser.h50
-rw-r--r--include/clang/Rewrite/Core/Rewriter.h11
-rw-r--r--include/clang/Sema/Overload.h102
-rw-r--r--include/clang/Sema/ParsedAttr.h212
-rw-r--r--include/clang/Sema/ScopeInfo.h10
-rw-r--r--include/clang/Sema/Sema.h577
-rw-r--r--include/clang/Sema/SemaInternal.h2
-rw-r--r--include/clang/Sema/TypoCorrection.h8
-rw-r--r--include/clang/Serialization/ASTBitCodes.h17
-rw-r--r--include/clang/Serialization/ASTReader.h14
-rw-r--r--include/clang/StaticAnalyzer/Checkers/Checkers.td43
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.def32
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h68
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h656
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h217
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h40
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h1
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h24
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h27
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h17
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h55
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h73
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h46
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h63
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h54
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h4
-rw-r--r--include/clang/Tooling/ASTDiff/ASTDiff.h2
-rw-r--r--include/clang/Tooling/AllTUsExecution.h3
-rw-r--r--include/clang/Tooling/ArgumentsAdjusters.h4
-rw-r--r--include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h188
-rw-r--r--include/clang/Tooling/DependencyScanning/DependencyScanningService.h65
-rw-r--r--include/clang/Tooling/DependencyScanning/DependencyScanningTool.h48
-rw-r--r--include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h42
-rw-r--r--include/clang/Tooling/Execution.h7
-rw-r--r--include/clang/Tooling/Inclusions/HeaderIncludes.h1
-rw-r--r--include/clang/Tooling/Inclusions/IncludeStyle.h2
-rwxr-xr-xinclude/clang/Tooling/Refactoring/Extract/SourceExtraction.h51
-rw-r--r--include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h15
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h10
-rw-r--r--include/clang/Tooling/StandaloneExecution.h2
-rw-r--r--include/clang/Tooling/Syntax/Tokens.h10
-rw-r--r--include/clang/Tooling/Tooling.h30
-rw-r--r--include/clang/Tooling/Transformer/MatchConsumer.h62
-rw-r--r--include/clang/Tooling/Transformer/RangeSelector.h (renamed from include/clang/Tooling/Refactoring/RangeSelector.h)30
-rw-r--r--include/clang/Tooling/Transformer/RewriteRule.h (renamed from include/clang/Tooling/Refactoring/Transformer.h)109
-rw-r--r--include/clang/Tooling/Transformer/SourceCode.h (renamed from include/clang/Tooling/Refactoring/SourceCode.h)19
-rw-r--r--include/clang/Tooling/Transformer/SourceCodeBuilders.h86
-rw-r--r--include/clang/Tooling/Transformer/Stencil.h (renamed from include/clang/Tooling/Refactoring/Stencil.h)130
-rw-r--r--include/clang/Tooling/Transformer/Transformer.h52
-rw-r--r--include/clang/module.modulemap6
185 files changed, 7416 insertions, 2840 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index 6943479831ec..63359294ef63 100644
--- a/include/clang/AST/APValue.h
+++ b/include/clang/AST/APValue.h
@@ -53,6 +53,34 @@ public:
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
};
+
+/// Symbolic representation of a dynamic allocation.
+class DynamicAllocLValue {
+ unsigned Index;
+
+public:
+ DynamicAllocLValue() : Index(0) {}
+ explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
+ unsigned getIndex() { return Index - 1; }
+
+ explicit operator bool() const { return Index != 0; }
+
+ void *getOpaqueValue() {
+ return reinterpret_cast<void *>(static_cast<uintptr_t>(Index)
+ << NumLowBitsAvailable);
+ }
+ static DynamicAllocLValue getFromOpaqueValue(void *Value) {
+ DynamicAllocLValue V;
+ V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
+ return V;
+ }
+
+ static unsigned getMaxIndex() {
+ return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
+ }
+
+ static constexpr int NumLowBitsAvailable = 3;
+};
}
namespace llvm {
@@ -67,6 +95,17 @@ template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
// to include Type.h.
static constexpr int NumLowBitsAvailable = 3;
};
+
+template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
+ static void *getAsVoidPointer(clang::DynamicAllocLValue V) {
+ return V.getOpaqueValue();
+ }
+ static clang::DynamicAllocLValue getFromVoidPointer(void *P) {
+ return clang::DynamicAllocLValue::getFromOpaqueValue(P);
+ }
+ static constexpr int NumLowBitsAvailable =
+ clang::DynamicAllocLValue::NumLowBitsAvailable;
+};
}
namespace clang {
@@ -97,13 +136,15 @@ public:
};
class LValueBase {
- typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue>
+ typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
+ DynamicAllocLValue>
PtrTy;
public:
LValueBase() : Local{} {}
LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
+ static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
template <class T>
@@ -124,6 +165,7 @@ public:
unsigned getCallIndex() const;
unsigned getVersion() const;
QualType getTypeInfoType() const;
+ QualType getDynamicAllocType() const;
friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
@@ -140,6 +182,8 @@ public:
LocalState Local;
/// The type std::type_info, if this is a TypeInfoLValue.
void *TypeInfoType;
+ /// The QualType, if this is a DynamicAllocLValue.
+ void *DynamicAllocType;
};
};
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 1d1aaf4fb115..5e2f4031d96c 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -139,6 +139,12 @@ class FullComment;
} // namespace comments
+namespace interp {
+
+class Context;
+
+} // namespace interp
+
struct TypeInfo {
uint64_t Width = 0;
unsigned Align = 0;
@@ -179,7 +185,8 @@ private:
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
- mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
+ mutable llvm::ContextualFoldingSet<ConstantArrayType, ASTContext &>
+ ConstantArrayTypes;
mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
mutable std::vector<VariableArrayType*> VariableArrayTypes;
mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
@@ -507,6 +514,8 @@ private:
/// need to be consistently numbered for the mangler).
llvm::DenseMap<const DeclContext *, std::unique_ptr<MangleNumberingContext>>
MangleNumberingContexts;
+ llvm::DenseMap<const Decl *, std::unique_ptr<MangleNumberingContext>>
+ ExtraMangleNumberingContexts;
/// Side-table of mangling numbers for declarations which rarely
/// need them (like static local vars).
@@ -564,6 +573,7 @@ private:
const TargetInfo *Target = nullptr;
const TargetInfo *AuxTarget = nullptr;
clang::PrintingPolicy PrintingPolicy;
+ std::unique_ptr<interp::Context> InterpContext;
public:
IdentifierTable &Idents;
@@ -573,6 +583,9 @@ public:
IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
ASTMutationListener *Listener = nullptr;
+ /// Returns the clang bytecode interpreter context.
+ interp::Context &getInterpContext();
+
/// Container for either a single DynTypedNode or for an ArrayRef to
/// DynTypedNode. For use with ParentMap.
class DynTypedNodeList {
@@ -729,71 +742,49 @@ public:
/// True if comments are already loaded from ExternalASTSource.
mutable bool CommentsLoaded = false;
- class RawCommentAndCacheFlags {
- public:
- enum Kind {
- /// We searched for a comment attached to the particular declaration, but
- /// didn't find any.
- ///
- /// getRaw() == 0.
- NoCommentInDecl = 0,
-
- /// We have found a comment attached to this particular declaration.
- ///
- /// getRaw() != 0.
- FromDecl,
-
- /// This declaration does not have an attached comment, and we have
- /// searched the redeclaration chain.
- ///
- /// If getRaw() == 0, the whole redeclaration chain does not have any
- /// comments.
- ///
- /// If getRaw() != 0, it is a comment propagated from other
- /// redeclaration.
- FromRedecl
- };
-
- Kind getKind() const LLVM_READONLY {
- return Data.getInt();
- }
-
- void setKind(Kind K) {
- Data.setInt(K);
- }
-
- const RawComment *getRaw() const LLVM_READONLY {
- return Data.getPointer();
- }
-
- void setRaw(const RawComment *RC) {
- Data.setPointer(RC);
- }
-
- const Decl *getOriginalDecl() const LLVM_READONLY {
- return OriginalDecl;
- }
-
- void setOriginalDecl(const Decl *Orig) {
- OriginalDecl = Orig;
- }
-
- private:
- llvm::PointerIntPair<const RawComment *, 2, Kind> Data;
- const Decl *OriginalDecl;
- };
+ /// Mapping from declaration to directly attached comment.
+ ///
+ /// Raw comments are owned by Comments list. This mapping is populated
+ /// lazily.
+ mutable llvm::DenseMap<const Decl *, const RawComment *> DeclRawComments;
- /// Mapping from declarations to comments attached to any
- /// redeclaration.
+ /// Mapping from canonical declaration to the first redeclaration in chain
+ /// that has a comment attached.
///
/// Raw comments are owned by Comments list. This mapping is populated
/// lazily.
- mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments;
+ mutable llvm::DenseMap<const Decl *, const Decl *> RedeclChainComments;
+
+ /// Keeps track of redeclaration chains that don't have any comment attached.
+ /// Mapping from canonical declaration to redeclaration chain that has no
+ /// comments attached to any redeclaration. Specifically it's mapping to
+ /// the last redeclaration we've checked.
+ ///
+ /// Shall not contain declarations that have comments attached to any
+ /// redeclaration in their chain.
+ mutable llvm::DenseMap<const Decl *, const Decl *> CommentlessRedeclChains;
/// Mapping from declarations to parsed comments attached to any
/// redeclaration.
mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments;
+ /// Attaches \p Comment to \p OriginalD and to its redeclaration chain
+ /// and removes the redeclaration chain from the set of commentless chains.
+ ///
+ /// Don't do anything if a comment has already been attached to \p OriginalD
+ /// or its redeclaration chain.
+ void cacheRawCommentForDecl(const Decl &OriginalD,
+ const RawComment &Comment) const;
+
+ /// \returns searches \p CommentsInFile for doc comment for \p D.
+ ///
+ /// \p RepresentativeLocForDecl is used as a location for searching doc
+ /// comments. \p CommentsInFile is a mapping offset -> comment of files in the
+ /// same file where \p RepresentativeLocForDecl is.
+ RawComment *getRawCommentForDeclNoCacheImpl(
+ const Decl *D, const SourceLocation RepresentativeLocForDecl,
+ const std::map<unsigned, RawComment *> &CommentsInFile) const;
+
/// Return the documentation comment attached to a given declaration,
/// without looking into cache.
RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
@@ -818,6 +809,16 @@ public:
getRawCommentForAnyRedecl(const Decl *D,
const Decl **OriginalDecl = nullptr) const;
+ /// Searches existing comments for doc comments that should be attached to \p
+ /// Decls. If any doc comment is found, it is parsed.
+ ///
+ /// Requirement: All \p Decls are in the same file.
+ ///
+ /// If the last comment in the file is already attached we assume
+ /// there are not comments left to be attached to \p Decls.
+ void attachCommentsToJustParsedDecls(ArrayRef<Decl *> Decls,
+ const Preprocessor *PP);
+
/// Return parsed documentation comment attached to a given declaration.
/// Returns nullptr if no comment is attached.
///
@@ -1054,6 +1055,9 @@ public:
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
CanQualType Id##Ty;
#include "clang/Basic/OpenCLExtensionTypes.def"
+#define SVE_TYPE(Name, Id, SingletonId) \
+ CanQualType SingletonId;
+#include "clang/Basic/AArch64SVEACLETypes.def"
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
mutable QualType AutoDeductTy; // Deduction against 'auto'.
@@ -1329,6 +1333,7 @@ public:
/// Return the unique reference to the type for a constant array of
/// the specified element type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
+ const Expr *SizeExpr,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals) const;
@@ -1498,8 +1503,7 @@ public:
bool isKindOf) const;
QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
- ArrayRef<ObjCProtocolDecl *> protocols,
- QualType Canonical = QualType()) const;
+ ArrayRef<ObjCProtocolDecl *> protocols) const;
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
@@ -2054,6 +2058,11 @@ public:
/// types.
bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
+ /// Return true if the type has been explicitly qualified with ObjC ownership.
+ /// A type may be implicitly qualified with ownership under ObjC ARC, and in
+ /// some cases the compiler treats these differently.
+ bool hasDirectOwnershipQualifier(QualType Ty) const;
+
/// Return true if this is an \c NSObject object with its \c NSObject
/// attribute set.
static bool isObjCNSObjectType(QualType Ty) {
@@ -2577,10 +2586,12 @@ public:
return T == getObjCSelType();
}
- bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
+ bool ObjCQualifiedIdTypesAreCompatible(const ObjCObjectPointerType *LHS,
+ const ObjCObjectPointerType *RHS,
bool ForCompare);
- bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
+ bool ObjCQualifiedClassTypesAreCompatible(const ObjCObjectPointerType *LHS,
+ const ObjCObjectPointerType *RHS);
// Check the safety of assignment from LHS to RHS
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
@@ -2802,6 +2813,9 @@ public:
/// Retrieve the context for computing mangling numbers in the given
/// DeclContext.
MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
+ enum NeedExtraManglingDecl_t { NeedExtraManglingDecl };
+ MangleNumberingContext &getManglingNumberContext(NeedExtraManglingDecl_t,
+ const Decl *D);
std::unique_ptr<MangleNumberingContext> createMangleNumberingContext() const;
diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h
index 93919bbdd52f..25c321485443 100644
--- a/include/clang/AST/ASTFwd.h
+++ b/include/clang/AST/ASTFwd.h
@@ -24,7 +24,7 @@ class Stmt;
#include "clang/AST/StmtNodes.inc"
class Type;
#define TYPE(DERIVED, BASE) class DERIVED##Type;
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
class CXXCtorInitializer;
} // end namespace clang
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 4a55c120a457..c82dcab35db5 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -87,6 +87,10 @@ class TypeSourceInfo;
using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>;
using ImportedCXXBaseSpecifierMap =
llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>;
+ using FileIDImportHandlerType =
+ std::function<void(FileID /*ToID*/, FileID /*FromID*/)>;
+
+ enum class ODRHandlingType { Conservative, Liberal };
// An ImportPath is the list of the AST nodes which we visit during an
// Import call.
@@ -210,6 +214,8 @@ class TypeSourceInfo;
};
private:
+ FileIDImportHandlerType FileIDImportHandler;
+
std::shared_ptr<ASTImporterSharedState> SharedState = nullptr;
/// The path which we go through during the import of a given AST node.
@@ -232,6 +238,8 @@ class TypeSourceInfo;
/// Whether to perform a minimal import.
bool Minimal;
+ ODRHandlingType ODRHandling;
+
/// Whether the last diagnostic came from the "from" context.
bool LastDiagFromFrom = false;
@@ -310,10 +318,20 @@ class TypeSourceInfo;
virtual ~ASTImporter();
+ /// Set a callback function for FileID import handling.
+ /// The function is invoked when a FileID is imported from the From context.
+ /// The imported FileID in the To context and the original FileID in the
+ /// From context is passed to it.
+ void setFileIDImportHandler(FileIDImportHandlerType H) {
+ FileIDImportHandler = H;
+ }
+
/// Whether the importer will perform a minimal import, creating
/// to-be-completed forward declarations when possible.
bool isMinimalImport() const { return Minimal; }
+ void setODRHandling(ODRHandlingType T) { ODRHandling = T; }
+
/// \brief Import the given object, returns the result.
///
/// \param To Import the object into this variable.
@@ -366,6 +384,20 @@ class TypeSourceInfo;
/// imported. If it does not exist nullptr is returned.
TranslationUnitDecl *GetFromTU(Decl *ToD);
+ /// Return the declaration in the "from" context from which the declaration
+ /// in the "to" context was imported. If it was not imported or of the wrong
+ /// type a null value is returned.
+ template <typename DeclT>
+ llvm::Optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const {
+ auto FromI = ImportedFromDecls.find(ToD);
+ if (FromI == ImportedFromDecls.end())
+ return {};
+ auto *FromD = dyn_cast<DeclT>(FromI->second);
+ if (!FromD)
+ return {};
+ return FromD;
+ }
+
/// Import the given declaration context from the "from"
/// AST context into the "to" AST context.
///
@@ -491,12 +523,11 @@ class TypeSourceInfo;
///
/// \param NumDecls the number of conflicting declarations in \p Decls.
///
- /// \returns the name that the newly-imported declaration should have.
- virtual DeclarationName HandleNameConflict(DeclarationName Name,
- DeclContext *DC,
- unsigned IDNS,
- NamedDecl **Decls,
- unsigned NumDecls);
+ /// \returns the name that the newly-imported declaration should have. Or
+ /// an error if we can't handle the name conflict.
+ virtual Expected<DeclarationName>
+ HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS,
+ NamedDecl **Decls, unsigned NumDecls);
/// Retrieve the context that AST nodes are being imported into.
ASTContext &getToContext() const { return ToContext; }
diff --git a/include/clang/AST/ASTImporterSharedState.h b/include/clang/AST/ASTImporterSharedState.h
index 3635a62deef0..829eb1c611c3 100644
--- a/include/clang/AST/ASTImporterSharedState.h
+++ b/include/clang/AST/ASTImporterSharedState.h
@@ -47,7 +47,7 @@ public:
ASTImporterSharedState() = default;
ASTImporterSharedState(TranslationUnitDecl &ToTU) {
- LookupTable = llvm::make_unique<ASTImporterLookupTable>(ToTU);
+ LookupTable = std::make_unique<ASTImporterLookupTable>(ToTU);
}
ASTImporterLookupTable *getLookupTable() { return LookupTable.get(); }
diff --git a/include/clang/AST/ASTNodeTraverser.h b/include/clang/AST/ASTNodeTraverser.h
index e43eacef86c6..0bb2aad553fb 100644
--- a/include/clang/AST/ASTNodeTraverser.h
+++ b/include/clang/AST/ASTNodeTraverser.h
@@ -237,6 +237,9 @@ public:
for (const auto &TP : *TPL)
Visit(TP);
+
+ if (const Expr *RC = TPL->getRequiresClause())
+ Visit(RC);
}
void
diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h
index 70e0daa08a9a..36a42070fd28 100644
--- a/include/clang/AST/ASTStructuralEquivalence.h
+++ b/include/clang/AST/ASTStructuralEquivalence.h
@@ -18,7 +18,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
-#include <deque>
+#include <queue>
#include <utility>
namespace clang {
@@ -42,14 +42,13 @@ struct StructuralEquivalenceContext {
/// AST contexts for which we are checking structural equivalence.
ASTContext &FromCtx, &ToCtx;
- /// The set of "tentative" equivalences between two canonical
- /// declarations, mapping from a declaration in the first context to the
- /// declaration in the second context that we believe to be equivalent.
- llvm::DenseMap<Decl *, Decl *> TentativeEquivalences;
+ // Queue of from-to Decl pairs that are to be checked to determine the final
+ // result of equivalence of a starting Decl pair.
+ std::queue<std::pair<Decl *, Decl *>> DeclsToCheck;
- /// Queue of declarations in the first context whose equivalence
- /// with a declaration in the second context still needs to be verified.
- std::deque<Decl *> DeclsToCheck;
+ // Set of from-to Decl pairs that are already visited during the check
+ // (are in or were once in \c DeclsToCheck) of a starting Decl pair.
+ llvm::DenseSet<std::pair<Decl *, Decl *>> VisitedDecls;
/// Declaration (from, to) pairs that are known not to be equivalent
/// (which we have already complained about).
@@ -88,14 +87,14 @@ struct StructuralEquivalenceContext {
/// Implementation functions (all static functions in
/// ASTStructuralEquivalence.cpp) must never call this function because that
/// will wreak havoc the internal state (\c DeclsToCheck and
- /// \c TentativeEquivalences members) and can cause faulty equivalent results.
+ /// \c VisitedDecls members) and can cause faulty equivalent results.
bool IsEquivalent(Decl *D1, Decl *D2);
/// Determine whether the two types are structurally equivalent.
/// Implementation functions (all static functions in
/// ASTStructuralEquivalence.cpp) must never call this function because that
/// will wreak havoc the internal state (\c DeclsToCheck and
- /// \c TentativeEquivalences members) and can cause faulty equivalent results.
+ /// \c VisitedDecls members) and can cause faulty equivalent results.
bool IsEquivalent(QualType T1, QualType T2);
/// Find the index of the given anonymous struct/union within its
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index a29a04e5d242..dd4ead2f0c2b 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -148,7 +148,7 @@ private:
#include "clang/AST/StmtNodes.inc"
NKI_Type,
#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
NKI_OMPClause,
#define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class,
#include "clang/Basic/OpenMPKinds.def"
@@ -205,7 +205,7 @@ KIND_TO_KIND_ID(OMPClause)
#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"
+#include "clang/AST/TypeNodes.inc"
#define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class)
#include "clang/Basic/OpenMPKinds.def"
#undef KIND_TO_KIND_ID
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 1fbed7ceebfa..d315dde6ed45 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
@@ -32,6 +33,7 @@
namespace clang {
class ASTContext;
+ class AttributeCommonInfo;
class IdentifierInfo;
class ObjCInterfaceDecl;
class Expr;
@@ -40,84 +42,79 @@ namespace clang {
class TypeSourceInfo;
/// Attr - This represents one attribute.
-class Attr {
-private:
- SourceRange Range;
- unsigned AttrKind : 16;
-
-protected:
- /// An index into the spelling list of an
- /// attribute defined in Attr.td file.
- unsigned SpellingListIndex : 4;
- unsigned Inherited : 1;
- unsigned IsPackExpansion : 1;
- unsigned Implicit : 1;
- // FIXME: These are properties of the attribute kind, not state for this
- // instance of the attribute.
- unsigned IsLateParsed : 1;
- unsigned InheritEvenIfAlreadyPresent : 1;
-
- void *operator new(size_t bytes) noexcept {
- llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
- }
- void operator delete(void *data) noexcept {
- llvm_unreachable("Attrs cannot be released with regular 'delete'.");
- }
-
-public:
- // Forward so that the regular new and delete do not hide global ones.
- void *operator new(size_t Bytes, ASTContext &C,
- size_t Alignment = 8) noexcept {
- return ::operator new(Bytes, C, Alignment);
- }
- void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
- return ::operator delete(Ptr, C, Alignment);
- }
+ class Attr : public AttributeCommonInfo {
+ private:
+ unsigned AttrKind : 16;
+
+ protected:
+ /// An index into the spelling list of an
+ /// attribute defined in Attr.td file.
+ unsigned Inherited : 1;
+ unsigned IsPackExpansion : 1;
+ unsigned Implicit : 1;
+ // FIXME: These are properties of the attribute kind, not state for this
+ // instance of the attribute.
+ unsigned IsLateParsed : 1;
+ unsigned InheritEvenIfAlreadyPresent : 1;
+
+ void *operator new(size_t bytes) noexcept {
+ llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
+ }
+ void operator delete(void *data) noexcept {
+ llvm_unreachable("Attrs cannot be released with regular 'delete'.");
+ }
-protected:
- Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed)
- : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
- Inherited(false), IsPackExpansion(false), Implicit(false),
- IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {}
+ public:
+ // Forward so that the regular new and delete do not hide global ones.
+ void *operator new(size_t Bytes, ASTContext &C,
+ size_t Alignment = 8) noexcept {
+ return ::operator new(Bytes, C, Alignment);
+ }
+ void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
+ return ::operator delete(Ptr, C, Alignment);
+ }
-public:
+ protected:
+ Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+ attr::Kind AK, bool IsLateParsed)
+ : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false),
+ IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed),
+ InheritEvenIfAlreadyPresent(false) {}
- attr::Kind getKind() const {
- return static_cast<attr::Kind>(AttrKind);
- }
+ public:
+ attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
- unsigned getSpellingListIndex() const { return SpellingListIndex; }
- const char *getSpelling() const;
+ unsigned getSpellingListIndex() const {
+ return getAttributeSpellingListIndex();
+ }
+ const char *getSpelling() const;
- SourceLocation getLocation() const { return Range.getBegin(); }
- SourceRange getRange() const { return Range; }
- void setRange(SourceRange R) { Range = R; }
+ SourceLocation getLocation() const { return getRange().getBegin(); }
- bool isInherited() const { return Inherited; }
+ bool isInherited() const { return Inherited; }
- /// Returns true if the attribute has been implicitly created instead
- /// of explicitly written by the user.
- bool isImplicit() const { return Implicit; }
- void setImplicit(bool I) { Implicit = I; }
+ /// Returns true if the attribute has been implicitly created instead
+ /// of explicitly written by the user.
+ bool isImplicit() const { return Implicit; }
+ void setImplicit(bool I) { Implicit = I; }
- void setPackExpansion(bool PE) { IsPackExpansion = PE; }
- bool isPackExpansion() const { return IsPackExpansion; }
+ void setPackExpansion(bool PE) { IsPackExpansion = PE; }
+ bool isPackExpansion() const { return IsPackExpansion; }
- // Clone this attribute.
- Attr *clone(ASTContext &C) const;
+ // Clone this attribute.
+ Attr *clone(ASTContext &C) const;
- bool isLateParsed() const { return IsLateParsed; }
+ bool isLateParsed() const { return IsLateParsed; }
- // Pretty print this attribute.
- void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
-};
+ // Pretty print this attribute.
+ void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
+ };
class TypeAttr : public Attr {
protected:
- TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed)
- : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
+ TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+ attr::Kind AK, bool IsLateParsed)
+ : Attr(Context, CommonInfo, AK, IsLateParsed) {}
public:
static bool classof(const Attr *A) {
@@ -128,9 +125,9 @@ public:
class StmtAttr : public Attr {
protected:
- StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed)
- : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
+ StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+ attr::Kind AK, bool IsLateParsed)
+ : Attr(Context, CommonInfo, AK, IsLateParsed) {}
public:
static bool classof(const Attr *A) {
@@ -141,9 +138,10 @@ public:
class InheritableAttr : public Attr {
protected:
- InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
- bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
- : Attr(AK, R, SpellingListIndex, IsLateParsed) {
+ InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+ attr::Kind AK, bool IsLateParsed,
+ bool InheritEvenIfAlreadyPresent)
+ : Attr(Context, CommonInfo, AK, IsLateParsed) {
this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
}
@@ -165,9 +163,10 @@ public:
class InheritableParamAttr : public InheritableAttr {
protected:
- InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ InheritableParamAttr(ASTContext &Context,
+ const AttributeCommonInfo &CommonInfo, attr::Kind AK,
bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
- : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
+ : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
@@ -182,11 +181,11 @@ public:
/// for the parameter.
class ParameterABIAttr : public InheritableParamAttr {
protected:
- ParameterABIAttr(attr::Kind AK, SourceRange R,
- unsigned SpellingListIndex, bool IsLateParsed,
+ ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+ attr::Kind AK, bool IsLateParsed,
bool InheritEvenIfAlreadyPresent)
- : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed,
- InheritEvenIfAlreadyPresent) {}
+ : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
+ InheritEvenIfAlreadyPresent) {}
public:
ParameterABI getABI() const {
diff --git a/include/clang/AST/CXXRecordDeclDefinitionBits.def b/include/clang/AST/CXXRecordDeclDefinitionBits.def
new file mode 100644
index 000000000000..bd4d8247aeca
--- /dev/null
+++ b/include/clang/AST/CXXRecordDeclDefinitionBits.def
@@ -0,0 +1,236 @@
+//===-- CXXRecordDeclDefinitionBits.def - Class definition bits -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file enumerates the various bitfields that we want to store on C++ class
+// definitions.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file CXXRecordDeclDefinitionBits.def
+///
+/// In this file, each of the bitfields representing data about a C++ class
+/// results in an expansion of the FIELD macro, which should be defined before
+/// including this file.
+///
+/// The macro have three operands:
+///
+/// Name: The name of the field, as a member of CXXRecordDecl::DefinitionData.
+///
+/// BitWidth: The width of the field in bits.
+///
+/// MergePolicy: How to behave when the value of the field is different in
+/// multiple translation units, one of:
+/// NO_MERGE: It is an ODR violation if the fields do not match.
+/// MERGE_OR: Merge the fields by ORing them together.
+
+#ifndef FIELD
+#error define FIELD before including this file
+#endif
+
+/// True if this class has any user-declared constructors.
+FIELD(UserDeclaredConstructor, 1, NO_MERGE)
+
+/// The user-declared special members which this class has.
+FIELD(UserDeclaredSpecialMembers, 6, NO_MERGE)
+
+/// True when this class is an aggregate.
+FIELD(Aggregate, 1, NO_MERGE)
+
+/// True when this class is a POD-type.
+FIELD(PlainOldData, 1, NO_MERGE)
+
+/// True when this class is empty for traits purposes, that is:
+/// * has no data members other than 0-width bit-fields and empty fields
+/// marked [[no_unique_address]]
+/// * has no virtual function/base, and
+/// * doesn't inherit from a non-empty class.
+/// Doesn't take union-ness into account.
+FIELD(Empty, 1, NO_MERGE)
+
+/// True when this class is polymorphic, i.e., has at
+/// least one virtual member or derives from a polymorphic class.
+FIELD(Polymorphic, 1, NO_MERGE)
+
+/// True when this class is abstract, i.e., has at least
+/// one pure virtual function, (that can come from a base class).
+FIELD(Abstract, 1, NO_MERGE)
+
+/// True when this class is standard-layout, per the applicable
+/// language rules (including DRs).
+FIELD(IsStandardLayout, 1, NO_MERGE)
+
+/// True when this class was standard-layout under the C++11
+/// definition.
+///
+/// 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),
+/// * has the same access control (Clause 11) for all non-static data
+/// members
+/// * has no non-standard-layout base classes,
+/// * either has no non-static data members in the most derived class and at
+/// most one base class with non-static data members, or has no base
+/// classes with non-static data members, and
+/// * has no base classes of the same type as the first non-static data
+/// member.
+FIELD(IsCXX11StandardLayout, 1, NO_MERGE)
+
+/// True when any base class has any declared non-static data
+/// members or bit-fields.
+/// This is a helper bit of state used to implement IsStandardLayout more
+/// efficiently.
+FIELD(HasBasesWithFields, 1, NO_MERGE)
+
+/// True when any base class has any declared non-static data
+/// members.
+/// This is a helper bit of state used to implement IsCXX11StandardLayout
+/// more efficiently.
+FIELD(HasBasesWithNonStaticDataMembers, 1, NO_MERGE)
+
+/// True when there are private non-static data members.
+FIELD(HasPrivateFields, 1, NO_MERGE)
+
+/// True when there are protected non-static data members.
+FIELD(HasProtectedFields, 1, NO_MERGE)
+
+/// True when there are private non-static data members.
+FIELD(HasPublicFields, 1, NO_MERGE)
+
+/// True if this class (or any subobject) has mutable fields.
+FIELD(HasMutableFields, 1, NO_MERGE)
+
+/// True if this class (or any nested anonymous struct or union)
+/// has variant members.
+FIELD(HasVariantMembers, 1, NO_MERGE)
+
+/// True if there no non-field members declared by the user.
+FIELD(HasOnlyCMembers, 1, NO_MERGE)
+
+/// True if any field has an in-class initializer, including those
+/// within anonymous unions or structs.
+FIELD(HasInClassInitializer, 1, NO_MERGE)
+
+/// 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.
+FIELD(HasUninitializedReferenceMember, 1, NO_MERGE)
+
+/// True if any non-mutable field whose type doesn't have a user-
+/// provided default ctor also doesn't have an in-class initializer.
+FIELD(HasUninitializedFields, 1, NO_MERGE)
+
+/// True if there are any member using-declarations that inherit
+/// constructors from a base class.
+FIELD(HasInheritedConstructor, 1, NO_MERGE)
+
+/// True if there are any member using-declarations named
+/// 'operator='.
+FIELD(HasInheritedAssignment, 1, NO_MERGE)
+
+/// These flags are \c true if a defaulted corresponding special
+/// member can't be fully analyzed without performing overload resolution.
+/// @{
+FIELD(NeedOverloadResolutionForCopyConstructor, 1, NO_MERGE)
+FIELD(NeedOverloadResolutionForMoveConstructor, 1, NO_MERGE)
+FIELD(NeedOverloadResolutionForMoveAssignment, 1, NO_MERGE)
+FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE)
+/// @}
+
+/// These flags are \c true if an implicit defaulted corresponding
+/// special member would be defined as deleted.
+/// @{
+FIELD(DefaultedCopyConstructorIsDeleted, 1, NO_MERGE)
+FIELD(DefaultedMoveConstructorIsDeleted, 1, NO_MERGE)
+FIELD(DefaultedMoveAssignmentIsDeleted, 1, NO_MERGE)
+FIELD(DefaultedDestructorIsDeleted, 1, NO_MERGE)
+/// @}
+
+/// The trivial special members which this class has, per
+/// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
+/// C++11 [class.dtor]p5, or would have if the member were not suppressed.
+///
+/// This excludes any user-declared but not user-provided special members
+/// which have been declared but not yet defined.
+FIELD(HasTrivialSpecialMembers, 6, MERGE_OR)
+
+/// These bits keep track of the triviality of special functions for the
+/// purpose of calls. Only the bits corresponding to SMF_CopyConstructor,
+/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
+FIELD(HasTrivialSpecialMembersForCall, 6, MERGE_OR)
+
+/// The declared special members of this class which are known to be
+/// non-trivial.
+///
+/// This excludes any user-declared but not user-provided special members
+/// which have been declared but not yet defined, and any implicit special
+/// members which have not yet been declared.
+FIELD(DeclaredNonTrivialSpecialMembers, 6, MERGE_OR)
+
+/// These bits keep track of the declared special members that are
+/// non-trivial for the purpose of calls.
+/// Only the bits corresponding to SMF_CopyConstructor,
+/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
+FIELD(DeclaredNonTrivialSpecialMembersForCall, 6, MERGE_OR)
+
+/// True when this class has a destructor with no semantic effect.
+FIELD(HasIrrelevantDestructor, 1, NO_MERGE)
+
+/// True when this class has at least one user-declared constexpr
+/// constructor which is neither the copy nor move constructor.
+FIELD(HasConstexprNonCopyMoveConstructor, 1, MERGE_OR)
+
+/// True if this class has a (possibly implicit) defaulted default
+/// constructor.
+FIELD(HasDefaultedDefaultConstructor, 1, MERGE_OR)
+
+/// True if a defaulted default constructor for this class would
+/// be constexpr.
+FIELD(DefaultedDefaultConstructorIsConstexpr, 1, NO_MERGE)
+
+/// 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.
+FIELD(HasConstexprDefaultConstructor, 1, MERGE_OR)
+
+/// True if a defaulted destructor for this class would be constexpr.
+FIELD(DefaultedDestructorIsConstexpr, 1, NO_MERGE)
+
+/// True when this class contains at least one non-static data
+/// member or base class of non-literal or volatile type.
+FIELD(HasNonLiteralTypeFieldsOrBases, 1, NO_MERGE)
+
+/// Whether we have a C++11 user-provided default constructor (not
+/// explicitly deleted or defaulted).
+FIELD(UserProvidedDefaultConstructor, 1, NO_MERGE)
+
+/// The special members which have been declared for this class,
+/// either by the user or implicitly.
+FIELD(DeclaredSpecialMembers, 6, MERGE_OR)
+
+/// Whether an implicit copy constructor could have a const-qualified
+/// parameter, for initializing virtual bases and for other subobjects.
+FIELD(ImplicitCopyConstructorCanHaveConstParamForVBase, 1, NO_MERGE)
+FIELD(ImplicitCopyConstructorCanHaveConstParamForNonVBase, 1, NO_MERGE)
+
+/// Whether an implicit copy assignment operator would have a
+/// const-qualified parameter.
+FIELD(ImplicitCopyAssignmentHasConstParam, 1, NO_MERGE)
+
+/// Whether any declared copy constructor has a const-qualified
+/// parameter.
+FIELD(HasDeclaredCopyConstructorWithConstParam, 1, MERGE_OR)
+
+/// Whether any declared copy assignment operator has either a
+/// const-qualified reference parameter or a non-reference parameter.
+FIELD(HasDeclaredCopyAssignmentWithConstParam, 1, MERGE_OR)
+
+#undef FIELD
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 37f489c7708a..f14d3abf71e5 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_AST_CHARUNITS_H
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
@@ -177,6 +178,10 @@ namespace clang {
/// getQuantity - Get the raw integer representation of this quantity.
QuantityType getQuantity() const { return Quantity; }
+ /// getAsAlign - Returns Quantity as a valid llvm::Align,
+ /// Beware llvm::Align assumes power of two 8-bit bytes.
+ llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
+
/// alignTo - Returns the next integer (mod 2**64) that is
/// greater than or equal to this quantity and is a multiple of \p Align.
/// Align must be non-zero.
diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td
index 958ee032e71f..3b0d1603d407 100644
--- a/include/clang/AST/CommentCommands.td
+++ b/include/clang/AST/CommentCommands.td
@@ -139,6 +139,7 @@ def Post : BlockCommand<"post">;
def Pre : BlockCommand<"pre">;
def Remark : BlockCommand<"remark">;
def Remarks : BlockCommand<"remarks">;
+def Retval : BlockCommand<"retval">;
def Sa : BlockCommand<"sa">;
def See : BlockCommand<"see">;
def Since : BlockCommand<"since">;
diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
index 9ddbb7d31d99..138fdaca0ff6 100644
--- a/include/clang/AST/CommentLexer.h
+++ b/include/clang/AST/CommentLexer.h
@@ -352,8 +352,7 @@ public:
void lex(Token &T);
- StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr,
- bool *Invalid = nullptr) const;
+ StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr) const;
};
} // end namespace comments
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 02742801f37c..ce674e09c44d 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -310,6 +310,14 @@ public:
void printQualifiedName(raw_ostream &OS) const;
void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const;
+ /// Print only the nested name specifier part of a fully-qualified name,
+ /// including the '::' at the end. E.g.
+ /// when `printQualifiedName(D)` prints "A::B::i",
+ /// this function prints "A::B::".
+ void printNestedNameSpecifier(raw_ostream &OS) const;
+ void printNestedNameSpecifier(raw_ostream &OS,
+ const PrintingPolicy &Policy) const;
+
// FIXME: Remove string version.
std::string getQualifiedNameAsString() const;
@@ -800,12 +808,19 @@ struct EvaluatedStmt {
/// valid if CheckedICE is true.
bool IsICE : 1;
+ /// Whether this variable is known to have constant destruction. That is,
+ /// whether running the destructor on the initial value is a side-effect
+ /// (and doesn't inspect any state that might have changed during program
+ /// execution). This is currently only computed if the destructor is
+ /// non-trivial.
+ bool HasConstantDestruction : 1;
+
Stmt *Value;
APValue Evaluated;
- EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
- CheckingICE(false), IsICE(false) {}
-
+ EvaluatedStmt()
+ : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
+ CheckingICE(false), IsICE(false), HasConstantDestruction(false) {}
};
/// Represents a variable declaration or definition.
@@ -1226,6 +1241,14 @@ public:
void setInit(Expr *I);
+ /// Get the initializing declaration of this variable, if any. This is
+ /// usually the definition, except that for a static data member it can be
+ /// the in-class declaration.
+ VarDecl *getInitializingDeclaration();
+ const VarDecl *getInitializingDeclaration() const {
+ return const_cast<VarDecl *>(this)->getInitializingDeclaration();
+ }
+
/// Determine whether this variable's value might be usable in a
/// constant expression, according to the relevant language standard.
/// This only checks properties of the declaration, and does not check
@@ -1251,6 +1274,14 @@ public:
/// to untyped APValue if the value could not be evaluated.
APValue *getEvaluatedValue() const;
+ /// Evaluate the destruction of this variable to determine if it constitutes
+ /// constant destruction.
+ ///
+ /// \pre isInitICE()
+ /// \return \c true if this variable has constant destruction, \c false if
+ /// not.
+ bool evaluateDestruction(SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
+
/// Determines whether it is already known whether the
/// initializer is an integral constant expression or not.
bool isInitKnownICE() const;
@@ -1489,9 +1520,14 @@ public:
// has no definition within this source file.
bool isKnownToBeDefined() const;
- /// Do we need to emit an exit-time destructor for this variable?
+ /// Is destruction of this variable entirely suppressed? If so, the variable
+ /// need not have a usable destructor at all.
bool isNoDestroy(const ASTContext &) const;
+ /// Do we need to emit an exit-time destructor for this variable, and if so,
+ /// what kind?
+ QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const;
+
// 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; }
@@ -4078,13 +4114,9 @@ public:
void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
bool CapturesCXXThis);
- unsigned getBlockManglingNumber() const {
- return ManglingNumber;
- }
+ unsigned getBlockManglingNumber() const { return ManglingNumber; }
- Decl *getBlockManglingContextDecl() const {
- return ManglingContextDecl;
- }
+ Decl *getBlockManglingContextDecl() const { return ManglingContextDecl; }
void setBlockMangling(unsigned Number, Decl *Ctx) {
ManglingNumber = Number;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index d64d0cb425db..01c2f1809771 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -959,7 +959,7 @@ public:
/// as this declaration, or NULL if there is no previous declaration.
Decl *getPreviousDecl() { return getPreviousDeclImpl(); }
- /// Retrieve the most recent declaration that declares the same entity
+ /// Retrieve the previous declaration that declares the same entity
/// as this declaration, or NULL if there is no previous declaration.
const Decl *getPreviousDecl() const {
return const_cast<Decl *>(this)->getPreviousDeclImpl();
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 7add83f89624..66212f72b787 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -42,6 +42,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
@@ -73,52 +74,6 @@ class TemplateDecl;
class TemplateParameterList;
class UsingDecl;
-/// Represents any kind of function declaration, whether it is a
-/// concrete function or a function template.
-class AnyFunctionDecl {
- NamedDecl *Function;
-
- AnyFunctionDecl(NamedDecl *ND) : Function(ND) {}
-
-public:
- AnyFunctionDecl(FunctionDecl *FD) : Function(FD) {}
- AnyFunctionDecl(FunctionTemplateDecl *FTD);
-
- /// Implicily converts any function or function template into a
- /// named declaration.
- operator NamedDecl *() const { return Function; }
-
- /// Retrieve the underlying function or function template.
- NamedDecl *get() const { return Function; }
-
- static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
- return AnyFunctionDecl(ND);
- }
-};
-
-} // namespace clang
-
-namespace llvm {
-
- // Provide PointerLikeTypeTraits for non-cvr pointers.
- template<>
- struct PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
- static void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
- return F.get();
- }
-
- static ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
- return ::clang::AnyFunctionDecl::getFromNamedDecl(
- static_cast< ::clang::NamedDecl*>(P));
- }
-
- enum { NumLowBitsAvailable = 2 };
- };
-
-} // namespace llvm
-
-namespace clang {
-
/// Represents an access specifier followed by colon ':'.
///
/// An objects of this class represents sugar for the syntactic occurrence
@@ -322,207 +277,9 @@ class CXXRecordDecl : public RecordDecl {
};
struct DefinitionData {
- /// True if this class has any user-declared constructors.
- unsigned UserDeclaredConstructor : 1;
-
- /// The user-declared special members which this class has.
- unsigned UserDeclaredSpecialMembers : 6;
-
- /// True when this class is an aggregate.
- unsigned Aggregate : 1;
-
- /// True when this class is a POD-type.
- unsigned PlainOldData : 1;
-
- /// True when this class is empty for traits purposes, that is:
- /// * has no data members other than 0-width bit-fields and empty fields
- /// marked [[no_unique_address]]
- /// * has no virtual function/base, and
- /// * doesn't inherit from a non-empty class.
- /// Doesn't take union-ness into account.
- unsigned Empty : 1;
-
- /// True when this class is polymorphic, i.e., has at
- /// least one virtual member or derives from a polymorphic class.
- unsigned Polymorphic : 1;
-
- /// True when this class is abstract, i.e., has at least
- /// one pure virtual function, (that can come from a base class).
- unsigned Abstract : 1;
-
- /// True when this class is standard-layout, per the applicable
- /// language rules (including DRs).
- unsigned IsStandardLayout : 1;
-
- /// True when this class was standard-layout under the C++11
- /// definition.
- ///
- /// 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),
- /// * has the same access control (Clause 11) for all non-static data
- /// members
- /// * has no non-standard-layout base classes,
- /// * either has no non-static data members in the most derived class and at
- /// most one base class with non-static data members, or has no base
- /// classes with non-static data members, and
- /// * has no base classes of the same type as the first non-static data
- /// member.
- unsigned IsCXX11StandardLayout : 1;
-
- /// True when any base class has any declared non-static data
- /// members or bit-fields.
- /// This is a helper bit of state used to implement IsStandardLayout more
- /// efficiently.
- unsigned HasBasesWithFields : 1;
-
- /// True when any base class has any declared non-static data
- /// members.
- /// This is a helper bit of state used to implement IsCXX11StandardLayout
- /// more efficiently.
- unsigned HasBasesWithNonStaticDataMembers : 1;
-
- /// True when there are private non-static data members.
- unsigned HasPrivateFields : 1;
-
- /// True when there are protected non-static data members.
- unsigned HasProtectedFields : 1;
-
- /// True when there are private non-static data members.
- unsigned HasPublicFields : 1;
-
- /// True if this class (or any subobject) has mutable fields.
- unsigned HasMutableFields : 1;
-
- /// True if this class (or any nested anonymous struct or union)
- /// has variant members.
- unsigned HasVariantMembers : 1;
-
- /// True if there no non-field members declared by the user.
- unsigned HasOnlyCMembers : 1;
-
- /// True if any field has an in-class initializer, including those
- /// within anonymous unions or structs.
- unsigned HasInClassInitializer : 1;
-
- /// 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.
- unsigned HasUninitializedReferenceMember : 1;
-
- /// True if any non-mutable field whose type doesn't have a user-
- /// provided default ctor also doesn't have an in-class initializer.
- unsigned HasUninitializedFields : 1;
-
- /// True if there are any member using-declarations that inherit
- /// constructors from a base class.
- unsigned HasInheritedConstructor : 1;
-
- /// True if there are any member using-declarations named
- /// 'operator='.
- unsigned HasInheritedAssignment : 1;
-
- /// These flags are \c true if a defaulted corresponding special
- /// member can't be fully analyzed without performing overload resolution.
- /// @{
- unsigned NeedOverloadResolutionForCopyConstructor : 1;
- unsigned NeedOverloadResolutionForMoveConstructor : 1;
- unsigned NeedOverloadResolutionForMoveAssignment : 1;
- unsigned NeedOverloadResolutionForDestructor : 1;
- /// @}
-
- /// These flags are \c true if an implicit defaulted corresponding
- /// special member would be defined as deleted.
- /// @{
- unsigned DefaultedCopyConstructorIsDeleted : 1;
- unsigned DefaultedMoveConstructorIsDeleted : 1;
- unsigned DefaultedMoveAssignmentIsDeleted : 1;
- unsigned DefaultedDestructorIsDeleted : 1;
- /// @}
-
- /// The trivial special members which this class has, per
- /// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
- /// C++11 [class.dtor]p5, or would have if the member were not suppressed.
- ///
- /// This excludes any user-declared but not user-provided special members
- /// which have been declared but not yet defined.
- unsigned HasTrivialSpecialMembers : 6;
-
- /// These bits keep track of the triviality of special functions for the
- /// purpose of calls. Only the bits corresponding to SMF_CopyConstructor,
- /// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
- unsigned HasTrivialSpecialMembersForCall : 6;
-
- /// The declared special members of this class which are known to be
- /// non-trivial.
- ///
- /// This excludes any user-declared but not user-provided special members
- /// which have been declared but not yet defined, and any implicit special
- /// members which have not yet been declared.
- unsigned DeclaredNonTrivialSpecialMembers : 6;
-
- /// These bits keep track of the declared special members that are
- /// non-trivial for the purpose of calls.
- /// Only the bits corresponding to SMF_CopyConstructor,
- /// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
- unsigned DeclaredNonTrivialSpecialMembersForCall : 6;
-
- /// True when this class has a destructor with no semantic effect.
- unsigned HasIrrelevantDestructor : 1;
-
- /// True when this class has at least one user-declared constexpr
- /// constructor which is neither the copy nor move constructor.
- unsigned HasConstexprNonCopyMoveConstructor : 1;
-
- /// True if this class has a (possibly implicit) defaulted default
- /// constructor.
- unsigned HasDefaultedDefaultConstructor : 1;
-
- /// True if a defaulted default constructor for this class would
- /// be constexpr.
- unsigned DefaultedDefaultConstructorIsConstexpr : 1;
-
- /// 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.
- unsigned HasConstexprDefaultConstructor : 1;
-
- /// True when this class contains at least one non-static data
- /// member or base class of non-literal or volatile type.
- unsigned HasNonLiteralTypeFieldsOrBases : 1;
-
- /// True when visible conversion functions are already computed
- /// and are available.
- unsigned ComputedVisibleConversions : 1;
-
- /// Whether we have a C++11 user-provided default constructor (not
- /// explicitly deleted or defaulted).
- unsigned UserProvidedDefaultConstructor : 1;
-
- /// The special members which have been declared for this class,
- /// either by the user or implicitly.
- unsigned DeclaredSpecialMembers : 6;
-
- /// Whether an implicit copy constructor could have a const-qualified
- /// parameter, for initializing virtual bases and for other subobjects.
- unsigned ImplicitCopyConstructorCanHaveConstParamForVBase : 1;
- unsigned ImplicitCopyConstructorCanHaveConstParamForNonVBase : 1;
-
- /// Whether an implicit copy assignment operator would have a
- /// const-qualified parameter.
- unsigned ImplicitCopyAssignmentHasConstParam : 1;
-
- /// Whether any declared copy constructor has a const-qualified
- /// parameter.
- unsigned HasDeclaredCopyConstructorWithConstParam : 1;
-
- /// Whether any declared copy assignment operator has either a
- /// const-qualified reference parameter or a non-reference parameter.
- unsigned HasDeclaredCopyAssignmentWithConstParam : 1;
+ #define FIELD(Name, Width, Merge) \
+ unsigned Name : Width;
+ #include "CXXRecordDeclDefinitionBits.def"
/// Whether this class describes a C++ lambda.
unsigned IsLambda : 1;
@@ -530,6 +287,10 @@ class CXXRecordDecl : public RecordDecl {
/// Whether we are currently parsing base specifiers.
unsigned IsParsingBaseSpecifiers : 1;
+ /// True when visible conversion functions are already computed
+ /// and are available.
+ unsigned ComputedVisibleConversions : 1;
+
unsigned HasODRHash : 1;
/// A hash of parts of the class to help in ODR checking.
@@ -628,9 +389,12 @@ class CXXRecordDecl : public RecordDecl {
/// The number of explicit captures in this lambda.
unsigned NumExplicitCaptures : 13;
+ /// Has known `internal` linkage.
+ unsigned HasKnownInternalLinkage : 1;
+
/// The number used to indicate this lambda expression for name
/// mangling in the Itanium C++ ABI.
- unsigned ManglingNumber = 0;
+ unsigned ManglingNumber : 31;
/// The declaration that provides context for this lambda, if the
/// actual DeclContext does not suffice. This is used for lambdas that
@@ -645,12 +409,12 @@ class CXXRecordDecl : public RecordDecl {
/// The type of the call method.
TypeSourceInfo *MethodTyInfo;
- LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
- bool Dependent, bool IsGeneric,
- LambdaCaptureDefault CaptureDefault)
- : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
- CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(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), HasKnownInternalLinkage(0), ManglingNumber(0),
+ MethodTyInfo(Info) {
IsLambda = true;
// C++1z [expr.prim.lambda]p4:
@@ -1214,6 +978,10 @@ public:
/// if this is a closure type.
CXXMethodDecl *getLambdaCallOperator() const;
+ /// Retrieve the dependent lambda call operator of the closure type
+ /// if this is a templated closure type.
+ FunctionTemplateDecl *getDependentLambdaCallOperator() const;
+
/// 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.
@@ -1398,7 +1166,8 @@ public:
/// would be constexpr.
bool defaultedDefaultConstructorIsConstexpr() const {
return data().DefaultedDefaultConstructorIsConstexpr &&
- (!isUnion() || hasInClassInitializer() || !hasVariantMembers());
+ (!isUnion() || hasInClassInitializer() || !hasVariantMembers() ||
+ getASTContext().getLangOpts().CPlusPlus2a);
}
/// Determine whether this class has a constexpr default constructor.
@@ -1486,6 +1255,16 @@ public:
!(data().HasTrivialSpecialMembers & SMF_MoveAssignment));
}
+ /// Determine whether a defaulted default constructor for this class
+ /// would be constexpr.
+ bool defaultedDestructorIsConstexpr() const {
+ return data().DefaultedDestructorIsConstexpr &&
+ getASTContext().getLangOpts().CPlusPlus2a;
+ }
+
+ /// Determine whether this class has a constexpr destructor.
+ bool hasConstexprDestructor() const;
+
/// Determine whether this class has a trivial destructor
/// (C++ [class.dtor]p3)
bool hasTrivialDestructor() const {
@@ -1577,8 +1356,10 @@ public:
///
/// Only in C++17 and beyond, are lambdas literal types.
bool isLiteral() const {
- return hasTrivialDestructor() &&
- (!isLambda() || getASTContext().getLangOpts().CPlusPlus17) &&
+ ASTContext &Ctx = getASTContext();
+ return (Ctx.getLangOpts().CPlusPlus2a ? hasConstexprDestructor()
+ : hasTrivialDestructor()) &&
+ (!isLambda() || Ctx.getLangOpts().CPlusPlus17) &&
!hasNonLiteralTypeFieldsOrBases() &&
(isAggregate() || isLambda() ||
hasConstexprNonCopyMoveConstructor() ||
@@ -1927,6 +1708,13 @@ public:
return getLambdaData().ManglingNumber;
}
+ /// The lambda is known to has internal linkage no matter whether it has name
+ /// mangling number.
+ bool hasKnownLambdaInternalLinkage() const {
+ assert(isLambda() && "Not a lambda closure type!");
+ return getLambdaData().HasKnownInternalLinkage;
+ }
+
/// Retrieve the declaration that provides additional context for a
/// lambda, when the normal declaration context is not specific enough.
///
@@ -1940,9 +1728,12 @@ public:
/// Set the mangling number and context declaration for a lambda
/// class.
- void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
+ void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl,
+ bool HasKnownInternalLinkage = false) {
+ assert(isLambda() && "Not a lambda closure type!");
getLambdaData().ManglingNumber = ManglingNumber;
getLambdaData().ContextDecl = ContextDecl;
+ getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage;
}
/// Returns the inheritance model used for this record.
@@ -2265,7 +2056,7 @@ public:
const CXXRecordDecl *Decl);
Qualifiers getMethodQualifiers() const {
- return getType()->getAs<FunctionProtoType>()->getMethodQuals();
+ return getType()->castAs<FunctionProtoType>()->getMethodQuals();
}
/// Retrieve the ref-qualifier associated with this method.
@@ -2280,7 +2071,7 @@ public:
/// };
/// @endcode
RefQualifierKind getRefQualifier() const {
- return getType()->getAs<FunctionProtoType>()->getRefQualifier();
+ return getType()->castAs<FunctionProtoType>()->getRefQualifier();
}
bool hasInlineBody() const;
@@ -2600,9 +2391,9 @@ class CXXConstructorDecl final
ExplicitSpecifier getExplicitSpecifierInternal() const {
if (CXXConstructorDeclBits.HasTrailingExplicitSpecifier)
- return *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>();
+ return *getTrailingObjects<ExplicitSpecifier>();
return ExplicitSpecifier(
- nullptr, getCanonicalDecl()->CXXConstructorDeclBits.IsSimpleExplicit
+ nullptr, CXXConstructorDeclBits.IsSimpleExplicit
? ExplicitSpecKind::ResolvedTrue
: ExplicitSpecKind::ResolvedFalse);
}
@@ -2643,10 +2434,10 @@ public:
InheritedConstructor Inherited = InheritedConstructor());
ExplicitSpecifier getExplicitSpecifier() {
- return getExplicitSpecifierInternal();
+ return getCanonicalDecl()->getExplicitSpecifierInternal();
}
const ExplicitSpecifier getExplicitSpecifier() const {
- return getExplicitSpecifierInternal();
+ return getCanonicalDecl()->getExplicitSpecifierInternal();
}
/// Return true if the declartion is already resolved to be explicit.
@@ -2847,9 +2638,9 @@ class CXXDestructorDecl : public CXXMethodDecl {
CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, bool isInline,
- bool isImplicitlyDeclared)
+ bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind)
: CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
- SC_None, isInline, CSK_unspecified, SourceLocation()) {
+ SC_None, isInline, ConstexprKind, SourceLocation()) {
setImplicit(isImplicitlyDeclared);
}
@@ -2859,9 +2650,9 @@ public:
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo* TInfo,
- bool isInline,
- bool isImplicitlyDeclared);
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isImplicitlyDeclared,
+ ConstexprSpecKind ConstexprKind);
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
@@ -2934,7 +2725,7 @@ public:
/// Returns the type that this conversion function is converting to.
QualType getConversionType() const {
- return getType()->getAs<FunctionType>()->getReturnType();
+ return getType()->castAs<FunctionType>()->getReturnType();
}
/// Determine whether this conversion function is a conversion from
@@ -2971,8 +2762,10 @@ public:
/// 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
+ lang_c = llvm::dwarf::DW_LANG_C,
+ lang_cxx = llvm::dwarf::DW_LANG_C_plus_plus,
+ lang_cxx_11 = llvm::dwarf::DW_LANG_C_plus_plus_11,
+ lang_cxx_14 = llvm::dwarf::DW_LANG_C_plus_plus_14
};
private:
@@ -3469,12 +3262,6 @@ public:
return IsVirtual;
}
- /// Get the constructor or constructor template in the derived class
- /// correspnding to this using shadow declaration, if it has been implicitly
- /// declared already.
- CXXConstructorDecl *getConstructor() const;
- void setConstructor(NamedDecl *Ctor);
-
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ConstructorUsingShadow; }
};
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 235b31c1c312..ec14adc7de97 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -168,6 +168,16 @@ public:
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
}
+ /// \brief All associated constraints derived from this template parameter
+ /// list, including the requires clause and any constraints derived from
+ /// constrained-parameters.
+ ///
+ /// The constraints in the resulting list are to be treated as if in a
+ /// conjunction ("and").
+ void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
+
+ bool hasAssociatedConstraints() const;
+
SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -369,33 +379,7 @@ public:
// Kinds of Templates
//===----------------------------------------------------------------------===//
-/// Stores the template parameter list and associated constraints for
-/// \c TemplateDecl objects that track associated constraints.
-class ConstrainedTemplateDeclInfo {
- friend TemplateDecl;
-
-public:
- ConstrainedTemplateDeclInfo() = default;
-
- TemplateParameterList *getTemplateParameters() const {
- return TemplateParams;
- }
-
- Expr *getAssociatedConstraints() const { return AssociatedConstraints; }
-
-protected:
- void setTemplateParameters(TemplateParameterList *TParams) {
- TemplateParams = TParams;
- }
-
- void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; }
-
- TemplateParameterList *TemplateParams = nullptr;
- Expr *AssociatedConstraints = nullptr;
-};
-
-
-/// The base class of all kinds of template declarations (e.g.,
+/// \brief The base class of all kinds of template declarations (e.g.,
/// class, function, etc.).
///
/// The TemplateDecl class stores the list of template parameters and a
@@ -404,54 +388,32 @@ class TemplateDecl : public NamedDecl {
void anchor() override;
protected:
+ // Construct a template decl with name, parameters, and templated element.
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl);
+
// Construct a template decl with the given name and parameters.
// Used when there is no templated element (e.g., for tt-params).
- TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
- SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
- TemplateParams(CTDI) {
- this->setTemplateParameters(Params);
- }
-
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params)
- : TemplateDecl(nullptr, DK, DC, L, Name, Params) {}
-
- // Construct a template decl with name, parameters, and templated element.
- TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
- SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
- TemplateParams(CTDI) {
- this->setTemplateParameters(Params);
- }
-
- TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {}
+ : TemplateDecl(DK, DC, L, Name, Params, nullptr) {}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
- const auto *const CTDI =
- TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
- return CTDI ? CTDI->getTemplateParameters()
- : TemplateParams.get<TemplateParameterList *>();
+ return TemplateParams;
}
- /// Get the constraint-expression from the associated requires-clause (if any)
- const Expr *getRequiresClause() const {
- const TemplateParameterList *const TP = getTemplateParameters();
- return TP ? TP->getRequiresClause() : nullptr;
- }
+ /// \brief Get the total constraint-expression associated with this template,
+ /// including constraint-expressions derived from the requires-clause,
+ /// trailing requires-clause (for functions and methods) and constrained
+ /// template parameters.
+ void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
- Expr *getAssociatedConstraints() const {
- const auto *const C = cast<TemplateDecl>(getCanonicalDecl());
- const auto *const CTDI =
- C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
- return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
- }
+ bool hasAssociatedConstraints() const;
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
@@ -470,29 +432,10 @@ public:
protected:
NamedDecl *TemplatedDecl;
-
- /// The template parameter list and optional requires-clause
- /// associated with this declaration; alternatively, a
- /// \c ConstrainedTemplateDeclInfo if the associated constraints of the
- /// template are being tracked by this particular declaration.
- llvm::PointerUnion<TemplateParameterList *,
- ConstrainedTemplateDeclInfo *>
- TemplateParams;
+ TemplateParameterList *TemplateParams;
void setTemplateParameters(TemplateParameterList *TParams) {
- if (auto *const CTDI =
- TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) {
- CTDI->setTemplateParameters(TParams);
- } else {
- TemplateParams = TParams;
- }
- }
-
- void setAssociatedConstraints(Expr *AC) {
- assert(isCanonicalDecl() &&
- "Attaching associated constraints to non-canonical Decl");
- TemplateParams.get<ConstrainedTemplateDeclInfo *>()
- ->setAssociatedConstraints(AC);
+ TemplateParams = TParams;
}
public:
@@ -889,17 +832,10 @@ protected:
virtual CommonBase *newCommon(ASTContext &C) const = 0;
// Construct a template decl with name, parameters, and templated element.
- RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK,
- ASTContext &C, DeclContext *DC, SourceLocation L,
- DeclarationName Name, TemplateParameterList *Params,
- NamedDecl *Decl)
- : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C)
- {}
-
RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
- : RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {}
+ : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C) {}
public:
friend class ASTDeclReader;
@@ -2026,6 +1962,20 @@ public:
return TemplateParams;
}
+ /// \brief All associated constraints of this partial specialization,
+ /// including the requires clause and any constraints derived from
+ /// constrained-parameters.
+ ///
+ /// The constraints in the resulting list are to be treated as if in a
+ /// conjunction ("and").
+ void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
+ TemplateParams->getAssociatedConstraints(AC);
+ }
+
+ bool hasAssociatedConstraints() const {
+ return TemplateParams->hasAssociatedConstraints();
+ }
+
/// Get the template arguments as written.
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
@@ -2145,16 +2095,10 @@ protected:
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
getPartialSpecializations();
- ClassTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, ASTContext &C,
- DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : RedeclarableTemplateDecl(CTDI, ClassTemplate, C, DC, L, Name, Params,
- Decl) {}
-
ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl)
- : ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {}
+ : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
CommonBase *newCommon(ASTContext &C) const override;
@@ -2180,14 +2124,12 @@ public:
return getTemplatedDecl()->isThisDeclarationADefinition();
}
- // FIXME: remove default argument for AssociatedConstraints
- /// Create a class template node.
+ /// \brief Create a class template node.
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
- NamedDecl *Decl,
- Expr *AssociatedConstraints = nullptr);
+ NamedDecl *Decl);
/// Create an empty class template node.
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2527,10 +2469,6 @@ public:
}
};
-/// Implementation of inline functions that require the template declarations
-inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
- : Function(FTD) {}
-
/// Represents a variable template specialization, which refers to
/// a variable template with a given set of template arguments.
///
@@ -2866,7 +2804,21 @@ public:
return ArgsAsWritten;
}
- /// Retrieve the member variable template partial specialization from
+ /// \brief All associated constraints of this partial specialization,
+ /// including the requires clause and any constraints derived from
+ /// constrained-parameters.
+ ///
+ /// The constraints in the resulting list are to be treated as if in a
+ /// conjunction ("and").
+ void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
+ TemplateParams->getAssociatedConstraints(AC);
+ }
+
+ bool hasAssociatedConstraints() const {
+ return TemplateParams->hasAssociatedConstraints();
+ }
+
+ /// \brief Retrieve the member variable template partial specialization from
/// which this particular variable template partial specialization was
/// instantiated.
///
@@ -3095,11 +3047,9 @@ class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
protected:
Expr *ConstraintExpr;
- ConceptDecl(DeclContext *DC,
- SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params,
- Expr *ConstraintExpr)
- : TemplateDecl(nullptr, Concept, DC, L, Name, Params),
+ ConceptDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, Expr *ConstraintExpr)
+ : TemplateDecl(Concept, DC, L, Name, Params),
ConstraintExpr(ConstraintExpr) {};
public:
static ConceptDecl *Create(ASTContext &C, DeclContext *DC,
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index d44a815c8699..ffa7d4db96a4 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -906,6 +906,11 @@ public:
return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
}
+ /// Checks that the two Expr's will refer to the same value as a comparison
+ /// operand. The caller must ensure that the values referenced by the Expr's
+ /// are not modified between E1 and E2 or the result my be invalid.
+ static bool isSameComparisonOperand(const Expr* E1, const Expr* E2);
+
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
T->getStmtClass() <= lastExprConstant;
@@ -2619,9 +2624,8 @@ public:
/// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr):
///
/// \code{.cpp}
- /// llvm::AlignedCharArray<alignof(CallExpr),
- /// sizeof(CallExpr) + sizeof(Stmt *)> Buffer;
- /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.buffer, etc);
+ /// alignas(CallExpr) char Buffer[sizeof(CallExpr) + sizeof(Stmt *)];
+ /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer, etc);
/// \endcode
static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
ExprValueKind VK, SourceLocation RParenLoc,
@@ -4496,6 +4500,8 @@ public:
// Explicit InitListExpr's originate from source code (and have valid source
// locations). Implicit InitListExpr's are created by the semantic analyzer.
+ // FIXME: This is wrong; InitListExprs created by semantic analysis have
+ // valid source locations too!
bool isExplicit() const {
return LBraceLoc.isValid() && RBraceLoc.isValid();
}
@@ -4830,6 +4836,10 @@ public:
SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; }
void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; }
+ /// Whether this designated initializer should result in direct-initialization
+ /// of the designated subobject (eg, '{.foo{1, 2, 3}}').
+ bool isDirectInit() const { return EqualOrColonLoc.isInvalid(); }
+
/// Determines whether this designated initializer used the
/// deprecated GNU syntax for designated initializers.
bool usesGNUSyntax() const { return GNUSyntax; }
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 28ed6cdfde14..2152e108c7cb 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -17,6 +17,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
@@ -185,15 +186,20 @@ public:
static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
EmptyShell Empty);
- /// Retrieves the implicit object argument for the member call.
+ /// Retrieve 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.
+ /// Retrieve the type of the object argument.
+ ///
+ /// Note that this always returns a non-pointer type.
+ QualType getObjectType() const;
+
+ /// Retrieve the declaration of the called method.
CXXMethodDecl *getMethodDecl() const;
- /// Retrieves the CXXRecordDecl for the underlying type of
+ /// Retrieve 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
@@ -248,6 +254,96 @@ public:
}
};
+/// A rewritten comparison expression that was originally written using
+/// operator syntax.
+///
+/// In C++20, the following rewrites are performed:
+/// - <tt>a == b</tt> -> <tt>b == a</tt>
+/// - <tt>a != b</tt> -> <tt>!(a == b)</tt>
+/// - <tt>a != b</tt> -> <tt>!(b == a)</tt>
+/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>:
+/// - <tt>a @ b</tt> -> <tt>(a <=> b) @ 0</tt>
+/// - <tt>a @ b</tt> -> <tt>0 @ (b <=> a)</tt>
+///
+/// This expression provides access to both the original syntax and the
+/// rewritten expression.
+///
+/// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically
+/// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators.
+class CXXRewrittenBinaryOperator : public Expr {
+ friend class ASTStmtReader;
+
+ /// The rewritten semantic form.
+ Stmt *SemanticForm;
+
+public:
+ CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed)
+ : Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(),
+ SemanticForm->getValueKind(), SemanticForm->getObjectKind(),
+ SemanticForm->isTypeDependent(), SemanticForm->isValueDependent(),
+ SemanticForm->isInstantiationDependent(),
+ SemanticForm->containsUnexpandedParameterPack()),
+ SemanticForm(SemanticForm) {
+ CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed;
+ }
+ CXXRewrittenBinaryOperator(EmptyShell Empty)
+ : Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {}
+
+ /// Get an equivalent semantic form for this expression.
+ Expr *getSemanticForm() { return cast<Expr>(SemanticForm); }
+ const Expr *getSemanticForm() const { return cast<Expr>(SemanticForm); }
+
+ struct DecomposedForm {
+ /// The original opcode, prior to rewriting.
+ BinaryOperatorKind Opcode;
+ /// The original left-hand side.
+ const Expr *LHS;
+ /// The original right-hand side.
+ const Expr *RHS;
+ /// The inner \c == or \c <=> operator expression.
+ const Expr *InnerBinOp;
+ };
+
+ /// Decompose this operator into its syntactic form.
+ DecomposedForm getDecomposedForm() const LLVM_READONLY;
+
+ /// Determine whether this expression was rewritten in reverse form.
+ bool isReversed() const { return CXXRewrittenBinaryOperatorBits.IsReversed; }
+
+ BinaryOperatorKind getOperator() const { return getDecomposedForm().Opcode; }
+ const Expr *getLHS() const { return getDecomposedForm().LHS; }
+ const Expr *getRHS() const { return getDecomposedForm().RHS; }
+
+ SourceLocation getOperatorLoc() const LLVM_READONLY {
+ return getDecomposedForm().InnerBinOp->getExprLoc();
+ }
+ SourceLocation getExprLoc() const LLVM_READONLY { return getOperatorLoc(); }
+
+ /// Compute the begin and end locations from the decomposed form.
+ /// The locations of the semantic form are not reliable if this is
+ /// a reversed expression.
+ //@{
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getDecomposedForm().LHS->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getDecomposedForm().RHS->getEndLoc();
+ }
+ SourceRange getSourceRange() const LLVM_READONLY {
+ DecomposedForm DF = getDecomposedForm();
+ return SourceRange(DF.LHS->getBeginLoc(), DF.RHS->getEndLoc());
+ }
+ //@}
+
+ child_range children() {
+ return child_range(&SemanticForm, &SemanticForm + 1);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXRewrittenBinaryOperatorClass;
+ }
+};
+
/// Abstract class common to all of the C++ "named"/"keyword" casts.
///
/// This abstract class is inherited by all of the classes
@@ -1902,6 +1998,10 @@ public:
/// lambda expression.
CXXMethodDecl *getCallOperator() const;
+ /// Retrieve the function template call operator associated with this
+ /// lambda expression.
+ FunctionTemplateDecl *getDependentCallOperator() const;
+
/// If this is a generic lambda expression, retrieve the template
/// parameter list associated with it, or else return null.
TemplateParameterList *getTemplateParameterList() const;
@@ -2091,8 +2191,7 @@ public:
bool IsParenTypeId);
QualType getAllocatedType() const {
- assert(getType()->isPointerType());
- return getType()->getAs<PointerType>()->getPointeeType();
+ return getType()->castAs<PointerType>()->getPointeeType();
}
TypeSourceInfo *getAllocatedTypeSourceInfo() const {
@@ -2270,8 +2369,8 @@ public:
CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm,
bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize,
FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc)
- : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
- Arg->isInstantiationDependent(),
+ : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false,
+ Arg->isValueDependent(), Arg->isInstantiationDependent(),
Arg->containsUnexpandedParameterPack()),
OperatorDelete(OperatorDelete), Argument(Arg) {
CXXDeleteExprBits.GlobalDelete = GlobalDelete;
@@ -4335,9 +4434,6 @@ private:
};
llvm::PointerUnion<Stmt *, ExtraState *> State;
- void initializeExtraState(const ValueDecl *ExtendedBy,
- unsigned ManglingNumber);
-
public:
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
bool BoundToLvalueReference)
@@ -4745,6 +4841,125 @@ public:
}
};
+/// \brief Represents the specialization of a concept - evaluates to a prvalue
+/// of type bool.
+///
+/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the
+/// specialization of a concept results in a prvalue of type bool.
+class ConceptSpecializationExpr final : public Expr,
+ private llvm::TrailingObjects<ConceptSpecializationExpr,
+ TemplateArgument> {
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
+ // \brief The optional nested name specifier used when naming the concept.
+ NestedNameSpecifierLoc NestedNameSpec;
+
+ /// \brief The location of the template keyword, if specified when naming the
+ /// concept.
+ SourceLocation TemplateKWLoc;
+
+ /// \brief The location of the concept name in the expression.
+ SourceLocation ConceptNameLoc;
+
+ /// \brief The declaration found by name lookup when the expression was
+ /// created.
+ /// Can differ from NamedConcept when, for example, the concept was found
+ /// through a UsingShadowDecl.
+ NamedDecl *FoundDecl;
+
+ /// \brief The concept named, and whether or not the concept with the given
+ /// arguments was satisfied when the expression was created.
+ /// If any of the template arguments are dependent (this expr would then be
+ /// isValueDependent()), this bit is to be ignored.
+ llvm::PointerIntPair<ConceptDecl *, 1, bool> NamedConcept;
+
+ /// \brief The template argument list source info used to specialize the
+ /// concept.
+ const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
+
+ /// \brief The number of template arguments in the tail-allocated list of
+ /// converted template arguments.
+ unsigned NumTemplateArgs;
+
+ ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,
+ SourceLocation TemplateKWLoc,
+ SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ Optional<bool> IsSatisfied);
+
+ ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
+
+public:
+
+ static ConceptSpecializationExpr *
+ Create(ASTContext &C, NestedNameSpecifierLoc NNS,
+ SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);
+
+ static ConceptSpecializationExpr *
+ Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
+
+ const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
+ return NestedNameSpec;
+ }
+
+ NamedDecl *getFoundDecl() const {
+ return FoundDecl;
+ }
+
+ ConceptDecl *getNamedConcept() const {
+ return NamedConcept.getPointer();
+ }
+
+ ArrayRef<TemplateArgument> getTemplateArguments() const {
+ return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
+ NumTemplateArgs);
+ }
+
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// \brief Set new template arguments for this concept specialization.
+ void setTemplateArguments(const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> Converted);
+
+ /// \brief Whether or not the concept with the given arguments was satisfied
+ /// when the expression was created. This method assumes that the expression
+ /// is not dependent!
+ bool isSatisfied() const {
+ assert(!isValueDependent()
+ && "isSatisfied called on a dependent ConceptSpecializationExpr");
+ return NamedConcept.getInt();
+ }
+
+ SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }
+
+ SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConceptSpecializationExprClass;
+ }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY { return ConceptNameLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return ArgsAsWritten->RAngleLoc;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ const_child_range children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+};
+
} // namespace clang
#endif // LLVM_CLANG_AST_EXPRCXX_H
diff --git a/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h
index d89189da04f0..0230495a5ef3 100644
--- a/include/clang/AST/ExternalASTMerger.h
+++ b/include/clang/AST/ExternalASTMerger.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_AST_EXTERNALASTMERGER_H
#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ASTImporterSharedState.h"
#include "clang/AST/ExternalASTSource.h"
#include "llvm/Support/raw_ostream.h"
@@ -22,7 +23,7 @@ namespace clang {
/// ExternalASTSource implementation that merges information from several
/// ASTContexts.
///
-/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import
+/// ExternalASTMerger maintains a vector of ASTImporters that it uses to import
/// (potentially incomplete) Decls and DeclContexts from the source ASTContexts
/// in response to ExternalASTSource API calls.
///
@@ -36,7 +37,7 @@ namespace clang {
/// lookup. In this case, Origins contains an entry overriding lookup and
/// specifying the correct pair of DeclContext/ASTContext.
///
-/// - The DeclContext of origin was determined by another ExterenalASTMerger.
+/// - The DeclContext of origin was determined by another ExternalASTMerger.
/// (This is possible when the source ASTContext for one of the Importers has
/// its own ExternalASTMerger). The origin must be properly forwarded in this
/// case.
@@ -79,20 +80,47 @@ public:
/// import SourceLocations properly. Additionally, when import occurs for
/// a DeclContext whose origin has been overridden, then this
/// ExternalASTMerger must be able to determine that.
- struct ImporterSource {
+ class ImporterSource {
ASTContext &AST;
FileManager &FM;
const OriginMap &OM;
+ /// True iff the source only exists temporary, i.e., it will be removed from
+ /// the ExternalASTMerger during the life time of the ExternalASTMerger.
+ bool Temporary;
+ /// If the ASTContext of this source has an ExternalASTMerger that imports
+ /// into this source, then this will point to that other ExternalASTMerger.
+ ExternalASTMerger *Merger;
+
+ public:
+ ImporterSource(ASTContext &AST, FileManager &FM, const OriginMap &OM,
+ bool Temporary = false, ExternalASTMerger *Merger = nullptr)
+ : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {}
+ ASTContext &getASTContext() const { return AST; }
+ FileManager &getFileManager() const { return FM; }
+ const OriginMap &getOriginMap() const { return OM; }
+ bool isTemporary() const { return Temporary; }
+ ExternalASTMerger *getMerger() const { return Merger; }
};
private:
- /// The target for this ExtenralASTMerger.
+ /// The target for this ExternalASTMerger.
ImporterTarget Target;
+ /// ExternalASTMerger has multiple ASTImporters that import into the same
+ /// TU. This is the shared state for all ASTImporters of this
+ /// ExternalASTMerger.
+ /// See also the CrossTranslationUnitContext that has a similar setup.
+ std::shared_ptr<ASTImporterSharedState> SharedState;
public:
ExternalASTMerger(const ImporterTarget &Target,
llvm::ArrayRef<ImporterSource> Sources);
+ /// Asks all connected ASTImporters if any of them imported the given
+ /// declaration. If any ASTImporter did import the given declaration,
+ /// then this function returns the declaration that D was imported from.
+ /// Returns nullptr if no ASTImporter did import import D.
+ Decl *FindOriginalDecl(Decl *D);
+
/// Add a set of ASTContexts as possible origins.
///
/// Usually the set will be initialized in the constructor, but long-lived
@@ -145,7 +173,7 @@ public:
/// OriginContext.
bool HasImporterForOrigin(ASTContext &OriginContext);
- /// Returns a reference to the ASTRImporter from Importers whose origin
+ /// Returns a reference to the ASTImporter from Importers whose origin
/// is OriginContext. This allows manual import of ASTs while preserving the
/// OriginMap correctly.
ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
diff --git a/include/clang/AST/FormatString.h b/include/clang/AST/FormatString.h
index 643fb822f7f4..8c944451f796 100644
--- a/include/clang/AST/FormatString.h
+++ b/include/clang/AST/FormatString.h
@@ -251,7 +251,21 @@ public:
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
AnyCharTy, CStrTy, WCStrTy, WIntTy };
- enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };
+ /// How well a given conversion specifier matches its argument.
+ enum MatchKind {
+ /// The conversion specifier and the argument types are incompatible. For
+ /// instance, "%d" and float.
+ NoMatch = 0,
+ /// The conversion specifier and the argument type are compatible. For
+ /// instance, "%d" and _Bool.
+ Match = 1,
+ /// The conversion specifier and the argument type are disallowed by the C
+ /// standard, but are in practice harmless. For instance, "%p" and int*.
+ NoMatchPedantic,
+ /// The conversion specifier and the argument type are compatible, but still
+ /// seems likely to be an error. For instance, "%hd" and _Bool.
+ NoMatchTypeConfusion,
+ };
private:
const Kind K;
@@ -748,6 +762,12 @@ bool ParseScanfString(FormatStringHandler &H,
const char *beg, const char *end, const LangOptions &LO,
const TargetInfo &Target);
+/// Return true if the given string has at least one formatting specifier.
+bool parseFormatStringHasFormattingSpecifiers(const char *Begin,
+ const char *End,
+ const LangOptions &LO,
+ const TargetInfo &Target);
+
} // end analyze_format_string namespace
} // end clang namespace
#endif
diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h
index 86fd0f6aa907..145e961a23a3 100644
--- a/include/clang/AST/GlobalDecl.h
+++ b/include/clang/AST/GlobalDecl.h
@@ -59,6 +59,7 @@ public:
GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); }
+ GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); }
GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {}
GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {}
GlobalDecl(const VarDecl *D, DynamicInitKind StubKind)
diff --git a/include/clang/AST/JSONNodeDumper.h b/include/clang/AST/JSONNodeDumper.h
index 238e43aad78b..5f34440b8b56 100644
--- a/include/clang/AST/JSONNodeDumper.h
+++ b/include/clang/AST/JSONNodeDumper.h
@@ -141,6 +141,8 @@ class JSONNodeDumper
JOS.attribute(Key, Value);
}
+ void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false);
+
// Writes the attributes of a SourceLocation object without.
void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling);
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index b1fbe936136a..5db5c5b977da 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -56,7 +56,7 @@ private:
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
- llvm::DenseMap<const TagDecl*, uint64_t> AnonStructIds;
+ llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
public:
ManglerKind getKind() const { return Kind; }
@@ -82,9 +82,9 @@ public:
return Result.first->second;
}
- uint64_t getAnonymousStructId(const TagDecl *TD) {
- std::pair<llvm::DenseMap<const TagDecl *, uint64_t>::iterator, bool>
- Result = AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size()));
+ uint64_t getAnonymousStructId(const NamedDecl *D) {
+ std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool>
+ Result = AnonStructIds.insert(std::make_pair(D, AnonStructIds.size()));
return Result.first->second;
}
@@ -170,6 +170,8 @@ public:
virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
raw_ostream &) = 0;
+ virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
+
static bool classof(const MangleContext *C) {
return C->getKind() == MK_Itanium;
}
@@ -248,8 +250,16 @@ class ASTNameGenerator {
public:
explicit ASTNameGenerator(ASTContext &Ctx);
~ASTNameGenerator();
+
+ /// Writes name for \p D to \p OS.
+ /// \returns true on failure, false on success.
bool writeName(const Decl *D, raw_ostream &OS);
+
+ /// \returns name for \p D
std::string getName(const Decl *D);
+
+ /// \returns all applicable mangled names.
+ /// For example C++ constructors/destructors can have multiple.
std::vector<std::string> getAllManglings(const Decl *D);
private:
diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index 21f0c5458d81..a8bd2d0f17e6 100644
--- a/include/clang/AST/NSAPI.h
+++ b/include/clang/AST/NSAPI.h
@@ -55,9 +55,6 @@ public:
/// The Objective-C NSString selectors.
Selector getNSStringSelector(NSStringMethodKind MK) const;
- /// Return NSStringMethodKind if \param Sel is such a selector.
- Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
-
/// Returns true if the expression \param E is a reference of
/// "NSUTF8StringEncoding" enum constant.
bool isNSUTF8StringEncodingConstant(const Expr *E) const {
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index eadcc62a3457..b2a2035dcb3c 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -519,7 +519,7 @@ public:
/// \endcode
/// In this example directive '#pragma omp task' has simple 'final'
/// clause with condition 'a > 5'.
-class OMPFinalClause : public OMPClause {
+class OMPFinalClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
/// Location of '('.
@@ -534,18 +534,25 @@ class OMPFinalClause : public OMPClause {
public:
/// Build 'final' clause with condition \a Cond.
///
+ /// \param Cond Condition of the clause.
+ /// \param HelperCond Helper condition for the construct.
+ /// \param CaptureRegion Innermost OpenMP region where expressions in this
+ /// clause must be captured.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
- /// \param Cond Condition of the clause.
/// \param EndLoc Ending location of the clause.
- OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc)
- : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Condition(Cond) {}
+ OMPFinalClause(Expr *Cond, Stmt *HelperCond,
+ OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_final, StartLoc, EndLoc), OMPClauseWithPreInit(this),
+ LParenLoc(LParenLoc), Condition(Cond) {
+ setPreInitStmt(HelperCond, CaptureRegion);
+ }
/// Build an empty clause.
OMPFinalClause()
- : OMPClause(OMPC_final, SourceLocation(), SourceLocation()) {}
+ : OMPClause(OMPC_final, SourceLocation(), SourceLocation()),
+ OMPClauseWithPreInit(this) {}
/// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
@@ -562,11 +569,10 @@ public:
return const_child_range(&Condition, &Condition + 1);
}
- child_range used_children() {
- return child_range(child_iterator(), child_iterator());
- }
+ child_range used_children();
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPFinalClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *T) {
@@ -2099,10 +2105,12 @@ public:
}
child_range used_children() {
- return child_range(child_iterator(), child_iterator());
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPFirstprivateClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *T) {
@@ -2616,10 +2624,12 @@ public:
}
child_range used_children() {
- return child_range(child_iterator(), child_iterator());
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPReductionClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *T) {
@@ -3212,6 +3222,14 @@ class OMPLinearClause final
return llvm::makeArrayRef(getUpdates().end(), varlist_size());
}
+ /// Gets the list of used expressions for linear variables.
+ MutableArrayRef<Expr *> getUsedExprs() {
+ return MutableArrayRef<Expr *>(getFinals().end() + 2, varlist_size() + 1);
+ }
+ ArrayRef<const Expr *> getUsedExprs() const {
+ return llvm::makeArrayRef(getFinals().end() + 2, varlist_size() + 1);
+ }
+
/// Sets the list of the copies of original linear variables.
/// \param PL List of expressions.
void setPrivates(ArrayRef<Expr *> PL);
@@ -3291,6 +3309,9 @@ public:
/// \param FL List of expressions.
void setFinals(ArrayRef<Expr *> FL);
+ /// Sets the list of used expressions for the linear clause.
+ void setUsedExprs(ArrayRef<Expr *> UE);
+
using privates_iterator = MutableArrayRef<Expr *>::iterator;
using privates_const_iterator = ArrayRef<const Expr *>::iterator;
using privates_range = llvm::iterator_range<privates_iterator>;
@@ -3343,6 +3364,21 @@ public:
return finals_const_range(getFinals().begin(), getFinals().end());
}
+ using used_expressions_iterator = MutableArrayRef<Expr *>::iterator;
+ using used_expressions_const_iterator = ArrayRef<const Expr *>::iterator;
+ using used_expressions_range =
+ llvm::iterator_range<used_expressions_iterator>;
+ using used_expressions_const_range =
+ llvm::iterator_range<used_expressions_const_iterator>;
+
+ used_expressions_range used_expressions() {
+ return finals_range(getUsedExprs().begin(), getUsedExprs().end());
+ }
+
+ used_expressions_const_range used_expressions() const {
+ return finals_const_range(getUsedExprs().begin(), getUsedExprs().end());
+ }
+
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
@@ -3353,11 +3389,11 @@ public:
return const_child_range(Children.begin(), Children.end());
}
- child_range used_children() {
- return child_range(child_iterator(), child_iterator());
- }
+ child_range used_children();
+
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPLinearClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *T) {
@@ -4995,12 +5031,17 @@ public:
}
child_range used_children() {
+ if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_tofrom)
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
return child_range(child_iterator(), child_iterator());
}
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPMapClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
+
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_map;
}
@@ -5165,7 +5206,7 @@ public:
/// \endcode
/// In this example directive '#pragma omp teams' has clause 'priority' with
/// single expression 'n'.
-class OMPPriorityClause : public OMPClause {
+class OMPPriorityClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
/// Location of '('.
@@ -5182,18 +5223,25 @@ class OMPPriorityClause : public OMPClause {
public:
/// Build 'priority' clause.
///
- /// \param E Expression associated with this clause.
+ /// \param Priority Expression associated with this clause.
+ /// \param HelperPriority Helper priority for the construct.
+ /// \param CaptureRegion Innermost OpenMP region where expressions in this
+ /// clause must be captured.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc)
- : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Priority(E) {}
+ OMPPriorityClause(Expr *Priority, Stmt *HelperPriority,
+ OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_priority, StartLoc, EndLoc), OMPClauseWithPreInit(this),
+ LParenLoc(LParenLoc), Priority(Priority) {
+ setPreInitStmt(HelperPriority, CaptureRegion);
+ }
/// Build an empty clause.
OMPPriorityClause()
- : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()) {}
+ : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()),
+ OMPClauseWithPreInit(this) {}
/// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
@@ -5213,11 +5261,10 @@ public:
return const_child_range(&Priority, &Priority + 1);
}
- child_range used_children() {
- return child_range(child_iterator(), child_iterator());
- }
+ child_range used_children();
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPPriorityClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *T) {
@@ -5233,7 +5280,7 @@ public:
/// \endcode
/// In this example directive '#pragma omp taskloop' has clause 'grainsize'
/// with single expression '4'.
-class OMPGrainsizeClause : public OMPClause {
+class OMPGrainsizeClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
/// Location of '('.
@@ -5249,16 +5296,23 @@ public:
/// Build 'grainsize' clause.
///
/// \param Size Expression associated with this clause.
+ /// \param HelperSize Helper grainsize for the construct.
+ /// \param CaptureRegion Innermost OpenMP region where expressions in this
+ /// clause must be captured.
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
+ OMPGrainsizeClause(Expr *Size, Stmt *HelperSize,
+ OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
- : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Grainsize(Size) {}
+ : OMPClause(OMPC_grainsize, StartLoc, EndLoc), OMPClauseWithPreInit(this),
+ LParenLoc(LParenLoc), Grainsize(Size) {
+ setPreInitStmt(HelperSize, CaptureRegion);
+ }
/// Build an empty clause.
explicit OMPGrainsizeClause()
- : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()) {}
+ : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()),
+ OMPClauseWithPreInit(this) {}
/// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
@@ -5275,11 +5329,10 @@ public:
return const_child_range(&Grainsize, &Grainsize + 1);
}
- child_range used_children() {
- return child_range(child_iterator(), child_iterator());
- }
+ child_range used_children();
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPGrainsizeClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *T) {
@@ -5334,7 +5387,7 @@ public:
/// \endcode
/// In this example directive '#pragma omp taskloop' has clause 'num_tasks'
/// with single expression '4'.
-class OMPNumTasksClause : public OMPClause {
+class OMPNumTasksClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
/// Location of '('.
@@ -5350,16 +5403,23 @@ public:
/// Build 'num_tasks' clause.
///
/// \param Size Expression associated with this clause.
+ /// \param HelperSize Helper grainsize for the construct.
+ /// \param CaptureRegion Innermost OpenMP region where expressions in this
+ /// clause must be captured.
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
- OMPNumTasksClause(Expr *Size, SourceLocation StartLoc,
+ OMPNumTasksClause(Expr *Size, Stmt *HelperSize,
+ OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
- : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc),
- NumTasks(Size) {}
+ : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), OMPClauseWithPreInit(this),
+ LParenLoc(LParenLoc), NumTasks(Size) {
+ setPreInitStmt(HelperSize, CaptureRegion);
+ }
/// Build an empty clause.
explicit OMPNumTasksClause()
- : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()) {}
+ : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()),
+ OMPClauseWithPreInit(this) {}
/// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
@@ -5376,11 +5436,10 @@ public:
return const_child_range(&NumTasks, &NumTasks + 1);
}
- child_range used_children() {
- return child_range(child_iterator(), child_iterator());
- }
+ child_range used_children();
const_child_range used_children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ auto Children = const_cast<OMPNumTasksClause *>(this)->used_children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *T) {
diff --git a/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def
index 9af92c1ae7ff..f29664e8eb33 100644
--- a/include/clang/AST/OperationKinds.def
+++ b/include/clang/AST/OperationKinds.def
@@ -66,8 +66,9 @@ CAST_OPERATION(BitCast)
/// bool b; reinterpret_cast<char&>(b) = 'a';
CAST_OPERATION(LValueBitCast)
-/// CK_LValueToRValueBitCast - A conversion that causes us to reinterpret an
-/// lvalue as an rvalue of a different type. Created by __builtin_bit_cast.
+/// CK_LValueToRValueBitCast - A conversion that causes us to reinterpret the
+/// object representation of an lvalue as an rvalue. Created by
+/// __builtin_bit_cast.
CAST_OPERATION(LValueToRValueBitCast)
/// CK_LValueToRValue - A conversion which causes the extraction of
diff --git a/include/clang/AST/OptionalDiagnostic.h b/include/clang/AST/OptionalDiagnostic.h
new file mode 100644
index 000000000000..c57199f0fdf1
--- /dev/null
+++ b/include/clang/AST/OptionalDiagnostic.h
@@ -0,0 +1,78 @@
+//===- OptionalDiagnostic.h - An optional diagnostic ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Implements a partial diagnostic which may not be emitted.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H
+#define LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H
+
+#include "clang/AST/APValue.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+/// A partial diagnostic which we might know in advance that we are not going
+/// to emit.
+class OptionalDiagnostic {
+ PartialDiagnostic *Diag;
+
+public:
+ explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) : Diag(Diag) {}
+
+ template <typename T> OptionalDiagnostic &operator<<(const T &v) {
+ if (Diag)
+ *Diag << v;
+ return *this;
+ }
+
+ OptionalDiagnostic &operator<<(const llvm::APSInt &I) {
+ if (Diag) {
+ SmallVector<char, 32> Buffer;
+ I.toString(Buffer);
+ *Diag << StringRef(Buffer.data(), Buffer.size());
+ }
+ return *this;
+ }
+
+ OptionalDiagnostic &operator<<(const llvm::APFloat &F) {
+ if (Diag) {
+ // FIXME: Force the precision of the source value down so we don't
+ // print digits which are usually useless (we don't really care here if
+ // we truncate a digit by accident in edge cases). Ideally,
+ // APFloat::toString would automatically print the shortest
+ // representation which rounds to the correct value, but it's a bit
+ // tricky to implement. Could use std::to_chars.
+ unsigned precision = llvm::APFloat::semanticsPrecision(F.getSemantics());
+ precision = (precision * 59 + 195) / 196;
+ SmallVector<char, 32> Buffer;
+ F.toString(Buffer, precision);
+ *Diag << StringRef(Buffer.data(), Buffer.size());
+ }
+ return *this;
+ }
+
+ OptionalDiagnostic &operator<<(const APFixedPoint &FX) {
+ if (Diag) {
+ SmallVector<char, 32> Buffer;
+ FX.toString(Buffer);
+ *Diag << StringRef(Buffer.data(), Buffer.size());
+ }
+ return *this;
+ }
+};
+
+} // namespace clang
+
+#endif
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index 5dc8694e77e9..1eea56dee622 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/include/clang/AST/RawCommentList.h
@@ -10,8 +10,11 @@
#define LLVM_CLANG_AST_RAWCOMMENTLIST_H
#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include <map>
namespace clang {
@@ -196,17 +199,25 @@ public:
void addComment(const RawComment &RC, const CommentOptions &CommentOpts,
llvm::BumpPtrAllocator &Allocator);
- ArrayRef<RawComment *> getComments() const {
- return Comments;
- }
+ /// \returns A mapping from an offset of the start of the comment to the
+ /// comment itself, or nullptr in case there are no comments in \p File.
+ const std::map<unsigned, RawComment *> *getCommentsInFile(FileID File) const;
+
+ bool empty() const;
+
+ unsigned getCommentBeginLine(RawComment *C, FileID File,
+ unsigned Offset) const;
+ unsigned getCommentEndOffset(RawComment *C) const;
private:
SourceManager &SourceMgr;
- std::vector<RawComment *> Comments;
-
- void addDeserializedComments(ArrayRef<RawComment *> DeserializedComments);
+ // mapping: FileId -> comment begin offset -> comment
+ llvm::DenseMap<FileID, std::map<unsigned, RawComment *>> OrderedComments;
+ mutable llvm::DenseMap<RawComment *, unsigned> CommentBeginLine;
+ mutable llvm::DenseMap<RawComment *, unsigned> CommentEndOffset;
friend class ASTReader;
+ friend class ASTWriter;
};
} // end namespace clang
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 698fba2f4ed1..5b58eab95d60 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -431,7 +431,7 @@ public:
// Declare Traverse*() for all concrete Type classes.
#define ABSTRACT_TYPE(CLASS, BASE)
#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T);
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
// The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
// Define WalkUpFrom*() and empty Visit*() for all Type classes.
@@ -444,7 +444,7 @@ public:
return true; \
} \
bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
// ---- Methods on TypeLocs ----
// FIXME: this currently just calls the matching Type methods
@@ -460,7 +460,7 @@ public:
bool VisitTypeLoc(TypeLoc TL) { return true; }
// QualifiedTypeLoc and UnqualTypeLoc are not declared in
- // TypeNodes.def and thus need to be handled specially.
+ // TypeNodes.inc and thus need to be handled specially.
bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
}
@@ -478,7 +478,7 @@ public:
return true; \
} \
bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
// ---- Methods on Decls ----
@@ -676,7 +676,7 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
#define TYPE(CLASS, BASE) \
case Type::CLASS: \
DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr()));
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
}
return true;
@@ -722,12 +722,6 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
break;
#include "clang/AST/DeclNodes.inc"
}
-
- // Visit any attributes attached to this declaration.
- for (auto *I : D->attrs()) {
- if (!getDerived().TraverseAttr(I))
- return false;
- }
return true;
}
@@ -965,8 +959,11 @@ DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
-DEF_TRAVERSE_TYPE(ConstantArrayType,
- { TRY_TO(TraverseType(T->getElementType())); })
+DEF_TRAVERSE_TYPE(ConstantArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ if (T->getSizeExpr())
+ TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr())));
+})
DEF_TRAVERSE_TYPE(IncompleteArrayType,
{ TRY_TO(TraverseType(T->getElementType())); })
@@ -1407,6 +1404,11 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
{ CODE; } \
if (ReturnValue && ShouldVisitChildren) \
TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
+ if (ReturnValue) { \
+ /* Visit any attributes attached to this declaration. */ \
+ for (auto *I : D->attrs()) \
+ TRY_TO(getDerived().TraverseAttr(I)); \
+ } \
if (ReturnValue && getDerived().shouldTraversePostOrder()) \
TRY_TO(WalkUpFrom##DECL(D)); \
return ReturnValue; \
@@ -1631,9 +1633,11 @@ template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
TemplateParameterList *TPL) {
if (TPL) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
+ for (NamedDecl *D : *TPL) {
+ TRY_TO(TraverseDecl(D));
+ }
+ if (Expr *RequiresClause = TPL->getRequiresClause()) {
+ TRY_TO(TraverseStmt(RequiresClause));
}
}
return true;
@@ -2023,11 +2027,18 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers.
for (auto *I : Ctor->inits()) {
- TRY_TO(TraverseConstructorInitializer(I));
+ if (I->isWritten() || getDerived().shouldVisitImplicitCode())
+ TRY_TO(TraverseConstructorInitializer(I));
}
}
- if (D->isThisDeclarationADefinition()) {
+ bool VisitBody = D->isThisDeclarationADefinition();
+ // If a method is set to default outside the class definition the compiler
+ // generates the method body and adds it to the AST.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
+ VisitBody &= !MD->isDefaulted() || getDerived().shouldVisitImplicitCode();
+
+ if (VisitBody) {
TRY_TO(TraverseStmt(D->getBody())); // Function body.
}
return true;
@@ -2308,19 +2319,30 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
return true;
}
-// This method is called once for each pair of syntactic and semantic
-// InitListExpr, and it traverses the subtrees defined by the two forms. This
-// may cause some of the children to be visited twice, if they appear both in
-// the syntactic and the semantic form.
+// If shouldVisitImplicitCode() returns false, this method traverses only the
+// syntactic form of InitListExpr.
+// If shouldVisitImplicitCode() return true, this method is called once for
+// each pair of syntactic and semantic InitListExpr, and it traverses the
+// subtrees defined by the two forms. This may cause some of the children to be
+// visited twice, if they appear both in the syntactic and the semantic form.
//
// There is no guarantee about which form \p S takes when this method is called.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
InitListExpr *S, DataRecursionQueue *Queue) {
+ if (S->isSemanticForm() && S->isSyntacticForm()) {
+ // `S` does not have alternative forms, traverse only once.
+ TRY_TO(TraverseSynOrSemInitListExpr(S, Queue));
+ return true;
+ }
TRY_TO(TraverseSynOrSemInitListExpr(
S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
- TRY_TO(TraverseSynOrSemInitListExpr(
- S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
+ if (getDerived().shouldVisitImplicitCode()) {
+ // Only visit the semantic form if the clients are interested in implicit
+ // compiler-generated.
+ TRY_TO(TraverseSynOrSemInitListExpr(
+ S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
+ }
return true;
}
@@ -2584,6 +2606,15 @@ DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
+DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
+ S->getDecomposedForm();
+ TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.LHS)));
+ TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.RHS)));
+ ShouldVisitChildren = false;
+ }
+})
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
DEF_TRAVERSE_STMT(TypoExpr, {})
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
@@ -2639,6 +2670,12 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {
}
})
+DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getTemplateArgsAsWritten()->getTemplateArgs(),
+ S->getTemplateArgsAsWritten()->NumTemplateArgs));
+})
+
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, {})
DEF_TRAVERSE_STMT(FixedPointLiteral, {})
@@ -2768,6 +2805,15 @@ DEF_TRAVERSE_STMT(OMPTaskLoopDirective,
DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPMasterTaskLoopDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPMasterTaskLoopSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPDistributeDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2826,6 +2872,8 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
#include "clang/Basic/OpenMPKinds.def"
case OMPC_threadprivate:
case OMPC_uniform:
+ case OMPC_device_type:
+ case OMPC_match:
case OMPC_unknown:
break;
}
@@ -2870,6 +2918,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
+ TRY_TO(VisitOMPClauseWithPreInit(C));
TRY_TO(TraverseStmt(C->getCondition()));
return true;
}
@@ -3240,6 +3289,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause(
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
OMPPriorityClause *C) {
+ TRY_TO(VisitOMPClauseWithPreInit(C));
TRY_TO(TraverseStmt(C->getPriority()));
return true;
}
@@ -3247,6 +3297,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
OMPGrainsizeClause *C) {
+ TRY_TO(VisitOMPClauseWithPreInit(C));
TRY_TO(TraverseStmt(C->getGrainsize()));
return true;
}
@@ -3254,6 +3305,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause(
OMPNumTasksClause *C) {
+ TRY_TO(VisitOMPClauseWithPreInit(C));
TRY_TO(TraverseStmt(C->getNumTasks()));
return true;
}
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 403b88ac3a3c..7aebbf2cb6a3 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -604,6 +604,15 @@ protected:
unsigned FPFeatures : 3;
};
+ class CXXRewrittenBinaryOperatorBitfields {
+ friend class ASTStmtReader;
+ friend class CXXRewrittenBinaryOperator;
+
+ unsigned : NumCallExprBits;
+
+ unsigned IsReversed : 1;
+ };
+
class CXXBoolLiteralExprBitfields {
friend class CXXBoolLiteralExpr;
@@ -978,6 +987,7 @@ protected:
// C++ Expressions
CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
+ CXXRewrittenBinaryOperatorBitfields CXXRewrittenBinaryOperatorBits;
CXXBoolLiteralExprBitfields CXXBoolLiteralExprBits;
CXXNullPtrLiteralExprBitfields CXXNullPtrLiteralExprBits;
CXXThisExprBitfields CXXThisExprBits;
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index e37f5b1e0004..ddfb3060b158 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -17,6 +17,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceLocation.h"
@@ -448,7 +449,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
PreInitsOffset = 8,
// The '...End' enumerators do not correspond to child expressions - they
// specify the offset to the end (and start of the following counters/
- // updates/finals arrays).
+ // updates/finals/dependent_counters/dependent_inits/finals_conditions
+ // arrays).
DefaultEnd = 9,
// The following 8 exprs are used by worksharing and distribute loops only.
IsLastIterVariableOffset = 9,
@@ -474,7 +476,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
CombinedNextUpperBoundOffset = 27,
CombinedDistConditionOffset = 28,
CombinedParForInDistConditionOffset = 29,
- // Offset to the end (and start of the following counters/updates/finals
+ // Offset to the end (and start of the following
+ // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
// arrays) for combined distribute loop directives.
CombinedDistributeEnd = 30,
};
@@ -517,6 +520,30 @@ class OMPLoopDirective : public OMPExecutableDirective {
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
+ /// Get the dependent counters storage.
+ MutableArrayRef<Expr *> getDependentCounters() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 5 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// Get the dependent inits storage.
+ MutableArrayRef<Expr *> getDependentInits() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 6 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// Get the finals conditions storage.
+ MutableArrayRef<Expr *> getFinalsConditions() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 7 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
protected:
/// Build instance of loop directive of class \a Kind.
///
@@ -551,9 +578,10 @@ protected:
/// Children number.
static unsigned numLoopChildren(unsigned CollapsedNum,
OpenMPDirectiveKind Kind) {
- return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
- // PrivateCounters, Inits,
- // Updates and Finals
+ return getArraysOffset(Kind) +
+ 8 * CollapsedNum; // Counters, PrivateCounters, Inits,
+ // Updates, Finals, DependentCounters,
+ // DependentInits, FinalsConditions.
}
void setIterationVariable(Expr *IV) {
@@ -703,6 +731,9 @@ protected:
void setInits(ArrayRef<Expr *> A);
void setUpdates(ArrayRef<Expr *> A);
void setFinals(ArrayRef<Expr *> A);
+ void setDependentCounters(ArrayRef<Expr *> A);
+ void setDependentInits(ArrayRef<Expr *> A);
+ void setFinalsConditions(ArrayRef<Expr *> A);
public:
/// The expressions built to support OpenMP loops in combined/composite
@@ -798,6 +829,15 @@ public:
SmallVector<Expr *, 4> Updates;
/// Final loop counter values for GodeGen.
SmallVector<Expr *, 4> Finals;
+ /// List of counters required for the generation of the non-rectangular
+ /// loops.
+ SmallVector<Expr *, 4> DependentCounters;
+ /// List of initializers required for the generation of the non-rectangular
+ /// loops.
+ SmallVector<Expr *, 4> DependentInits;
+ /// List of final conditions required for the generation of the
+ /// non-rectangular loops.
+ SmallVector<Expr *, 4> FinalsConditions;
/// Init statement for all captured expressions.
Stmt *PreInits;
@@ -813,7 +853,9 @@ public:
}
/// Initialize all the fields to null.
- /// \param Size Number of elements in the counters/finals/updates arrays.
+ /// \param Size Number of elements in the
+ /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
+ /// arrays.
void clear(unsigned Size) {
IterationVarRef = nullptr;
LastIteration = nullptr;
@@ -839,12 +881,18 @@ public:
Inits.resize(Size);
Updates.resize(Size);
Finals.resize(Size);
+ DependentCounters.resize(Size);
+ DependentInits.resize(Size);
+ FinalsConditions.resize(Size);
for (unsigned i = 0; i < Size; ++i) {
Counters[i] = nullptr;
PrivateCounters[i] = nullptr;
Inits[i] = nullptr;
Updates[i] = nullptr;
Finals[i] = nullptr;
+ DependentCounters[i] = nullptr;
+ DependentInits[i] = nullptr;
+ FinalsConditions[i] = nullptr;
}
PreInits = nullptr;
DistCombinedFields.LB = nullptr;
@@ -1040,10 +1088,22 @@ public:
// This relies on the loop form is already checked by Sema.
const Stmt *Body =
getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
- Body = cast<ForStmt>(Body)->getBody();
+ if (auto *For = dyn_cast<ForStmt>(Body)) {
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(Body) &&
+ "Expected canonical for loop or range-based for loop.");
+ Body = cast<CXXForRangeStmt>(Body)->getBody();
+ }
for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
Body = Body->IgnoreContainers();
- Body = cast<ForStmt>(Body)->getBody();
+ if (auto *For = dyn_cast<ForStmt>(Body)) {
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(Body) &&
+ "Expected canonical for loop or range-based for loop.");
+ Body = cast<CXXForRangeStmt>(Body)->getBody();
+ }
}
return Body;
}
@@ -1078,6 +1138,24 @@ public:
return const_cast<OMPLoopDirective *>(this)->getFinals();
}
+ ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }
+
+ ArrayRef<Expr *> dependent_counters() const {
+ return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
+ }
+
+ ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }
+
+ ArrayRef<Expr *> dependent_inits() const {
+ return const_cast<OMPLoopDirective *>(this)->getDependentInits();
+ }
+
+ ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }
+
+ ArrayRef<Expr *> finals_conditions() const {
+ return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSimdDirectiveClass ||
T->getStmtClass() == OMPForDirectiveClass ||
@@ -1086,6 +1164,9 @@ public:
T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
T->getStmtClass() == OMPTaskLoopDirectiveClass ||
T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
+ T->getStmtClass() == OMPMasterTaskLoopDirectiveClass ||
+ T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass ||
+ T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass ||
T->getStmtClass() == OMPDistributeDirectiveClass ||
T->getStmtClass() == OMPTargetParallelForDirectiveClass ||
T->getStmtClass() == OMPDistributeParallelForDirectiveClass ||
@@ -3041,6 +3122,211 @@ public:
}
};
+/// This represents '#pragma omp master taskloop' directive.
+///
+/// \code
+/// #pragma omp master taskloop private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp master taskloop' has clauses
+/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
+/// and 'num_tasks' with expression 'num'.
+///
+class OMPMasterTaskLoopDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
+ OMPD_master_taskloop, StartLoc, EndLoc, CollapsedNum,
+ NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
+ OMPD_master_taskloop, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// 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 CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPMasterTaskLoopDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp master taskloop simd' directive.
+///
+/// \code
+/// #pragma omp master taskloop simd private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp master taskloop simd' has clauses
+/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
+/// and 'num_tasks' with expression 'num'.
+///
+class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass,
+ OMPD_master_taskloop_simd, StartLoc, EndLoc,
+ CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass,
+ OMPD_master_taskloop_simd, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// Creates directive with a list of \p Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPMasterTaskLoopSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place for \p NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPMasterTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp parallel master taskloop' directive.
+///
+/// \code
+/// #pragma omp parallel master taskloop private(a,b) grainsize(val)
+/// num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp parallel master taskloop' has clauses
+/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
+/// and 'num_tasks' with expression 'num'.
+///
+class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
+ OMPD_parallel_master_taskloop, StartLoc, EndLoc,
+ CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
+ OMPD_parallel_master_taskloop, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// 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 CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPParallelMasterTaskLoopDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPParallelMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass;
+ }
+};
+
/// This represents '#pragma omp distribute' directive.
///
/// \code
diff --git a/include/clang/AST/TextNodeDumper.h b/include/clang/AST/TextNodeDumper.h
index 4c2d0710963b..0ff5a614a864 100644
--- a/include/clang/AST/TextNodeDumper.h
+++ b/include/clang/AST/TextNodeDumper.h
@@ -146,8 +146,6 @@ class TextNodeDumper
const comments::CommandTraits *Traits;
- const ASTContext *Context;
-
const char *getCommandName(unsigned CommandID);
public:
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 584655fe789e..c9238e952101 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -126,7 +126,7 @@ using CanQualType = CanQual<Type>;
// Provide forward declarations for all of the *Type classes.
#define TYPE(Class, Base) class Class##Type;
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
/// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers:
@@ -972,6 +972,9 @@ public:
friend bool operator!=(const QualType &LHS, const QualType &RHS) {
return LHS.Value != RHS.Value;
}
+ friend bool operator<(const QualType &LHS, const QualType &RHS) {
+ return LHS.Value < RHS.Value;
+ }
static std::string getAsString(SplitQualType split,
const PrintingPolicy &Policy) {
@@ -1434,10 +1437,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
public:
enum TypeClass {
#define TYPE(Class, Base) Class,
-#define LAST_TYPE(Class) TypeLast = Class,
+#define LAST_TYPE(Class) TypeLast = Class
#define ABSTRACT_TYPE(Class, Base)
-#include "clang/AST/TypeNodes.def"
- TagFirst = Record, TagLast = Enum
+#include "clang/AST/TypeNodes.inc"
};
private:
@@ -1511,6 +1513,15 @@ protected:
unsigned SizeModifier : 3;
};
+ class ConstantArrayTypeBitfields {
+ friend class ConstantArrayType;
+
+ unsigned : NumTypeBits + 3 + 3;
+
+ /// Whether we have a stored size expression.
+ unsigned HasStoredSizeExpr : 1;
+ };
+
class BuiltinTypeBitfields {
friend class BuiltinType;
@@ -1732,6 +1743,7 @@ protected:
union {
TypeBitfields TypeBits;
ArrayTypeBitfields ArrayTypeBits;
+ ConstantArrayTypeBitfields ConstantArrayTypeBits;
AttributedTypeBitfields AttributedTypeBits;
AutoTypeBitfields AutoTypeBits;
BuiltinTypeBitfields BuiltinTypeBits;
@@ -2053,6 +2065,7 @@ public:
bool isCARCBridgableType() const;
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++11 std::nullptr_t
+ bool isNothrowT() const; // C++ std::nothrow_t
bool isAlignValT() const; // C++17 std::align_val_t
bool isStdByteType() const; // C++17 std::byte
bool isAtomicType() const; // C11 _Atomic()
@@ -2416,7 +2429,7 @@ template <> inline const Class##Type *Type::getAs() const { \
template <> inline const Class##Type *Type::castAs() const { \
return cast<Class##Type>(CanonicalType); \
}
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
/// This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
@@ -2429,6 +2442,9 @@ public:
// OpenCL extension types
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) Id,
#include "clang/Basic/OpenCLExtensionTypes.def"
+// SVE Types
+#define SVE_TYPE(Name, Id, SingletonId) Id,
+#include "clang/Basic/AArch64SVEACLETypes.def"
// All other builtin types
#define BUILTIN_TYPE(Id, SingletonId) Id,
#define LAST_BUILTIN_TYPE(Id) LastKind = Id
@@ -2858,22 +2874,8 @@ private:
protected:
friend class ASTContext; // ASTContext creates these.
- // C++ [temp.dep.type]p1:
- // A type is dependent if it is...
- // - an array type constructed from any dependent type or whose
- // size is specified by a constant expression that is
- // value-dependent,
- ArrayType(TypeClass tc, QualType et, QualType can,
- ArraySizeModifier sm, unsigned tq,
- bool ContainsUnexpandedParameterPack)
- : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
- et->isInstantiationDependentType() || tc == DependentSizedArray,
- (tc == VariableArray || et->isVariablyModifiedType()),
- ContainsUnexpandedParameterPack),
- ElementType(et) {
- ArrayTypeBits.IndexTypeQuals = tq;
- ArrayTypeBits.SizeModifier = sm;
- }
+ ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm,
+ unsigned tq, const Expr *sz = nullptr);
public:
QualType getElementType() const { return ElementType; }
@@ -2901,25 +2903,35 @@ public:
/// Represents the canonical version of C arrays with a specified constant size.
/// For example, the canonical type for 'int A[4 + 4*100]' is a
/// ConstantArrayType where the element type is 'int' and the size is 404.
-class ConstantArrayType : public ArrayType {
+class ConstantArrayType final
+ : public ArrayType,
+ private llvm::TrailingObjects<ConstantArrayType, const Expr *> {
+ friend class ASTContext; // ASTContext creates these.
+ friend TrailingObjects;
+
llvm::APInt Size; // Allows us to unique the type.
ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
- ArraySizeModifier sm, unsigned tq)
- : ArrayType(ConstantArray, et, can, sm, tq,
- et->containsUnexpandedParameterPack()),
- Size(size) {}
-
-protected:
- friend class ASTContext; // ASTContext creates these.
+ const Expr *sz, ArraySizeModifier sm, unsigned tq)
+ : ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) {
+ ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr;
+ if (ConstantArrayTypeBits.HasStoredSizeExpr) {
+ assert(!can.isNull() && "canonical constant array should not have size");
+ *getTrailingObjects<const Expr*>() = sz;
+ }
+ }
- ConstantArrayType(TypeClass tc, QualType et, QualType can,
- const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
- : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
- Size(size) {}
+ unsigned numTrailingObjects(OverloadToken<const Expr*>) const {
+ return ConstantArrayTypeBits.HasStoredSizeExpr;
+ }
public:
const llvm::APInt &getSize() const { return Size; }
+ const Expr *getSizeExpr() const {
+ return ConstantArrayTypeBits.HasStoredSizeExpr
+ ? *getTrailingObjects<const Expr *>()
+ : nullptr;
+ }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2933,19 +2945,15 @@ public:
/// can require, which limits the maximum size of the array.
static unsigned getMaxSizeBits(const ASTContext &Context);
- void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getElementType(), getSize(),
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
+ Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(),
getSizeModifier(), getIndexTypeCVRQualifiers());
}
- static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
- const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
- unsigned TypeQuals) {
- ID.AddPointer(ET.getAsOpaquePtr());
- ID.AddInteger(ArraySize.getZExtValue());
- ID.AddInteger(SizeMod);
- ID.AddInteger(TypeQuals);
- }
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx,
+ QualType ET, const llvm::APInt &ArraySize,
+ const Expr *SizeExpr, ArraySizeModifier SizeMod,
+ unsigned TypeQuals);
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray;
@@ -2960,8 +2968,7 @@ class IncompleteArrayType : public ArrayType {
IncompleteArrayType(QualType et, QualType can,
ArraySizeModifier sm, unsigned tq)
- : ArrayType(IncompleteArray, et, can, sm, tq,
- et->containsUnexpandedParameterPack()) {}
+ : ArrayType(IncompleteArray, et, can, sm, tq) {}
public:
friend class StmtIteratorBase;
@@ -3013,8 +3020,7 @@ class VariableArrayType : public ArrayType {
VariableArrayType(QualType et, QualType can, Expr *e,
ArraySizeModifier sm, unsigned tq,
SourceRange brackets)
- : ArrayType(VariableArray, et, can, sm, tq,
- et->containsUnexpandedParameterPack()),
+ : ArrayType(VariableArray, et, can, sm, tq, e),
SizeExpr((Stmt*) e), Brackets(brackets) {}
public:
@@ -4429,7 +4435,7 @@ public:
bool isBeingDefined() const;
static bool classof(const Type *T) {
- return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
+ return T->getTypeClass() == Enum || T->getTypeClass() == Record;
}
};
@@ -5563,7 +5569,7 @@ class ObjCTypeParamType : public Type,
public:
bool isSugared() const { return true; }
- QualType desugar() const { return getCanonicalTypeInternal(); }
+ QualType desugar() const;
static bool classof(const Type *T) {
return T->getTypeClass() == ObjCTypeParam;
@@ -6347,6 +6353,7 @@ inline bool QualType::isCForbiddenLValueType() const {
/// \returns True for types specified in C++0x [basic.fundamental].
inline bool Type::isFundamentalType() const {
return isVoidType() ||
+ isNullPtrType() ||
// FIXME: It's really annoying that we don't have an
// 'isArithmeticType()' which agrees with the standard definition.
(isArithmeticType() && !isEnumeralType());
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 40d17f991f1f..f305680d775c 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -106,7 +106,7 @@ public:
#define ABSTRACT_TYPE(Class, Base)
#define TYPE(Class, Base) \
Class = Type::Class,
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
Qualified
};
diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def
index c0dfe150d6cc..81448c7e7ce5 100644
--- a/include/clang/AST/TypeLocNodes.def
+++ b/include/clang/AST/TypeLocNodes.def
@@ -31,7 +31,7 @@
TYPELOC(Qualified, TypeLoc)
#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc)
#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc)
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
#undef DECLARATOR_TYPELOC
#undef TYPESPEC_TYPELOC
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
deleted file mode 100644
index 58a5f880cbe6..000000000000
--- a/include/clang/AST/TypeNodes.def
+++ /dev/null
@@ -1,135 +0,0 @@
-//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the AST type info database. Each type node is
-// enumerated by providing its name (e.g., "Builtin" or "Enum") and
-// base class (e.g., "Type" or "TagType"). Depending on where in the
-// abstract syntax tree the type will show up, the enumeration uses
-// one of five different macros:
-//
-// TYPE(Class, Base) - A type that can show up anywhere in the AST,
-// and might be dependent, canonical, or non-canonical. All clients
-// will need to understand these types.
-//
-// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
-// the type hierarchy but has no concrete instances.
-//
-// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
-// anywhere in the AST but will never be a part of a canonical
-// type. Clients that only need to deal with canonical types
-// (ignoring, e.g., typedefs and other type aliases used for
-// pretty-printing) can ignore these types.
-//
-// DEPENDENT_TYPE(Class, Base) - A type that will only show up
-// within a C++ template that has not been instantiated, e.g., a
-// type that is always dependent. Clients that do not need to deal
-// with uninstantiated C++ templates can ignore these types.
-//
-// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
-// is non-canonical unless it is dependent. Defaults to TYPE because
-// it is neither reliably dependent nor reliably non-canonical.
-//
-// There is a sixth macro, independent of the others. Most clients
-// will not need to use it.
-//
-// LEAF_TYPE(Class) - A type that never has inner types. Clients
-// which can operate on such types more efficiently may wish to do so.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ABSTRACT_TYPE
-# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-#ifndef NON_CANONICAL_TYPE
-# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-#ifndef DEPENDENT_TYPE
-# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
-# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
-#endif
-
-TYPE(Builtin, Type)
-TYPE(Complex, Type)
-TYPE(Pointer, Type)
-TYPE(BlockPointer, Type)
-ABSTRACT_TYPE(Reference, Type)
-TYPE(LValueReference, ReferenceType)
-TYPE(RValueReference, ReferenceType)
-TYPE(MemberPointer, Type)
-ABSTRACT_TYPE(Array, Type)
-TYPE(ConstantArray, ArrayType)
-TYPE(IncompleteArray, ArrayType)
-TYPE(VariableArray, ArrayType)
-DEPENDENT_TYPE(DependentSizedArray, ArrayType)
-DEPENDENT_TYPE(DependentSizedExtVector, Type)
-DEPENDENT_TYPE(DependentAddressSpace, Type)
-TYPE(Vector, Type)
-DEPENDENT_TYPE(DependentVector, Type)
-TYPE(ExtVector, VectorType)
-ABSTRACT_TYPE(Function, Type)
-TYPE(FunctionProto, FunctionType)
-TYPE(FunctionNoProto, FunctionType)
-DEPENDENT_TYPE(UnresolvedUsing, Type)
-NON_CANONICAL_TYPE(Paren, Type)
-NON_CANONICAL_TYPE(Typedef, Type)
-NON_CANONICAL_TYPE(MacroQualified, Type)
-NON_CANONICAL_TYPE(Adjusted, Type)
-NON_CANONICAL_TYPE(Decayed, AdjustedType)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type)
-ABSTRACT_TYPE(Tag, Type)
-TYPE(Record, TagType)
-TYPE(Enum, TagType)
-NON_CANONICAL_TYPE(Elaborated, Type)
-NON_CANONICAL_TYPE(Attributed, Type)
-DEPENDENT_TYPE(TemplateTypeParm, Type)
-NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
-DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
-ABSTRACT_TYPE(Deduced, Type)
-TYPE(Auto, DeducedType)
-TYPE(DeducedTemplateSpecialization, DeducedType)
-DEPENDENT_TYPE(InjectedClassName, Type)
-DEPENDENT_TYPE(DependentName, Type)
-DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
-NON_CANONICAL_TYPE(ObjCTypeParam, Type)
-TYPE(ObjCObject, Type)
-TYPE(ObjCInterface, ObjCObjectType)
-TYPE(ObjCObjectPointer, Type)
-TYPE(Pipe, Type)
-TYPE(Atomic, Type)
-
-#ifdef LAST_TYPE
-LAST_TYPE(Atomic)
-#undef LAST_TYPE
-#endif
-
-// These types are always leaves in the type hierarchy.
-#ifdef LEAF_TYPE
-LEAF_TYPE(Enum)
-LEAF_TYPE(Builtin)
-LEAF_TYPE(Record)
-LEAF_TYPE(InjectedClassName)
-LEAF_TYPE(ObjCInterface)
-LEAF_TYPE(TemplateTypeParm)
-#undef LEAF_TYPE
-#endif
-
-#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
-#undef DEPENDENT_TYPE
-#undef NON_CANONICAL_TYPE
-#undef ABSTRACT_TYPE
-#undef TYPE
diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h
index 8930ec853949..17301835fb18 100644
--- a/include/clang/AST/TypeVisitor.h
+++ b/include/clang/AST/TypeVisitor.h
@@ -70,7 +70,7 @@ public:
switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
}
llvm_unreachable("Unknown type class!");
}
@@ -80,7 +80,7 @@ public:
#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \
DISPATCH(PARENT); \
}
-#include "clang/AST/TypeNodes.def"
+#include "clang/AST/TypeNodes.inc"
/// Method called if \c ImpClass doesn't provide specific handler
/// for some type class.
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 063d8217d9aa..e34b31cbda88 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -19,15 +19,15 @@
//
// For more complicated match expressions we're often interested in accessing
// multiple parts of the matched AST nodes once a match is found. In that case,
-// use the id(...) matcher around the match expressions that match the nodes
-// you want to access.
+// call `.bind("name")` on match expressions that match the nodes you want to
+// access.
//
// For example, when we're interested in child classes of a certain class, we
// would write:
-// cxxRecordDecl(hasName("MyClass"), has(id("child", recordDecl())))
+// cxxRecordDecl(hasName("MyClass"), has(recordDecl().bind("child")))
// When the match is found via the MatchFinder, a user provided callback will
// be called with a BoundNodes instance that contains a mapping from the
-// strings that we provided for the id(...) calls to the nodes that were
+// strings that we provided for the `.bind()` calls to the nodes that were
// matched.
// In the given example, each time our matcher finds a match we get a callback
// where "child" is bound to the RecordDecl node of the matching child
@@ -131,15 +131,6 @@ private:
internal::BoundNodesMap MyBoundNodes;
};
-/// If the provided matcher matches a node, binds the node to \c ID.
-///
-/// FIXME: Do we want to support this now that we have bind()?
-template <typename T>
-internal::Matcher<T> id(StringRef ID,
- const internal::BindableMatcher<T> &InnerMatcher) {
- return InnerMatcher.bind(ID);
-}
-
/// Types of matchers for the top-level classes in the AST class
/// hierarchy.
/// @{
@@ -2611,8 +2602,9 @@ hasOverloadedOperatorName(StringRef Name) {
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name);
}
-/// Matches C++ classes that are directly or indirectly derived from
-/// a class matching \c Base.
+/// Matches C++ classes that are directly or indirectly derived from a class
+/// matching \c Base, or Objective-C classes that directly or indirectly
+/// subclass a class matching \c Base.
///
/// Note that a class is not considered to be derived from itself.
///
@@ -2632,33 +2624,128 @@ hasOverloadedOperatorName(StringRef Name) {
/// typedef Foo X;
/// class Bar : public Foo {}; // derived from a type that X is a typedef of
/// \endcode
-AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
- internal::Matcher<NamedDecl>, Base) {
- return Finder->classIsDerivedFrom(&Node, Base, Builder);
+///
+/// In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
+/// \code
+/// @interface NSObject @end
+/// @interface Bar : NSObject @end
+/// \endcode
+///
+/// Usable as: Matcher<CXXRecordDecl>, Matcher<ObjCInterfaceDecl>
+AST_POLYMORPHIC_MATCHER_P(
+ isDerivedFrom,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
+ internal::Matcher<NamedDecl>, Base) {
+ // Check if the node is a C++ struct/union/class.
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
+ return Finder->classIsDerivedFrom(RD, Base, Builder, /*Directly=*/false);
+
+ // The node must be an Objective-C class.
+ const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
+ return Finder->objcClassIsDerivedFrom(InterfaceDecl, Base, Builder,
+ /*Directly=*/false);
}
/// Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) {
- assert(!BaseName.empty());
- return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ isDerivedFrom,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
+ std::string, BaseName, 1) {
+ if (BaseName.empty())
+ return false;
+
+ const auto M = isDerivedFrom(hasName(BaseName));
+
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
+ return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
+
+ const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
+ return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
}
/// Similar to \c isDerivedFrom(), but also matches classes that directly
/// match \c Base.
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
- internal::Matcher<NamedDecl>, Base, 0) {
- return Matcher<CXXRecordDecl>(anyOf(Base, isDerivedFrom(Base)))
- .matches(Node, Finder, Builder);
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ isSameOrDerivedFrom,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
+ internal::Matcher<NamedDecl>, Base, 0) {
+ const auto M = anyOf(Base, isDerivedFrom(Base));
+
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
+ return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
+
+ const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
+ return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
}
/// Overloaded method as shortcut for
/// \c isSameOrDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
- BaseName, 1) {
- assert(!BaseName.empty());
- return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ isSameOrDerivedFrom,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
+ std::string, BaseName, 1) {
+ if (BaseName.empty())
+ return false;
+
+ const auto M = isSameOrDerivedFrom(hasName(BaseName));
+
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
+ return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
+
+ const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
+ return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
}
+/// Matches C++ or Objective-C classes that are directly derived from a class
+/// matching \c Base.
+///
+/// Note that a class is not considered to be derived from itself.
+///
+/// Example matches Y, C (Base == hasName("X"))
+/// \code
+/// class X;
+/// class Y : public X {}; // directly derived
+/// class Z : public Y {}; // indirectly derived
+/// typedef X A;
+/// typedef A B;
+/// class C : public B {}; // derived from a typedef of X
+/// \endcode
+///
+/// In the following example, Bar matches isDerivedFrom(hasName("X")):
+/// \code
+/// class Foo;
+/// typedef Foo X;
+/// class Bar : public Foo {}; // derived from a type that X is a typedef of
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ isDirectlyDerivedFrom,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
+ internal::Matcher<NamedDecl>, Base, 0) {
+ // Check if the node is a C++ struct/union/class.
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
+ return Finder->classIsDerivedFrom(RD, Base, Builder, /*Directly=*/true);
+
+ // The node must be an Objective-C class.
+ const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
+ return Finder->objcClassIsDerivedFrom(InterfaceDecl, Base, Builder,
+ /*Directly=*/true);
+}
+
+/// Overloaded method as shortcut for \c isDirectlyDerivedFrom(hasName(...)).
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ isDirectlyDerivedFrom,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
+ std::string, BaseName, 1) {
+ if (BaseName.empty())
+ return false;
+ const auto M = isDirectlyDerivedFrom(hasName(BaseName));
+
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(&Node))
+ return Matcher<CXXRecordDecl>(M).matches(*RD, Finder, Builder);
+
+ const auto *InterfaceDecl = cast<ObjCInterfaceDecl>(&Node);
+ return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
+}
/// Matches the first method of a class or struct that satisfies \c
/// InnerMatcher.
///
@@ -6358,10 +6445,9 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
/// expr(nullPointerConstant())
/// matches the initializer for v1, v2, v3, cp, and ip. Does not match the
/// initializer for i.
-AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
- return anyOf(
- gnuNullExpr(), cxxNullPtrLiteralExpr(),
- integerLiteral(equals(0), hasParent(expr(hasType(pointerType())))));
+AST_MATCHER(Expr, nullPointerConstant) {
+ return Node.isNullPointerConstant(Finder->getASTContext(),
+ Expr::NPC_ValueDependentIsNull);
}
/// Matches declaration of the function the statement belongs to
@@ -6375,7 +6461,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
/// \endcode
/// returnStmt(forFunction(hasName("operator=")))
/// matches 'return *this'
-/// but does match 'return > 0'
+/// but does not match 'return v > 0'
AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
InnerMatcher) {
const auto &Parents = Finder->getASTContext().getParents(Node);
@@ -6498,14 +6584,15 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
}
/// Matches expressions that match InnerMatcher that are possibly wrapped in an
-/// elidable constructor.
+/// elidable constructor and other corresponding bookkeeping nodes.
///
-/// In C++17 copy elidable constructors are no longer being
-/// generated in the AST as it is not permitted by the standard. They are
-/// however part of the AST in C++14 and earlier. Therefore, to write a matcher
-/// that works in all language modes, the matcher has to skip elidable
-/// constructor AST nodes if they appear in the AST. This matcher can be used to
-/// skip those elidable constructors.
+/// In C++17, elidable copy constructors are no longer being generated in the
+/// AST as it is not permitted by the standard. They are, however, part of the
+/// AST in C++14 and earlier. So, a matcher must abstract over these differences
+/// to work in all language modes. This matcher skips elidable constructor-call
+/// AST nodes, `ExprWithCleanups` nodes wrapping elidable constructor-calls and
+/// various implicit nodes inside the constructor calls, all of which will not
+/// appear in the C++17 AST.
///
/// Given
///
@@ -6517,13 +6604,20 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
/// }
/// \endcode
///
-/// ``varDecl(hasInitializer(any(
-/// ignoringElidableConstructorCall(callExpr()),
-/// exprWithCleanups(ignoringElidableConstructorCall(callExpr()))))``
-/// matches ``H D = G()``
+/// ``varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))``
+/// matches ``H D = G()`` in C++11 through C++17 (and beyond).
AST_MATCHER_P(Expr, ignoringElidableConstructorCall,
ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
- if (const auto *CtorExpr = dyn_cast<CXXConstructExpr>(&Node)) {
+ // E tracks the node that we are examining.
+ const Expr *E = &Node;
+ // If present, remove an outer `ExprWithCleanups` corresponding to the
+ // underlying `CXXConstructExpr`. This check won't cover all cases of added
+ // `ExprWithCleanups` corresponding to `CXXConstructExpr` nodes (because the
+ // EWC is placed on the outermost node of the expression, which this may not
+ // be), but, it still improves the coverage of this matcher.
+ if (const auto *CleanupsExpr = dyn_cast<ExprWithCleanups>(&Node))
+ E = CleanupsExpr->getSubExpr();
+ if (const auto *CtorExpr = dyn_cast<CXXConstructExpr>(E)) {
if (CtorExpr->isElidable()) {
if (const auto *MaterializeTemp =
dyn_cast<MaterializeTemporaryExpr>(CtorExpr->getArg(0))) {
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index b1bb0bfa3218..e9fa920b6bce 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -183,7 +183,8 @@ public:
/// Note that we're using std::map here, as for memoization:
/// - we need a comparison operator
/// - we need an assignment operator
- using IDToNodeMap = std::map<std::string, ast_type_traits::DynTypedNode>;
+ using IDToNodeMap =
+ std::map<std::string, ast_type_traits::DynTypedNode, std::less<>>;
const IDToNodeMap &getMap() const {
return NodeMap;
@@ -971,13 +972,23 @@ public:
virtual ~ASTMatchFinder() = default;
- /// Returns true if the given class is directly or indirectly derived
+ /// Returns true if the given C++ class is directly or indirectly derived
/// from a base type matching \c base.
///
- /// A class is considered to be also derived from itself.
+ /// A class is not considered to be derived from itself.
virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
const Matcher<NamedDecl> &Base,
- BoundNodesTreeBuilder *Builder) = 0;
+ BoundNodesTreeBuilder *Builder,
+ bool Directly) = 0;
+
+ /// Returns true if the given Objective-C class is directly or indirectly
+ /// derived from a base class matching \c base.
+ ///
+ /// A class is not considered to be derived from itself.
+ virtual bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder,
+ bool Directly) = 0;
template <typename T>
bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
@@ -1315,7 +1326,7 @@ class ForEachMatcher : public WrapperMatcherInterface<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.
+/// conversion operator.
template <typename... Ps> class VariadicOperatorMatcher {
public:
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
@@ -1324,14 +1335,14 @@ public:
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::constructVariadic(
Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
- getMatchers<T>(llvm::index_sequence_for<Ps...>()))
+ getMatchers<T>(std::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
private:
// Helper method to unpack the tuple into a vector.
template <typename T, std::size_t... Is>
- std::vector<DynTypedMatcher> getMatchers(llvm::index_sequence<Is...>) const {
+ std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const {
return {Matcher<T>(std::get<Is>(Params))...};
}
diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h
index 1961d571e9e1..9faa78cde89c 100644
--- a/include/clang/Analysis/AnalysisDeclContext.h
+++ b/include/clang/Analysis/AnalysisDeclContext.h
@@ -183,9 +183,8 @@ public:
const ImplicitParamDecl *getSelfDecl() const;
const StackFrameContext *getStackFrame(LocationContext const *Parent,
- const Stmt *S,
- const CFGBlock *Blk,
- unsigned Idx);
+ const Stmt *S, const CFGBlock *Blk,
+ unsigned BlockCount, unsigned Idx);
const BlockInvocationContext *
getBlockInvocationContext(const LocationContext *parent,
@@ -258,7 +257,7 @@ public:
return getAnalysisDeclContext()->getAnalysis<T>();
}
- ParentMap &getParentMap() const {
+ const ParentMap &getParentMap() const {
return getAnalysisDeclContext()->getParentMap();
}
@@ -303,15 +302,19 @@ class StackFrameContext : public LocationContext {
// The parent block of the callsite.
const CFGBlock *Block;
+ // The number of times the 'Block' has been visited.
+ // It allows discriminating between stack frames of the same call that is
+ // called multiple times in a loop.
+ const unsigned BlockCount;
+
// The index of the callsite in the CFGBlock.
- unsigned Index;
+ const unsigned Index;
StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
- const Stmt *s, const CFGBlock *blk,
- unsigned idx,
- int64_t ID)
- : LocationContext(StackFrame, ctx, parent, ID), CallSite(s),
- Block(blk), Index(idx) {}
+ const Stmt *s, const CFGBlock *blk, unsigned blockCount,
+ unsigned idx, int64_t ID)
+ : LocationContext(StackFrame, ctx, parent, ID), CallSite(s), Block(blk),
+ BlockCount(blockCount), Index(idx) {}
public:
~StackFrameContext() override = default;
@@ -329,9 +332,10 @@ public:
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const Stmt *s,
- const CFGBlock *blk, unsigned idx) {
+ const CFGBlock *blk, unsigned blockCount, unsigned idx) {
ProfileCommon(ID, StackFrame, ctx, parent, s);
ID.AddPointer(blk);
+ ID.AddInteger(blockCount);
ID.AddInteger(idx);
}
@@ -410,8 +414,8 @@ public:
const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
const LocationContext *parent,
- const Stmt *s,
- const CFGBlock *blk, unsigned idx);
+ const Stmt *s, const CFGBlock *blk,
+ unsigned blockCount, unsigned idx);
const ScopeContext *getScope(AnalysisDeclContext *ctx,
const LocationContext *parent,
@@ -483,26 +487,25 @@ public:
bool synthesizeBodies() const { return SynthesizeBodies; }
const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
- LocationContext const *Parent,
- const Stmt *S,
- const CFGBlock *Blk,
- unsigned Idx) {
- return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
+ const LocationContext *Parent,
+ const Stmt *S, const CFGBlock *Blk,
+ unsigned BlockCount, unsigned Idx) {
+ return LocContexts.getStackFrame(Ctx, Parent, S, Blk, BlockCount, Idx);
}
// Get the top level stack frame.
const StackFrameContext *getStackFrame(const Decl *D) {
return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
- 0);
+ 0, 0);
}
// Get a stack frame with parent.
StackFrameContext const *getStackFrame(const Decl *D,
- LocationContext const *Parent,
- const Stmt *S,
- const CFGBlock *Blk,
- unsigned Idx) {
- return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
+ const LocationContext *Parent,
+ const Stmt *S, const CFGBlock *Blk,
+ unsigned BlockCount, unsigned Idx) {
+ return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, BlockCount,
+ Idx);
}
/// Get a reference to {@code BodyFarm} instance.
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 277b2292e5ea..a8301a0e0063 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -121,6 +121,12 @@ public:
x |= Data1.getInt();
return (Kind) x;
}
+
+ void dumpToStream(llvm::raw_ostream &OS) const;
+
+ void dump() const {
+ dumpToStream(llvm::errs());
+ }
};
class CFGStmt : public CFGElement {
@@ -610,6 +616,153 @@ class CFGBlock {
bool empty() const { return Impl.empty(); }
};
+ /// A convenience class for comparing CFGElements, since methods of CFGBlock
+ /// like operator[] return CFGElements by value. This is practically a wrapper
+ /// around a (CFGBlock, Index) pair.
+ template <bool IsConst> class ElementRefImpl {
+
+ template <bool IsOtherConst> friend class ElementRefImpl;
+
+ using CFGBlockPtr =
+ typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
+
+ using CFGElementPtr = typename std::conditional<IsConst, const CFGElement *,
+ CFGElement *>::type;
+
+ protected:
+ CFGBlockPtr Parent;
+ size_t Index;
+
+ public:
+ ElementRefImpl(CFGBlockPtr Parent, size_t Index)
+ : Parent(Parent), Index(Index) {}
+
+ template <bool IsOtherConst>
+ ElementRefImpl(ElementRefImpl<IsOtherConst> Other)
+ : ElementRefImpl(Other.Parent, Other.Index) {}
+
+ size_t getIndexInBlock() const { return Index; }
+
+ CFGBlockPtr getParent() { return Parent; }
+ CFGBlockPtr getParent() const { return Parent; }
+
+ bool operator<(ElementRefImpl Other) const {
+ return std::make_pair(Parent, Index) <
+ std::make_pair(Other.Parent, Other.Index);
+ }
+
+ bool operator==(ElementRefImpl Other) const {
+ return Parent == Other.Parent && Index == Other.Index;
+ }
+
+ bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }
+ CFGElement operator*() const { return (*Parent)[Index]; }
+ CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }
+
+ void dumpToStream(llvm::raw_ostream &OS) const {
+ OS << getIndexInBlock() + 1 << ": ";
+ (*this)->dumpToStream(OS);
+ }
+
+ void dump() const {
+ dumpToStream(llvm::errs());
+ }
+ };
+
+ template <bool IsReverse, bool IsConst> class ElementRefIterator {
+
+ template <bool IsOtherReverse, bool IsOtherConst>
+ friend class ElementRefIterator;
+
+ using CFGBlockRef =
+ typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
+
+ using UnderlayingIteratorTy = typename std::conditional<
+ IsConst,
+ typename std::conditional<IsReverse,
+ ElementList::const_reverse_iterator,
+ ElementList::const_iterator>::type,
+ typename std::conditional<IsReverse, ElementList::reverse_iterator,
+ ElementList::iterator>::type>::type;
+
+ using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>;
+ using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>;
+
+ public:
+ using difference_type = typename IteratorTraits::difference_type;
+ using value_type = ElementRef;
+ using pointer = ElementRef *;
+ using iterator_category = typename IteratorTraits::iterator_category;
+
+ private:
+ CFGBlockRef Parent;
+ UnderlayingIteratorTy Pos;
+
+ public:
+ ElementRefIterator(CFGBlockRef Parent, UnderlayingIteratorTy Pos)
+ : Parent(Parent), Pos(Pos) {}
+
+ template <bool IsOtherConst>
+ ElementRefIterator(ElementRefIterator<false, IsOtherConst> E)
+ : ElementRefIterator(E.Parent, E.Pos.base()) {}
+
+ template <bool IsOtherConst>
+ ElementRefIterator(ElementRefIterator<true, IsOtherConst> E)
+ : ElementRefIterator(E.Parent, llvm::make_reverse_iterator(E.Pos)) {}
+
+ bool operator<(ElementRefIterator Other) const {
+ assert(Parent == Other.Parent);
+ return Pos < Other.Pos;
+ }
+
+ bool operator==(ElementRefIterator Other) const {
+ return Parent == Other.Parent && Pos == Other.Pos;
+ }
+
+ bool operator!=(ElementRefIterator Other) const {
+ return !(*this == Other);
+ }
+
+ private:
+ template <bool IsOtherConst>
+ static size_t
+ getIndexInBlock(CFGBlock::ElementRefIterator<true, IsOtherConst> E) {
+ return E.Parent->size() - (E.Pos - E.Parent->rbegin()) - 1;
+ }
+
+ template <bool IsOtherConst>
+ static size_t
+ getIndexInBlock(CFGBlock::ElementRefIterator<false, IsOtherConst> E) {
+ return E.Pos - E.Parent->begin();
+ }
+
+ public:
+ value_type operator*() { return {Parent, getIndexInBlock(*this)}; }
+
+ difference_type operator-(ElementRefIterator Other) const {
+ return Pos - Other.Pos;
+ }
+
+ ElementRefIterator operator++() {
+ ++this->Pos;
+ return *this;
+ }
+ ElementRefIterator operator++(int) {
+ ElementRefIterator Ret = *this;
+ ++*this;
+ return Ret;
+ }
+ ElementRefIterator operator+(size_t count) {
+ this->Pos += count;
+ return *this;
+ }
+ ElementRefIterator operator-(size_t count) {
+ this->Pos -= count;
+ return *this;
+ }
+ };
+
+public:
/// The set of statements in the basic block.
ElementList Elements;
@@ -715,6 +868,8 @@ public:
using reverse_iterator = ElementList::reverse_iterator;
using const_reverse_iterator = ElementList::const_reverse_iterator;
+ size_t getIndexInCFG() const;
+
CFGElement front() const { return Elements.front(); }
CFGElement back() const { return Elements.back(); }
@@ -728,6 +883,38 @@ public:
const_reverse_iterator rbegin() const { return Elements.rbegin(); }
const_reverse_iterator rend() const { return Elements.rend(); }
+ using CFGElementRef = ElementRefImpl<false>;
+ using ConstCFGElementRef = ElementRefImpl<true>;
+
+ using ref_iterator = ElementRefIterator<false, false>;
+ using ref_iterator_range = llvm::iterator_range<ref_iterator>;
+ using const_ref_iterator = ElementRefIterator<false, true>;
+ using const_ref_iterator_range = llvm::iterator_range<const_ref_iterator>;
+
+ using reverse_ref_iterator = ElementRefIterator<true, false>;
+ using reverse_ref_iterator_range = llvm::iterator_range<reverse_ref_iterator>;
+
+ using const_reverse_ref_iterator = ElementRefIterator<true, true>;
+ using const_reverse_ref_iterator_range =
+ llvm::iterator_range<const_reverse_ref_iterator>;
+
+ ref_iterator ref_begin() { return {this, begin()}; }
+ ref_iterator ref_end() { return {this, end()}; }
+ const_ref_iterator ref_begin() const { return {this, begin()}; }
+ const_ref_iterator ref_end() const { return {this, end()}; }
+
+ reverse_ref_iterator rref_begin() { return {this, rbegin()}; }
+ reverse_ref_iterator rref_end() { return {this, rend()}; }
+ const_reverse_ref_iterator rref_begin() const { return {this, rbegin()}; }
+ const_reverse_ref_iterator rref_end() const { return {this, rend()}; }
+
+ ref_iterator_range refs() { return {ref_begin(), ref_end()}; }
+ const_ref_iterator_range refs() const { return {ref_begin(), ref_end()}; }
+ reverse_ref_iterator_range rrefs() { return {rref_begin(), rref_end()}; }
+ const_reverse_ref_iterator_range rrefs() const {
+ return {rref_begin(), rref_end()};
+ }
+
unsigned size() const { return Elements.size(); }
bool empty() const { return Elements.empty(); }
@@ -855,6 +1042,10 @@ public:
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
void setHasNoReturnElement() { HasNoReturnElement = true; }
+ /// Returns true if the block would eventually end with a sink (a noreturn
+ /// node).
+ bool isInevitablySinking() const;
+
CFGTerminator getTerminator() const { return Terminator; }
Stmt *getTerminatorStmt() { return Terminator.getStmt(); }
@@ -894,7 +1085,7 @@ public:
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
bool AddQuotes) const;
-
+
void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
OS << "BB#" << getBlockID();
}
@@ -1010,7 +1201,6 @@ public:
*I = CFGScopeEnd(VD, S);
return ++I;
}
-
};
/// CFGCallback defines methods that should be called when a logical
@@ -1023,6 +1213,7 @@ public:
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
virtual void compareBitwiseEquality(const BinaryOperator *B,
bool isAlwaysTrue) {}
+ virtual void compareBitwiseOr(const BinaryOperator *B) {}
};
/// Represents a source-level, intra-procedural CFG that represents the
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index 49c04490fed2..dae2b58ffc10 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -131,6 +131,7 @@ public:
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool shouldVisitTemplateInstantiations() const { return true; }
+ bool shouldVisitImplicitCode() const { return true; }
private:
/// Add the given declaration to the call graph.
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h
index 5230742a4aa4..6730057cf0ad 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/Analysis/PathDiagnostic.h
@@ -52,11 +52,6 @@ class SourceManager;
namespace ento {
-class ExplodedNode;
-class SymExpr;
-
-using SymbolRef = const SymExpr *;
-
//===----------------------------------------------------------------------===//
// High-level interface for handlers of path-sensitive diagnostics.
//===----------------------------------------------------------------------===//
@@ -125,6 +120,13 @@ public:
};
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
+
+ bool shouldGenerateDiagnostics() const {
+ return getGenerationScheme() != None;
+ }
+
+ bool shouldAddPathEdges() const { return getGenerationScheme() == Extensive; }
+
virtual bool supportsLogicalOpControlFlow() const { return false; }
/// Return true if the PathDiagnosticConsumer supports individual
@@ -269,19 +271,21 @@ public:
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
const SourceManager &SM);
- /// Create a location corresponding to the given valid ExplodedNode.
+ /// Create a location corresponding to the given valid ProgramPoint.
static PathDiagnosticLocation create(const ProgramPoint &P,
const SourceManager &SMng);
- /// Create a location corresponding to the next valid ExplodedNode as end
- /// of path location.
- static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N,
- const SourceManager &SM);
-
/// Convert the given location into a single kind location.
static PathDiagnosticLocation createSingleLocation(
const PathDiagnosticLocation &PDL);
+ /// Construct a source location that corresponds to either the beginning
+ /// or the end of the given statement, or a nearby valid source location
+ /// if the statement does not have a valid source location of its own.
+ static SourceLocation
+ getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC,
+ bool UseEndOfStatement = false);
+
bool operator==(const PathDiagnosticLocation &X) const {
return K == X.K && Loc == X.Loc && Range == X.Range;
}
@@ -326,13 +330,6 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const;
void dump() const;
-
- /// Given an exploded node, retrieve the statement that should be used
- /// for the diagnostic location.
- static const Stmt *getStmt(const ExplodedNode *N);
-
- /// Retrieve the statement corresponding to the successor node.
- static const Stmt *getNextStmt(const ExplodedNode *N);
};
class PathDiagnosticLocationPair {
@@ -386,6 +383,7 @@ private:
StringRef Tag;
std::vector<SourceRange> ranges;
+ std::vector<FixItHint> fixits;
protected:
PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
@@ -430,9 +428,16 @@ public:
ranges.push_back(SourceRange(B,E));
}
+ void addFixit(FixItHint F) {
+ fixits.push_back(F);
+ }
+
/// Return the SourceRanges associated with this PathDiagnosticPiece.
ArrayRef<SourceRange> getRanges() const { return ranges; }
+ /// Return the fix-it hints associated with this PathDiagnosticPiece.
+ ArrayRef<FixItHint> getFixits() const { return fixits; }
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
void setAsLastInMainSourceFile() {
@@ -446,7 +451,9 @@ public:
virtual void dump() const = 0;
};
-class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> {
+using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
+
+class PathPieces : public std::list<PathDiagnosticPieceRef> {
void flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const;
@@ -486,65 +493,13 @@ public:
}
};
-/// Interface for classes constructing Stack hints.
-///
-/// If a PathDiagnosticEvent occurs in a different frame than the final
-/// diagnostic the hints can be used to summarize the effect of the call.
-class StackHintGenerator {
-public:
- virtual ~StackHintGenerator() = 0;
-
- /// Construct the Diagnostic message for the given ExplodedNode.
- virtual std::string getMessage(const ExplodedNode *N) = 0;
-};
-
-/// Constructs a Stack hint for the given symbol.
-///
-/// The class knows how to construct the stack hint message based on
-/// traversing the CallExpr associated with the call and checking if the given
-/// symbol is returned or is one of the arguments.
-/// The hint can be customized by redefining 'getMessageForX()' methods.
-class StackHintGeneratorForSymbol : public StackHintGenerator {
-private:
- SymbolRef Sym;
- std::string Msg;
-
-public:
- StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
- ~StackHintGeneratorForSymbol() override = default;
-
- /// Search the call expression for the symbol Sym and dispatch the
- /// 'getMessageForX()' methods to construct a specific message.
- std::string getMessage(const ExplodedNode *N) override;
-
- /// Produces the message of the following form:
- /// 'Msg via Nth parameter'
- virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
-
- virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
- return Msg;
- }
-
- virtual std::string getMessageForSymbolNotFound() {
- return Msg;
- }
-};
-
class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
Optional<bool> IsPrunable;
- /// If the event occurs in a different frame than the final diagnostic,
- /// supply a message that will be used to construct an extra hint on the
- /// returns from all the calls on the stack from this event to the final
- /// diagnostic.
- std::unique_ptr<StackHintGenerator> CallStackHint;
-
public:
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
- StringRef s, bool addPosRange = true,
- StackHintGenerator *stackHint = nullptr)
- : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
- CallStackHint(stackHint) {}
+ StringRef s, bool addPosRange = true)
+ : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
~PathDiagnosticEventPiece() override;
/// Mark the diagnostic piece as being potentially prunable. This
@@ -561,16 +516,6 @@ public:
return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
}
- bool hasCallStackHint() { return (bool)CallStackHint; }
-
- /// Produce the hint for the given node. The node contains
- /// information about the call for which the diagnostic can be generated.
- std::string getCallStackMessage(const ExplodedNode *N) {
- if (CallStackHint)
- return CallStackHint->getMessage(N);
- return {};
- }
-
void dump() const override;
static bool classof(const PathDiagnosticPiece *P) {
@@ -726,8 +671,6 @@ public:
PathPieces subPieces;
- bool containsEvent() const;
-
void flattenLocations() override {
PathDiagnosticSpotPiece::flattenLocations();
for (const auto &I : subPieces)
@@ -782,7 +725,7 @@ using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>;
/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
/// each which represent the pieces of the path.
class PathDiagnostic : public llvm::FoldingSetNode {
- std::string CheckName;
+ std::string CheckerName;
const Decl *DeclWithIssue;
std::string BugType;
std::string VerboseDesc;
@@ -806,7 +749,7 @@ class PathDiagnostic : public llvm::FoldingSetNode {
public:
PathDiagnostic() = delete;
- PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
+ PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
StringRef category, PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique,
@@ -836,7 +779,7 @@ public:
bool isWithinCall() const { return !pathStack.empty(); }
- void setEndOfPath(std::shared_ptr<PathDiagnosticPiece> EndPiece) {
+ void setEndOfPath(PathDiagnosticPieceRef EndPiece) {
assert(!Loc.isValid() && "End location already set!");
Loc = EndPiece->getLocation();
assert(Loc.isValid() && "Invalid location for end-of-path piece");
@@ -849,26 +792,16 @@ public:
VerboseDesc += S;
}
- /// 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;
}
- StringRef getCheckName() const { return CheckName; }
+ StringRef getCheckerName() const { return CheckerName; }
StringRef getBugType() const { return BugType; }
StringRef getCategory() const { return Category; }
- /// Return the semantic context where an issue occurred. If the
- /// issue occurs along a path, this represents the "central" area
- /// where the bug manifests.
- const Decl *getDeclWithIssue() const { return DeclWithIssue; }
-
using meta_iterator = std::deque<std::string>::const_iterator;
meta_iterator meta_begin() const { return OtherDesc.begin(); }
@@ -883,10 +816,23 @@ public:
return *ExecutedLines;
}
+ /// Return the semantic context where an issue occurred. If the
+ /// issue occurs along a path, this represents the "central" area
+ /// where the bug manifests.
+ const Decl *getDeclWithIssue() const { return DeclWithIssue; }
+
+ void setDeclWithIssue(const Decl *D) {
+ DeclWithIssue = D;
+ }
+
PathDiagnosticLocation getLocation() const {
return Loc;
}
+ void setLocation(PathDiagnosticLocation NewLoc) {
+ Loc = NewLoc;
+ }
+
/// Get the location on which the report should be uniqued.
PathDiagnosticLocation getUniqueingLoc() const {
return UniqueingLoc;
@@ -917,7 +863,6 @@ public:
};
} // namespace ento
-
} // namespace clang
#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
diff --git a/include/clang/Basic/AArch64SVEACLETypes.def b/include/clang/Basic/AArch64SVEACLETypes.def
new file mode 100644
index 000000000000..7d387587dc29
--- /dev/null
+++ b/include/clang/Basic/AArch64SVEACLETypes.def
@@ -0,0 +1,70 @@
+//===-- AArch64SVEACLETypes.def - Metadata about SVE types ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines various SVE builtin types. The macros are:
+//
+// SVE_TYPE(Name, Id, SingletonId) - A builtin type that has not been
+// covered by any other #define. Defining this macro covers all
+// the builtins.
+//
+// SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP) -
+// An SVE scalable vector.
+//
+// SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind) - An SVE scalable
+// predicate.
+//
+// where:
+//
+// - Name is the name of the builtin type.
+//
+// - BuiltinType::Id is the enumerator defining the type.
+//
+// - Context.SingletonId is the global singleton of this type.
+//
+// - ElKind enumerates the type of the elements.
+//
+// - ElBits is the size of one element in bits.
+//
+// - IsSigned is true for vectors of signed integer elements and
+// for vectors of floating-point elements.
+//
+// - IsFP is true for vectors of floating-point elements.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SVE_VECTOR_TYPE
+#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\
+ SVE_TYPE(Name, Id, SingletonId)
+#endif
+
+#ifndef SVE_PREDICATE_TYPE
+#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind)\
+ SVE_TYPE(Name, Id, SingletonId)
+#endif
+
+//===- Vector point types -----------------------------------------------===//
+
+SVE_VECTOR_TYPE("__SVInt8_t", SveInt8, SveInt8Ty, SveElSInt8, 8, true, false)
+SVE_VECTOR_TYPE("__SVInt16_t", SveInt16, SveInt16Ty, SveElSInt16, 16, true, false)
+SVE_VECTOR_TYPE("__SVInt32_t", SveInt32, SveInt32Ty, SveElSInt32, 32, true, false)
+SVE_VECTOR_TYPE("__SVInt64_t", SveInt64, SveInt64Ty, SveElSInt64, 64, true, false)
+
+SVE_VECTOR_TYPE("__SVUint8_t", SveUint8, SveUint8Ty, SveElUInt8, 8, false, false)
+SVE_VECTOR_TYPE("__SVUint16_t", SveUint16, SveUint16Ty, SveElUInt16, 16, false, false)
+SVE_VECTOR_TYPE("__SVUint32_t", SveUint32, SveUint32Ty, SveElUInt32, 32, false, false)
+SVE_VECTOR_TYPE("__SVUint64_t", SveUint64, SveUint64Ty, SveElUInt64, 64, false, false)
+
+SVE_VECTOR_TYPE("__SVFloat16_t", SveFloat16, SveFloat16Ty, SveElHalf, 16, true, true)
+SVE_VECTOR_TYPE("__SVFloat32_t", SveFloat32, SveFloat32Ty, SveElFloat, 32, true, true)
+SVE_VECTOR_TYPE("__SVFloat64_t", SveFloat64, SveFloat64Ty, SveElDouble, 64, true, true)
+
+SVE_PREDICATE_TYPE("__SVBool_t", SveBool, SveBoolTy, SveElBool)
+
+#undef SVE_VECTOR_TYPE
+#undef SVE_PREDICATE_TYPE
+#undef SVE_TYPE
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index d39b16e62b7f..c3a2ee325dfe 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -722,9 +722,25 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
def AsmLabel : InheritableAttr {
let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
- let Args = [StringArgument<"Label">];
+ let Args = [
+ // Label specifies the mangled name for the decl.
+ StringArgument<"Label">,
+
+ // IsLiteralLabel specifies whether the label is literal (i.e. suppresses
+ // the global C symbol prefix) or not. If not, the mangle-suppression prefix
+ // ('\01') is omitted from the decl name at the LLVM IR level.
+ //
+ // Non-literal labels are used by some external AST sources like LLDB.
+ BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
+ ];
let SemaHandler = 0;
- let Documentation = [Undocumented];
+ let Documentation = [AsmLabelDocs];
+ let AdditionalMembers =
+[{
+bool isEquivalent(AsmLabelAttr *Other) const {
+ return getLabel() == Other->getLabel() && getIsLiteralLabel() == Other->getIsLiteralLabel();
+}
+}];
}
def Availability : InheritableAttr {
@@ -911,6 +927,17 @@ def Const : InheritableAttr {
let Documentation = [Undocumented];
}
+def ConstInit : InheritableAttr {
+ // This attribute does not have a C [[]] spelling because it requires the
+ // CPlusPlus language option.
+ let Spellings = [Keyword<"constinit">,
+ Clang<"require_constant_initialization", 0>];
+ let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
+ let Accessors = [Accessor<"isConstinit", [Keyword<"constinit">]>];
+ let Documentation = [ConstInitDocs];
+ let LangOpts = [CPlusPlus];
+}
+
def Constructor : InheritableAttr {
let Spellings = [GCC<"constructor">];
let Args = [DefaultIntArgument<"Priority", 65535>];
@@ -1170,7 +1197,7 @@ def ExtVectorType : Attr {
def FallThrough : StmtAttr {
let Spellings = [CXX11<"", "fallthrough", 201603>, C2x<"", "fallthrough">,
- CXX11<"clang", "fallthrough">];
+ CXX11<"clang", "fallthrough">, GCC<"fallthrough">];
// let Subjects = [NullStmt];
let Documentation = [FallthroughDocs];
}
@@ -1935,15 +1962,6 @@ def ReqdWorkGroupSize : InheritableAttr {
let Documentation = [Undocumented];
}
-def RequireConstantInit : InheritableAttr {
- // This attribute does not have a C [[]] spelling because it requires the
- // CPlusPlus language option.
- let Spellings = [Clang<"require_constant_initialization", 0>];
- let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
- let Documentation = [RequireConstantInitDocs];
- let LangOpts = [CPlusPlus];
-}
-
def WorkGroupSizeHint : InheritableAttr {
// Does not have a [[]] spelling because it is an OpenCL-related attribute.
let Spellings = [GNU<"work_group_size_hint">];
@@ -2002,6 +2020,14 @@ def PragmaClangRodataSection : InheritableAttr {
let Documentation = [Undocumented];
}
+def PragmaClangRelroSection : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let Args = [StringArgument<"Name">];
+ let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
def PragmaClangTextSection : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
@@ -2335,11 +2361,19 @@ def WarnUnused : InheritableAttr {
}
def WarnUnusedResult : InheritableAttr {
- let Spellings = [CXX11<"", "nodiscard", 201603>, C2x<"", "nodiscard">,
+ let Spellings = [CXX11<"", "nodiscard", 201907>, C2x<"", "nodiscard">,
CXX11<"clang", "warn_unused_result">,
GCC<"warn_unused_result">];
let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>;
+ let Args = [StringArgument<"Message", 1>];
let Documentation = [WarnUnusedResultsDocs];
+ let AdditionalMembers = [{
+ // Check whether this the C++11 nodiscard version, even in non C++11
+ // spellings.
+ bool IsCXX11NoDiscard() const {
+ return this->getSemanticSpelling() == CXX11_nodiscard;
+ }
+ }];
}
def Weak : InheritableAttr {
@@ -2428,6 +2462,12 @@ def NoSanitizeSpecific : InheritableAttr {
let ASTNode = 0;
}
+def CFICanonicalJumpTable : InheritableAttr {
+ let Spellings = [Clang<"cfi_canonical_jump_table">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [CFICanonicalJumpTableDocs];
+}
+
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
// Not all of these attributes will be given a [[]] spelling. The attributes
// which require access to function parameter names cannot use the [[]] spelling
@@ -2788,6 +2828,20 @@ def TypeTagForDatatype : InheritableAttr {
let Documentation = [TypeTagForDatatypeDocs];
}
+def Owner : InheritableAttr {
+ let Spellings = [CXX11<"gsl", "Owner">];
+ let Subjects = SubjectList<[Struct]>;
+ let Args = [TypeArgument<"DerefType", /*opt=*/1>];
+ let Documentation = [LifetimeOwnerDocs];
+}
+
+def Pointer : InheritableAttr {
+ let Spellings = [CXX11<"gsl", "Pointer">];
+ let Subjects = SubjectList<[Struct]>;
+ let Args = [TypeArgument<"DerefType", /*opt=*/1>];
+ let Documentation = [LifetimePointerDocs];
+}
+
// Microsoft-related attributes
def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
@@ -2981,10 +3035,12 @@ def LoopHint : Attr {
let Args = [EnumArgument<"Option", "OptionType",
["vectorize", "vectorize_width", "interleave", "interleave_count",
"unroll", "unroll_count", "unroll_and_jam", "unroll_and_jam_count",
- "pipeline", "pipeline_initiation_interval", "distribute"],
+ "pipeline", "pipeline_initiation_interval", "distribute",
+ "vectorize_predicate"],
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
"Unroll", "UnrollCount", "UnrollAndJam", "UnrollAndJamCount",
- "PipelineDisabled", "PipelineInitiationInterval", "Distribute"]>,
+ "PipelineDisabled", "PipelineInitiationInterval", "Distribute",
+ "VectorizePredicate"]>,
EnumArgument<"State", "LoopHintState",
["enable", "disable", "numeric", "assume_safety", "full"],
["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
@@ -3004,12 +3060,13 @@ def LoopHint : Attr {
case PipelineDisabled: return "pipeline";
case PipelineInitiationInterval: return "pipeline_initiation_interval";
case Distribute: return "distribute";
+ case VectorizePredicate: return "vectorize_predicate";
}
llvm_unreachable("Unhandled LoopHint option.");
}
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
- unsigned SpellingIndex = getSpellingListIndex();
+ unsigned SpellingIndex = getAttributeSpellingListIndex();
// For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
// "nounroll" is already emitted as the pragma name.
if (SpellingIndex == Pragma_nounroll || SpellingIndex == Pragma_nounroll_and_jam)
@@ -3045,7 +3102,7 @@ def LoopHint : Attr {
// Return a string suitable for identifying this attribute in diagnostics.
std::string getDiagnosticName(const PrintingPolicy &Policy) const {
- unsigned SpellingIndex = getSpellingListIndex();
+ unsigned SpellingIndex = getAttributeSpellingListIndex();
if (SpellingIndex == Pragma_nounroll)
return "#pragma nounroll";
else if (SpellingIndex == Pragma_unroll)
@@ -3176,11 +3233,16 @@ def OMPDeclareTargetDecl : InheritableAttr {
let Args = [
EnumArgument<"MapType", "MapTypeTy",
[ "to", "link" ],
- [ "MT_To", "MT_Link" ]>
+ [ "MT_To", "MT_Link" ]>,
+ EnumArgument<"DevType", "DevTypeTy",
+ [ "host", "nohost", "any" ],
+ [ "DT_Host", "DT_NoHost", "DT_Any" ]>
];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
// Use fake syntax because it is for testing and debugging purpose only.
+ if (getDevType() != DT_Any)
+ OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
if (getMapType() != MT_To)
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
}
@@ -3193,6 +3255,14 @@ def OMPDeclareTargetDecl : InheritableAttr {
return llvm::None;
}
+ static llvm::Optional<DevTypeTy> getDeviceType(const ValueDecl *VD) {
+ if (!VD->hasAttrs())
+ return llvm::None;
+ if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
+ return Attr->getDevType();
+
+ return llvm::None;
+ }
}];
}
@@ -3219,6 +3289,82 @@ def OMPAllocateDecl : InheritableAttr {
let Documentation = [Undocumented];
}
+def OMPDeclareVariant : InheritableAttr {
+ let Spellings = [Pragma<"omp", "declare variant">];
+ let Subjects = SubjectList<[Function]>;
+ let SemaHandler = 0;
+ let HasCustomParsing = 1;
+ let InheritEvenIfAlreadyPresent = 1;
+ let Documentation = [OMPDeclareVariantDocs];
+ let Args = [
+ ExprArgument<"VariantFuncRef">,
+ ExprArgument<"Score">,
+ EnumArgument<"CtxSelectorSet", "CtxSelectorSetType",
+ [ "", "implementation"
+ ],
+ [
+ "CtxSetUnknown", "CtxSetImplementation"
+ ]>,
+ EnumArgument<"CtxScore", "ScoreType",
+ [ "", "score"
+ ],
+ [
+ "ScoreUnknown", "ScoreSpecified"
+ ]>,
+ EnumArgument<"CtxSelector", "CtxSelectorType",
+ [ "", "vendor"
+ ],
+ [
+ "CtxUnknown", "CtxVendor"
+ ]>,
+ VariadicStringArgument<"ImplVendors">
+ ];
+ let AdditionalMembers = [{
+ void printScore(raw_ostream & OS, const PrintingPolicy &Policy) const {
+ if (const Expr *E = getScore()) {
+ OS << "score(";
+ E->printPretty(OS, nullptr, Policy);
+ OS << "):";
+ }
+ }
+ void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
+ const {
+ assert(getCtxSelectorSet() != CtxSetUnknown &&
+ getCtxSelector() != CtxUnknown && "Unknown context selector.");
+ if (const Expr *E = getVariantFuncRef()) {
+ OS << "(";
+ E->printPretty(OS, nullptr, Policy);
+ OS << ")";
+ }
+ // TODO: add printing of real context selectors.
+ OS << " match(";
+ switch (getCtxSelectorSet()) {
+ case CtxSetImplementation:
+ OS << "implementation={";
+ switch (getCtxSelector()) {
+ case CtxVendor:
+ OS << "vendor(";
+ printScore(OS, Policy);
+ if (implVendors_size() > 0) {
+ OS << *implVendors(). begin();
+ for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
+ OS << ", " << VendorName;
+ }
+ OS << ")";
+ break;
+ case CtxUnknown:
+ llvm_unreachable("Unknown context selector.");
+ }
+ OS << "}";
+ break;
+ case CtxSetUnknown:
+ llvm_unreachable("Unknown context selector set.");
+ }
+ OS << ")";
+ }
+ }];
+}
+
def InternalLinkage : InheritableAttr {
let Spellings = [Clang<"internal_linkage">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index fac6116057dc..114a9856c5fb 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -1408,15 +1408,17 @@ all optional, but the attribute has to have at least one clause.
}];
}
-def RequireConstantInitDocs : Documentation {
+def ConstInitDocs : Documentation {
let Category = DocCatVariable;
+ let Heading = "require_constant_initialization, constinit (C++20)";
let Content = [{
This attribute specifies that the variable to which it is attached is intended
to have a `constant initializer <http://en.cppreference.com/w/cpp/language/constant_initialization>`_
according to the rules of [basic.start.static]. The variable is required to
have static or thread storage duration. If the initialization of the variable
is not a constant initializer an error will be produced. This attribute may
-only be used in C++.
+only be used in C++; the ``constinit`` spelling is only accepted in C++20
+onwards.
Note that in C++03 strict constant expression checking is not done. Instead
the attribute reports if Clang can emit the variable as a constant, even if it's
@@ -1431,6 +1433,12 @@ for constant initialization have been met. Since these requirements change
between dialects and have subtle pitfalls it's important to fail fast instead
of silently falling back on dynamic initialization.
+The first use of the attribute on a variable must be part of, or precede, the
+initializing declaration of the variable. C++20 requires the ``constinit``
+spelling of the attribute to be present on the initializing declaration if it
+is used anywhere. The other spellings can be specified on a forward declaration
+and omitted on a later initializing declaration.
+
.. code-block:: c++
// -std=c++14
@@ -1482,6 +1490,13 @@ generated when a function or its return type is marked with ``[[nodiscard]]``
potentially-evaluated discarded-value expression that is not explicitly cast to
`void`.
+A string literal may optionally be provided to the attribute, which will be
+reproduced in any resulting diagnostics. Redeclarations using different forms
+of the attribute (with or without the string literal or with different string
+literal contents) are allowed. If there are redeclarations of the entity with
+differing string literals, it is unspecified which one will be used by Clang
+in any resulting diagnostics.
+
.. code-block: c++
struct [[nodiscard]] error_info { /*...*/ };
error_info enable_missile_safety_mode();
@@ -1493,6 +1508,33 @@ potentially-evaluated discarded-value expression that is not explicitly cast to
}
error_info &foo();
void f() { foo(); } // Does not diagnose, error_info is a reference.
+
+Additionally, discarded temporaries resulting from a call to a constructor
+marked with ``[[nodiscard]]`` or a constructor of a type marked
+``[[nodiscard]]`` will also diagnose. This also applies to type conversions that
+use the annotated ``[[nodiscard]]`` constructor or result in an annotated type.
+
+.. code-block: c++
+ struct [[nodiscard]] marked_type {/*..*/ };
+ struct marked_ctor {
+ [[nodiscard]] marked_ctor();
+ marked_ctor(int);
+ };
+
+ struct S {
+ operator marked_type() const;
+ [[nodiscard]] operator int() const;
+ };
+
+ void usages() {
+ marked_type(); // diagnoses.
+ marked_ctor(); // diagnoses.
+ marked_ctor(3); // Does not diagnose, int constructor isn't marked nodiscard.
+
+ S s;
+ static_cast<marked_type>(s); // diagnoses
+ (int)s; // diagnoses
+ }
}];
}
@@ -2187,6 +2229,18 @@ to avoid false positives in other places.
}];
}
+def CFICanonicalJumpTableDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "cfi_canonical_jump_table";
+ let Content = [{
+.. _langext-cfi_canonical_jump_table:
+
+Use ``__attribute__((cfi_canonical_jump_table))`` on a function declaration to
+make the function's CFI jump table canonical. See :ref:`the CFI documentation
+<cfi-canonical-jump-tables>` for more details.
+ }];
+}
+
def DocCatTypeSafety : DocumentationCategory<"Type Safety Checking"> {
let Content = [{
Clang supports additional attributes to enable checking type safety properties
@@ -2504,6 +2558,30 @@ manipulating bits of the enumerator when issuing warnings.
}];
}
+def AsmLabelDocs : Documentation {
+ let Category = DocCatDecl;
+ let Content = [{
+This attribute can be used on a function or variable to specify its symbol name.
+
+On some targets, all C symbols are prefixed by default with a single character, typically ``_``. This was done historically to distinguish them from symbols used by other languages. (This prefix is also added to the standard Itanium C++ ABI prefix on "mangled" symbol names, so that e.g. on such targets the true symbol name for a C++ variable declared as ``int cppvar;`` would be ``__Z6cppvar``; note the two underscores.) This prefix is *not* added to the symbol names specified by the ``asm`` attribute; programmers wishing to match a C symbol name must compensate for this.
+
+For example, consider the following C code:
+
+.. code-block:: c
+
+ int var1 asm("altvar") = 1; // "altvar" in symbol table.
+ int var2 = 1; // "_var2" in symbol table.
+
+ void func1(void) asm("altfunc");
+ void func1(void) {} // "altfunc" in symbol table.
+ void func2(void) {} // "_func2" in symbol table.
+
+Clang's implementation of this attribute is compatible with GCC's, `documented here <https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html>`_.
+
+While it is possible to use this attribute to name a special symbol used internally by the compiler, such as an LLVM intrinsic, this is neither recommended nor supported and may cause the compiler to crash or miscompile. Users who wish to gain access to intrinsic behavior are strongly encouraged to request new builtin functions.
+ }];
+}
+
def EnumExtensibilityDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
@@ -2583,7 +2661,7 @@ is retained by the return value of the annotated function
It is only supported in C++.
This attribute provides an experimental implementation of the facility
-described in the C++ committee paper [http://wg21.link/p0936r0](P0936R0),
+described in the C++ committee paper `P0936R0 <http://wg21.link/p0936r0>`_,
and is subject to change as the design of the corresponding functionality
changes.
}];
@@ -2709,9 +2787,10 @@ def LoopHintDocs : Documentation {
let Content = [{
The ``#pragma clang loop`` directive allows loop optimization hints to be
specified for the subsequent loop. The directive allows pipelining to be
-disabled, or vectorization, interleaving, and unrolling to be enabled or disabled.
-Vector width, interleave count, unrolling count, and the initiation interval
-for pipelining can be explicitly specified. See `language extensions
+disabled, or vectorization, vector predication, interleaving, and unrolling to
+be enabled or disabled. Vector width, vector predication, interleave count,
+unrolling count, and the initiation interval for pipelining can be explicitly
+specified. See `language extensions
<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
for details.
}];
@@ -3129,6 +3208,55 @@ The syntax of the declare target directive is as follows:
#pragma omp declare target new-line
declarations-definition-seq
#pragma omp end declare target new-line
+
+or
+
+ .. code-block:: c
+
+ #pragma omp declare target (extended-list) new-line
+
+or
+
+ .. code-block:: c
+
+ #pragma omp declare target clause[ [,] clause ... ] new-line
+
+where clause is one of the following:
+
+
+ .. code-block:: c
+
+ to(extended-list)
+ link(list)
+ device_type(host | nohost | any)
+ }];
+}
+
+def OMPDeclareVariantDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "#pragma omp declare variant";
+ let Content = [{
+The `declare variant` directive declares a specialized variant of a base
+ function and specifies the context in which that specialized variant is used.
+ The declare variant directive is a declarative directive.
+The syntax of the `declare variant` construct is as follows:
+
+ .. code-block:: none
+
+ #pragma omp declare variant(variant-func-id) clause new-line
+ [#pragma omp declare variant(variant-func-id) clause new-line]
+ [...]
+ function definition or declaration
+
+where clause is one of the following:
+
+ .. code-block:: none
+
+ match(context-selector-specification)
+
+and where `variant-func-id` is the name of a function variant that is either a
+ base language identifier or, for C++, a template-id.
+
}];
}
@@ -4194,4 +4322,72 @@ be accessed on both device side and host side. It has external linkage and is
not initialized on device side. It has internal linkage and is initialized by
the initializer on host side.
}];
-} \ No newline at end of file
+}
+
+def LifetimeOwnerDocs : Documentation {
+ let Category = DocCatDecl;
+ let Content = [{
+.. Note:: This attribute is experimental and its effect on analysis is subject to change in
+ a future version of clang.
+
+The attribute ``[[gsl::Owner(T)]]`` applies to structs and classes that own an
+object of type ``T``:
+
+.. code-block:: c++
+
+ class [[gsl::Owner(int)]] IntOwner {
+ private:
+ int value;
+ public:
+ int *getInt() { return &value; }
+ };
+
+The argument ``T`` is optional and is ignored.
+This attribute may be used by analysis tools and has no effect on code
+generation.
+
+See Pointer_ for an example.
+}];
+}
+
+def LifetimePointerDocs : Documentation {
+ let Category = DocCatDecl;
+ let Content = [{
+.. Note:: This attribute is experimental and its effect on analysis is subject to change in
+ a future version of clang.
+
+The attribute ``[[gsl::Pointer(T)]]`` applies to structs and classes that behave
+like pointers to an object of type ``T``:
+
+.. code-block:: c++
+
+ class [[gsl::Pointer(int)]] IntPointer {
+ private:
+ int *valuePointer;
+ public:
+ int *getInt() { return &valuePointer; }
+ };
+
+The argument ``T`` is optional and is ignored.
+This attribute may be used by analysis tools and has no effect on code
+generation.
+
+Example:
+When constructing an instance of a class annotated like this (a Pointer) from
+an instance of a class annotated with ``[[gsl::Owner]]`` (an Owner),
+then the analysis will consider the Pointer to point inside the Owner.
+When the Owner's lifetime ends, it will consider the Pointer to be dangling.
+
+.. code-block:: c++
+
+ int f() {
+ IntPointer P;
+ if (true) {
+ IntOwner O(7);
+ P = IntPointer(O); // P "points into" O
+ } // P is dangling
+ return P.get(); // error: Using a dangling Pointer.
+ }
+
+}];
+}
diff --git a/include/clang/Basic/AttributeCommonInfo.h b/include/clang/Basic/AttributeCommonInfo.h
new file mode 100644
index 000000000000..545e7e9a2b47
--- /dev/null
+++ b/include/clang/Basic/AttributeCommonInfo.h
@@ -0,0 +1,190 @@
+//======- AttributeCommonInfo.h - Base info about Attributes-----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AttributeCommonInfo type, which is the base for a
+// ParsedAttr and is used by Attr as a way to share info between the two.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
+#define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class IdentifierInfo;
+class ASTRecordWriter;
+
+class AttributeCommonInfo {
+public:
+ /// The style used to specify an attribute.
+ enum Syntax {
+ /// __attribute__((...))
+ AS_GNU,
+
+ /// [[...]]
+ AS_CXX11,
+
+ /// [[...]]
+ AS_C2x,
+
+ /// __declspec(...)
+ AS_Declspec,
+
+ /// [uuid("...")] class Foo
+ AS_Microsoft,
+
+ /// __ptr16, alignas(...), etc.
+ AS_Keyword,
+
+ /// #pragma ...
+ AS_Pragma,
+
+ // Note TableGen depends on the order above. Do not add or change the order
+ // without adding related code to TableGen/ClangAttrEmitter.cpp.
+ /// Context-sensitive version of a keyword attribute.
+ AS_ContextSensitiveKeyword,
+ };
+ enum Kind {
+#define PARSED_ATTR(NAME) AT_##NAME,
+#include "clang/Sema/AttrParsedAttrList.inc"
+#undef PARSED_ATTR
+ NoSemaHandlerAttribute,
+ IgnoredAttribute,
+ UnknownAttribute,
+ };
+
+private:
+ const IdentifierInfo *AttrName = nullptr;
+ const IdentifierInfo *ScopeName = nullptr;
+ SourceRange AttrRange;
+ const SourceLocation ScopeLoc;
+ // Corresponds to the Kind enum.
+ unsigned AttrKind : 16;
+ /// Corresponds to the Syntax enum.
+ unsigned SyntaxUsed : 3;
+ unsigned SpellingIndex : 4;
+
+protected:
+ static constexpr unsigned SpellingNotCalculated = 0xf;
+
+public:
+ AttributeCommonInfo(SourceRange AttrRange)
+ : AttrRange(AttrRange), ScopeLoc(), AttrKind(0), SyntaxUsed(0),
+ SpellingIndex(SpellingNotCalculated) {}
+
+ AttributeCommonInfo(SourceLocation AttrLoc)
+ : AttrRange(AttrLoc), ScopeLoc(), AttrKind(0), SyntaxUsed(0),
+ SpellingIndex(SpellingNotCalculated) {}
+
+ AttributeCommonInfo(const IdentifierInfo *AttrName,
+ const IdentifierInfo *ScopeName, SourceRange AttrRange,
+ SourceLocation ScopeLoc, Syntax SyntaxUsed)
+ : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
+ ScopeLoc(ScopeLoc),
+ AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
+ SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
+
+ AttributeCommonInfo(const IdentifierInfo *AttrName,
+ const IdentifierInfo *ScopeName, SourceRange AttrRange,
+ SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed)
+ : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
+ ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
+ SpellingIndex(SpellingNotCalculated) {}
+
+ AttributeCommonInfo(const IdentifierInfo *AttrName,
+ const IdentifierInfo *ScopeName, SourceRange AttrRange,
+ SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed,
+ unsigned Spelling)
+ : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
+ ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
+ SpellingIndex(Spelling) {}
+
+ AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
+ Syntax SyntaxUsed)
+ : AttrName(AttrName), ScopeName(nullptr), AttrRange(AttrRange),
+ ScopeLoc(), AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
+ SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
+
+ AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed)
+ : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
+ AttrKind(K), SyntaxUsed(SyntaxUsed),
+ SpellingIndex(SpellingNotCalculated) {}
+
+ AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed,
+ unsigned Spelling)
+ : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
+ AttrKind(K), SyntaxUsed(SyntaxUsed), SpellingIndex(Spelling) {}
+
+ AttributeCommonInfo(AttributeCommonInfo &&) = default;
+ AttributeCommonInfo(const AttributeCommonInfo &) = default;
+
+ Kind getParsedKind() const { return Kind(AttrKind); }
+ Syntax getSyntax() const { return Syntax(SyntaxUsed); }
+ const IdentifierInfo *getAttrName() const { return AttrName; }
+ SourceLocation getLoc() const { return AttrRange.getBegin(); }
+ SourceRange getRange() const { return AttrRange; }
+ void setRange(SourceRange R) { AttrRange = R; }
+
+ bool hasScope() const { return ScopeName; }
+ const IdentifierInfo *getScopeName() const { return ScopeName; }
+ SourceLocation getScopeLoc() const { return ScopeLoc; }
+
+ bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
+ bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
+
+ bool isGNUScope() const;
+
+ bool isAlignasAttribute() const {
+ // FIXME: Use a better mechanism to determine this.
+ return getParsedKind() == AT_Aligned && isKeywordAttribute();
+ }
+
+ bool isCXX11Attribute() const {
+ return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
+ }
+
+ bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; }
+
+ bool isKeywordAttribute() const {
+ return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
+ }
+
+ bool isContextSensitiveKeywordAttribute() const {
+ return SyntaxUsed == AS_ContextSensitiveKeyword;
+ }
+
+ unsigned getAttributeSpellingListIndex() const {
+ assert((isAttributeSpellingListCalculated() || AttrName) &&
+ "Spelling cannot be found");
+ return isAttributeSpellingListCalculated()
+ ? SpellingIndex
+ : calculateAttributeSpellingListIndex();
+ }
+ void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
+
+ static Kind getParsedKind(const IdentifierInfo *Name,
+ const IdentifierInfo *Scope, Syntax SyntaxUsed);
+
+private:
+ /// Get an index into the attribute spelling list
+ /// defined in Attr.td. This index is used by an attribute
+ /// to pretty print itself.
+ unsigned calculateAttributeSpellingListIndex() const;
+
+ friend class clang::ASTRecordWriter;
+ // Used exclusively by ASTDeclWriter to get the raw spelling list state.
+ unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
+
+protected:
+ bool isAttributeSpellingListCalculated() const {
+ return SpellingIndex != SpellingNotCalculated;
+ }
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 984e607a2fc4..76e3b03de833 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -113,14 +113,17 @@ BUILTIN(__builtin_atan2l, "LdLdLd", "Fne")
BUILTIN(__builtin_abs , "ii" , "ncF")
BUILTIN(__builtin_copysign, "ddd", "ncF")
BUILTIN(__builtin_copysignf, "fff", "ncF")
+BUILTIN(__builtin_copysignf16, "hhh", "ncF")
BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
BUILTIN(__builtin_copysignf128, "LLdLLdLLd", "ncF")
BUILTIN(__builtin_fabs , "dd" , "ncF")
BUILTIN(__builtin_fabsf, "ff" , "ncF")
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
+BUILTIN(__builtin_fabsf16, "hh" , "ncF")
BUILTIN(__builtin_fabsf128, "LLdLLd", "ncF")
BUILTIN(__builtin_fmod , "ddd" , "Fne")
BUILTIN(__builtin_fmodf, "fff" , "Fne")
+BUILTIN(__builtin_fmodf16, "hhh" , "Fne")
BUILTIN(__builtin_fmodl, "LdLdLd", "Fne")
BUILTIN(__builtin_frexp , "ddi*" , "Fn")
BUILTIN(__builtin_frexpf, "ffi*" , "Fn")
@@ -154,6 +157,7 @@ BUILTIN(__builtin_powif, "ffi" , "Fnc")
BUILTIN(__builtin_powil, "LdLdi", "Fnc")
BUILTIN(__builtin_pow , "ddd" , "Fne")
BUILTIN(__builtin_powf, "fff" , "Fne")
+BUILTIN(__builtin_powf16, "hhh" , "Fne")
BUILTIN(__builtin_powl, "LdLdLd", "Fne")
// Standard unary libc/libm functions with double/float/long double variants:
@@ -180,9 +184,11 @@ BUILTIN(__builtin_cbrtf, "ff", "Fnc")
BUILTIN(__builtin_cbrtl, "LdLd", "Fnc")
BUILTIN(__builtin_ceil , "dd" , "Fnc")
BUILTIN(__builtin_ceilf, "ff" , "Fnc")
+BUILTIN(__builtin_ceilf16, "hh" , "Fnc")
BUILTIN(__builtin_ceill, "LdLd", "Fnc")
BUILTIN(__builtin_cos , "dd" , "Fne")
BUILTIN(__builtin_cosf, "ff" , "Fne")
+BUILTIN(__builtin_cosf16, "hh" , "Fne")
BUILTIN(__builtin_cosh , "dd" , "Fne")
BUILTIN(__builtin_coshf, "ff" , "Fne")
BUILTIN(__builtin_coshl, "LdLd", "Fne")
@@ -195,9 +201,11 @@ BUILTIN(__builtin_erfcf, "ff", "Fne")
BUILTIN(__builtin_erfcl, "LdLd", "Fne")
BUILTIN(__builtin_exp , "dd" , "Fne")
BUILTIN(__builtin_expf, "ff" , "Fne")
+BUILTIN(__builtin_expf16, "hh" , "Fne")
BUILTIN(__builtin_expl, "LdLd", "Fne")
BUILTIN(__builtin_exp2 , "dd" , "Fne")
BUILTIN(__builtin_exp2f, "ff" , "Fne")
+BUILTIN(__builtin_exp2f16, "hh" , "Fne")
BUILTIN(__builtin_exp2l, "LdLd", "Fne")
BUILTIN(__builtin_expm1 , "dd", "Fne")
BUILTIN(__builtin_expm1f, "ff", "Fne")
@@ -207,15 +215,19 @@ BUILTIN(__builtin_fdimf, "fff", "Fne")
BUILTIN(__builtin_fdiml, "LdLdLd", "Fne")
BUILTIN(__builtin_floor , "dd" , "Fnc")
BUILTIN(__builtin_floorf, "ff" , "Fnc")
+BUILTIN(__builtin_floorf16, "hh" , "Fnc")
BUILTIN(__builtin_floorl, "LdLd", "Fnc")
BUILTIN(__builtin_fma, "dddd", "Fne")
BUILTIN(__builtin_fmaf, "ffff", "Fne")
+BUILTIN(__builtin_fmaf16, "hhhh", "Fne")
BUILTIN(__builtin_fmal, "LdLdLdLd", "Fne")
BUILTIN(__builtin_fmax, "ddd", "Fnc")
BUILTIN(__builtin_fmaxf, "fff", "Fnc")
+BUILTIN(__builtin_fmaxf16, "hhh", "Fnc")
BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc")
BUILTIN(__builtin_fmin, "ddd", "Fnc")
BUILTIN(__builtin_fminf, "fff", "Fnc")
+BUILTIN(__builtin_fminf16, "hhh", "Fnc")
BUILTIN(__builtin_fminl, "LdLdLd", "Fnc")
BUILTIN(__builtin_hypot , "ddd" , "Fne")
BUILTIN(__builtin_hypotf, "fff" , "Fne")
@@ -235,17 +247,20 @@ BUILTIN(__builtin_llroundl, "LLiLd", "Fne")
BUILTIN(__builtin_log , "dd" , "Fne")
BUILTIN(__builtin_log10 , "dd" , "Fne")
BUILTIN(__builtin_log10f, "ff" , "Fne")
+BUILTIN(__builtin_log10f16, "hh" , "Fne")
BUILTIN(__builtin_log10l, "LdLd", "Fne")
BUILTIN(__builtin_log1p , "dd" , "Fne")
BUILTIN(__builtin_log1pf, "ff" , "Fne")
BUILTIN(__builtin_log1pl, "LdLd", "Fne")
BUILTIN(__builtin_log2, "dd" , "Fne")
BUILTIN(__builtin_log2f, "ff" , "Fne")
+BUILTIN(__builtin_log2f16, "hh" , "Fne")
BUILTIN(__builtin_log2l, "LdLd" , "Fne")
BUILTIN(__builtin_logb , "dd", "Fne")
BUILTIN(__builtin_logbf, "ff", "Fne")
BUILTIN(__builtin_logbl, "LdLd", "Fne")
BUILTIN(__builtin_logf, "ff" , "Fne")
+BUILTIN(__builtin_logf16, "hh" , "Fne")
BUILTIN(__builtin_logl, "LdLd", "Fne")
BUILTIN(__builtin_lrint , "Lid", "Fne")
BUILTIN(__builtin_lrintf, "Lif", "Fne")
@@ -270,9 +285,11 @@ BUILTIN(__builtin_remquof, "fffi*", "Fn")
BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn")
BUILTIN(__builtin_rint , "dd", "Fnc")
BUILTIN(__builtin_rintf, "ff", "Fnc")
+BUILTIN(__builtin_rintf16, "hh", "Fnc")
BUILTIN(__builtin_rintl, "LdLd", "Fnc")
BUILTIN(__builtin_round, "dd" , "Fnc")
BUILTIN(__builtin_roundf, "ff" , "Fnc")
+BUILTIN(__builtin_roundf16, "hh" , "Fnc")
BUILTIN(__builtin_roundl, "LdLd" , "Fnc")
BUILTIN(__builtin_scalbln , "ddLi", "Fne")
BUILTIN(__builtin_scalblnf, "ffLi", "Fne")
@@ -282,12 +299,14 @@ BUILTIN(__builtin_scalbnf, "ffi", "Fne")
BUILTIN(__builtin_scalbnl, "LdLdi", "Fne")
BUILTIN(__builtin_sin , "dd" , "Fne")
BUILTIN(__builtin_sinf, "ff" , "Fne")
+BUILTIN(__builtin_sinf16, "hh" , "Fne")
BUILTIN(__builtin_sinh , "dd" , "Fne")
BUILTIN(__builtin_sinhf, "ff" , "Fne")
BUILTIN(__builtin_sinhl, "LdLd", "Fne")
BUILTIN(__builtin_sinl, "LdLd", "Fne")
BUILTIN(__builtin_sqrt , "dd" , "Fne")
BUILTIN(__builtin_sqrtf, "ff" , "Fne")
+BUILTIN(__builtin_sqrtf16, "hh" , "Fne")
BUILTIN(__builtin_sqrtl, "LdLd", "Fne")
BUILTIN(__builtin_tan , "dd" , "Fne")
BUILTIN(__builtin_tanf, "ff" , "Fne")
@@ -301,6 +320,7 @@ BUILTIN(__builtin_tgammal, "LdLd", "Fne")
BUILTIN(__builtin_trunc , "dd", "Fnc")
BUILTIN(__builtin_truncf, "ff", "Fnc")
BUILTIN(__builtin_truncl, "LdLd", "Fnc")
+BUILTIN(__builtin_truncf16, "hh", "Fnc")
// C99 complex builtins
BUILTIN(__builtin_cabs, "dXd", "Fne")
@@ -394,6 +414,7 @@ BUILTIN(__builtin_signbitl, "iLd", "Fnc")
// Special FP builtins.
BUILTIN(__builtin_canonicalize, "dd", "nc")
BUILTIN(__builtin_canonicalizef, "ff", "nc")
+BUILTIN(__builtin_canonicalizef16, "hh", "nc")
BUILTIN(__builtin_canonicalizel, "LdLd", "nc")
// Builtins for arithmetic.
@@ -440,7 +461,7 @@ BUILTIN(__builtin_rotateleft64, "UWiUWiUWi", "nc")
BUILTIN(__builtin_rotateright8, "UcUcUc", "nc")
BUILTIN(__builtin_rotateright16, "UsUsUs", "nc")
BUILTIN(__builtin_rotateright32, "UZiUZiUZi", "nc")
-BUILTIN(__builtin_rotateright64, "UWiUWiWi", "nc")
+BUILTIN(__builtin_rotateright64, "UWiUWiUWi", "nc")
// Random GCC builtins
BUILTIN(__builtin_constant_p, "i.", "nctu")
@@ -984,9 +1005,7 @@ LIBBUILTIN(pthread_create, "", "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES)
LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
LIBBUILTIN(__sigsetjmp, "iSJi", "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_GNU_LANGUAGES)
@@ -1449,7 +1468,7 @@ BUILTIN(__builtin_operator_new, "v*z", "tc")
BUILTIN(__builtin_operator_delete, "vv*", "tn")
BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
-BUILTIN(__builtin_preserve_access_index, "vC*vC*", "nU")
+BUILTIN(__builtin_preserve_access_index, "v.", "t")
// Safestack builtins
BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
index 7701ad98f483..4df8d5a16762 100644
--- a/include/clang/Basic/BuiltinsAArch64.def
+++ b/include/clang/Basic/BuiltinsAArch64.def
@@ -91,12 +91,18 @@ LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
// Misc
BUILTIN(__builtin_sponentry, "v*", "c")
+// Transactional Memory Extension
+BUILTIN(__builtin_arm_tstart, "WUi", "nj")
+BUILTIN(__builtin_arm_tcommit, "v", "n")
+BUILTIN(__builtin_arm_tcancel, "vWUIi", "n")
+BUILTIN(__builtin_arm_ttest, "WUi", "nc")
+
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedAdd, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAdd, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -106,9 +112,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h"
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -125,9 +131,9 @@ TARGET_HEADER_BUILTIN(_InterlockedExchange8_rel, "ccD*c", "nh", "intrin.h
TARGET_HEADER_BUILTIN(_InterlockedExchange16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -138,9 +144,9 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_rel, "ccD*cc", "nh",
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_acq, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_nf, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_rel, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -151,9 +157,9 @@ TARGET_HEADER_BUILTIN(_InterlockedOr8_rel, "ccD*c", "nh", "intrin.h", ALL
TARGET_HEADER_BUILTIN(_InterlockedOr16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -164,9 +170,9 @@ TARGET_HEADER_BUILTIN(_InterlockedXor8_rel, "ccD*c", "nh", "intrin.h", AL
TARGET_HEADER_BUILTIN(_InterlockedXor16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -177,9 +183,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd8_rel, "ccD*c", "nh", "intrin.h", AL
TARGET_HEADER_BUILTIN(_InterlockedAnd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -187,9 +193,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", AL
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -197,9 +203,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h",
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def
index 2f8fb9000a76..9b3a0f96798f 100644
--- a/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/include/clang/Basic/BuiltinsAMDGPU.def
@@ -118,6 +118,13 @@ BUILTIN(__builtin_amdgcn_cvt_pknorm_u16, "E2Usff", "nc")
BUILTIN(__builtin_amdgcn_cvt_pk_i16, "E2sii", "nc")
BUILTIN(__builtin_amdgcn_cvt_pk_u16, "E2UsUiUi", "nc")
BUILTIN(__builtin_amdgcn_cvt_pk_u8_f32, "UifUiUi", "nc")
+BUILTIN(__builtin_amdgcn_sad_u8, "UiUiUiUi", "nc")
+BUILTIN(__builtin_amdgcn_msad_u8, "UiUiUiUi", "nc")
+BUILTIN(__builtin_amdgcn_sad_hi_u8, "UiUiUiUi", "nc")
+BUILTIN(__builtin_amdgcn_sad_u16, "UiUiUiUi", "nc")
+BUILTIN(__builtin_amdgcn_qsad_pk_u16_u8, "LUiLUiUiLUi", "nc")
+BUILTIN(__builtin_amdgcn_mqsad_pk_u16_u8, "LUiLUiUiLUi", "nc")
+BUILTIN(__builtin_amdgcn_mqsad_u32_u8, "V4UiLUiUiV4Ui", "nc")
//===----------------------------------------------------------------------===//
// CI+ only builtins.
@@ -125,6 +132,8 @@ BUILTIN(__builtin_amdgcn_cvt_pk_u8_f32, "UifUiUi", "nc")
TARGET_BUILTIN(__builtin_amdgcn_s_dcache_inv_vol, "v", "n", "ci-insts")
TARGET_BUILTIN(__builtin_amdgcn_buffer_wbinvl1_vol, "v", "n", "ci-insts")
TARGET_BUILTIN(__builtin_amdgcn_ds_gws_sema_release_all, "vUi", "n", "ci-insts")
+TARGET_BUILTIN(__builtin_amdgcn_is_shared, "bvC*0", "nc", "flat-address-space")
+TARGET_BUILTIN(__builtin_amdgcn_is_private, "bvC*0", "nc", "flat-address-space")
//===----------------------------------------------------------------------===//
// Interpolation builtins.
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 3f0765115b1c..19b51694aa22 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -221,9 +221,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h"
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -240,9 +240,9 @@ TARGET_HEADER_BUILTIN(_InterlockedExchange8_rel, "ccD*c", "nh", "intrin.h
TARGET_HEADER_BUILTIN(_InterlockedExchange16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -253,9 +253,9 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_rel, "ccD*cc", "nh",
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_acq, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_nf, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_rel, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "NiNiD*NiNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -266,9 +266,9 @@ TARGET_HEADER_BUILTIN(_InterlockedOr8_rel, "ccD*c", "nh", "intrin.h", ALL
TARGET_HEADER_BUILTIN(_InterlockedOr16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -279,9 +279,9 @@ TARGET_HEADER_BUILTIN(_InterlockedXor8_rel, "ccD*c", "nh", "intrin.h", AL
TARGET_HEADER_BUILTIN(_InterlockedXor16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -292,9 +292,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd8_rel, "ccD*c", "nh", "intrin.h", AL
TARGET_HEADER_BUILTIN(_InterlockedAnd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "NiNiD*Ni", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -302,9 +302,9 @@ TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", AL
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -312,9 +312,9 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h",
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
-TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "NiNiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
diff --git a/include/clang/Basic/BuiltinsBPF.def b/include/clang/Basic/BuiltinsBPF.def
new file mode 100644
index 000000000000..bd96b9ef531b
--- /dev/null
+++ b/include/clang/Basic/BuiltinsBPF.def
@@ -0,0 +1,24 @@
+//===--- BuiltinsBPF.def - BPF Builtin function database --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the BPF-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.
+
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+// Get record field information.
+TARGET_BUILTIN(__builtin_preserve_field_info, "Ui.", "t", "")
+
+#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def
index 3b6348ad7d70..314e1cc05907 100644
--- a/include/clang/Basic/BuiltinsPPC.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -50,17 +50,17 @@ BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vrfip, "V4fV4f", "")
-BUILTIN(__builtin_altivec_vcfsx, "V4fV4iIi", "")
-BUILTIN(__builtin_altivec_vcfux, "V4fV4iIi", "")
+BUILTIN(__builtin_altivec_vcfsx, "V4fV4SiIi", "")
+BUILTIN(__builtin_altivec_vcfux, "V4fV4UiIi", "")
BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fIi", "")
BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fIi", "")
-BUILTIN(__builtin_altivec_dss, "vUi", "")
+BUILTIN(__builtin_altivec_dss, "vUIi", "")
BUILTIN(__builtin_altivec_dssall, "v", "")
-BUILTIN(__builtin_altivec_dst, "vvC*iUi", "")
-BUILTIN(__builtin_altivec_dstt, "vvC*iUi", "")
-BUILTIN(__builtin_altivec_dstst, "vvC*iUi", "")
-BUILTIN(__builtin_altivec_dststt, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dst, "vvC*iUIi", "")
+BUILTIN(__builtin_altivec_dstt, "vvC*iUIi", "")
+BUILTIN(__builtin_altivec_dstst, "vvC*iUIi", "")
+BUILTIN(__builtin_altivec_dststt, "vvC*iUIi", "")
BUILTIN(__builtin_altivec_vexptefp, "V4fV4f", "")
diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def
index 63177f016ac7..7fed9d2e43e7 100644
--- a/include/clang/Basic/BuiltinsWebAssembly.def
+++ b/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,6 +31,8 @@ TARGET_BUILTIN(__builtin_wasm_data_drop, "vIUi", "", "bulk-memory")
// Thread-local storage
TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_align, "z", "nc", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
// Floating point min/max
BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
@@ -47,6 +49,16 @@ BUILTIN(__builtin_wasm_atomic_wait_i32, "ii*iLLi", "n")
BUILTIN(__builtin_wasm_atomic_wait_i64, "iLLi*LLiLLi", "n")
BUILTIN(__builtin_wasm_atomic_notify, "Uii*Ui", "n")
+// Trapping fp-to-int conversions
+BUILTIN(__builtin_wasm_trunc_s_i32_f32, "if", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i32_f32, "if", "nc")
+BUILTIN(__builtin_wasm_trunc_s_i32_f64, "id", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i32_f64, "id", "nc")
+BUILTIN(__builtin_wasm_trunc_s_i64_f32, "LLif", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i64_f32, "LLif", "nc")
+BUILTIN(__builtin_wasm_trunc_s_i64_f64, "LLid", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i64_f64, "LLid", "nc")
+
// Saturating fp-to-int conversions
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f32, "if", "nc", "nontrapping-fptoint")
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f32, "if", "nc", "nontrapping-fptoint")
@@ -58,6 +70,8 @@ TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f64, "LLid", "nc", "nontrappi
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f64, "LLid", "nc", "nontrapping-fptoint")
// SIMD builtins
+TARGET_BUILTIN(__builtin_wasm_swizzle_v8x16, "V16cV16cV16c", "nc", "unimplemented-simd128")
+
TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i8x16, "iV16cIi", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_extract_lane_u_i8x16, "iV16cIi", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i16x8, "iV8sIi", "nc", "simd128")
@@ -106,10 +120,29 @@ TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd1
TARGET_BUILTIN(__builtin_wasm_sqrt_f32x4, "V4fV4f", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_qfma_f32x4, "V4fV4fV4fV4f", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_qfms_f32x4, "V4fV4fV4fV4f", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_qfma_f64x2, "V2dV2dV2dV2d", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_qfms_f64x2, "V2dV2dV2dV2d", "nc", "unimplemented-simd128")
+
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32x4_f32x4, "V4iV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32x4_f32x4, "V4iV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128")
+TARGET_BUILTIN(__builtin_wasm_narrow_s_i8x16_i16x8, "V16cV8sV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_narrow_u_i8x16_i16x8, "V16cV8sV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_narrow_s_i16x8_i32x4, "V8sV4iV4i", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_narrow_u_i16x8_i32x4, "V8sV4iV4i", "nc", "simd128")
+
+TARGET_BUILTIN(__builtin_wasm_widen_low_s_i16x8_i8x16, "V8sV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_widen_high_s_i16x8_i8x16, "V8sV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_widen_low_u_i16x8_i8x16, "V8sV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_widen_high_u_i16x8_i8x16, "V8sV16c", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_widen_low_s_i32x4_i16x8, "V4iV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_widen_high_s_i32x4_i16x8, "V4iV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_widen_low_u_i32x4_i16x8, "V4iV8s", "nc", "simd128")
+TARGET_BUILTIN(__builtin_wasm_widen_high_u_i32x4_i16x8, "V4iV8s", "nc", "simd128")
+
#undef BUILTIN
#undef TARGET_BUILTIN
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index a0ba0ecf36bb..5ab9dc1c3ac3 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -751,8 +751,8 @@ TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "nc", "tbm")
// LWP
TARGET_BUILTIN(__builtin_ia32_llwpcb, "vv*", "n", "lwp")
TARGET_BUILTIN(__builtin_ia32_slwpcb, "v*", "n", "lwp")
-TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "n", "lwp")
-TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiIUi", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiIUi", "n", "lwp")
// SHA
TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "ncV:128:", "sha")
diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def
index 56051af55e7d..c535f43203e5 100644
--- a/include/clang/Basic/BuiltinsX86_64.def
+++ b/include/clang/Basic/BuiltinsX86_64.def
@@ -86,8 +86,8 @@ TARGET_BUILTIN(__builtin_ia32_bzhi_di, "UOiUOiUOi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pdep_di, "UOiUOiUOi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pext_di, "UOiUOiUOi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_bextri_u64, "UOiUOiIUOi", "nc", "tbm")
-TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcUOiUiUi", "n", "lwp")
-TARGET_BUILTIN(__builtin_ia32_lwpval64, "vUOiUiUi", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcUOiUiIUi", "n", "lwp")
+TARGET_BUILTIN(__builtin_ia32_lwpval64, "vUOiUiIUi", "n", "lwp")
TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "OiV2dIi", "ncV:128:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "UOiV2dIi", "ncV:128:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "OiV4fIi", "ncV:128:", "avx512f")
diff --git a/include/clang/Basic/CodeGenOptions.def b/include/clang/Basic/CodeGenOptions.def
index cd7a84548765..d2266cc2d613 100644
--- a/include/clang/Basic/CodeGenOptions.def
+++ b/include/clang/Basic/CodeGenOptions.def
@@ -47,7 +47,8 @@ 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(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names.
-CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled.
+ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none
+
CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
CODEGENOPT(DiscardValueNames , 1, 0) ///< Discard Value Names from the IR (LLVMContext flag)
CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
@@ -132,6 +133,7 @@ CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is
CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled.
CODEGENOPT(FatalWarnings , 1, 0) ///< Set when -Wa,--fatal-warnings is
///< enabled.
+CODEGENOPT(NoWarn , 1, 0) ///< Set when -Wa,--no-warn is enabled.
CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
@@ -155,8 +157,6 @@ CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
/// Replace certain message sends with calls to ObjC runtime entrypoints
CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
-CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
- ///< enabled.
VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
@@ -195,6 +195,8 @@ CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime f
///< diagnostics.
CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in
///< CFI icall function signatures
+CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical
+ ///< instead of creating a local jump table.
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
@@ -226,6 +228,8 @@ CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definiti
CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers
CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
CODEGENOPT(TimeTrace , 1, 0) ///< Set when -ftime-trace is enabled.
+VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500) ///< Minimum time granularity (in microseconds),
+ ///< traced by time profiler
CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled.
CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled.
@@ -274,6 +278,10 @@ CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program
/// vtable optimization.
+CODEGENOPT(VirtualFunctionElimination, 1, 0) ///< Whether to apply the dead
+ /// virtual function elimination
+ /// optimization.
+
/// Whether to use public LTO visibility for entities in std and stdext
/// namespaces. This is enabled by clang-cl's /MT and /MTd flags.
CODEGENOPT(LTOVisibilityPublicStd, 1, 0)
diff --git a/include/clang/Basic/CodeGenOptions.h b/include/clang/Basic/CodeGenOptions.h
index 4e9025d2fea9..8881a316d1fb 100644
--- a/include/clang/Basic/CodeGenOptions.h
+++ b/include/clang/Basic/CodeGenOptions.h
@@ -117,6 +117,12 @@ public:
enum SignReturnAddressKeyValue { AKey, BKey };
+ enum class FramePointerKind {
+ None, // Omit all frame pointers.
+ NonLeaf, // Keep non-leaf frame pointers.
+ All, // Keep all frame pointers.
+ };
+
/// The code model to use (-mcmodel).
std::string CodeModel;
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 5a707007e463..9e494aa371cd 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -632,24 +632,22 @@ public:
/// Suppress all diagnostics, to silence the front end when we
/// know that we don't want any more diagnostics to be passed along to the
/// client
- void setSuppressAllDiagnostics(bool Val = true) {
- SuppressAllDiagnostics = Val;
- }
+ void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; }
bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
/// Set type eliding, to skip outputting same types occurring in
/// template types.
- void setElideType(bool Val = true) { ElideType = Val; }
+ void setElideType(bool Val) { ElideType = Val; }
bool getElideType() { return ElideType; }
/// Set tree printing, to outputting the template difference in a
/// tree format.
- void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
+ void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; }
bool getPrintTemplateTree() { return PrintTemplateTree; }
/// Set color printing, so the type diffing will inject color markers
/// into the output.
- void setShowColors(bool Val = false) { ShowColors = Val; }
+ void setShowColors(bool Val) { ShowColors = Val; }
bool getShowColors() { return ShowColors; }
/// Specify which overload candidates to show when overload resolution
@@ -667,7 +665,7 @@ public:
/// the middle of another diagnostic.
///
/// This can be used by clients who suppress diagnostics themselves.
- void setLastDiagnosticIgnored(bool Ignored = true) {
+ void setLastDiagnosticIgnored(bool Ignored) {
if (LastDiagLevel == DiagnosticIDs::Fatal)
FatalErrorOccurred = true;
LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning;
@@ -1127,11 +1125,6 @@ public:
Emit();
}
- /// Retrieve an empty diagnostic builder.
- static DiagnosticBuilder getEmpty() {
- return {};
- }
-
/// Forces the diagnostic to be emitted.
const DiagnosticBuilder &setForceEmit() const {
IsForceEmit = true;
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 23502152b4ac..04d767445a8f 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -37,8 +37,9 @@ def note_constexpr_virtual_call : Note<
def note_constexpr_pure_virtual_call : Note<
"pure virtual function %q0 called">;
def note_constexpr_polymorphic_unknown_dynamic_type : Note<
- "%select{||||virtual function called on|dynamic_cast applied to|"
- "typeid applied to}0 object '%1' whose dynamic type is not constant">;
+ "%select{|||||virtual function called on|dynamic_cast applied to|"
+ "typeid applied to|construction of|destruction of}0 object '%1' "
+ "whose dynamic type is not constant">;
def note_constexpr_dynamic_cast_to_reference_failed : Note<
"reference dynamic_cast failed: %select{"
"static type %1 of operand is a non-public base class of dynamic type %2|"
@@ -53,6 +54,9 @@ 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_dynamic_alloc : Note<
+ "%select{pointer|reference}0 to %select{|subobject of }1"
+ "heap-allocated object is not a constant expression">;
def note_constexpr_uninitialized : Note<
"%select{|sub}0object of type %1 is not initialized">;
def note_constexpr_subobject_declared_here : Note<
@@ -100,6 +104,7 @@ def note_constexpr_typeid_polymorphic : Note<
def note_constexpr_void_comparison : Note<
"comparison between unequal pointers to void has unspecified result">;
def note_constexpr_temporary_here : Note<"temporary created here">;
+def note_constexpr_dynamic_alloc_here : Note<"heap allocation performed here">;
def note_constexpr_conditional_never_const : Note<
"both arms of conditional operator are unable to produce a "
"constant expression">;
@@ -109,16 +114,20 @@ 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_heap_alloc_limit_exceeded : Note<
+ "constexpr evaluation hit maximum heap allocation limit">;
def note_constexpr_this : Note<
"%select{|implicit }0use of 'this' pointer is only allowed within the "
"evaluation of a call to a 'constexpr' member function">;
def note_constexpr_lifetime_ended : Note<
- "%select{read of|assignment to|increment of|decrement of|member call on|"
- "dynamic_cast of|typeid applied to}0 "
- "%select{temporary|variable}1 whose lifetime has ended">;
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|construction of|"
+ "destruction of}0 %select{temporary|variable}1 whose "
+ "%plural{8:storage duration|:lifetime}0 has ended">;
def note_constexpr_access_uninit : Note<
- "%select{read of|assignment to|increment of|decrement of|member call on|"
- "dynamic_cast of|typeid applied to}0 "
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|"
+ "construction of subobject of|destruction of}0 "
"%select{object outside its lifetime|uninitialized object}1 "
"is not allowed in a constant expression">;
def note_constexpr_use_uninit_reference : Note<
@@ -128,16 +137,21 @@ def note_constexpr_modify_const_type : Note<
"modification of object of const-qualified type %0 is not allowed "
"in a constant expression">;
def note_constexpr_access_volatile_type : Note<
- "%select{read of|assignment to|increment of|decrement of|<ERROR>|<ERROR>}0 "
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "<ERROR>|<ERROR>|<ERROR>|<ERROR>}0 "
"volatile-qualified type %1 is not allowed in a constant expression">;
def note_constexpr_access_volatile_obj : Note<
- "%select{read of|assignment to|increment of|decrement of|<ERROR>|<ERROR>}0 "
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "<ERROR>|<ERROR>|<ERROR>|<ERROR>}0 "
"volatile %select{temporary|object %2|member %2}1 is not allowed in "
"a constant expression">;
def note_constexpr_volatile_here : Note<
"volatile %select{temporary created|object declared|member declared}0 here">;
-def note_constexpr_ltor_mutable : Note<
- "read of mutable member %0 is not allowed in a constant expression">;
+def note_constexpr_access_mutable : Note<
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|construction of|"
+ "destruction of}0 "
+ "mutable member %1 is not allowed in a constant expression">;
def note_constexpr_ltor_non_const_int : Note<
"read of non-const variable %0 is not allowed in a constant expression">;
def note_constexpr_ltor_non_constexpr : Note<
@@ -145,31 +159,44 @@ def note_constexpr_ltor_non_constexpr : Note<
def note_constexpr_ltor_incomplete_type : Note<
"read of incomplete type %0 is not allowed in a constant expression">;
def note_constexpr_access_null : Note<
- "%select{read of|assignment to|increment of|decrement of|member call on|"
- "dynamic_cast of|typeid applied to}0 "
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|construction of|"
+ "destruction of}0 "
"dereferenced null pointer is not allowed in a constant expression">;
def note_constexpr_access_past_end : Note<
- "%select{read of|assignment to|increment of|decrement of|member call on|"
- "dynamic_cast of|typeid applied to}0 "
- "dereferenced one-past-the-end pointer is not allowed in a constant expression">;
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|construction of|"
+ "destruction of}0 "
+ "dereferenced one-past-the-end pointer is not allowed "
+ "in a constant expression">;
def note_constexpr_access_unsized_array : Note<
- "%select{read of|assignment to|increment of|decrement of|member call on|"
- "dynamic_cast of|typeid applied to}0 "
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|construction of|"
+ "destruction of}0 "
"element of array without known bound "
"is not allowed in a constant expression">;
def note_constexpr_access_inactive_union_member : Note<
- "%select{read of|assignment to|increment of|decrement of|member call on|"
- "dynamic_cast of|typeid applied to}0 "
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|"
+ "construction of subobject of|destruction 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|member call on|"
- "dynamic_cast of|typeid applied to}0 temporary "
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|reconstruction of|"
+ "destruction of}0 temporary "
"is not allowed in a constant expression outside the expression that "
"created the temporary">;
def note_constexpr_access_unreadable_object : Note<
- "%select{read of|assignment to|increment of|decrement of|member call on|"
- "dynamic_cast of|typeid applied to}0 object '%1' whose value is not known">;
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|construction of|"
+ "destruction of}0 "
+ "object '%1' whose value is not known">;
+def note_constexpr_access_deleted_object : Note<
+ "%select{read of|read of|assignment to|increment of|decrement of|"
+ "member call on|dynamic_cast of|typeid applied to|construction of|"
+ "destruction of}0 "
+ "heap allocated object that has been deleted">;
def note_constexpr_modify_global : Note<
"a constant expression cannot modify an object that is visible outside "
"that expression">;
@@ -189,6 +216,13 @@ def note_constexpr_baa_insufficient_alignment : Note<
def note_constexpr_baa_value_insufficient_alignment : Note<
"value of the aligned pointer (%0) is not a multiple of the asserted %1 "
"%plural{1:byte|:bytes}1">;
+def note_constexpr_destroy_out_of_lifetime : Note<
+ "destroying object '%0' whose lifetime has already ended">;
+def note_constexpr_unsupported_destruction : Note<
+ "non-trivial destruction of type %0 in a constant expression is not supported">;
+def note_constexpr_unsupported_tempoarary_nontrivial_dtor : Note<
+ "non-trivial destruction of lifetime-extended temporary with type %0 "
+ "used in the result of a constant expression is not yet supported">;
def note_constexpr_unsupported_unsized_array : Note<
"array-to-pointer decay of array member without known bound is not supported">;
def note_constexpr_unsized_array_indexed : Note<
@@ -228,6 +262,62 @@ def note_constexpr_bit_cast_invalid_subtype : Note<
def note_constexpr_bit_cast_indet_dest : Note<
"indeterminate value can only initialize an object of type 'unsigned char'"
"%select{, 'char',|}1 or 'std::byte'; %0 is invalid">;
+def note_constexpr_pseudo_destructor : Note<
+ "pseudo-destructor call is not permitted in constant expressions "
+ "until C++20">;
+def note_constexpr_construct_complex_elem : Note<
+ "construction of individual component of complex number is not yet supported "
+ "in constant expressions">;
+def note_constexpr_destroy_complex_elem : Note<
+ "destruction of individual component of complex number is not yet supported "
+ "in constant expressions">;
+def note_constexpr_new : Note<
+ "dynamic memory allocation is not permitted in constant expressions "
+ "until C++20">;
+def note_constexpr_new_non_replaceable : Note<
+ "call to %select{placement|class-specific}0 %1">;
+def note_constexpr_new_placement : Note<
+ "this placement new expression is not yet supported in constant expressions">;
+def note_constexpr_placement_new_wrong_type : Note<
+ "placement new would change type of storage from %0 to %1">;
+def note_constexpr_new_negative : Note<
+ "cannot allocate array; evaluated array bound %0 is negative">;
+def note_constexpr_new_too_large : Note<
+ "cannot allocate array; evaluated array bound %0 is too large">;
+def note_constexpr_new_too_small : Note<
+ "cannot allocate array; evaluated array bound %0 is too small to hold "
+ "%1 explicitly initialized elements">;
+def note_constexpr_new_untyped : Note<
+ "cannot allocate untyped memory in a constant expression; "
+ "use 'std::allocator<T>::allocate' to allocate memory of type 'T'">;
+def note_constexpr_new_not_complete_object_type : Note<
+ "cannot allocate memory of %select{incomplete|function}0 type %1">;
+def note_constexpr_operator_new_bad_size : Note<
+ "allocated size %0 is not a multiple of size %1 of element type %2">;
+def note_constexpr_delete_not_heap_alloc : Note<
+ "delete of pointer '%0' that does not point to a heap-allocated object">;
+def note_constexpr_double_delete : Note<
+ "delete of pointer that has already been deleted">;
+def note_constexpr_double_destroy : Note<
+ "destruction of object that is already being destroyed">;
+def note_constexpr_new_delete_mismatch : Note<
+ "%plural{2:'delete' used to delete pointer to object "
+ "allocated with 'std::allocator<...>::allocate'|"
+ ":%select{non-array delete|array delete|'std::allocator<...>::deallocate'}0 "
+ "used to delete pointer to "
+ "%select{array object of type %2|non-array object of type %2|"
+ "object allocated with 'new'}0}1">;
+def note_constexpr_delete_subobject : Note<
+ "delete of pointer%select{ to subobject|}1 '%0' "
+ "%select{|that does not point to complete object}1">;
+def note_constexpr_delete_base_nonvirt_dtor : Note<
+ "delete of object with dynamic type %1 through pointer to "
+ "base class type %0 with non-virtual destructor">;
+def note_constexpr_memory_leak : Note<
+ "allocation performed here was not deallocated"
+ "%plural{0:|: (along with %0 other memory leak%s0)}0">;
+def err_experimental_clang_interp_failed : Error<
+ "the experimental clang interpreter failed to evaluate an expression">;
def warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
@@ -277,7 +367,6 @@ def warn_odr_variable_multiple_def : Warning<
"external variable %0 defined in multiple translation units">,
InGroup<ODR>;
def note_odr_value_here : Note<"declared here with type %0">;
-def note_odr_defined_here : Note<"also defined here">;
def err_odr_function_type_inconsistent : Error<
"external function %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td
index fcda3f3a2113..c577ac408539 100644
--- a/include/clang/Basic/DiagnosticCommentKinds.td
+++ b/include/clang/Basic/DiagnosticCommentKinds.td
@@ -153,6 +153,12 @@ def warn_doc_deprecated_not_sync : Warning<
def note_add_deprecation_attr : Note<
"add a deprecation attribute to the declaration to silence this warning">;
+// inline contents commands
+
+def warn_doc_inline_contents_no_argument : Warning<
+ "'%select{\\|@}0%1' command does not have a valid word argument">,
+ InGroup<Documentation>, DefaultIgnore;
+
// verbatim block commands
def warn_verbatim_block_end_without_start : Warning<
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index ca2faf59d70f..484cc317f965 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -12,11 +12,21 @@
let Component = "Common" in {
+// Substitutions.
+
+def select_constexpr_spec_kind : TextSubstitution<
+ "%select{<ERROR>|constexpr|consteval|constinit}0">;
+
// Basic.
def fatal_too_many_errors
: Error<"too many errors emitted, stopping now">, DefaultFatal;
+def warn_stack_exhausted : Warning<
+ "stack nearly exhausted; compilation time may suffer, and "
+ "crashes due to stack overflow are likely">,
+ InGroup<DiagGroup<"stack-exhausted">>, NoSFINAE;
+
def note_declared_at : Note<"declared here">;
def note_previous_definition : Note<"previous definition is here">;
def note_previous_declaration : Note<"previous declaration is here">;
@@ -107,6 +117,10 @@ def err_attribute_not_type_attr : Error<
"%0 attribute cannot be applied to types">;
def err_enum_template : Error<"enumeration cannot be a template">;
+def warn_cxx20_compat_consteval : Warning<
+ "'consteval' specifier is incompatible with C++ standards before C++20">,
+ InGroup<CXX2aCompat>, DefaultIgnore;
+
}
let CategoryName = "Nullability Issue" in {
@@ -172,9 +186,6 @@ def ext_cxx11_longlong : Extension<
def warn_cxx98_compat_longlong : Warning<
"'long long' is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
-def warn_cxx20_compat_consteval : Warning<
- "consteval is incompatible with C++ standards before C++20">,
- InGroup<CXX2aCompat>, DefaultIgnore;
def err_integer_literal_too_large : Error<
"integer literal is too large to be represented in any %select{signed |}0"
"integer type">;
@@ -259,8 +270,6 @@ def err_target_unsupported_mcmse : Error<
"-mcmse is not supported for %0">;
def err_opt_not_valid_with_opt : Error<
"option '%0' cannot be specified with '%1'">;
-def err_opt_not_valid_without_opt : Error<
- "option '%0' cannot be specified without '%1'">;
def err_opt_not_valid_on_target : Error<
"option '%0' cannot be specified on this target">;
@@ -300,8 +309,13 @@ def err_omp_more_one_clause : Error<
"directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
// Static Analyzer Core
-def err_unknown_analyzer_checker : Error<
+def err_unknown_analyzer_checker_or_package : Error<
"no analyzer checkers or packages are associated with '%0'">;
def note_suggest_disabling_all_checkers : Note<
"use -analyzer-disable-all-checks to disable all static analyzer checkers">;
+
+// Poison system directories.
+def warn_poison_system_directories : Warning <
+ "include location '%0' is unsafe for cross-compilation">,
+ InGroup<DiagGroup<"poison-system-directories">>, DefaultIgnore;
}
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index eab453ee20ec..5ff03e133563 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -184,9 +184,6 @@ def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning<
def warn_drv_ycyu_different_arg_clang_cl : Warning<
"support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored">,
InGroup<ClangClPch>;
-def warn_drv_ycyu_no_fi_arg_clang_cl : Warning<
- "support for '%0' without a corresponding /FI flag not implemented yet; flag ignored">,
- InGroup<ClangClPch>;
def warn_drv_yc_multiple_inputs_clang_cl : Warning<
"support for '/Yc' with more than one source file not implemented yet; flag ignored">,
InGroup<ClangClPch>;
@@ -368,6 +365,9 @@ def err_drv_ropi_rwpi_incompatible_with_pic : Error<
def err_drv_ropi_incompatible_with_cxx : Error<
"ROPI is not compatible with c++">;
+def err_stack_tagging_requires_hardware_feature : Error<
+ "'-fsanitize=memtag' requires hardware support (+memtag)">;
+
def warn_target_unsupported_nan2008 : Warning<
"ignoring '-mnan=2008' option because the '%0' architecture does not support it">,
InGroup<UnsupportedNan>;
@@ -383,6 +383,9 @@ def warn_target_unsupported_abs2008 : Warning<
def warn_target_unsupported_compact_branches : Warning<
"ignoring '-mcompact-branches=' option because the '%0' architecture does not"
" support it">, InGroup<UnsupportedCB>;
+def warn_target_unsupported_extension : Warning<
+ "ignoring extension '%0' because the '%1' architecture does not support it">,
+ InGroup<InvalidCommandLineArgument>;
def warn_drv_unsupported_gpopt : Warning<
"ignoring '-mgpopt' option as it cannot be used with %select{|the implicit"
" usage of }0-mabicalls">,
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 7a990164b0d9..a798b498d4e9 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -64,8 +64,6 @@ def err_fe_backend_unsupported : Error<"%0">, BackendInfo;
def err_fe_invalid_code_complete_file : Error<
"cannot locate code-completion file %0">, DefaultFatal;
-def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
- DefaultFatal;
def err_fe_dependency_file_requires_MT : Error<
"-dependency-file requires at least one -MT or -MQ option">;
def err_fe_invalid_plugin_name : Error<
@@ -217,10 +215,6 @@ def err_modules_embed_file_not_found :
DefaultFatal;
def err_module_header_file_not_found :
Error<"module header file '%0' not found">, DefaultFatal;
-def err_module_header_file_invalid :
- Error<"unexpected module header file input '%0'">, DefaultFatal;
-
-def err_interface_stubs : Error<"clang-ifs (-emit-iterface-stubs): %0">;
def err_test_module_file_extension_version : Error<
"test module file extension '%0' has different version (%1.%2) than expected "
@@ -275,7 +269,12 @@ def warn_profile_data_missing : Warning<
def warn_profile_data_unprofiled : Warning<
"no profile data available for file \"%0\"">,
InGroup<ProfileInstrUnprofiled>;
-
+def warn_profile_data_misexpect : Warning<
+ "Potential performance regression from use of __builtin_expect(): "
+ "Annotation was correct on %0 of profiled executions.">,
+ BackendInfo,
+ InGroup<MisExpect>,
+ DefaultIgnore;
} // end of instrumentation issue category
}
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 56f2ecfe8e4a..928059539558 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -61,8 +61,16 @@ def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
UndefinedBoolConversion]>;
def IntConversion : DiagGroup<"int-conversion">;
def EnumConversion : DiagGroup<"enum-conversion">;
-def ImplicitIntConversion : DiagGroup<"implicit-int-conversion">;
-def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion">;
+def ObjCSignedCharBoolImplicitIntConversion :
+ DiagGroup<"objc-signed-char-bool-implicit-int-conversion">;
+def ImplicitIntConversion : DiagGroup<"implicit-int-conversion",
+ [ObjCSignedCharBoolImplicitIntConversion]>;
+def ImplicitIntFloatConversion : DiagGroup<"implicit-int-float-conversion">;
+def ObjCSignedCharBoolImplicitFloatConversion :
+ DiagGroup<"objc-signed-char-bool-implicit-float-conversion">;
+def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion",
+ [ImplicitIntFloatConversion,
+ ObjCSignedCharBoolImplicitFloatConversion]>;
def ImplicitFixedPointConversion : DiagGroup<"implicit-fixed-point-conversion">;
def FloatOverflowConversion : DiagGroup<"float-overflow-conversion">;
@@ -99,7 +107,6 @@ 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 UndefinedVarTemplate : DiagGroup<"undefined-var-template">;
@@ -113,11 +120,13 @@ def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor",
[DeleteNonAbstractNonVirtualDtor,
DeleteAbstractNonVirtualDtor]>;
def AbstractFinalClass : DiagGroup<"abstract-final-class">;
+def FinalDtorNonFinalClass : DiagGroup<"final-dtor-non-final-class">;
def CXX11CompatDeprecatedWritableStr :
DiagGroup<"c++11-compat-deprecated-writable-strings">;
def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
+def DeprecatedCommaSubscript : DiagGroup<"deprecated-comma-subscript">;
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">;
@@ -131,18 +140,27 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
def DeprecatedRegister : DiagGroup<"deprecated-register">;
def DeprecatedThisCapture : DiagGroup<"deprecated-this-capture">;
+def DeprecatedVolatile : DiagGroup<"deprecated-volatile">;
def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
[CXX11CompatDeprecatedWritableStr]>;
// FIXME: Why is DeprecatedImplementations not in this group?
def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
+ DeprecatedCommaSubscript,
DeprecatedDeclarations,
DeprecatedDynamicExceptionSpec,
DeprecatedIncrementBool,
DeprecatedRegister,
DeprecatedThisCapture,
+ DeprecatedVolatile,
DeprecatedWritableStr]>,
DiagCategory<"Deprecations">;
+def CXX2aDesignator : DiagGroup<"c++2a-designator">;
+// Allow -Wno-c99-designator to be used to turn off all warnings on valid C99
+// designators (including the warning controlled by -Wc++2a-designator).
+def C99Designator : DiagGroup<"c99-designator", [CXX2aDesignator]>;
+def GNUDesignator : DiagGroup<"gnu-designator">;
+
def DynamicExceptionSpec
: DiagGroup<"dynamic-exception-spec", [DeprecatedDynamicExceptionSpec]>;
@@ -278,6 +296,7 @@ def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
def GlobalConstructors : DiagGroup<"global-constructors">;
+def BitwiseConditionalParentheses: DiagGroup<"bitwise-conditional-parentheses">;
def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">;
@@ -286,9 +305,11 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
+def DanglingGsl : DiagGroup<"dangling-gsl">;
def ReturnStackAddress : DiagGroup<"return-stack-address">;
def Dangling : DiagGroup<"dangling", [DanglingField,
DanglingInitializerList,
+ DanglingGsl,
ReturnStackAddress]>;
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
@@ -481,6 +502,7 @@ def StringCompare : DiagGroup<"string-compare">;
def StringPlusInt : DiagGroup<"string-plus-int">;
def StringPlusChar : DiagGroup<"string-plus-char">;
def StrncatSize : DiagGroup<"strncat-size">;
+def IntInBoolContext : DiagGroup<"int-in-bool-context">;
def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">;
def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">;
def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">;
@@ -495,12 +517,14 @@ def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare",
[TautologicalOutOfRangeCompare]>;
def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
+def TautologicalBitwiseCompare : DiagGroup<"tautological-bitwise-compare">;
def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
def TautologicalObjCBoolCompare : DiagGroup<"tautological-objc-bool-compare">;
def TautologicalCompare : DiagGroup<"tautological-compare",
[TautologicalConstantCompare,
TautologicalPointerCompare,
TautologicalOverlapCompare,
+ TautologicalBitwiseCompare,
TautologicalUndefinedCompare,
TautologicalObjCBoolCompare]>;
def HeaderHygiene : DiagGroup<"header-hygiene">;
@@ -509,6 +533,7 @@ 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 XorUsedAsPow : DiagGroup<"xor-used-as-pow">;
def Unsequenced : DiagGroup<"unsequenced">;
// GCC name for -Wunsequenced
@@ -543,6 +568,7 @@ def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
def SwitchBool : DiagGroup<"switch-bool">;
def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch">;
+def EnumCompareConditional : DiagGroup<"enum-compare-conditional">;
def EnumCompareSwitch : DiagGroup<"enum-compare-switch">;
def EnumCompare : DiagGroup<"enum-compare", [EnumCompareSwitch]>;
def ImplicitFallthroughPerFunction :
@@ -620,7 +646,9 @@ def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
def UserDefinedWarnings : DiagGroup<"user-defined-warnings">;
-def Reorder : DiagGroup<"reorder">;
+def ReorderCtor : DiagGroup<"reorder-ctor">;
+def ReorderInitList : DiagGroup<"reorder-init-list">;
+def Reorder : DiagGroup<"reorder", [ReorderCtor, ReorderInitList]>;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
def CustomAtomic : DiagGroup<"custom-atomic-properties">;
@@ -710,6 +738,7 @@ def ParenthesesOnEquality : DiagGroup<"parentheses-equality">;
def Parentheses : DiagGroup<"parentheses",
[LogicalOpParentheses,
LogicalNotParentheses,
+ BitwiseConditionalParentheses,
BitwiseOpParentheses,
ShiftOpParentheses,
OverloadedShiftOpParentheses,
@@ -757,6 +786,7 @@ def FormatSecurity : DiagGroup<"format-security">;
def FormatNonStandard : DiagGroup<"format-non-iso">;
def FormatY2K : DiagGroup<"format-y2k">;
def FormatPedantic : DiagGroup<"format-pedantic">;
+def FormatTypeConfusion : DiagGroup<"format-type-confusion">;
def Format : DiagGroup<"format",
[FormatExtraArgs, FormatZeroLength, NonNull,
FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,
@@ -800,6 +830,7 @@ def Most : DiagGroup<"most", [
Format,
Implicit,
InfiniteRecursion,
+ IntInBoolContext,
MismatchedTags,
MissingBraces,
Move,
@@ -890,7 +921,7 @@ def CXX17 : DiagGroup<"c++17-extensions">;
// A warning group for warnings about using C++2a features as extensions in
// earlier C++ versions.
-def CXX2a : DiagGroup<"c++2a-extensions">;
+def CXX2a : DiagGroup<"c++2a-extensions", [CXX2aDesignator]>;
def : DiagGroup<"c++0x-extensions", [CXX11]>;
def : DiagGroup<"c++1y-extensions", [CXX14]>;
@@ -903,7 +934,7 @@ def DelegatingCtorCycles :
def C11 : DiagGroup<"c11-extensions">;
// A warning group for warnings about using C99 features as extensions.
-def C99 : DiagGroup<"c99-extensions">;
+def C99 : DiagGroup<"c99-extensions", [C99Designator]>;
// A warning group for warnings about GCC extensions.
def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
@@ -1001,6 +1032,12 @@ def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
ObjCStringComparison
]>;
+def ObjCSignedCharBool : DiagGroup<"objc-signed-char-bool",
+ [ObjCSignedCharBoolImplicitIntConversion,
+ ObjCSignedCharBoolImplicitFloatConversion,
+ ObjCBoolConstantConversion,
+ TautologicalObjCBoolCompare]>;
+
// Inline ASM warnings.
def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
def ASMIgnoredQualifier : DiagGroup<"asm-ignored-qualifier">;
@@ -1028,6 +1065,7 @@ def BackendOptimizationFailure : DiagGroup<"pass-failed">;
def ProfileInstrMissing : DiagGroup<"profile-instr-missing">;
def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
+def MisExpect : DiagGroup<"misexpect">;
// AddressSanitizer frontend instrumentation remarks.
def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def
index baafd7ac723f..6d1a1af92821 100644
--- a/include/clang/Basic/DiagnosticOptions.def
+++ b/include/clang/Basic/DiagnosticOptions.def
@@ -49,6 +49,7 @@ DIAGOPT(Pedantic, 1, 0) /// -pedantic
DIAGOPT(PedanticErrors, 1, 0) /// -pedantic-errors
DIAGOPT(ShowColumn, 1, 1) /// Show column number on diagnostics.
DIAGOPT(ShowLocation, 1, 1) /// Show source location information.
+DIAGOPT(ShowLevel, 1, 1) /// Show diagnostic level.
DIAGOPT(AbsolutePath, 1, 0) /// Use absolute paths.
DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics.
DIAGOPT(ShowFixits, 1, 1) /// Show fixit information.
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 8e6ced0dea54..7c9f4da778a6 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -119,18 +119,16 @@ def warn_microsoft_qualifiers_ignored : Warning<
"qualifiers after comma in declarator list are ignored">,
InGroup<IgnoredAttributes>;
-def ext_c11_generic_selection : Extension<
- "generic selections are a C11-specific feature">, InGroup<C11>;
def err_duplicate_default_assoc : Error<
"duplicate default generic association">;
def note_previous_default_assoc : Note<
"previous default generic association is here">;
-def ext_c11_alignment : Extension<
- "%0 is a C11-specific feature">, InGroup<C11>;
+def ext_c99_feature : Extension<
+ "'%0' is a C99 extension">, InGroup<C99>;
+def ext_c11_feature : Extension<
+ "'%0' is a C11 extension">, InGroup<C11>;
-def ext_c11_noreturn : Extension<
- "_Noreturn functions are a C11-specific feature">, InGroup<C11>;
def err_c11_noreturn_misplaced : Error<
"'_Noreturn' keyword must precede function declarator">;
@@ -203,6 +201,7 @@ def err_invalid_token_after_declarator_suggest_equal : Error<
"invalid %0 at end of declaration; did you mean '='?">;
def err_expected_statement : Error<"expected statement">;
def err_expected_lparen_after : Error<"expected '(' after '%0'">;
+def err_expected_lbrace_after : Error<"expected '{' after '%0'">;
def err_expected_rparen_after : Error<"expected ')' after '%0'">;
def err_expected_punc : Error<"expected ')' or ',' after '%0'">;
def err_expected_less_after : Error<"expected '<' after '%0'">;
@@ -360,7 +359,8 @@ def err_typename_invalid_storageclass : Error<
def err_typename_invalid_functionspec : Error<
"type name does not allow function specifier to be specified">;
def err_typename_invalid_constexpr : Error<
- "type name does not allow %select{constexpr|consteval}0 specifier to be specified">;
+ "type name does not allow %sub{select_constexpr_spec_kind}0 specifier "
+ "to be specified">;
def err_typename_identifiers_only : Error<
"typename is allowed for identifiers only">;
@@ -374,8 +374,6 @@ def err_unexpected_token_in_nested_name_spec : Error<
"'%0' cannot be a part of nested name specifier; did you mean ':'?">;
def err_bool_redeclaration : Error<
"redeclaration of C++ built-in type 'bool'">;
-def ext_c11_static_assert : Extension<
- "_Static_assert is a C11-specific feature">, InGroup<C11>;
def warn_cxx98_compat_static_assert : Warning<
"static_assert declarations are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -436,8 +434,6 @@ def err_objc_property_requires_field_name : Error<
"property requires fields to be named">;
def err_objc_property_bitfield : Error<"property name cannot be a bit-field">;
def err_objc_expected_property_attr : Error<"unknown property attribute %0">;
-def err_objc_properties_require_objc2 : Error<
- "properties are an Objective-C 2 feature">;
def err_objc_unexpected_attr : Error<
"prefix attribute must be followed by an interface, protocol, or implementation">;
def err_objc_postfix_attribute : Error <
@@ -976,11 +972,13 @@ def warn_pragma_missing_argument : Warning<
def warn_pragma_invalid_argument : Warning<
"unexpected argument '%0' to '#pragma %1'%select{|; expected %3}2">, InGroup<IgnoredPragmas>;
+def err_pragma_misplaced_in_decl : Error<"this pragma cannot appear in %0 declaration">;
+
// '#pragma clang section' related errors
def err_pragma_expected_clang_section_name : Error<
- "expected one of [bss|data|rodata|text] section kind in '#pragma %0'">;
+ "expected one of [bss|data|rodata|text|relro] section kind in '#pragma %0'">;
def err_pragma_clang_section_expected_equal : Error<
- "expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
+ "expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text|relro}0'">;
def warn_pragma_expected_section_name : Warning<
"expected a string literal for the section name in '#pragma %0' - ignored">,
InGroup<IgnoredPragmas>;
@@ -1180,8 +1178,8 @@ def err_omp_expected_identifier_for_critical : Error<
"expected identifier specifying the name of the 'omp critical' directive">;
def err_omp_expected_reduction_identifier : Error<
"expected identifier or one of the following operators: '+', '-', '*', '&', '|', '^', '&&', or '||'">;
-def err_omp_decl_in_declare_simd : Error<
- "function declaration is expected after 'declare simd' directive">;
+def err_omp_decl_in_declare_simd_variant : Error<
+ "function declaration is expected after 'declare %select{simd|variant}0' directive">;
def err_omp_unknown_map_type : Error<
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
def err_omp_unknown_map_type_modifier : Error<
@@ -1195,13 +1193,36 @@ def err_omp_declare_simd_inbranch_notinbranch : Error<
def err_expected_end_declare_target : Error<
"expected '#pragma omp end declare target'">;
def err_omp_declare_target_unexpected_clause: Error<
- "unexpected '%0' clause, only 'to' or 'link' clauses expected">;
+ "unexpected '%0' clause, only %select{'to' or 'link'|'to', 'link' or 'device_type'}1 clauses expected">;
def err_omp_expected_clause: Error<
"expected at least one clause on '#pragma omp %0' directive">;
def err_omp_mapper_illegal_identifier : Error<
"illegal OpenMP user-defined mapper identifier">;
def err_omp_mapper_expected_declarator : Error<
"expected declarator on 'omp declare mapper' directive">;
+def err_omp_declare_variant_wrong_clause : Error<
+ "expected '%0' clause on 'omp declare variant' directive">;
+def err_omp_declare_variant_no_ctx_selector : Error<
+ "expected context selector in '%0' clause on 'omp declare variant' directive">;
+def err_omp_declare_variant_equal_expected : Error<
+ "expected '=' after '%0' context selector set name on 'omp declare variant' directive">;
+def warn_omp_declare_variant_cs_name_expected : Warning<
+ "unknown context selector in '%0' context selector set of 'omp declare variant' directive, ignored">,
+ InGroup<OpenMPClauses>;
+def err_omp_declare_variant_item_expected : Error<
+ "expected %0 in '%1' context selector of '%2' selector set of 'omp declare variant' directive">;
+def err_omp_declare_variant_ctx_set_mutiple_use : Error<
+ "context selector set '%0' is used already in the same 'omp declare variant' directive">;
+def note_omp_declare_variant_ctx_set_used_here : Note<
+ "previously context selector set '%0' used here">;
+def err_omp_expected_comma_brace : Error<"expected '}' or ',' after '%0'">;
+def err_omp_declare_variant_ctx_mutiple_use : Error<
+ "context trait selector '%0' is used already in the same '%1' context selector set of 'omp declare variant' directive">;
+def note_omp_declare_variant_ctx_used_here : Note<
+ "previously context trait selector '%0' used here">;
+def warn_omp_more_one_device_type_clause : Warning<
+ "more than one 'device_type' clause is specified">,
+ InGroup<OpenMPClauses>;
// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
@@ -1210,7 +1231,7 @@ def err_pragma_loop_missing_argument : Error<
def err_pragma_loop_invalid_option : Error<
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
"vectorize_width, interleave, interleave_count, unroll, unroll_count, "
- "pipeline, pipeline_initiation_interval, or distribute">;
+ "pipeline, pipeline_initiation_interval, vectorize_predicate, or distribute">;
def err_pragma_fp_invalid_option : Error<
"%select{invalid|missing}0 option%select{ %1|}0; expected contract">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index effcbad78b23..d802a92c42c0 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12,7 +12,6 @@
let Component = "Sema" in {
let CategoryName = "Semantic Issue" in {
-
def note_previous_decl : Note<"%0 declared here">;
def note_entity_declared_at : Note<"%0 declared here">;
def note_callee_decl : Note<"%0 declared here">;
@@ -155,7 +154,7 @@ def err_variably_modified_new_type : Error<
// C99 Designated Initializers
def ext_designated_init : Extension<
- "designated initializers are a C99 feature">, InGroup<C99>;
+ "designated initializers are a C99 feature">, InGroup<C99Designator>;
def err_array_designator_negative : Error<
"array designator value '%0' is negative">;
def err_array_designator_empty_range : Error<
@@ -174,15 +173,17 @@ def err_field_designator_nonfield : Error<
def note_field_designator_found : Note<"field designator refers here">;
def err_designator_for_scalar_init : Error<
"designator in initializer for scalar type %0">;
-def warn_subobject_initializer_overrides : Warning<
- "subobject initialization overrides initialization of other fields "
- "within its enclosing subobject">, InGroup<InitializerOverrides>;
def warn_initializer_overrides : Warning<
- "initializer overrides prior initialization of this subobject">,
- InGroup<InitializerOverrides>;
+ "initializer %select{partially |}0overrides prior initialization of "
+ "this subobject">, InGroup<InitializerOverrides>;
+def ext_initializer_overrides : ExtWarn<warn_initializer_overrides.Text>,
+ InGroup<InitializerOverrides>, SFINAEFailure;
+def err_initializer_overrides_destructed : Error<
+ "initializer would partially override prior initialization of object of "
+ "type %1 with non-trivial destruction">;
def note_previous_initializer : Note<
"previous initialization %select{|with side effects }0is here"
- "%select{| (side effects may not occur at run time)}0">;
+ "%select{| (side effects will not occur at run time)}0">;
def err_designator_into_flexible_array_member : Error<
"designator into flexible array member subobject">;
def note_flexible_array_member : Note<
@@ -190,6 +191,28 @@ def note_flexible_array_member : Note<
def ext_flexible_array_init : Extension<
"flexible array initialization is a GNU extension">, InGroup<GNUFlexibleArrayInitializer>;
+// C++20 designated initializers
+def ext_cxx_designated_init : Extension<
+ "designated initializers are a C++20 extension">, InGroup<CXX2aDesignator>;
+def warn_cxx17_compat_designated_init : Warning<
+ "designated initializers are incompatible with C++ standards before C++20">,
+ InGroup<CXXPre2aCompatPedantic>, DefaultIgnore;
+def ext_designated_init_mixed : ExtWarn<
+ "mixture of designated and non-designated initializers in the same "
+ "initializer list is a C99 extension">, InGroup<C99Designator>;
+def note_designated_init_mixed : Note<
+ "first non-designated initializer is here">;
+def ext_designated_init_array : ExtWarn<
+ "array designators are a C99 extension">, InGroup<C99Designator>;
+def ext_designated_init_nested : ExtWarn<
+ "nested designators are a C99 extension">, InGroup<C99Designator>;
+def ext_designated_init_reordered : ExtWarn<
+ "ISO C++ requires field designators to be specified in declaration order; "
+ "field %1 will be initialized after field %0">, InGroup<ReorderInitList>,
+ SFINAEFailure;
+def note_previous_field_init : Note<
+ "previous initialization for field %0 is here">;
+
// Declarations.
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
@@ -598,6 +621,10 @@ def ext_implicit_lib_function_decl : ExtWarn<
def note_include_header_or_declare : Note<
"include the header <%0> or explicitly provide a declaration for '%1'">;
def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
+def warn_implicit_decl_no_jmp_buf
+ : Warning<"declaration of built-in function '%0' requires the declaration"
+ " of the 'jmp_buf' type, commonly provided in the header <setjmp.h>.">,
+ InGroup<DiagGroup<"incomplete-setjmp-declaration">>;
def warn_implicit_decl_requires_sysheader : Warning<
"declaration of built-in function '%1' requires inclusion of the header <%0>">,
InGroup<BuiltinRequiresHeader>;
@@ -2212,6 +2239,11 @@ def err_class_marked_final_used_as_base : Error<
"base %0 is marked '%select{final|sealed}1'">;
def warn_abstract_final_class : Warning<
"abstract class is marked '%select{final|sealed}0'">, InGroup<AbstractFinalClass>;
+def warn_final_dtor_non_final_class : Warning<
+ "class with destructor marked '%select{final|sealed}0' cannot be inherited from">,
+ InGroup<FinalDtorNonFinalClass>;
+def note_final_dtor_non_final_class_silence : Note<
+ "mark %0 as '%select{final|sealed}1' to silence this warning">;
// C++11 attributes
def err_repeat_attribute : Error<"%0 attribute cannot be repeated">;
@@ -2326,18 +2358,24 @@ def warn_cxx14_compat_constexpr_not_const : Warning<
"in C++14; add 'const' to avoid a change in behavior">,
InGroup<DiagGroup<"constexpr-not-const">>;
def err_invalid_constexpr : Error<
- "%select{function parameter|typedef|non-static data member}0 "
- "cannot be %select{constexpr|consteval}1">;
+ "%select{function parameter|typedef}0 "
+ "cannot be %sub{select_constexpr_spec_kind}1">;
def err_invalid_constexpr_member : Error<"non-static data member cannot be "
"constexpr%select{; did you intend to make it %select{const|static}0?|}1">;
def err_constexpr_tag : Error<
"%select{class|struct|interface|union|enum}0 "
- "cannot be marked %select{constexpr|consteval}1">;
+ "cannot be marked %sub{select_constexpr_spec_kind}1">;
def err_constexpr_dtor : Error<
- "destructor cannot be marked %select{constexpr|consteval}0">;
+ "destructor cannot be declared %sub{select_constexpr_spec_kind}0">;
+def err_constexpr_dtor_subobject : Error<
+ "destructor cannot be declared %sub{select_constexpr_spec_kind}0 because "
+ "%select{data member %2|base class %3}1 does not have a "
+ "constexpr destructor">;
+def note_constexpr_dtor_subobject : Note<
+ "%select{data member %1|base class %2}0 declared here">;
def err_constexpr_wrong_decl_kind : Error<
- "%select{constexpr|consteval}0 can only be used "
- "in %select{variable and |}0function declarations">;
+ "%sub{select_constexpr_spec_kind}0 can only be used "
+ "in %select{|variable and function|function|variable}0 declarations">;
def err_invalid_constexpr_var_decl : Error<
"constexpr variable declaration must be a definition">;
def err_constexpr_static_mem_var_requires_init : Error<
@@ -2346,6 +2384,8 @@ def err_constexpr_var_non_literal : Error<
"constexpr variable cannot have non-literal type %0">;
def err_constexpr_var_requires_const_init : Error<
"constexpr variable %0 must be initialized by a constant expression">;
+def err_constexpr_var_requires_const_destruction : Error<
+ "constexpr variable %0 must have constant destruction">;
def err_constexpr_redecl_mismatch : Error<
"%select{non-constexpr|constexpr|consteval}1 declaration of %0"
" follows %select{non-constexpr|constexpr|consteval}2 declaration">;
@@ -2406,9 +2446,13 @@ def err_constexpr_local_var_static : Error<
def err_constexpr_local_var_non_literal_type : Error<
"variable of non-literal type %1 cannot be defined in a constexpr "
"%select{function|constructor}0">;
-def err_constexpr_local_var_no_init : Error<
- "variables defined in a constexpr %select{function|constructor}0 must be "
- "initialized">;
+def ext_constexpr_local_var_no_init : ExtWarn<
+ "uninitialized variable in a constexpr %select{function|constructor}0 "
+ "is a C++20 extension">, InGroup<CXX2a>;
+def warn_cxx17_compat_constexpr_local_var_no_init : Warning<
+ "uninitialized variable in a constexpr %select{function|constructor}0 "
+ "is incompatible with C++ standards before C++20">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
def ext_constexpr_function_never_constant_expr : ExtWarn<
"constexpr %select{function|constructor}0 never produces a "
"constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
@@ -2433,10 +2477,8 @@ def warn_cxx11_compat_constexpr_body_multiple_return : Warning<
InGroup<CXXPre14Compat>, DefaultIgnore;
def note_constexpr_body_previous_return : Note<
"previous return statement is here">;
-def err_constexpr_function_try_block : Error<
- "function try block not allowed in constexpr %select{function|constructor}0">;
-// c++2a function try blocks in constexpr
+// C++2a function try blocks in constexpr
def ext_constexpr_function_try_block_cxx2a : ExtWarn<
"function try block in constexpr %select{function|constructor}0 is "
"a C++2a extension">, InGroup<CXX2a>;
@@ -2445,10 +2487,20 @@ def warn_cxx17_compat_constexpr_function_try_block : Warning<
"incompatible with C++ standards before C++2a">,
InGroup<CXXPre2aCompat>, DefaultIgnore;
-def err_constexpr_union_ctor_no_init : Error<
- "constexpr union constructor does not initialize any member">;
-def err_constexpr_ctor_missing_init : Error<
- "constexpr constructor must initialize all members">;
+def ext_constexpr_union_ctor_no_init : ExtWarn<
+ "constexpr union constructor that does not initialize any member "
+ "is a C++20 extension">, InGroup<CXX2a>;
+def warn_cxx17_compat_constexpr_union_ctor_no_init : Warning<
+ "constexpr union constructor that does not initialize any member "
+ "is incompatible with C++ standards before C++20">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
+def ext_constexpr_ctor_missing_init : ExtWarn<
+ "constexpr constructor that does not initialize all members "
+ "is a C++20 extension">, InGroup<CXX2a>;
+def warn_cxx17_compat_constexpr_ctor_missing_init : Warning<
+ "constexpr constructor that does not initialize all members "
+ "is incompatible with C++ standards before C++20">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
def note_constexpr_ctor_missing_init : Note<
"member not initialized by constructor">;
def note_non_literal_no_constexpr_ctors : Note<
@@ -2463,6 +2515,8 @@ def note_non_literal_user_provided_dtor : Note<
"%0 is not literal because it has a user-provided destructor">;
def note_non_literal_nontrivial_dtor : Note<
"%0 is not literal because it has a non-trivial destructor">;
+def note_non_literal_non_constexpr_dtor : Note<
+ "%0 is not literal because its destructor is not constexpr">;
def note_non_literal_lambda : Note<
"lambda closure types are non-literal types before C++17">;
def warn_private_extern : Warning<
@@ -2472,8 +2526,6 @@ def note_private_extern : Note<
"use __attribute__((visibility(\"hidden\"))) attribute instead">;
// C++ Concepts
-def err_concept_initialized_with_non_bool_type : Error<
- "constraint expression must be of type 'bool' but is of type %0">;
def err_concept_decls_may_only_appear_in_global_namespace_scope : Error<
"concept declarations may only appear in global or namespace scope">;
def err_concept_no_parameters : Error<
@@ -2485,9 +2537,14 @@ def err_concept_no_associated_constraints : Error<
"concept cannot have associated constraints">;
def err_concept_not_implemented : Error<
"sorry, unimplemented concepts feature %0 used">;
+def err_non_constant_constraint_expression : Error<
+ "substitution into constraint expression resulted in a non-constant "
+ "expression">;
+def err_non_bool_atomic_constraint : Error<
+ "atomic constraint must be of type 'bool' (found %0)">;
-def err_template_different_associated_constraints : Error<
- "associated constraints differ in template redeclaration">;
+def err_template_different_requires_clause : Error<
+ "requires clause differs in template redeclaration">;
// C++11 char16_t/char32_t
def warn_cxx98_compat_unicode_type : Warning<
@@ -2519,6 +2576,9 @@ def err_nsobject_attribute : Error<
"'NSObject' attribute is for pointer types only">;
def err_attributes_are_not_compatible : Error<
"%0 and %1 attributes are not compatible">;
+def err_attribute_invalid_argument : Error<
+ "%select{'void'|a reference type|an array type|a non-vector or "
+ "non-vectorizable scalar type}0 is an invalid argument to attribute %1">;
def err_attribute_wrong_number_arguments : Error<
"%0 attribute %plural{0:takes no arguments|1:takes one argument|"
":requires exactly %1 arguments}1">;
@@ -2567,8 +2627,6 @@ def err_attribute_argument_out_of_range : Error<
def err_init_priority_object_attr : Error<
"can only use 'init_priority' attribute on file-scope definitions "
"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_out_of_bounds : Error<
"%0 attribute parameter %1 is out of bounds">;
def err_attribute_only_once_per_parameter : Error<
@@ -2778,6 +2836,11 @@ def err_no_accessor_for_property : Error<
def err_cannot_find_suitable_accessor : Error<
"cannot find suitable %select{getter|setter}0 for property %1">;
+def warn_alloca : Warning<
+ "use of function %0 is discouraged; there is no way to check for failure but "
+ "failure may still occur, resulting in a possibly exploitable security vulnerability">,
+ InGroup<DiagGroup<"alloca">>, DefaultIgnore;
+
def warn_alloca_align_alignof : Warning<
"second argument to __builtin_alloca_with_align is supposed to be in bits">,
InGroup<DiagGroup<"alloca-with-align-alignof">>;
@@ -2793,6 +2856,10 @@ def err_alignment_dependent_typedef_name : Error<
def err_attribute_aligned_too_great : Error<
"requested alignment must be %0 bytes or smaller">;
+def warn_assume_aligned_too_great
+ : Warning<"requested alignment must be %0 bytes or smaller; maximum "
+ "alignment assumed">,
+ InGroup<DiagGroup<"builtin-assume-aligned-alignment">>;
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
"%q0 redeclared without %1 attribute: previous %1 ignored">,
InGroup<MicrosoftInconsistentDllImport>;
@@ -2950,6 +3017,10 @@ def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">,
InGroup<IgnoredAttributes>;
+def warn_gnu_inline_cplusplus_without_extern : Warning<
+ "'gnu_inline' attribute without 'extern' in C++ treated as externally"
+ " available, this changed in Clang 10">,
+ InGroup<DiagGroup<"gnu-inline-cpp-without-extern">>;
def err_attribute_vecreturn_only_vector_member : Error<
"the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">;
def err_attribute_vecreturn_only_pod_record : Error<
@@ -2966,6 +3037,7 @@ def warn_cconv_unsupported : Warning<
"|on builtin function"
"}1">,
InGroup<IgnoredAttributes>;
+def error_cconv_unsupported : Error<warn_cconv_unsupported.Text>;
def err_cconv_knr : Error<
"function with no prototype cannot use the %0 calling convention">;
def warn_cconv_knr : Warning<
@@ -3251,9 +3323,9 @@ def warn_impcast_integer_precision_constant : Warning<
def warn_impcast_bitfield_precision_constant : Warning<
"implicit truncation from %2 to bit-field changes value from %0 to %1">,
InGroup<BitFieldConstantConversion>;
-def warn_impcast_constant_int_to_objc_bool : Warning<
- "implicit conversion from constant value %0 to BOOL; "
- "the only well defined values for BOOL are YES and NO">,
+def warn_impcast_constant_value_to_objc_bool : Warning<
+ "implicit conversion from constant value %0 to 'BOOL'; "
+ "the only well defined values for 'BOOL' are YES and NO">,
InGroup<ObjCBoolConstantConversion>;
def warn_impcast_fixed_point_range : Warning<
@@ -3269,6 +3341,20 @@ def warn_impcast_literal_float_to_integer_out_of_range : Warning<
def warn_impcast_float_integer : Warning<
"implicit conversion turns floating-point number into integer: %0 to %1">,
InGroup<FloatConversion>, DefaultIgnore;
+def warn_impcast_float_to_objc_signed_char_bool : Warning<
+ "implicit conversion from floating-point type %0 to 'BOOL'">,
+ InGroup<ObjCSignedCharBoolImplicitFloatConversion>;
+def warn_impcast_int_to_objc_signed_char_bool : Warning<
+ "implicit conversion from integral type %0 to 'BOOL'">,
+ InGroup<ObjCSignedCharBoolImplicitIntConversion>, DefaultIgnore;
+
+// Implicit int -> float conversion precision loss warnings.
+def warn_impcast_integer_float_precision : Warning<
+ "implicit conversion from %0 to %1 may lose precision">,
+ InGroup<ImplicitIntFloatConversion>, DefaultIgnore;
+def warn_impcast_integer_float_precision_constant : Warning<
+ "implicit conversion from %2 to %3 changes value from %0 to %1">,
+ InGroup<ImplicitIntFloatConversion>;
def warn_impcast_float_to_integer : Warning<
"implicit conversion from %0 to %1 changes value from %2 to %3">,
@@ -3292,6 +3378,10 @@ def warn_impcast_bool_to_null_pointer : Warning<
def warn_non_literal_null_pointer : Warning<
"expression which evaluates to zero treated as a null pointer constant of "
"type %0">, InGroup<NonLiteralNullConversion>;
+def warn_pointer_compare : Warning<
+ "comparing a pointer to a null character constant; did you mean "
+ "to compare to %select{NULL|(void *)0}0?">,
+ InGroup<DiagGroup<"pointer-compare">>;
def warn_impcast_null_pointer_to_integer : Warning<
"implicit conversion of %select{NULL|nullptr}0 constant to %1">,
InGroup<NullConversion>;
@@ -3318,6 +3408,18 @@ def warn_address_of_reference_bool_conversion : Warning<
"code; pointer may be assumed to always convert to true">,
InGroup<UndefinedBoolConversion>;
+def warn_xor_used_as_pow : Warning<
+ "result of '%0' is %1; did you mean exponentiation?">,
+ InGroup<XorUsedAsPow>;
+def warn_xor_used_as_pow_base_extra : Warning<
+ "result of '%0' is %1; did you mean '%2' (%3)?">,
+ InGroup<XorUsedAsPow>;
+def warn_xor_used_as_pow_base : Warning<
+ "result of '%0' is %1; did you mean '%2'?">,
+ InGroup<XorUsedAsPow>;
+def note_xor_used_as_pow_silence : Note<
+ "replace expression with '%0' %select{|or use 'xor' instead of '^' }1to silence this warning">;
+
def warn_null_pointer_compare : Warning<
"comparison of %select{address of|function|array}0 '%1' %select{not |}2"
"equal to a null pointer is always %select{true|false}2">,
@@ -3338,9 +3440,15 @@ def warn_address_of_reference_null_compare : Warning<
InGroup<TautologicalUndefinedCompare>;
def note_reference_is_return_value : Note<"%0 returns a reference">;
+def note_pointer_declared_here : Note<
+ "pointer %0 declared here">;
def warn_division_sizeof_ptr : Warning<
"'%0' will return the size of the pointer, not the array itself">,
InGroup<DiagGroup<"sizeof-pointer-div">>;
+def warn_division_sizeof_array : Warning<
+ "expression does not compute the number of elements in this array; element "
+ "type is %0, not %1">,
+ InGroup<DiagGroup<"sizeof-array-div">>;
def note_function_warning_silence : Note<
"prefix with the address-of operator to silence this warning">;
@@ -3661,7 +3769,8 @@ def note_ovl_too_many_candidates : Note<
"pass -fshow-overloads=all to show them">;
def select_ovl_candidate_kind : TextSubstitution<
- "%select{function|function|constructor|"
+ "%select{function|function|function (with reversed parameter order)|"
+ "constructor|"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
"constructor (the implicit move constructor)|"
@@ -3855,10 +3964,7 @@ def note_implicit_member_target_infer_collision : Note<
def note_ambiguous_type_conversion: Note<
"because of ambiguity in conversion %diff{of $ to $|between types}0,1">;
-def note_ovl_builtin_binary_candidate : Note<
- "built-in candidate %0">;
-def note_ovl_builtin_unary_candidate : Note<
- "built-in candidate %0">;
+def note_ovl_builtin_candidate : Note<"built-in candidate %0">;
def err_ovl_no_viable_function_in_init : Error<
"no matching constructor for initialization of %0">;
def err_ovl_no_conversion_in_cast : Error<
@@ -3885,6 +3991,13 @@ def err_ovl_ambiguous_oper_unary : Error<
"use of overloaded operator '%0' is ambiguous (operand type %1)">;
def err_ovl_ambiguous_oper_binary : Error<
"use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">;
+def ext_ovl_ambiguous_oper_binary_reversed : ExtWarn<
+ "ISO C++20 considers use of overloaded operator '%0' (with operand types %1 "
+ "and %2) to be ambiguous despite there being a unique best viable function">,
+ InGroup<DiagGroup<"ambiguous-reversed-operator">>, SFINAEFailure;
+def note_ovl_ambiguous_oper_binary_reversed_candidate : Note<
+ "ambiguity is between a regular call to this operator and a call with the "
+ "argument order reversed">;
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<
@@ -3892,6 +4005,9 @@ def err_ovl_deleted_oper : Error<
def err_ovl_deleted_special_oper : Error<
"object of type %0 cannot be %select{constructed|copied|moved|assigned|"
"assigned|destroyed}1 because its %sub{select_special_member_kind}1 is implicitly deleted">;
+def err_ovl_rewrite_equalequal_not_bool : Error<
+ "return type %0 of selected 'operator==' function for rewritten "
+ "'%1' comparison is not 'bool'">;
def err_ovl_no_viable_subscript :
Error<"no viable overloaded operator[] for type %0">;
def err_ovl_no_oper :
@@ -3934,6 +4050,8 @@ def err_ovl_no_viable_literal_operator : Error<
// C++ Template Declarations
def err_template_param_shadow : Error<
"declaration of %0 shadows template parameter">;
+def ext_template_param_shadow : ExtWarn<
+ err_template_param_shadow.Text>, InGroup<MicrosoftTemplate>;
def note_template_param_here : Note<"template parameter is declared here">;
def warn_template_export_unsupported : Warning<
"exported templates are unsupported">;
@@ -4392,6 +4510,10 @@ def note_prior_template_arg_substitution : Note<
" template parameter%1 %2">;
def note_template_default_arg_checking : Note<
"while checking a default template argument used here">;
+def note_concept_specialization_here : Note<
+ "while checking the satisfaction of concept '%0' requested here">;
+def note_constraint_substitution_here : Note<
+ "while substituting template arguments into constraint expression here">;
def note_instantiation_contexts_suppressed : Note<
"(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "
"see all)">;
@@ -5334,9 +5456,6 @@ def err_arc_mismatched_cast : Error<
" to %3 is disallowed with ARC">;
def err_arc_nolifetime_behavior : Error<
"explicit ownership qualifier on cast result has no effect">;
-def err_arc_objc_object_in_tag : Error<
- "ARC forbids %select{Objective-C objects|blocks}0 in "
- "%select{struct|interface|union|<<ERROR>>|enum}1">;
def err_arc_objc_property_default_assign_on_object : Error<
"ARC forbids synthesizing a property of an Objective-C object "
"with unspecified ownership or storage attribute">;
@@ -5626,9 +5745,18 @@ def note_precedence_silence : Note<
def warn_precedence_conditional : Warning<
"operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">,
InGroup<Parentheses>;
+def warn_precedence_bitwise_conditional : Warning<
+ "operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">,
+ InGroup<BitwiseConditionalParentheses>;
def note_precedence_conditional_first : Note<
"place parentheses around the '?:' expression to evaluate it first">;
+def warn_enum_constant_in_bool_context : Warning<
+ "converting the enum constant to a boolean">,
+ InGroup<IntInBoolContext>, DefaultIgnore;
+def warn_left_shift_in_bool_context : Warning<
+ "converting the result of '<<' to a boolean; did you mean '(%0) != 0'?">,
+ InGroup<IntInBoolContext>, DefaultIgnore;
def warn_logical_instead_of_bitwise : Warning<
"use of logical '%0' with constant operand">,
InGroup<DiagGroup<"constant-logical-operand">>;
@@ -5638,10 +5766,10 @@ def note_logical_instead_of_bitwise_remove_constant : Note<
"remove constant to silence this warning">;
def warn_bitwise_op_in_bitwise_op : Warning<
- "'%0' within '%1'">, InGroup<BitwiseOpParentheses>;
+ "'%0' within '%1'">, InGroup<BitwiseOpParentheses>, DefaultIgnore;
def warn_logical_and_in_logical_or : Warning<
- "'&&' within '||'">, InGroup<LogicalOpParentheses>;
+ "'&&' within '||'">, InGroup<LogicalOpParentheses>, DefaultIgnore;
def warn_overloaded_shift_in_comparison :Warning<
"overloaded operator %select{>>|<<}0 has higher precedence than "
@@ -5718,6 +5846,9 @@ def err_arithmetic_nonfragile_interface : Error<
"arithmetic on pointer to interface %0, which is not a constant size for "
"this architecture and platform">;
+def warn_deprecated_comma_subscript : Warning<
+ "top-level comma expression in array subscript is deprecated">,
+ InGroup<DeprecatedCommaSubscript>;
def ext_subscript_non_lvalue : Extension<
"ISO C90 does not allow subscripting non-lvalue array">;
@@ -6038,8 +6169,8 @@ def warn_tautological_constant_compare : Warning<
"%select{%1|%3}0 is always %4">,
InGroup<TautologicalTypeLimitCompare>, DefaultIgnore;
def warn_tautological_compare_objc_bool : Warning<
- "result of comparison of constant %0 with expression of type BOOL"
- " is always %1, as the only well defined values for BOOL are YES and NO">,
+ "result of comparison of constant %0 with expression of type 'BOOL'"
+ " is always %1, as the only well defined values for 'BOOL' are YES and NO">,
InGroup<TautologicalObjCBoolCompare>;
def warn_mixed_sign_comparison : Warning<
@@ -6051,10 +6182,22 @@ def warn_out_of_range_compare : Warning<
InGroup<TautologicalOutOfRangeCompare>;
def warn_tautological_bool_compare : Warning<warn_out_of_range_compare.Text>,
InGroup<TautologicalConstantCompare>;
+def warn_integer_constants_in_conditional_always_true : Warning<
+ "converting the result of '?:' with integer constants to a boolean always "
+ "evaluates to 'true'">,
+ InGroup<TautologicalConstantCompare>;
+def warn_left_shift_always : Warning<
+ "converting the result of '<<' to a boolean always evaluates "
+ "to %select{false|true}0">,
+ InGroup<TautologicalConstantCompare>;
def warn_comparison_of_mixed_enum_types : Warning<
"comparison of two values with different enumeration types"
"%diff{ ($ and $)|}0,1">,
InGroup<EnumCompare>;
+def warn_conditional_mixed_enum_types : Warning<
+ "enumeration type mismatch in conditional expression"
+ "%diff{ ($ and $)|}0,1">,
+ InGroup<EnumCompareConditional>, DefaultIgnore;
def warn_comparison_of_mixed_enum_types_switch : Warning<
"comparison of two values with different enumeration types in switch statement"
"%diff{ ($ and $)|}0,1">,
@@ -6093,6 +6236,8 @@ def err_invalid_qualified_function_type : Error<
def err_compound_qualified_function_type : Error<
"%select{block pointer|pointer|reference}0 to function type %select{%2 |}1"
"cannot have '%3' qualifier">;
+def err_qualified_function_typeid : Error<
+ "type operand %0 of 'typeid' cannot have '%1' qualifier">;
def err_ref_qualifier_overload : Error<
"cannot overload a member function %select{without a ref-qualifier|with "
@@ -6517,6 +6662,10 @@ def note_member_declared_here : Note<
"member %0 declared here">;
def note_member_first_declared_here : Note<
"member %0 first declared here">;
+def warn_bitwise_negation_bool : Warning<
+ "bitwise negation of a boolean expression%select{;| always evaluates to 'true';}0 "
+ "did you mean logical negation?">,
+ InGroup<DiagGroup<"bool-operation">>;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
def warn_increment_bool : Warning<
"incrementing expression of type bool is deprecated and "
@@ -6526,6 +6675,26 @@ def ext_increment_bool : ExtWarn<
DefaultError, InGroup<IncrementBool>;
def err_increment_decrement_enum : Error<
"cannot %select{decrement|increment}0 expression of enum type %1">;
+
+def warn_deprecated_increment_decrement_volatile : Warning<
+ "%select{decrement|increment}0 of object of volatile-qualified type %1 "
+ "is deprecated">, InGroup<DeprecatedVolatile>;
+def warn_deprecated_simple_assign_volatile : Warning<
+ "use of result of assignment to object of volatile-qualified type %0 "
+ "is deprecated">, InGroup<DeprecatedVolatile>;
+def warn_deprecated_compound_assign_volatile : Warning<
+ "compound assignment to object of volatile-qualified type %0 is deprecated">,
+ InGroup<DeprecatedVolatile>;
+def warn_deprecated_volatile_return : Warning<
+ "volatile-qualified return type %0 is deprecated">,
+ InGroup<DeprecatedVolatile>;
+def warn_deprecated_volatile_param : Warning<
+ "volatile-qualified parameter type %0 is deprecated">,
+ InGroup<DeprecatedVolatile>;
+def warn_deprecated_volatile_structured_binding : Warning<
+ "volatile qualifier in structured binding declaration is deprecated">,
+ InGroup<DeprecatedVolatile>;
+
def err_catch_incomplete_ptr : Error<
"cannot catch pointer to incomplete type %0">;
def err_catch_incomplete_ref : Error<
@@ -7426,6 +7595,12 @@ def warn_unused_container_subscript_expr : Warning<
def warn_unused_call : Warning<
"ignoring return value of function declared with %0 attribute">,
InGroup<UnusedValue>;
+def warn_unused_constructor : Warning<
+ "ignoring temporary created by a constructor declared with %0 attribute">,
+ InGroup<UnusedValue>;
+def warn_unused_constructor_msg : Warning<
+ "ignoring temporary created by a constructor declared with %0 attribute: %1">,
+ InGroup<UnusedValue>;
def warn_side_effects_unevaluated_context : Warning<
"expression with side effects has no effect in an unevaluated context">,
InGroup<UnevaluatedExpression>;
@@ -7435,6 +7610,9 @@ def warn_side_effects_typeid : Warning<
def warn_unused_result : Warning<
"ignoring return value of function declared with %0 attribute">,
InGroup<UnusedResult>;
+def warn_unused_result_msg : Warning<
+ "ignoring return value of function declared with %0 attribute: %1">,
+ InGroup<UnusedResult>;
def warn_unused_volatile : Warning<
"expression result unused; assign into a variable to force a volatile load">,
InGroup<DiagGroup<"unused-volatile-lvalue">>;
@@ -7443,6 +7621,8 @@ def ext_cxx14_attr : Extension<
"use of the %0 attribute is a C++14 extension">, InGroup<CXX14>;
def ext_cxx17_attr : Extension<
"use of the %0 attribute is a C++17 extension">, InGroup<CXX17>;
+def ext_cxx2a_attr : Extension<
+ "use of the %0 attribute is a C++2a extension">, InGroup<CXX2a>;
def warn_unused_comparison : Warning<
"%select{equality|inequality|relational|three-way}0 comparison result unused">,
@@ -7453,10 +7633,30 @@ def note_inequality_comparison_to_or_assign : Note<
def err_incomplete_type_used_in_type_trait_expr : Error<
"incomplete type %0 used in type trait expression">;
+// C++20 constinit and require_constant_initialization attribute
+def warn_cxx20_compat_constinit : Warning<
+ "'constinit' specifier is incompatible with C++ standards before C++20">,
+ InGroup<CXX2aCompat>, DefaultIgnore;
+def err_constinit_local_variable : Error<
+ "local variable cannot be declared 'constinit'">;
def err_require_constant_init_failed : Error<
"variable does not have a constant initializer">;
def note_declared_required_constant_init_here : Note<
- "required by 'require_constant_initialization' attribute here">;
+ "required by %select{'require_constant_initialization' attribute|"
+ "'constinit' specifier}0 here">;
+def ext_constinit_missing : ExtWarn<
+ "'constinit' specifier missing on initializing declaration of %0">,
+ InGroup<DiagGroup<"missing-constinit">>;
+def note_constinit_specified_here : Note<"variable declared constinit here">;
+def err_constinit_added_too_late : Error<
+ "'constinit' specifier added after initialization of variable">;
+def warn_require_const_init_added_too_late : Warning<
+ "'require_constant_initialization' attribute added after initialization "
+ "of variable">, InGroup<IgnoredAttributes>;
+def note_constinit_missing_here : Note<
+ "add the "
+ "%select{'require_constant_initialization' attribute|'constinit' specifier}0 "
+ "to the initializing declaration here">;
def err_dimension_expr_not_constant_integer : Error<
"dimension expression does not evaluate to a constant unsigned int">;
@@ -7493,8 +7693,6 @@ let CategoryName = "Inline Assembly Issue" in {
"invalid lvalue in asm input for constraint '%0'">;
def err_asm_invalid_input_constraint : Error<
"invalid input constraint '%0' in asm">;
- def err_asm_immediate_expected : Error<"constraint '%0' expects "
- "an integer constant expression">;
def err_asm_tying_incompatible_types : Error<
"unsupported inline asm: input with type "
"%diff{$ matching output with type $|}0,1">;
@@ -7583,7 +7781,7 @@ def err_mem_init_not_member_or_class : Error<
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;
+ InGroup<ReorderCtor>, DefaultIgnore;
def warn_abstract_vbase_init_ignored : Warning<
"initializer for virtual base class %0 of abstract class %1 "
"will never be used">,
@@ -7919,7 +8117,7 @@ def warn_array_index_precedes_bounds : Warning<
def warn_array_index_exceeds_bounds : Warning<
"array index %0 is past the end of the array (which contains %1 "
"element%s2)">, InGroup<ArrayBounds>;
-def note_array_index_out_of_bounds : Note<
+def note_array_declared_here : Note<
"array %0 declared here">;
def warn_printf_insufficient_data_args : Warning<
@@ -7940,16 +8138,17 @@ def warn_format_conversion_argument_type_mismatch : Warning<
"%select{type|underlying type}2 %1">,
InGroup<Format>;
def warn_format_conversion_argument_type_mismatch_pedantic : Extension<
- "format specifies type %0 but the argument has "
- "%select{type|underlying type}2 %1">,
+ warn_format_conversion_argument_type_mismatch.Text>,
InGroup<FormatPedantic>;
+def warn_format_conversion_argument_type_mismatch_confusion : Warning<
+ warn_format_conversion_argument_type_mismatch.Text>,
+ InGroup<FormatTypeConfusion>, DefaultIgnore;
def warn_format_argument_needs_cast : Warning<
"%select{values of type|enum values with underlying type}2 '%0' should not "
"be used as format arguments; add an explicit cast to %1 instead">,
InGroup<Format>;
def warn_format_argument_needs_cast_pedantic : Warning<
- "%select{values of type|enum values with underlying type}2 '%0' should not "
- "be used as format arguments; add an explicit cast to %1 instead">,
+ warn_format_argument_needs_cast.Text>,
InGroup<FormatPedantic>, DefaultIgnore;
def warn_printf_positional_arg_exceeds_data_args : Warning <
"data argument position '%0' exceeds the number of data arguments (%1)">,
@@ -8023,6 +8222,9 @@ def warn_printf_invalid_objc_flag: Warning<
def warn_scanf_scanlist_incomplete : Warning<
"no closing ']' for '%%[' in scanf format string">,
InGroup<Format>;
+def warn_format_bool_as_character : Warning<
+ "using '%0' format specifier, but argument has boolean value">,
+ InGroup<Format>;
def note_format_string_defined : Note<"format string is defined here">;
def note_format_fix_specifier : Note<"did you mean to use '%0'?">;
def note_printf_c_str: Note<"did you mean to call the %0 method?">;
@@ -8085,6 +8287,10 @@ def warn_dangling_member : Warning<
"%select{binds to|is}2 a temporary object "
"whose lifetime is shorter than the lifetime of the constructed object">,
InGroup<DanglingField>;
+def warn_dangling_lifetime_pointer_member : Warning<
+ "initializing pointer member %0 to point to a temporary object "
+ "whose lifetime is shorter than the lifetime of the constructed object">,
+ InGroup<DanglingGsl>;
def note_lifetime_extending_member_declared_here : Note<
"%select{%select{reference|'std::initializer_list'}0 member|"
"member with %select{reference|'std::initializer_list'}0 subobject}1 "
@@ -8103,6 +8309,10 @@ def warn_new_dangling_reference : Warning<
"temporary bound to reference member of allocated object "
"will be destroyed at the end of the full-expression">,
InGroup<DanglingField>;
+def warn_dangling_lifetime_pointer : Warning<
+ "object backing the pointer "
+ "will be destroyed at the end of the full-expression">,
+ InGroup<DanglingGsl>;
def warn_new_dangling_initializer_list : Warning<
"array backing "
"%select{initializer list subobject of the allocated object|"
@@ -8120,11 +8330,15 @@ def warn_unsupported_lifetime_extension : Warning<
// should result in a warning, since these always evaluate to a constant.
// Array comparisons have similar warnings
def warn_comparison_always : Warning<
- "%select{self-|array }0comparison always evaluates to %select{a constant|%2}1">,
+ "%select{self-|array }0comparison always evaluates to "
+ "%select{a constant|true|false|'std::strong_ordering::equal'}1">,
InGroup<TautologicalCompare>;
def warn_comparison_bitwise_always : Warning<
"bitwise comparison always evaluates to %select{false|true}0">,
- InGroup<TautologicalCompare>;
+ InGroup<TautologicalBitwiseCompare>, DefaultIgnore;
+def warn_comparison_bitwise_or : Warning<
+ "bitwise or with non-zero value always evaluates to true">,
+ InGroup<TautologicalBitwiseCompare>, DefaultIgnore;
def warn_tautological_overlap_comparison : Warning<
"overlapping comparisons always evaluate to %select{false|true}0">,
InGroup<TautologicalOverlapCompare>, DefaultIgnore;
@@ -8503,10 +8717,11 @@ def warn_sync_fetch_and_nand_semantics_change : Warning<
InGroup<DiagGroup<"sync-fetch-and-nand-semantics-changed">>;
// Type
-def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
+def ext_wchar_t_sign_spec : ExtWarn<"'%0' cannot be signed or unsigned">,
+ InGroup<DiagGroup<"signed-unsigned-wchar">>, DefaultError;
def warn_receiver_forward_class : Warning<
- "receiver %0 is a forward class and corresponding @interface may not exist">,
- InGroup<ForwardClassReceiver>;
+ "receiver %0 is a forward class and corresponding @interface may not exist">,
+ InGroup<ForwardClassReceiver>;
def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
def ext_missing_declspec : ExtWarn<
"declaration specifier missing, defaulting to 'int'">;
@@ -8984,7 +9199,7 @@ def ext_omp_loop_not_canonical_init : ExtWarn<
"('var = init' or 'T var = init')">, InGroup<OpenMPLoopForm>;
def err_omp_loop_not_canonical_cond : Error<
"condition of OpenMP for loop must be a relational comparison "
- "('<', '<=', '>', or '>=') of loop variable %0">;
+ "('<', '<=', '>', %select{or '>='|'>=', or '!='}0) of loop variable %1">;
def err_omp_loop_not_canonical_incr : Error<
"increment clause of OpenMP for loop must perform simple addition "
"or subtraction on loop variable %0">;
@@ -9101,10 +9316,10 @@ def err_omp_single_copyprivate_with_nowait : Error<
"the 'copyprivate' clause must not be used with the 'nowait' clause">;
def note_omp_nowait_clause_here : Note<
"'nowait' clause is here">;
-def err_omp_single_decl_in_declare_simd : Error<
- "single declaration is expected after 'declare simd' directive">;
+def err_omp_single_decl_in_declare_simd_variant : Error<
+ "single declaration is expected after 'declare %select{simd|variant}0' directive">;
def err_omp_function_expected : Error<
- "'#pragma omp declare simd' can only be applied to functions">;
+ "'#pragma omp declare %select{simd|variant}0' can only be applied to functions">;
def err_omp_wrong_cancel_region : Error<
"one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">;
def err_omp_parent_cancel_region_nowait : Error<
@@ -9286,6 +9501,44 @@ def err_omp_wrong_dependency_iterator_type : Error<
"expected an integer or a pointer type of the outer loop counter '%0' for non-rectangular nests">;
def err_omp_unsupported_type : Error <
"host requires %0 bit size %1 type support, but device '%2' does not support it">;
+def err_omp_lambda_capture_in_declare_target_not_to : Error<
+ "variable captured in declare target region must appear in a to clause">;
+def err_omp_device_type_mismatch : Error<
+ "'device_type(%0)' does not match previously specified 'device_type(%1)' for the same declaration">;
+def err_omp_wrong_device_function_call : Error<
+ "function with 'device_type(%0)' is not available on %select{device|host}1">;
+def note_omp_marked_device_type_here : Note<"marked as 'device_type(%0)' here">;
+def warn_omp_declare_target_after_first_use : Warning<
+ "declaration marked as declare target after first use, it may lead to incorrect results">,
+ InGroup<OpenMPTarget>;
+def err_omp_declare_variant_incompat_attributes : Error<
+ "'#pragma omp declare variant' is not compatible with any target-specific attributes">;
+def warn_omp_declare_variant_after_used : Warning<
+ "'#pragma omp declare variant' cannot be applied for function after first "
+ "usage; the original function might be used">, InGroup<SourceUsesOpenMP>;
+def warn_omp_declare_variant_after_emitted : Warning<
+ "'#pragma omp declare variant' cannot be applied to the function that was defined already;"
+ " the original function might be used">, InGroup<SourceUsesOpenMP>;
+def err_omp_declare_variant_noproto : Error<
+ "function with '#pragma omp declare variant' must have a prototype">;
+def note_omp_declare_variant_specified_here : Note<
+ "'#pragma omp declare variant' for function specified here">;
+def err_omp_declare_variant_doesnt_support : Error<
+ "'#pragma omp declare variant' does not "
+ "support %select{function templates|virtual functions|"
+ "deduced return types|constructors|destructors|deleted functions|"
+ "defaulted functions|constexpr functions|consteval function}0">;
+def err_omp_declare_variant_diff : Error<
+ "function with '#pragma omp declare variant' has a different %select{calling convention"
+ "|return type|constexpr specification|inline specification|storage class|"
+ "linkage}0">;
+def err_omp_declare_variant_incompat_types : Error<
+ "variant in '#pragma omp declare variant' with type %0 is incompatible with type %1"
+ >;
+def warn_omp_declare_variant_marked_as_declare_variant : Warning<
+ "variant function in '#pragma omp declare variant' is itself marked as '#pragma omp declare variant'"
+ >, InGroup<SourceUsesOpenMP>;
+def note_omp_marked_declare_variant_here : Note<"marked as 'declare variant' here">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
@@ -9725,6 +9978,8 @@ def err_std_compare_type_not_supported : Error<
"member '%2' is missing|"
"the type is not trivially copyable|"
"the type does not have the expected form}1">;
+def note_rewriting_operator_as_spaceship : Note<
+ "while rewriting comparison as call to 'operator<=>' declared here">;
// Memory Tagging Extensions (MTE) diagnostics
def err_memtag_arg_null_or_pointer : Error<
@@ -9735,8 +9990,6 @@ def err_memtag_arg_must_be_pointer : Error<
"%0 argument of MTE builtin function must be a pointer (%1 invalid)">;
def err_memtag_arg_must_be_integer : Error<
"%0 argument of MTE builtin function must be an integer type (%1 invalid)">;
-def err_memtag_arg_must_be_unsigned : Error<
- "%0 argument of MTE builtin function must be an unsigned integer type (%1 invalid)">;
def warn_dereference_of_noderef_type : Warning<
"dereferencing %0; was declared with a 'noderef' type">, InGroup<NoDeref>;
@@ -9751,6 +10004,11 @@ def err_builtin_launder_invalid_arg : Error<
"%select{non-pointer|function pointer|void pointer}0 argument to "
"'__builtin_launder' is not allowed">;
+def err_preserve_field_info_not_field : Error<
+ "__builtin_preserve_field_info argument %0 not a field access">;
+def err_preserve_field_info_not_const: Error<
+ "__builtin_preserve_field_info argument %0 not a constant">;
+
def err_bit_cast_non_trivially_copyable : Error<
"__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">;
def err_bit_cast_type_size_mismatch : Error<
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 43ba19b5853e..757dbbeee3cc 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -18,13 +18,16 @@ def err_fe_pch_malformed : Error<
def err_fe_pch_malformed_block : Error<
"malformed block record in PCH file: '%0'">, DefaultFatal;
def err_fe_pch_file_modified : Error<
- "file '%0' has been modified since the precompiled header '%1' was built">,
+ "file '%0' has been modified since the precompiled header '%1' was built"
+ ": %select{size|mtime|content}2 changed">,
DefaultFatal;
def err_fe_module_file_modified : Error<
- "file '%0' has been modified since the module file '%1' was built">,
+ "file '%0' has been modified since the module file '%1' was built"
+ ": %select{size|mtime|content}2 changed">,
DefaultFatal;
def err_fe_ast_file_modified : Error<
- "file '%0' has been modified since the AST file '%1' was built">,
+ "file '%0' has been modified since the AST file '%1' was built"
+ ": %select{size|mtime|content}2 changed">,
DefaultFatal;
def err_fe_pch_file_overridden : Error<
"file '%0' from the precompiled header has been overridden">;
@@ -77,13 +80,13 @@ def remark_module_import : Remark<
InGroup<ModuleImport>;
def err_imported_module_not_found : Error<
- "module '%0' in AST file '%1' (imported by AST file '%2') "
+ "module '%0' in AST file '%1' %select{(imported by AST file '%2') |}4"
"is not defined in any loaded module map file; "
"maybe you need to load '%3'?">, DefaultFatal;
def note_imported_by_pch_module_not_found : Note<
"consider adding '%0' to the header search path">;
def err_imported_module_modmap_changed : Error<
- "module '%0' imported by AST file '%1' found in a different module map file"
+ "module '%0' %select{in|imported by}4 AST file '%1' found in a different module map file"
" (%2) than when the importing AST file was built (%3)">, DefaultFatal;
def err_imported_module_relocated : Error<
"module '%0' was built in directory '%1' but now resides in "
@@ -399,6 +402,8 @@ def warn_module_uses_date_time : Warning<
def err_module_no_size_mtime_for_header : Error<
"cannot emit module %0: %select{size|mtime}1 must be explicitly specified "
"for missing header file \"%2\"">;
+def err_module_unable_to_hash_content : Error<
+ "failed to hash content for '%0' because memory buffer cannot be retrieved">;
} // let CategoryName
} // let Component
diff --git a/include/clang/Basic/Features.def b/include/clang/Basic/Features.def
index 7081c02e83ea..28eb694ba9a8 100644
--- a/include/clang/Basic/Features.def
+++ b/include/clang/Basic/Features.def
@@ -39,6 +39,8 @@
FEATURE(address_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
SanitizerKind::KernelAddress))
+FEATURE(leak_sanitizer,
+ LangOpts.Sanitize.has(SanitizerKind::Leak))
FEATURE(hwaddress_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress |
SanitizerKind::KernelHWAddress))
@@ -187,7 +189,7 @@ FEATURE(cxx_variable_templates, LangOpts.CPlusPlus14)
// FEATURE(raw_invocation_type, LangOpts.CPlusPlus)
// Type traits
// N.B. Additional type traits should not be added to the following list.
-// Instead, they should be detected by has_extension.
+// Instead, they should be detected by has_builtin.
FEATURE(has_nothrow_assign, LangOpts.CPlusPlus)
FEATURE(has_nothrow_copy, LangOpts.CPlusPlus)
FEATURE(has_nothrow_constructor, LangOpts.CPlusPlus)
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index 96983475f454..28cd05818087 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -45,12 +45,31 @@ class FileSystemStatCache;
class DirectoryEntry {
friend class FileManager;
+ // FIXME: We should not be storing a directory entry name here.
StringRef Name; // Name of the directory.
public:
StringRef getName() const { return Name; }
};
+/// A reference to a \c DirectoryEntry that includes the name of the directory
+/// as it was accessed by the FileManager's client.
+class DirectoryEntryRef {
+public:
+ const DirectoryEntry &getDirEntry() const { return *Entry->getValue(); }
+
+ StringRef getName() const { return Entry->getKey(); }
+
+private:
+ friend class FileManager;
+
+ DirectoryEntryRef(
+ llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>> *Entry)
+ : Entry(Entry) {}
+
+ const llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>> *Entry;
+};
+
/// Cached information about one file (either on disk
/// or in the virtual file system).
///
@@ -64,8 +83,8 @@ class FileEntry {
off_t Size; // File size in bytes.
time_t ModTime; // Modification time of file.
const DirectoryEntry *Dir; // Directory file lives in.
- unsigned UID; // A unique (small) ID for the file.
llvm::sys::fs::UniqueID UniqueID;
+ unsigned UID; // A unique (small) ID for the file.
bool IsNamedPipe;
bool IsValid; // Is this \c FileEntry initialized and valid?
@@ -106,6 +125,42 @@ public:
bool isOpenForTests() const { return File != nullptr; }
};
+/// A reference to a \c FileEntry that includes the name of the file as it was
+/// accessed by the FileManager's client.
+class FileEntryRef {
+public:
+ FileEntryRef() = delete;
+ FileEntryRef(StringRef Name, const FileEntry &Entry)
+ : Name(Name), Entry(&Entry) {}
+
+ const StringRef getName() const { return Name; }
+
+ bool isValid() const { return Entry->isValid(); }
+
+ const FileEntry &getFileEntry() const { return *Entry; }
+
+ off_t getSize() const { return Entry->getSize(); }
+
+ unsigned getUID() const { return Entry->getUID(); }
+
+ const llvm::sys::fs::UniqueID &getUniqueID() const {
+ return Entry->getUniqueID();
+ }
+
+ time_t getModificationTime() const { return Entry->getModificationTime(); }
+
+ friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) {
+ return LHS.Entry == RHS.Entry && LHS.Name == RHS.Name;
+ }
+ friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) {
+ return !(LHS == RHS);
+ }
+
+private:
+ StringRef Name;
+ const FileEntry *Entry;
+};
+
/// Implements support for file system lookup, file system caching,
/// and directory search management.
///
@@ -131,21 +186,41 @@ class FileManager : public RefCountedBase<FileManager> {
/// The virtual files that we have allocated.
SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
+ /// A set of files that bypass the maps and uniquing. They can have
+ /// conflicting filenames.
+ SmallVector<std::unique_ptr<FileEntry>, 0> BypassFileEntries;
+
/// A cache that maps paths to directory entries (either real or
- /// virtual) we have looked up
+ /// virtual) we have looked up, or an error that occurred when we looked up
+ /// the directory.
///
/// The actual Entries for real directories/files are
/// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
/// for virtual directories/files are owned by
/// VirtualDirectoryEntries/VirtualFileEntries above.
///
- llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
+ llvm::StringMap<llvm::ErrorOr<DirectoryEntry &>, llvm::BumpPtrAllocator>
+ SeenDirEntries;
+
+ /// A reference to the file entry that is associated with a particular
+ /// filename, or a reference to another filename that should be looked up
+ /// instead of the accessed filename.
+ ///
+ /// The reference to another filename is specifically useful for Redirecting
+ /// VFSs that use external names. In that case, the \c FileEntryRef returned
+ /// by the \c FileManager will have the external name, and not the name that
+ /// was used to lookup the file.
+ using SeenFileEntryOrRedirect =
+ llvm::PointerUnion<FileEntry *, const StringRef *>;
/// A cache that maps paths to file entries (either real or
- /// virtual) we have looked up.
+ /// virtual) we have looked up, or an error that occurred when we looked up
+ /// the file.
///
/// \see SeenDirEntries
- llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
+ llvm::StringMap<llvm::ErrorOr<SeenFileEntryOrRedirect>,
+ llvm::BumpPtrAllocator>
+ SeenFileEntries;
/// The canonical names of directories.
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
@@ -157,15 +232,12 @@ class FileManager : public RefCountedBase<FileManager> {
///
unsigned NextFileUID;
- // Statistics.
- unsigned NumDirLookups, NumFileLookups;
- unsigned NumDirCacheMisses, NumFileCacheMisses;
-
// Caching.
std::unique_ptr<FileSystemStatCache> StatCache;
- bool getStatValue(StringRef Path, llvm::vfs::Status &Status, bool isFile,
- std::unique_ptr<llvm::vfs::File> *F);
+ std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status,
+ bool isFile,
+ std::unique_ptr<llvm::vfs::File> *F);
/// Add all ancestors of the given path (pointing to either a file
/// or a directory) as virtual directories.
@@ -195,27 +267,86 @@ public:
/// Removes the FileSystemStatCache object from the manager.
void clearStatCache();
+ /// Returns the number of unique real file entries cached by the file manager.
+ size_t getNumUniqueRealFiles() const { return UniqueRealFiles.size(); }
+
/// Lookup, cache, and verify the specified directory (real or
/// virtual).
///
- /// This returns NULL if the directory doesn't exist.
+ /// This returns a \c std::error_code if there was an error reading the
+ /// directory. On success, returns the reference to the directory entry
+ /// together with the exact path that was used to access a file by a
+ /// particular call to getDirectoryRef.
///
/// \param CacheFailure If true and the file does not exist, we'll cache
/// the failure to find this file.
- const DirectoryEntry *getDirectory(StringRef DirName,
- bool CacheFailure = true);
+ llvm::Expected<DirectoryEntryRef> getDirectoryRef(StringRef DirName,
+ bool CacheFailure = true);
+
+ /// Get a \c DirectoryEntryRef if it exists, without doing anything on error.
+ llvm::Optional<DirectoryEntryRef>
+ getOptionalDirectoryRef(StringRef DirName, bool CacheFailure = true) {
+ return llvm::expectedToOptional(getDirectoryRef(DirName, CacheFailure));
+ }
+
+ /// Lookup, cache, and verify the specified directory (real or
+ /// virtual).
+ ///
+ /// This function is deprecated and will be removed at some point in the
+ /// future, new clients should use
+ /// \c getDirectoryRef.
+ ///
+ /// This returns a \c std::error_code if there was an error reading the
+ /// directory. If there is no error, the DirectoryEntry is guaranteed to be
+ /// non-NULL.
+ ///
+ /// \param CacheFailure If true and the file does not exist, we'll cache
+ /// the failure to find this file.
+ llvm::ErrorOr<const DirectoryEntry *>
+ getDirectory(StringRef DirName, bool CacheFailure = true);
/// Lookup, cache, and verify the specified file (real or
/// virtual).
///
- /// This returns NULL if the file doesn't exist.
+ /// This function is deprecated and will be removed at some point in the
+ /// future, new clients should use
+ /// \c getFileRef.
+ ///
+ /// This returns a \c std::error_code if there was an error loading the file.
+ /// If there is no error, the FileEntry is guaranteed to be non-NULL.
///
/// \param OpenFile if true and the file exists, it will be opened.
///
/// \param CacheFailure If true and the file does not exist, we'll cache
/// the failure to find this file.
- const FileEntry *getFile(StringRef Filename, bool OpenFile = false,
- bool CacheFailure = true);
+ llvm::ErrorOr<const FileEntry *>
+ getFile(StringRef Filename, bool OpenFile = false, bool CacheFailure = true);
+
+ /// Lookup, cache, and verify the specified file (real or virtual). Return the
+ /// reference to the file entry together with the exact path that was used to
+ /// access a file by a particular call to getFileRef. If the underlying VFS is
+ /// a redirecting VFS that uses external file names, the returned FileEntryRef
+ /// will use the external name instead of the filename that was passed to this
+ /// method.
+ ///
+ /// This returns a \c std::error_code if there was an error loading the file,
+ /// or a \c FileEntryRef otherwise.
+ ///
+ /// \param OpenFile if true and the file exists, it will be opened.
+ ///
+ /// \param CacheFailure If true and the file does not exist, we'll cache
+ /// the failure to find this file.
+ llvm::Expected<FileEntryRef> getFileRef(StringRef Filename,
+ bool OpenFile = false,
+ bool CacheFailure = true);
+
+ /// Get a FileEntryRef if it exists, without doing anything on error.
+ llvm::Optional<FileEntryRef> getOptionalFileRef(StringRef Filename,
+ bool OpenFile = false,
+ bool CacheFailure = true) {
+ return llvm::expectedToOptional(
+ getFileRef(Filename, OpenFile, CacheFailure));
+ }
/// Returns the current file system options
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
@@ -223,6 +354,10 @@ public:
llvm::vfs::FileSystem &getVirtualFileSystem() const { return *FS; }
+ void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
+ this->FS = std::move(FS);
+ }
+
/// Retrieve a file entry for a "virtual" file that acts as
/// if there were a file with the given name on disk.
///
@@ -230,24 +365,38 @@ public:
const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
time_t ModificationTime);
+ /// Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual
+ /// file entry, to access the real file. The returned FileEntry will have
+ /// the same filename as FE but a different identity and its own stat.
+ ///
+ /// This should be used only for rare error recovery paths because it
+ /// bypasses all mapping and uniquing, blindly creating a new FileEntry.
+ /// There is no attempt to deduplicate these; if you bypass the same file
+ /// twice, you get two new file entries.
+ llvm::Optional<FileEntryRef> getBypassFile(FileEntryRef VFE);
+
/// Open the specified file as a MemoryBuffer, returning a new
/// MemoryBuffer if successful, otherwise returning null.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
- bool ShouldCloseOpenFile = true);
+ getBufferForFile(const FileEntry *Entry, bool isVolatile = false);
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBufferForFile(StringRef Filename, bool isVolatile = false) {
+ return getBufferForFileImpl(Filename, /*FileSize=*/-1, isVolatile);
+ }
+
+private:
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBufferForFile(StringRef Filename, bool isVolatile = false);
+ getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile);
+public:
/// Get the 'stat' information for the given \p Path.
///
/// If the path is relative, it will be resolved against the WorkingDir of the
/// FileManager's FileSystemOptions.
///
- /// \returns false on success, true on error.
- bool getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result);
-
- /// Remove the real file \p Entry from the cache.
- void invalidateCache(const FileEntry *Entry);
+ /// \returns a \c std::error_code describing an error, if there was one
+ std::error_code getNoncachedStatValue(StringRef Path,
+ llvm::vfs::Status &Result);
/// If path is not absolute and FileSystemOptions set the working
/// directory, the path is modified to be relative to the given
@@ -265,11 +414,6 @@ public:
void GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
- /// Modifies the size and modification time of a previously created
- /// FileEntry. Use with caution.
- static void modifyFileEntry(FileEntry *File, off_t Size,
- time_t ModificationTime);
-
/// Retrieve the canonical name for a given directory.
///
/// This is a very expensive operation, despite its results being cached,
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 465486ede715..37d7198c6401 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -750,6 +750,12 @@ public:
return getIdentifierInfoFlag() == ZeroArg;
}
+ /// If this selector is the specific keyword selector described by Names.
+ bool isKeywordSelector(ArrayRef<StringRef> Names) const;
+
+ /// If this selector is the specific unary selector described by Name.
+ bool isUnarySelector(StringRef Name) const;
+
unsigned getNumArgs() const;
/// Retrieve the identifier at a given position in the selector.
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index 31aca2b0d695..a423654d5e03 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -111,6 +111,7 @@ BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
LANGOPT(GNUMode , 1, 1, "GNU extensions")
LANGOPT(GNUKeywords , 1, 1, "GNU keywords")
+VALUE_LANGOPT(GNUCVersion , 32, 0, "GNU C compatibility version")
BENIGN_LANGOPT(ImplicitInt, 1, !C99 && !CPlusPlus, "C89 implicit 'int'")
LANGOPT(Digraphs , 1, 0, "digraphs")
BENIGN_LANGOPT(HexFloats , 1, C99, "C99 hexadecimal float constants")
@@ -119,7 +120,8 @@ LANGOPT(AppleKext , 1, 0, "Apple kext support")
BENIGN_LANGOPT(PascalStrings, 1, 0, "Pascal string support")
LANGOPT(WritableStrings , 1, 0, "writable string support")
LANGOPT(ConstStrings , 1, 0, "const-qualified string support")
-LANGOPT(LaxVectorConversions , 1, 1, "lax vector conversions")
+ENUM_LANGOPT(LaxVectorConversions, LaxVectorConversionKind, 2,
+ LaxVectorConversionKind::All, "lax vector conversions")
LANGOPT(AltiVec , 1, 0, "AltiVec-style vector initializers")
LANGOPT(ZVector , 1, 0, "System z vector extensions")
LANGOPT(Exceptions , 1, 0, "exception handling")
@@ -128,6 +130,7 @@ LANGOPT(CXXExceptions , 1, 0, "C++ exceptions")
LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling")
LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling")
LANGOPT(SEHExceptions , 1, 0, "SEH .xdata exception handling")
+LANGOPT(WasmExceptions , 1, 0, "WebAssembly exception handling")
LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind")
LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation")
LANGOPT(RTTI , 1, 1, "run-time type information")
@@ -224,6 +227,8 @@ LANGOPT(GPURelocatableDeviceCode, 1, 0, "generate relocatable device code")
LANGOPT(SYCLIsDevice , 1, 0, "Generate code for SYCL device")
+LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP")
+
LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable")
@@ -288,6 +293,10 @@ BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
"maximum constexpr call depth")
BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576,
"maximum constexpr evaluation steps")
+BENIGN_LANGOPT(EnableNewConstInterp, 1, 0,
+ "enable the experimental new constant interpreter")
+BENIGN_LANGOPT(ForceNewConstInterp, 1, 0,
+ "force the use of the experimental new constant interpreter")
BENIGN_LANGOPT(BracketDepth, 32, 256,
"maximum bracket nesting depth")
BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index 8099eed28c5e..5f808f04e9ae 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -138,6 +138,12 @@ public:
/// rather than returning the required alignment.
Ver7,
+ /// Attempt to be ABI-compatible with code generated by Clang 9.0.x
+ /// (SVN r351319). This causes vectors of __int128 to be passed in memory
+ /// instead of passing in multiple scalar registers on x86_64 on Linux and
+ /// NetBSD.
+ Ver9,
+
/// Conform to the underlying platform's C and C++ ABIs as closely
/// as we can.
Latest
@@ -178,6 +184,16 @@ public:
FEA_On
};
+ enum class LaxVectorConversionKind {
+ /// Permit no implicit vector bitcasts.
+ None,
+ /// Permit vector bitcasts between integer vectors with different numbers
+ /// of elements but the same total bit-width.
+ Integer,
+ /// Permit vector bitcasts between all vectors with the same total
+ /// bit-width.
+ All,
+ };
public:
/// Set of enabled sanitizers.
diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Basic/LangStandard.h
index 244f14c793de..e7deb7d64638 100644
--- a/include/clang/Frontend/LangStandard.h
+++ b/include/clang/Basic/LangStandard.h
@@ -6,16 +6,37 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_LANGSTANDARD_H
-#define LLVM_CLANG_FRONTEND_LANGSTANDARD_H
+#ifndef LLVM_CLANG_BASIC_LANGSTANDARD_H
+#define LLVM_CLANG_BASIC_LANGSTANDARD_H
#include "clang/Basic/LLVM.h"
-#include "clang/Frontend/FrontendOptions.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
-namespace frontend {
+/// The language for the input, used to select and validate the language
+/// standard and possible actions.
+enum class Language : uint8_t {
+ Unknown,
+
+ /// Assembly: we accept this only so that we can preprocess it.
+ Asm,
+
+ /// LLVM IR: we accept this so that we can run the optimizer on it,
+ /// and compile it to assembly or object code.
+ LLVM_IR,
+
+ ///@{ Languages that the frontend can parse and compile.
+ C,
+ CXX,
+ ObjC,
+ ObjCXX,
+ OpenCL,
+ CUDA,
+ RenderScript,
+ HIP,
+ ///@}
+};
enum LangFeatures {
LineComment = (1 << 0),
@@ -35,22 +56,20 @@ enum LangFeatures {
OpenCL = (1 << 14)
};
-}
-
/// LangStandard - Information about the properties of a particular language
/// standard.
struct LangStandard {
enum Kind {
#define LANGSTANDARD(id, name, lang, desc, features) \
lang_##id,
-#include "clang/Frontend/LangStandards.def"
+#include "clang/Basic/LangStandards.def"
lang_unspecified
};
const char *ShortName;
const char *Description;
unsigned Flags;
- InputKind::Language Language;
+ clang::Language Language;
public:
/// getName - Get the name of this standard.
@@ -60,54 +79,54 @@ public:
const char *getDescription() const { return Description; }
/// Get the language that this standard describes.
- InputKind::Language getLanguage() const { return Language; }
+ clang::Language getLanguage() const { return Language; }
/// Language supports '//' comments.
- bool hasLineComments() const { return Flags & frontend::LineComment; }
+ bool hasLineComments() const { return Flags & LineComment; }
/// isC99 - Language is a superset of C99.
- bool isC99() const { return Flags & frontend::C99; }
+ bool isC99() const { return Flags & C99; }
/// isC11 - Language is a superset of C11.
- bool isC11() const { return Flags & frontend::C11; }
+ bool isC11() const { return Flags & C11; }
/// isC17 - Language is a superset of C17.
- bool isC17() const { return Flags & frontend::C17; }
+ bool isC17() const { return Flags & C17; }
/// isC2x - Language is a superset of C2x.
- bool isC2x() const { return Flags & frontend::C2x; }
+ bool isC2x() const { return Flags & C2x; }
/// isCPlusPlus - Language is a C++ variant.
- bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; }
+ bool isCPlusPlus() const { return Flags & CPlusPlus; }
/// isCPlusPlus11 - Language is a C++11 variant (or later).
- bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; }
+ bool isCPlusPlus11() const { return Flags & CPlusPlus11; }
/// isCPlusPlus14 - Language is a C++14 variant (or later).
- bool isCPlusPlus14() const { return Flags & frontend::CPlusPlus14; }
+ bool isCPlusPlus14() const { return Flags & CPlusPlus14; }
/// isCPlusPlus17 - Language is a C++17 variant (or later).
- bool isCPlusPlus17() const { return Flags & frontend::CPlusPlus17; }
+ bool isCPlusPlus17() const { return Flags & CPlusPlus17; }
/// isCPlusPlus2a - Language is a post-C++17 variant (or later).
- bool isCPlusPlus2a() const { return Flags & frontend::CPlusPlus2a; }
-
+ bool isCPlusPlus2a() const { return Flags & CPlusPlus2a; }
/// hasDigraphs - Language supports digraphs.
- bool hasDigraphs() const { return Flags & frontend::Digraphs; }
+ bool hasDigraphs() const { return Flags & Digraphs; }
/// isGNUMode - Language includes GNU extensions.
- bool isGNUMode() const { return Flags & frontend::GNUMode; }
+ bool isGNUMode() const { return Flags & GNUMode; }
/// hasHexFloats - Language supports hexadecimal float constants.
- bool hasHexFloats() const { return Flags & frontend::HexFloat; }
+ bool hasHexFloats() const { return Flags & HexFloat; }
/// hasImplicitInt - Language allows variables to be typed as int implicitly.
- bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; }
+ bool hasImplicitInt() const { return Flags & ImplicitInt; }
/// isOpenCL - Language is a OpenCL variant.
- bool isOpenCL() const { return Flags & frontend::OpenCL; }
+ bool isOpenCL() const { return Flags & OpenCL; }
+ static Kind getLangKind(StringRef Name);
static const LangStandard &getLangStandardForKind(Kind K);
static const LangStandard *getLangStandardForName(StringRef Name);
};
diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Basic/LangStandards.def
index 0964e9b90a03..427691fb71e9 100644
--- a/include/clang/Frontend/LangStandards.def
+++ b/include/clang/Basic/LangStandards.def
@@ -14,7 +14,7 @@
///
/// \param IDENT - The name of the standard as a C++ identifier.
/// \param NAME - The name of the standard.
-/// \param LANG - The InputKind::Language for which this is a standard.
+/// \param LANG - The Language for which this is a standard.
/// \param DESC - A short description of the standard.
/// \param FEATURES - The standard features as flags, these are enums from the
/// clang::frontend namespace, which is assumed to be be available.
@@ -165,7 +165,7 @@ LANGSTANDARD(opencl12, "cl1.2",
LANGSTANDARD(opencl20, "cl2.0",
OpenCL, "OpenCL 2.0",
LineComment | C99 | Digraphs | HexFloat | OpenCL)
-LANGSTANDARD(openclcpp, "c++",
+LANGSTANDARD(openclcpp, "clc++",
OpenCL, "C++ for OpenCL",
LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 |
Digraphs | HexFloat | OpenCL)
@@ -174,6 +174,7 @@ LANGSTANDARD_ALIAS_DEPR(opencl10, "CL")
LANGSTANDARD_ALIAS_DEPR(opencl11, "CL1.1")
LANGSTANDARD_ALIAS_DEPR(opencl12, "CL1.2")
LANGSTANDARD_ALIAS_DEPR(opencl20, "CL2.0")
+LANGSTANDARD_ALIAS_DEPR(openclcpp, "CLC++")
// CUDA
LANGSTANDARD(cuda, "cuda", CUDA, "NVIDIA CUDA(tm)",
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 696f85b18535..f4d442c084cf 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -82,6 +82,12 @@ inline bool isDiscardableGVALinkage(GVALinkage L) {
return L <= GVA_DiscardableODR;
}
+/// Do we know that this will be the only definition of this symbol (excluding
+/// inlining-only definitions)?
+inline bool isUniqueGVALinkage(GVALinkage L) {
+ return L == GVA_Internal || L == GVA_StrongExternal;
+}
+
inline bool isExternallyVisible(Linkage L) {
return L >= VisibleNoLinkage;
}
diff --git a/include/clang/Basic/OpenCLOptions.h b/include/clang/Basic/OpenCLOptions.h
index 47310da1d6d9..15661154eab5 100644
--- a/include/clang/Basic/OpenCLOptions.h
+++ b/include/clang/Basic/OpenCLOptions.h
@@ -42,7 +42,7 @@ public:
// Is supported as either an extension or an (optional) core feature for
// OpenCL version \p CLVer.
- bool isSupported(llvm::StringRef Ext, LangOptions LO) const {
+ bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const {
// In C++ mode all extensions should work at least as in v2.0.
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
auto I = OptMap.find(Ext)->getValue();
@@ -51,7 +51,7 @@ public:
// Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
// For supported extension, return false.
- bool isSupportedCore(llvm::StringRef Ext, LangOptions LO) const {
+ bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const {
// In C++ mode all extensions should work at least as in v2.0.
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
auto I = OptMap.find(Ext)->getValue();
@@ -60,7 +60,7 @@ public:
// Is supported OpenCL extension for OpenCL version \p CLVer.
// For supported (optional) core feature, return false.
- bool isSupportedExtension(llvm::StringRef Ext, LangOptions LO) const {
+ bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const {
// In C++ mode all extensions should work at least as in v2.0.
auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
auto I = OptMap.find(Ext)->getValue();
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 9685af4cade8..ff8f07aa5def 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -92,6 +92,15 @@
#ifndef OPENMP_TASKLOOP_SIMD_CLAUSE
# define OPENMP_TASKLOOP_SIMD_CLAUSE(Name)
#endif
+#ifndef OPENMP_MASTER_TASKLOOP_CLAUSE
+# define OPENMP_MASTER_TASKLOOP_CLAUSE(Name)
+#endif
+#ifndef OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE
+# define OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE
+# define OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(Name)
+#endif
#ifndef OPENMP_CRITICAL_CLAUSE
# define OPENMP_CRITICAL_CLAUSE(Name)
#endif
@@ -191,6 +200,15 @@
#ifndef OPENMP_ALLOCATE_CLAUSE
# define OPENMP_ALLOCATE_CLAUSE(Name)
#endif
+#ifndef OPENMP_DEVICE_TYPE_KIND
+#define OPENMP_DEVICE_TYPE_KIND(Name)
+#endif
+#ifndef OPENMP_DECLARE_VARIANT_CLAUSE
+#define OPENMP_DECLARE_VARIANT_CLAUSE(Name)
+#endif
+#ifndef OPENMP_MATCH_KIND
+#define OPENMP_MATCH_KIND(Name)
+#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
@@ -248,6 +266,10 @@ OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for, "target teams distrib
OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for_simd, "target teams distribute parallel for simd")
OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd")
OPENMP_DIRECTIVE(allocate)
+OPENMP_DIRECTIVE_EXT(declare_variant, "declare variant")
+OPENMP_DIRECTIVE_EXT(master_taskloop, "master taskloop")
+OPENMP_DIRECTIVE_EXT(parallel_master_taskloop, "parallel master taskloop")
+OPENMP_DIRECTIVE_EXT(master_taskloop_simd, "master taskloop simd")
// OpenMP clauses.
OPENMP_CLAUSE(allocator, OMPAllocatorClause)
@@ -656,6 +678,69 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(reduction)
OPENMP_TASKLOOP_SIMD_CLAUSE(in_reduction)
OPENMP_TASKLOOP_SIMD_CLAUSE(allocate)
+// Clauses allowed for OpenMP directive 'master taskloop'.
+OPENMP_MASTER_TASKLOOP_CLAUSE(if)
+OPENMP_MASTER_TASKLOOP_CLAUSE(shared)
+OPENMP_MASTER_TASKLOOP_CLAUSE(private)
+OPENMP_MASTER_TASKLOOP_CLAUSE(firstprivate)
+OPENMP_MASTER_TASKLOOP_CLAUSE(lastprivate)
+OPENMP_MASTER_TASKLOOP_CLAUSE(default)
+OPENMP_MASTER_TASKLOOP_CLAUSE(collapse)
+OPENMP_MASTER_TASKLOOP_CLAUSE(final)
+OPENMP_MASTER_TASKLOOP_CLAUSE(untied)
+OPENMP_MASTER_TASKLOOP_CLAUSE(mergeable)
+OPENMP_MASTER_TASKLOOP_CLAUSE(priority)
+OPENMP_MASTER_TASKLOOP_CLAUSE(grainsize)
+OPENMP_MASTER_TASKLOOP_CLAUSE(nogroup)
+OPENMP_MASTER_TASKLOOP_CLAUSE(num_tasks)
+OPENMP_MASTER_TASKLOOP_CLAUSE(reduction)
+OPENMP_MASTER_TASKLOOP_CLAUSE(in_reduction)
+OPENMP_MASTER_TASKLOOP_CLAUSE(allocate)
+
+// Clauses allowed for OpenMP directive 'master taskloop simd'.
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(if)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(shared)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(private)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(firstprivate)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(lastprivate)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(default)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(collapse)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(final)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(untied)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(mergeable)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(priority)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(linear)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(aligned)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(safelen)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(simdlen)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(grainsize)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(nogroup)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(num_tasks)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(reduction)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(in_reduction)
+OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE(allocate)
+
+// Clauses allowed for OpenMP directive 'parallel master taskloop'.
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(if)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(shared)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(private)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(firstprivate)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(lastprivate)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(default)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(collapse)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(final)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(untied)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(mergeable)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(priority)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(grainsize)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(nogroup)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(num_tasks)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(reduction)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(allocate)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(num_threads)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(proc_bind)
+OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE(copyin)
+
// Clauses allowed for OpenMP directive 'critical'.
OPENMP_CRITICAL_CLAUSE(hint)
@@ -950,9 +1035,27 @@ OPENMP_TASKGROUP_CLAUSE(allocate)
// Clauses allowed for OpenMP directive 'declare mapper'.
OPENMP_DECLARE_MAPPER_CLAUSE(map)
+// Device types for 'device_type' clause.
+OPENMP_DEVICE_TYPE_KIND(host)
+OPENMP_DEVICE_TYPE_KIND(nohost)
+OPENMP_DEVICE_TYPE_KIND(any)
+
+// Clauses allowed for OpenMP directive 'declare variant'.
+OPENMP_DECLARE_VARIANT_CLAUSE(match)
+
+// Context selectors for 'match' clause.
+// TODO: add other context selectors.
+OPENMP_MATCH_KIND(implementation)
+
+#undef OPENMP_MATCH_KIND
+#undef OPENMP_DECLARE_VARIANT_CLAUSE
+#undef OPENMP_DEVICE_TYPE_KIND
#undef OPENMP_ALLOCATE_CLAUSE
#undef OPENMP_DECLARE_MAPPER_CLAUSE
#undef OPENMP_TASKGROUP_CLAUSE
+#undef OPENMP_PARALLEL_MASTER_TASKLOOP_CLAUSE
+#undef OPENMP_MASTER_TASKLOOP_SIMD_CLAUSE
+#undef OPENMP_MASTER_TASKLOOP_CLAUSE
#undef OPENMP_TASKLOOP_SIMD_CLAUSE
#undef OPENMP_TASKLOOP_CLAUSE
#undef OPENMP_LINEAR_KIND
diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h
index d8dee2310ec2..4129cca0fe68 100644
--- a/include/clang/Basic/OpenMPKinds.h
+++ b/include/clang/Basic/OpenMPKinds.h
@@ -35,6 +35,8 @@ enum OpenMPClauseKind {
#include "clang/Basic/OpenMPKinds.def"
OMPC_threadprivate,
OMPC_uniform,
+ OMPC_device_type,
+ OMPC_match,
OMPC_unknown
};
@@ -152,6 +154,14 @@ enum OpenMPAtomicDefaultMemOrderClauseKind {
OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
};
+/// OpenMP device type for 'device_type' clause.
+enum OpenMPDeviceType {
+#define OPENMP_DEVICE_TYPE_KIND(Name) \
+ OMPC_DEVICE_TYPE_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_DEVICE_TYPE_unknown
+};
+
/// Scheduling data for loop-based OpenMP directives.
struct OpenMPScheduleTy final {
OpenMPScheduleClauseKind Schedule = OMPC_SCHEDULE_unknown;
@@ -259,7 +269,8 @@ bool isOpenMPPrivate(OpenMPClauseKind Kind);
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind);
/// Checks if the specified directive kind is one of tasking directives - task,
-/// taskloop or taksloop simd.
+/// taskloop, taksloop simd, master taskloop, parallel master taskloop or master
+/// taskloop simd.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind);
/// Checks if the specified directive kind is one of the composite or combined
diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
index 9757acaa5300..d66189144511 100644
--- a/include/clang/Basic/OperatorKinds.h
+++ b/include/clang/Basic/OperatorKinds.h
@@ -30,6 +30,25 @@ enum OverloadedOperatorKind : int {
/// the preceding "operator" keyword.
const char *getOperatorSpelling(OverloadedOperatorKind Operator);
+/// Get the other overloaded operator that the given operator can be rewritten
+/// into, if any such operator exists.
+inline OverloadedOperatorKind
+getRewrittenOverloadedOperator(OverloadedOperatorKind Kind) {
+ switch (Kind) {
+ case OO_Less:
+ case OO_LessEqual:
+ case OO_Greater:
+ case OO_GreaterEqual:
+ return OO_Spaceship;
+
+ case OO_ExclaimEqual:
+ return OO_EqualEqual;
+
+ default:
+ return OO_None;
+ }
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index e32f749ae6ab..3185ca0f4a25 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -140,9 +140,9 @@ namespace SrcMgr {
/// exist.
unsigned BufferOverridden : 1;
- /// True if this content cache was initially created for a source
- /// file considered as a system one.
- unsigned IsSystemFile : 1;
+ /// True if this content cache was initially created for a source file
+ /// considered to be volatile (likely to change between stat and open).
+ unsigned IsFileVolatile : 1;
/// True if this file may be transient, that is, if it might not
/// exist at some later point in time when this content entry is used,
@@ -152,15 +152,15 @@ namespace SrcMgr {
ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
- : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
- BufferOverridden(false), IsSystemFile(false), IsTransient(false) {}
+ : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
+ BufferOverridden(false), IsFileVolatile(false), IsTransient(false) {}
/// The copy ctor does not allow copies where source object has either
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
/// is not transferred, so this is a logical error.
ContentCache(const ContentCache &RHS)
- : Buffer(nullptr, false), BufferOverridden(false), IsSystemFile(false),
- IsTransient(false) {
+ : Buffer(nullptr, false), BufferOverridden(false),
+ IsFileVolatile(false), IsTransient(false) {
OrigEntry = RHS.OrigEntry;
ContentsEntry = RHS.ContentsEntry;
@@ -185,7 +185,7 @@ namespace SrcMgr {
///
/// \param Invalid If non-NULL, will be set \c true if an error occurred.
const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
- const SourceManager &SM,
+ FileManager &FM,
SourceLocation Loc = SourceLocation(),
bool *Invalid = nullptr) const;
@@ -265,16 +265,21 @@ namespace SrcMgr {
llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind>
ContentAndKind;
+ /// The filename that is used to access the file entry represented by the
+ /// content cache.
+ StringRef Filename;
+
public:
/// Return a FileInfo object.
static FileInfo get(SourceLocation IL, const ContentCache *Con,
- CharacteristicKind FileCharacter) {
+ CharacteristicKind FileCharacter, StringRef Filename) {
FileInfo X;
X.IncludeLoc = IL.getRawEncoding();
X.NumCreatedFIDs = 0;
X.HasLineDirectives = false;
X.ContentAndKind.setPointer(Con);
X.ContentAndKind.setInt(FileCharacter);
+ X.Filename = Filename;
return X;
}
@@ -299,6 +304,10 @@ namespace SrcMgr {
void setHasLineDirectives() {
HasLineDirectives = true;
}
+
+ /// Returns the name of the file that was used when the file was loaded from
+ /// the underlying file system.
+ StringRef getName() const { return Filename; }
};
/// Each ExpansionInfo encodes the expansion location - where
@@ -821,7 +830,18 @@ public:
const SrcMgr::ContentCache *IR =
getOrCreateContentCache(SourceFile, isSystem(FileCharacter));
assert(IR && "getOrCreateContentCache() cannot return NULL");
- return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
+ return createFileID(IR, SourceFile->getName(), IncludePos, FileCharacter,
+ LoadedID, LoadedOffset);
+ }
+
+ FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter,
+ int LoadedID = 0, unsigned LoadedOffset = 0) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(
+ &SourceFile.getFileEntry(), isSystem(FileCharacter));
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
+ return createFileID(IR, SourceFile.getName(), IncludePos, FileCharacter,
+ LoadedID, LoadedOffset);
}
/// Create a new FileID that represents the specified memory buffer.
@@ -832,9 +852,10 @@ public:
SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
int LoadedID = 0, unsigned LoadedOffset = 0,
SourceLocation IncludeLoc = SourceLocation()) {
+ StringRef Name = Buffer->getBufferIdentifier();
return createFileID(
createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false),
- IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
+ Name, IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
}
enum UnownedTag { Unowned };
@@ -847,8 +868,9 @@ public:
SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
int LoadedID = 0, unsigned LoadedOffset = 0,
SourceLocation IncludeLoc = SourceLocation()) {
- return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/true),
- IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
+ return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/ true),
+ Buffer->getBufferIdentifier(), IncludeLoc,
+ FileCharacter, LoadedID, LoadedOffset);
}
/// Get the FileID for \p SourceFile if it exists. Otherwise, create a
@@ -930,11 +952,12 @@ public:
return false;
}
- /// Disable overridding the contents of a file, previously enabled
- /// with #overrideFileContents.
+ /// Bypass the overridden contents of a file. This creates a new FileEntry
+ /// and initializes the content cache for it. Returns nullptr if there is no
+ /// such file in the filesystem.
///
/// This should be called before parsing has begun.
- void disableFileContentsOverride(const FileEntry *File);
+ const FileEntry *bypassFileContentsOverride(const FileEntry &File);
/// Specify that a file is transient.
void setFileIsTransient(const FileEntry *SourceFile);
@@ -964,8 +987,8 @@ public:
return getFakeBufferForRecovery();
}
- return Entry.getFile().getContentCache()->getBuffer(Diag, *this, Loc,
- Invalid);
+ return Entry.getFile().getContentCache()->getBuffer(Diag, getFileManager(),
+ Loc, Invalid);
}
const llvm::MemoryBuffer *getBuffer(FileID FID,
@@ -979,9 +1002,8 @@ public:
return getFakeBufferForRecovery();
}
- return Entry.getFile().getContentCache()->getBuffer(Diag, *this,
- SourceLocation(),
- Invalid);
+ return Entry.getFile().getContentCache()->getBuffer(
+ Diag, getFileManager(), SourceLocation(), Invalid);
}
/// Returns the FileEntry record for the provided FileID.
@@ -997,6 +1019,19 @@ public:
return Content->OrigEntry;
}
+ /// Returns the FileEntryRef for the provided FileID.
+ Optional<FileEntryRef> getFileEntryRefForID(FileID FID) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return None;
+
+ const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache();
+ if (!Content || !Content->OrigEntry)
+ return None;
+ return FileEntryRef(Entry.getFile().getName(), *Content->OrigEntry);
+ }
+
/// Returns the FileEntry record for the provided SLocEntry.
const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
{
@@ -1785,10 +1820,10 @@ private:
///
/// This works regardless of whether the ContentCache corresponds to a
/// file or some other input source.
- FileID createFileID(const SrcMgr::ContentCache* File,
+ FileID createFileID(const SrcMgr::ContentCache *File, StringRef Filename,
SourceLocation IncludePos,
- SrcMgr::CharacteristicKind DirCharacter,
- int LoadedID, unsigned LoadedOffset);
+ SrcMgr::CharacteristicKind DirCharacter, int LoadedID,
+ unsigned LoadedOffset);
const SrcMgr::ContentCache *
getOrCreateContentCache(const FileEntry *SourceFile,
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index d1236e798e5d..fad97a26d957 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -32,7 +32,8 @@ namespace clang {
enum ConstexprSpecKind {
CSK_unspecified,
CSK_constexpr,
- CSK_consteval
+ CSK_consteval,
+ CSK_constinit
};
/// Specifies the width of a type, e.g., short, long, or long long.
diff --git a/include/clang/Basic/Stack.h b/include/clang/Basic/Stack.h
index e0b04099de58..3418c3bad11b 100644
--- a/include/clang/Basic/Stack.h
+++ b/include/clang/Basic/Stack.h
@@ -16,11 +16,40 @@
#include <cstddef>
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
+
namespace clang {
/// The amount of stack space that Clang would like to be provided with.
/// If less than this much is available, we may be unable to reach our
/// template instantiation depth limit and other similar limits.
constexpr size_t DesiredStackSize = 8 << 20;
+
+ /// Call this once on each thread, as soon after starting the thread as
+ /// feasible, to note the approximate address of the bottom of the stack.
+ void noteBottomOfStack();
+
+ /// Determine whether the stack is nearly exhausted.
+ bool isStackNearlyExhausted();
+
+ void runWithSufficientStackSpaceSlow(llvm::function_ref<void()> Diag,
+ llvm::function_ref<void()> Fn);
+
+ /// Run a given function on a stack with "sufficient" space. If stack space
+ /// is insufficient, calls Diag to emit a diagnostic before calling Fn.
+ inline void runWithSufficientStackSpace(llvm::function_ref<void()> Diag,
+ llvm::function_ref<void()> Fn) {
+#ifdef LLVM_ENABLE_THREADS
+ if (LLVM_UNLIKELY(isStackNearlyExhausted()))
+ runWithSufficientStackSpaceSlow(Diag, Fn);
+ else
+ Fn();
+#else
+ if (LLVM_UNLIKELY(isStackNearlyExhausted()))
+ Diag();
+ Fn();
+#endif
+ }
} // end namespace clang
#endif // LLVM_CLANG_BASIC_STACK_H
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index be364de1a76c..59444b2919a9 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -114,6 +114,7 @@ def GNUNullExpr : DStmt<Expr>;
// C++ Expressions.
def CXXOperatorCallExpr : DStmt<CallExpr>;
def CXXMemberCallExpr : DStmt<CallExpr>;
+def CXXRewrittenBinaryOperator : DStmt<Expr>;
def CXXNamedCastExpr : DStmt<ExplicitCastExpr, 1>;
def CXXStaticCastExpr : DStmt<CXXNamedCastExpr>;
def CXXDynamicCastExpr : DStmt<CXXNamedCastExpr>;
@@ -163,6 +164,9 @@ def CoawaitExpr : DStmt<CoroutineSuspendExpr>;
def DependentCoawaitExpr : DStmt<Expr>;
def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
+// C++2a Concepts expressions
+def ConceptSpecializationExpr : DStmt<Expr>;
+
// Obj-C Expressions.
def ObjCStringLiteral : DStmt<Expr>;
def ObjCBoxedExpr : DStmt<Expr>;
@@ -242,6 +246,9 @@ def OMPCancellationPointDirective : DStmt<OMPExecutableDirective>;
def OMPCancelDirective : DStmt<OMPExecutableDirective>;
def OMPTaskLoopDirective : DStmt<OMPLoopDirective>;
def OMPTaskLoopSimdDirective : DStmt<OMPLoopDirective>;
+def OMPMasterTaskLoopDirective : DStmt<OMPLoopDirective>;
+def OMPMasterTaskLoopSimdDirective : DStmt<OMPLoopDirective>;
+def OMPParallelMasterTaskLoopDirective : DStmt<OMPLoopDirective>;
def OMPDistributeDirective : DStmt<OMPLoopDirective>;
def OMPDistributeParallelForDirective : DStmt<OMPLoopDirective>;
def OMPDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>;
diff --git a/include/clang/Basic/SyncScope.h b/include/clang/Basic/SyncScope.h
index 15af02d83cde..ce8fb9cbed13 100644
--- a/include/clang/Basic/SyncScope.h
+++ b/include/clang/Basic/SyncScope.h
@@ -144,7 +144,7 @@ AtomicScopeModel::create(AtomicScopeModelKind K) {
case AtomicScopeModelKind::None:
return std::unique_ptr<AtomicScopeModel>{};
case AtomicScopeModelKind::OpenCL:
- return llvm::make_unique<AtomicScopeOpenCLModel>();
+ return std::make_unique<AtomicScopeOpenCLModel>();
}
llvm_unreachable("Invalid atomic scope model kind");
}
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index 50262fa310ce..0e2f0753b0c5 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -52,6 +52,16 @@ namespace clang {
};
}
+ /// BPF builtins
+ namespace BPF {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
+ #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+ #include "clang/Basic/BuiltinsBPF.def"
+ LastTSBuiltin
+ };
+ }
+
/// PPC builtins
namespace PPC {
enum {
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 7a8384f5fbc0..9a3bb986930e 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -19,14 +19,15 @@
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/IR/DataLayout.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/VersionTuple.h"
#include <cassert>
@@ -35,6 +36,7 @@
namespace llvm {
struct fltSemantics;
+class DataLayout;
}
namespace clang {
@@ -193,12 +195,12 @@ protected:
unsigned IsRenderScriptTarget : 1;
+ unsigned HasAArch64SVETypes : 1;
+
// TargetInfo Constructor. Default initializes all fields.
TargetInfo(const llvm::Triple &T);
- void resetDataLayout(StringRef DL) {
- DataLayout.reset(new llvm::DataLayout(DL));
- }
+ void resetDataLayout(StringRef DL);
public:
/// Construct a target for the given options.
@@ -789,6 +791,10 @@ public:
/// Returns true for RenderScript.
bool isRenderScriptTarget() const { return IsRenderScriptTarget; }
+ /// Returns whether or not the AArch64 SVE built-in types are
+ /// available on this target.
+ bool hasAArch64SVETypes() const { return HasAArch64SVETypes; }
+
/// Returns whether the passed in string is a valid clobber in an
/// inline asm statement.
///
@@ -1249,15 +1255,9 @@ public:
bool isBigEndian() const { return BigEndian; }
bool isLittleEndian() const { return !BigEndian; }
- enum CallingConvMethodType {
- CCMT_Unknown,
- CCMT_Member,
- CCMT_NonMember
- };
-
/// Gets the default calling convention for the given target and
/// declaration context.
- virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const {
+ virtual CallingConv getDefaultCallingConv() const {
// Not all targets will specify an explicit calling convention that we can
// express. This will always do the right thing, even though it's not
// an explicit calling convention.
@@ -1268,6 +1268,7 @@ public:
CCCR_OK,
CCCR_Warning,
CCCR_Ignore,
+ CCCR_Error,
};
/// Determines whether a given calling convention is valid for the
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 55e94d387c9d..94fe1ba63a9f 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -68,6 +68,9 @@
#ifndef ANNOTATION
#define ANNOTATION(X) TOK(annot_ ## X)
#endif
+#ifndef PRAGMA_ANNOTATION
+#define PRAGMA_ANNOTATION(X) ANNOTATION(X)
+#endif
//===----------------------------------------------------------------------===//
// Preprocessor keywords.
@@ -386,6 +389,7 @@ MODULES_KEYWORD(import)
// C++20 keywords.
CXX2A_KEYWORD(char8_t , CHAR8SUPPORT)
CXX2A_KEYWORD(consteval , 0)
+CXX2A_KEYWORD(constinit , 0)
// C11 Extension
KEYWORD(_Float16 , KEYALL)
@@ -446,16 +450,18 @@ TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX)
// MSVC14.0 / VS2015 Type Traits
TYPE_TRAIT_2(__is_assignable, IsAssignable, KEYCXX)
+// MSVC Type Traits of unknown vintage
+TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
+
// GNU and MS Type Traits
TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX)
-TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX)
TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYCXX)
TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYCXX)
-TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX)
TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX)
TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX)
@@ -472,17 +478,18 @@ TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX)
ALIAS("__is_literal_type", __is_literal, KEYCXX)
TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX)
TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX)
+TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX)
TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX)
+TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
+TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
+TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
TYPE_TRAIT_1(__has_unique_object_representations,
HasUniqueObjectRepresentations, KEYCXX)
+KEYWORD(__underlying_type , KEYCXX)
// Clang-only C++ Type Traits
-TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
-TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
-TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
-KEYWORD(__underlying_type , KEYCXX)
// Embarcadero Expression Traits
KEYWORD(__is_lvalue_expr , KEYCXX)
@@ -509,7 +516,6 @@ TYPE_TRAIT_1(__is_member_function_pointer, IsMemberFunctionPointer, KEYCXX)
TYPE_TRAIT_1(__is_member_pointer, IsMemberPointer, KEYCXX)
TYPE_TRAIT_1(__is_const, IsConst, KEYCXX)
TYPE_TRAIT_1(__is_volatile, IsVolatile, KEYCXX)
-TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX)
TYPE_TRAIT_1(__is_signed, IsSigned, KEYCXX)
TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
@@ -722,6 +728,11 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly
ANNOTATION(template_id) // annotation for a C++ template-id that names a
// function template specialization (not a type),
// e.g., "std::swap<int>"
+ANNOTATION(non_type) // annotation for a single non-type declaration
+ANNOTATION(non_type_undeclared) // annotation for an undeclared identifier that
+ // was assumed to be an ADL-only function name
+ANNOTATION(non_type_dependent) // annotation for an assumed non-type member of
+ // a dependent base class
ANNOTATION(primary_expr) // annotation for a primary expression
ANNOTATION(decltype) // annotation for a decltype expression,
// e.g., "decltype(foo.bar())"
@@ -729,103 +740,103 @@ ANNOTATION(decltype) // annotation for a decltype expression,
// Annotation for #pragma unused(...)
// For each argument inside the parentheses the pragma handler will produce
// one 'pragma_unused' annotation token followed by the argument token.
-ANNOTATION(pragma_unused)
+PRAGMA_ANNOTATION(pragma_unused)
// Annotation for #pragma GCC visibility...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_vis)
+PRAGMA_ANNOTATION(pragma_vis)
// Annotation for #pragma pack...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_pack)
+PRAGMA_ANNOTATION(pragma_pack)
// Annotation for #pragma clang __debug parser_crash...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_parser_crash)
+PRAGMA_ANNOTATION(pragma_parser_crash)
// Annotation for #pragma clang __debug captured...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_captured)
+PRAGMA_ANNOTATION(pragma_captured)
// Annotation for #pragma clang __debug dump...
// The lexer produces these so that the parser and semantic analysis can
// look up and dump the operand.
-ANNOTATION(pragma_dump)
+PRAGMA_ANNOTATION(pragma_dump)
// Annotation for #pragma ms_struct...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_msstruct)
+PRAGMA_ANNOTATION(pragma_msstruct)
// Annotation for #pragma align...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_align)
+PRAGMA_ANNOTATION(pragma_align)
// Annotation for #pragma weak id
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_weak)
+PRAGMA_ANNOTATION(pragma_weak)
// Annotation for #pragma weak id = id
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_weakalias)
+PRAGMA_ANNOTATION(pragma_weakalias)
// Annotation for #pragma redefine_extname...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_redefine_extname)
+PRAGMA_ANNOTATION(pragma_redefine_extname)
// Annotation for #pragma STDC FP_CONTRACT...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_fp_contract)
+PRAGMA_ANNOTATION(pragma_fp_contract)
// Annotation for #pragma STDC FENV_ACCESS
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_fenv_access)
+PRAGMA_ANNOTATION(pragma_fenv_access)
// Annotation for #pragma pointers_to_members...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_ms_pointers_to_members)
+PRAGMA_ANNOTATION(pragma_ms_pointers_to_members)
// Annotation for #pragma vtordisp...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_ms_vtordisp)
+PRAGMA_ANNOTATION(pragma_ms_vtordisp)
// Annotation for all microsoft #pragmas...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_ms_pragma)
+PRAGMA_ANNOTATION(pragma_ms_pragma)
// Annotation for #pragma OPENCL EXTENSION...
// The lexer produces these so that they only take effect when the parser
// handles them.
-ANNOTATION(pragma_opencl_extension)
+PRAGMA_ANNOTATION(pragma_opencl_extension)
// Annotations for OpenMP pragma directives - #pragma omp ...
// The lexer produces these so that they only take effect when the parser
// handles #pragma omp ... directives.
-ANNOTATION(pragma_openmp)
-ANNOTATION(pragma_openmp_end)
+PRAGMA_ANNOTATION(pragma_openmp)
+PRAGMA_ANNOTATION(pragma_openmp_end)
// Annotations for loop pragma directives #pragma clang loop ...
// The lexer produces these so that they only take effect when the parser
// handles #pragma loop ... directives.
-ANNOTATION(pragma_loop_hint)
+PRAGMA_ANNOTATION(pragma_loop_hint)
-ANNOTATION(pragma_fp)
+PRAGMA_ANNOTATION(pragma_fp)
// Annotation for the attribute pragma directives - #pragma clang attribute ...
-ANNOTATION(pragma_attribute)
+PRAGMA_ANNOTATION(pragma_attribute)
// Annotations for module import translated from #include etc.
ANNOTATION(module_include)
@@ -836,6 +847,7 @@ ANNOTATION(module_end)
// into the name of a header unit.
ANNOTATION(header_unit)
+#undef PRAGMA_ANNOTATION
#undef ANNOTATION
#undef TESTING_KEYWORD
#undef OBJC_AT_KEYWORD
diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
index 1d5be5f9152e..c25181e6827c 100644
--- a/include/clang/Basic/TokenKinds.h
+++ b/include/clang/Basic/TokenKinds.h
@@ -90,13 +90,10 @@ inline bool isLiteral(TokenKind K) {
}
/// Return true if this is any of tok::annot_* kinds.
-inline bool isAnnotation(TokenKind K) {
-#define ANNOTATION(NAME) \
- if (K == tok::annot_##NAME) \
- return true;
-#include "clang/Basic/TokenKinds.def"
- return false;
-}
+bool isAnnotation(TokenKind K);
+
+/// Return true if this is an annotation token representing a pragma.
+bool isPragmaAnnotation(TokenKind K);
} // end namespace tok
} // end namespace clang
diff --git a/include/clang/Basic/TypeNodes.td b/include/clang/Basic/TypeNodes.td
new file mode 100644
index 000000000000..b2554de24aaf
--- /dev/null
+++ b/include/clang/Basic/TypeNodes.td
@@ -0,0 +1,106 @@
+class Type<bit abstract = 0> {
+ bit Abstract = abstract;
+}
+
+class DerivedType<Type base, bit abstract = 0> : Type<abstract> {
+ Type Base = base;
+}
+
+/// A type node that is only used to represent dependent types in C++. For
+/// example, DependentTemplateSpecializationType is used to represent types
+/// where the base template-id is dependent (such as `T::foo<U>`). Code
+/// that only works with non-dependent types can ignore these type nodes.
+class AlwaysDependent {}
+
+/// A type node that is never used to represent a canonical type, which is to
+/// say that it always represents some sort of type "sugar" which can
+/// (supposedly) be erased without affecting the formal behavior of the
+/// language. For example, in standard C/C++, typedefs do not introduce new
+/// types and do not affect the semantics of the program. Code that only
+/// works with canonical types can ignore these type nodes.
+///
+/// Note that this simple story about non-canonical types is not the whole
+/// truth. Languages and extensions often have formation rules which differ
+/// based on how a type is spelled and which therefore are not consistent
+/// with immediately stipping away type sugar. More critically, attributes on
+/// typedefs can have semantic impacts in ways that are only reflected in our
+/// AST by preserving the typedef sugar; for example, we do not otherwise
+/// represent the alignment attribute on typedefs, and so it is necessary to
+/// preserve typedef structure into most parts of IR generation.
+class NeverCanonical {}
+
+/// A type node that only represents a canonical type in some dependent cases.
+/// For example, `std::vector<int>` (a TemplateSpecializationType) is
+/// considered to be a non-canonical representation for the RecordType
+/// referencing the concrete ClassTemplateSpecializationDecl; but
+/// `std::vector<T>` cannot be resolved to a concrete specialization
+/// and so remains canonical. Code which only works with non-dependent
+/// canonical types can ignore these nodes.
+class NeverCanonicalUnlessDependent {}
+
+/// A type node which never has component type structure. Some code may be
+/// able to operate on leaf types faster than they can on non-leaf types.
+///
+/// For example, the function type `void (int)` is not a leaf type because it
+/// is structurally composed of component types (`void` and `int`).
+///
+/// A struct type is a leaf type because its field types are not part of its
+/// type-expression.
+///
+/// Nodes like `TypedefType` which are syntactically leaves but can desugar
+/// to types that may not be leaves should not declare this.
+class LeafType {}
+
+def BuiltinType : Type, LeafType;
+def ComplexType : Type;
+def PointerType : Type;
+def BlockPointerType : Type;
+def ReferenceType : Type<1>;
+def LValueReferenceType : DerivedType<ReferenceType>;
+def RValueReferenceType : DerivedType<ReferenceType>;
+def MemberPointerType : Type;
+def ArrayType : Type<1>;
+def ConstantArrayType : DerivedType<ArrayType>;
+def IncompleteArrayType : DerivedType<ArrayType>;
+def VariableArrayType : DerivedType<ArrayType>;
+def DependentSizedArrayType : DerivedType<ArrayType>, AlwaysDependent;
+def DependentSizedExtVectorType : Type, AlwaysDependent;
+def DependentAddressSpaceType : Type, AlwaysDependent;
+def VectorType : Type;
+def DependentVectorType : Type, AlwaysDependent;
+def ExtVectorType : DerivedType<VectorType>;
+def FunctionType : Type<1>;
+def FunctionProtoType : DerivedType<FunctionType>;
+def FunctionNoProtoType : DerivedType<FunctionType>;
+def UnresolvedUsingType : Type, AlwaysDependent;
+def ParenType : Type, NeverCanonical;
+def TypedefType : Type, NeverCanonical;
+def MacroQualifiedType : Type, NeverCanonical;
+def AdjustedType : Type, NeverCanonical;
+def DecayedType : DerivedType<AdjustedType>, NeverCanonical;
+def TypeOfExprType : Type, NeverCanonicalUnlessDependent;
+def TypeOfType : Type, NeverCanonicalUnlessDependent;
+def DecltypeType : Type, NeverCanonicalUnlessDependent;
+def UnaryTransformType : Type, NeverCanonicalUnlessDependent;
+def TagType : Type<1>;
+def RecordType : DerivedType<TagType>, LeafType;
+def EnumType : DerivedType<TagType>, LeafType;
+def ElaboratedType : Type, NeverCanonical;
+def AttributedType : Type, NeverCanonical;
+def TemplateTypeParmType : Type, AlwaysDependent, LeafType;
+def SubstTemplateTypeParmType : Type, NeverCanonical;
+def SubstTemplateTypeParmPackType : Type, AlwaysDependent;
+def TemplateSpecializationType : Type, NeverCanonicalUnlessDependent;
+def DeducedType : Type<1>;
+def AutoType : DerivedType<DeducedType>;
+def DeducedTemplateSpecializationType : DerivedType<DeducedType>;
+def InjectedClassNameType : Type, AlwaysDependent, LeafType;
+def DependentNameType : Type, AlwaysDependent;
+def DependentTemplateSpecializationType : Type, AlwaysDependent;
+def PackExpansionType : Type, NeverCanonicalUnlessDependent;
+def ObjCTypeParamType : Type, NeverCanonical;
+def ObjCObjectType : Type;
+def ObjCInterfaceType : DerivedType<ObjCObjectType>, LeafType;
+def ObjCObjectPointerType : Type;
+def PipeType : Type;
+def AtomicType : Type;
diff --git a/include/clang/Basic/X86Target.def b/include/clang/Basic/X86Target.def
index 94ccb9fd8b2f..ba4e5981e7dc 100644
--- a/include/clang/Basic/X86Target.def
+++ b/include/clang/Basic/X86Target.def
@@ -173,6 +173,10 @@ PROC(IcelakeClient, "icelake-client", PROC_64_BIT)
/// Icelake server microarchitecture based processors.
PROC(IcelakeServer, "icelake-server", PROC_64_BIT)
+/// \name Tigerlake
+/// Tigerlake microarchitecture based processors.
+PROC(Tigerlake, "tigerlake", PROC_64_BIT)
+
/// \name Knights Landing
/// Knights Landing processor.
PROC_WITH_FEAT(KNL, "knl", PROC_64_BIT, FEATURE_AVX512F)
@@ -297,6 +301,7 @@ FEATURE(FEATURE_VPCLMULQDQ)
FEATURE(FEATURE_AVX512VNNI)
FEATURE(FEATURE_AVX512BITALG)
FEATURE(FEATURE_AVX512BF16)
+FEATURE(FEATURE_AVX512VP2INTERSECT)
// FIXME: When commented out features are supported in LLVM, enable them here.
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index 428c22d1a011..a52ed496580d 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -1651,10 +1651,10 @@ let ArchGuard = "defined(__ARM_FEATURE_DOTPROD) && defined(__aarch64__)" in {
// v8.2-A FP16 fused multiply-add long instructions.
let ArchGuard = "defined(__ARM_FEATURE_FP16FML) && defined(__aarch64__)" in {
- def VFMLAL_LOW : SInst<"vfmlal_low", "ffHH", "hQh">;
- def VFMLSL_LOW : SInst<"vfmlsl_low", "ffHH", "hQh">;
- def VFMLAL_HIGH : SInst<"vfmlal_high", "ffHH", "hQh">;
- def VFMLSL_HIGH : SInst<"vfmlsl_high", "ffHH", "hQh">;
+ def VFMLAL_LOW : SInst<"vfmlal_low", "nndd", "hQh">;
+ def VFMLSL_LOW : SInst<"vfmlsl_low", "nndd", "hQh">;
+ def VFMLAL_HIGH : SInst<"vfmlal_high", "nndd", "hQh">;
+ def VFMLSL_HIGH : SInst<"vfmlsl_high", "nndd", "hQh">;
def VFMLAL_LANE_LOW : SOpInst<"vfmlal_lane_low", "ffH0i", "hQh", OP_FMLAL_LN>;
def VFMLSL_LANE_LOW : SOpInst<"vfmlsl_lane_low", "ffH0i", "hQh", OP_FMLSL_LN>;
diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
index 1f81072e23d0..5069d9af42a3 100644
--- a/include/clang/CodeGen/CGFunctionInfo.h
+++ b/include/clang/CodeGen/CGFunctionInfo.h
@@ -109,14 +109,12 @@ private:
UnpaddedCoerceAndExpandType = T;
}
- ABIArgInfo(Kind K)
- : TheKind(K), PaddingInReg(false), InReg(false) {
- }
-
public:
- ABIArgInfo()
+ ABIArgInfo(Kind K = Direct)
: TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
- TheKind(Direct), PaddingInReg(false), InReg(false) {}
+ TheKind(K), PaddingInReg(false), InAllocaSRet(false),
+ IndirectByVal(false), IndirectRealign(false), SRetAfterThis(false),
+ InReg(false), CanBeFlattened(false), SignExt(false) {}
static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
llvm::Type *Padding = nullptr,
diff --git a/include/clang/CrossTU/CrossTranslationUnit.h b/include/clang/CrossTU/CrossTranslationUnit.h
index d64329cdff3e..4d2b7109c62a 100644
--- a/include/clang/CrossTU/CrossTranslationUnit.h
+++ b/include/clang/CrossTU/CrossTranslationUnit.h
@@ -17,6 +17,7 @@
#include "clang/AST/ASTImporterSharedState.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Error.h"
@@ -153,18 +154,34 @@ public:
/// was passed to the constructor.
///
/// \return Returns the resulting definition or an error.
- llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD);
- llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD);
+ llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD,
+ ASTUnit *Unit);
+ llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD,
+ ASTUnit *Unit);
/// Get a name to identify a named decl.
- static std::string getLookupName(const NamedDecl *ND);
+ static llvm::Optional<std::string> getLookupName(const NamedDecl *ND);
/// Emit diagnostics for the user for potential configuration errors.
void emitCrossTUDiagnostics(const IndexError &IE);
+ /// Determine the original source location in the original TU for an
+ /// imported source location.
+ /// \p ToLoc Source location in the imported-to AST.
+ /// \return Source location in the imported-from AST and the corresponding
+ /// ASTUnit object (the AST was loaded from a file using an internal ASTUnit
+ /// object that is returned here).
+ /// If any error happens (ToLoc is a non-imported source location) empty is
+ /// returned.
+ llvm::Optional<std::pair<SourceLocation /*FromLoc*/, ASTUnit *>>
+ getImportedFromSourceLocation(const clang::SourceLocation &ToLoc) const;
+
private:
+ using ImportedFileIDMap =
+ llvm::DenseMap<FileID, std::pair<FileID, ASTUnit *>>;
+
void lazyInitImporterSharedSt(TranslationUnitDecl *ToTU);
- ASTImporter &getOrCreateASTImporter(ASTContext &From);
+ ASTImporter &getOrCreateASTImporter(ASTUnit *Unit);
template <typename T>
llvm::Expected<const T *> getCrossTUDefinitionImpl(const T *D,
StringRef CrossTUDir,
@@ -174,20 +191,114 @@ private:
const T *findDefInDeclContext(const DeclContext *DC,
StringRef LookupName);
template <typename T>
- llvm::Expected<const T *> importDefinitionImpl(const T *D);
-
- llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap;
- llvm::StringMap<clang::ASTUnit *> NameASTUnitMap;
- llvm::StringMap<std::string> NameFileMap;
- llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>>
- ASTUnitImporterMap;
- CompilerInstance &CI;
+ llvm::Expected<const T *> importDefinitionImpl(const T *D, ASTUnit *Unit);
+
+ using ImporterMapTy =
+ llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>>;
+
+ ImporterMapTy ASTUnitImporterMap;
+
ASTContext &Context;
std::shared_ptr<ASTImporterSharedState> ImporterSharedSt;
- /// \p CTULoadTreshold should serve as an upper limit to the number of TUs
- /// imported in order to reduce the memory footprint of CTU analysis.
- const unsigned CTULoadThreshold;
- unsigned NumASTLoaded{0u};
+ /// Map of imported FileID's (in "To" context) to FileID in "From" context
+ /// and the ASTUnit for the From context.
+ /// This map is used by getImportedFromSourceLocation to lookup a FileID and
+ /// its Preprocessor when knowing only the FileID in the 'To' context. The
+ /// FileID could be imported by any of multiple 'From' ASTImporter objects.
+ /// we do not want to loop over all ASTImporter's to find the one that
+ /// imported the FileID.
+ ImportedFileIDMap ImportedFileIDs;
+
+ /// Functor for loading ASTUnits from AST-dump files.
+ class ASTFileLoader {
+ public:
+ ASTFileLoader(const CompilerInstance &CI);
+ std::unique_ptr<ASTUnit> operator()(StringRef ASTFilePath);
+
+ private:
+ const CompilerInstance &CI;
+ };
+
+ /// Maintain number of AST loads and check for reaching the load limit.
+ class ASTLoadGuard {
+ public:
+ ASTLoadGuard(unsigned Limit) : Limit(Limit) {}
+
+ /// Indicates, whether a new load operation is permitted, it is within the
+ /// threshold.
+ operator bool() const { return Count < Limit; }
+
+ /// Tell that a new AST was loaded successfully.
+ void indicateLoadSuccess() { ++Count; }
+
+ private:
+ /// The number of ASTs actually imported.
+ unsigned Count{0u};
+ /// The limit (threshold) value for number of loaded ASTs.
+ const unsigned Limit;
+ };
+
+ /// Storage and load of ASTUnits, cached access, and providing searchability
+ /// are the concerns of ASTUnitStorage class.
+ class ASTUnitStorage {
+ public:
+ ASTUnitStorage(const CompilerInstance &CI);
+ /// Loads an ASTUnit for a function.
+ ///
+ /// \param FunctionName USR name of the function.
+ /// \param CrossTUDir Path to the directory used to store CTU related files.
+ /// \param IndexName Name of the file inside \p CrossTUDir which maps
+ /// function USR names to file paths. These files contain the corresponding
+ /// AST-dumps.
+ /// \param DisplayCTUProgress Display a message about loading new ASTs.
+ ///
+ /// \return An Expected instance which contains the ASTUnit pointer or the
+ /// error occured during the load.
+ llvm::Expected<ASTUnit *> getASTUnitForFunction(StringRef FunctionName,
+ StringRef CrossTUDir,
+ StringRef IndexName,
+ bool DisplayCTUProgress);
+ /// Identifies the path of the file which can be used to load the ASTUnit
+ /// for a given function.
+ ///
+ /// \param FunctionName USR name of the function.
+ /// \param CrossTUDir Path to the directory used to store CTU related files.
+ /// \param IndexName Name of the file inside \p CrossTUDir which maps
+ /// function USR names to file paths. These files contain the corresponding
+ /// AST-dumps.
+ ///
+ /// \return An Expected instance containing the filepath.
+ llvm::Expected<std::string> getFileForFunction(StringRef FunctionName,
+ StringRef CrossTUDir,
+ StringRef IndexName);
+
+ private:
+ llvm::Error ensureCTUIndexLoaded(StringRef CrossTUDir, StringRef IndexName);
+ llvm::Expected<ASTUnit *> getASTUnitForFile(StringRef FileName,
+ bool DisplayCTUProgress);
+
+ template <typename... T> using BaseMapTy = llvm::StringMap<T...>;
+ using OwningMapTy = BaseMapTy<std::unique_ptr<clang::ASTUnit>>;
+ using NonOwningMapTy = BaseMapTy<clang::ASTUnit *>;
+
+ OwningMapTy FileASTUnitMap;
+ NonOwningMapTy NameASTUnitMap;
+
+ using IndexMapTy = BaseMapTy<std::string>;
+ IndexMapTy NameFileMap;
+
+ ASTFileLoader FileAccessor;
+
+ /// Limit the number of loaded ASTs. Used to limit the memory usage of the
+ /// CrossTranslationUnitContext.
+ /// The ASTUnitStorage has the knowledge about if the AST to load is
+ /// actually loaded or returned from cache. This information is needed to
+ /// maintain the counter.
+ ASTLoadGuard LoadGuard;
+ };
+
+ ASTUnitStorage ASTStorage;
+
};
} // namespace cross_tu
diff --git a/include/clang/DirectoryWatcher/DirectoryWatcher.h b/include/clang/DirectoryWatcher/DirectoryWatcher.h
index e74443e0bc81..4475807dfce9 100644
--- a/include/clang/DirectoryWatcher/DirectoryWatcher.h
+++ b/include/clang/DirectoryWatcher/DirectoryWatcher.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include <functional>
#include <memory>
#include <string>
@@ -98,10 +99,11 @@ public:
: Kind(Kind), Filename(Filename) {}
};
- /// Returns nullptr if \param Path doesn't exist or isn't a directory.
- /// Returns nullptr if OS kernel API told us we can't start watching. In such
- /// case it's unclear whether just retrying has any chance to succeeed.
- static std::unique_ptr<DirectoryWatcher>
+ /// llvm fatal_error if \param Path doesn't exist or isn't a directory.
+ /// Returns llvm::Expected Error if OS kernel API told us we can't start
+ /// watching. In such case it's unclear whether just retrying has any chance
+ /// to succeed.
+ static llvm::Expected<std::unique_ptr<DirectoryWatcher>>
create(llvm::StringRef Path,
std::function<void(llvm::ArrayRef<DirectoryWatcher::Event> Events,
bool IsInitial)>
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index c1ff0b1a6023..8ccbb6c2bbfa 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -65,15 +65,17 @@ public:
BackendJobClass,
AssembleJobClass,
LinkJobClass,
+ IfsMergeJobClass,
LipoJobClass,
DsymutilJobClass,
VerifyDebugInfoJobClass,
VerifyPCHJobClass,
OffloadBundlingJobClass,
OffloadUnbundlingJobClass,
+ OffloadWrapperJobClass,
JobClassFirst = PreprocessJobClass,
- JobClassLast = OffloadUnbundlingJobClass
+ JobClassLast = OffloadWrapperJobClass
};
// The offloading kind determines if this action is binded to a particular
@@ -485,6 +487,17 @@ public:
}
};
+class IfsMergeJobAction : public JobAction {
+ void anchor() override;
+
+public:
+ IfsMergeJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == IfsMergeJobClass;
+ }
+};
+
class LinkJobAction : public JobAction {
void anchor() override;
@@ -613,6 +626,17 @@ public:
}
};
+class OffloadWrapperJobAction : public JobAction {
+ void anchor() override;
+
+public:
+ OffloadWrapperJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == OffloadWrapperJobClass;
+ }
+};
+
} // namespace driver
} // namespace clang
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 1f6c000ecf6a..4518aca82ef6 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -140,7 +140,8 @@ def analyzer_checker_help_developer : Flag<["-"], "analyzer-checker-help-develop
"and debug checkers">;
def analyzer_config_help : Flag<["-"], "analyzer-config-help">,
- HelpText<"Display the list of -analyzer-config options">;
+ HelpText<"Display the list of -analyzer-config options. These are meant for "
+ "development purposes only!">;
def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">,
HelpText<"Display the list of enabled analyzer checkers">;
@@ -200,6 +201,8 @@ def compress_debug_sections_EQ : Joined<["-", "--"], "compress-debug-sections=">
HelpText<"DWARF debug sections compression type">;
def mno_exec_stack : Flag<["-"], "mnoexecstack">,
HelpText<"Mark the file as not needing an executable stack">;
+def massembler_no_warn : Flag<["-"], "massembler-no-warn">,
+ HelpText<"Make assembler not emit warnings">;
def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">,
HelpText<"Make assembler warnings fatal">;
def mrelax_relocations : Flag<["--"], "mrelax-relocations">,
@@ -285,8 +288,8 @@ def mcode_model : Separate<["-"], "mcode-model">,
HelpText<"The code model to use">, Values<"tiny,small,kernel,medium,large">;
def mdebug_pass : Separate<["-"], "mdebug-pass">,
HelpText<"Enable additional debug output">;
-def mdisable_fp_elim : Flag<["-"], "mdisable-fp-elim">,
- HelpText<"Disable frame pointer elimination optimization">;
+def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">,
+ HelpText<"Specify which frame pointers to retain (all, non-leaf, none).">, Values<"all,non-leaf,none">;
def mdisable_tail_calls : Flag<["-"], "mdisable-tail-calls">,
HelpText<"Disable tail call optimization, keeping the call stack accurate">;
def menable_no_infinities : Flag<["-"], "menable-no-infs">,
@@ -684,7 +687,7 @@ let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
def version : Flag<["-"], "version">,
HelpText<"Print the compiler version">;
def main_file_name : Separate<["-"], "main-file-name">,
- HelpText<"Main file name to use for debug info">;
+ HelpText<"Main file name to use for debug info and source if missing">;
def split_dwarf_output : Separate<["-"], "split-dwarf-output">,
HelpText<"File name to use for split dwarf debug info output">;
@@ -812,6 +815,9 @@ def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">,
HelpText<"Disable the module hash">;
def fmodules_hash_content : Flag<["-"], "fmodules-hash-content">,
HelpText<"Enable hashing the content of a module file">;
+def fmodules_strict_context_hash : Flag<["-"], "fmodules-strict-context-hash">,
+ HelpText<"Enable hashing of all compiler options that could impact the "
+ "semantics of a module in an implicit build">;
def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to the C SYSTEM include search path">;
def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,
@@ -843,6 +849,8 @@ def preamble_bytes_EQ : Joined<["-"], "preamble-bytes=">,
"covering the first N bytes of the main file">;
def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">,
HelpText<"include a detailed record of preprocessing actions">;
+def setup_static_analyzer : Flag<["-"], "setup-static-analyzer">,
+ HelpText<"Set up preprocessor for static analyzer (done automatically when static analyzer is run).">;
//===----------------------------------------------------------------------===//
// OpenCL Options
diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
index a0af3035ea46..50d4622009c9 100644
--- a/include/clang/Driver/CLCompatOptions.td
+++ b/include/clang/Driver/CLCompatOptions.td
@@ -254,7 +254,13 @@ def _SLASH_Zp_flag : CLFlag<"Zp">,
Alias<fpack_struct_EQ>, AliasArgs<["1"]>;
def _SLASH_Zs : CLFlag<"Zs">, HelpText<"Syntax-check only">,
Alias<fsyntax_only>;
-
+def _SLASH_openmp_ : CLFlag<"openmp-">,
+ HelpText<"Disable OpenMP support">, Alias<fno_openmp>;
+def _SLASH_openmp : CLFlag<"openmp">, HelpText<"Enable OpenMP support">,
+ Alias<fopenmp>;
+def _SLASH_openmp_experimental : CLFlag<"openmp:experimental">,
+ HelpText<"Enable OpenMP support with experimental SIMD support">,
+ Alias<fopenmp>;
// Non-aliases:
@@ -381,7 +387,6 @@ def _SLASH_FS : CLIgnoredFlag<"FS">;
def _SLASH_JMC : CLIgnoredFlag<"JMC">;
def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
def _SLASH_nologo : CLIgnoredFlag<"nologo">;
-def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
def _SLASH_permissive_ : CLIgnoredFlag<"permissive-">;
def _SLASH_RTC : CLIgnoredJoined<"RTC">;
def _SLASH_sdl : CLIgnoredFlag<"sdl">;
@@ -396,6 +401,9 @@ def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">;
def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">;
def _SLASH_Zc_ternary : CLIgnoredFlag<"Zc:ternary">;
def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">;
+def _SLASH_ZH_MD5 : CLIgnoredFlag<"ZH:MD5">;
+def _SLASH_ZH_SHA1 : CLIgnoredFlag<"ZH:SHA1">;
+def _SLASH_ZH_SHA_256 : CLIgnoredFlag<"ZH:SHA_256">;
def _SLASH_Zm : CLIgnoredJoined<"Zm">;
def _SLASH_Zo : CLIgnoredFlag<"Zo">;
def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">;
@@ -436,8 +444,6 @@ def _SLASH_hotpatch : CLFlag<"hotpatch">;
def _SLASH_kernel : CLFlag<"kernel">;
def _SLASH_LN : CLFlag<"LN">;
def _SLASH_MP : CLJoined<"MP">;
-def _SLASH_openmp : CLFlag<"openmp">;
-def _SLASH_openmp_experimental : CLFlag<"openmp:experimental">;
def _SLASH_Qfast_transcendentals : CLFlag<"Qfast_transcendentals">;
def _SLASH_QIfist : CLFlag<"QIfist">;
def _SLASH_Qimprecise_fwaits : CLFlag<"Qimprecise_fwaits">;
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index f9528641073a..5e7283e31ee0 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -12,12 +12,14 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
+#include "clang/Driver/Options.h"
#include "clang/Driver/Phases.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/StringSaver.h"
@@ -55,8 +57,6 @@ enum LTOKind {
/// Driver - Encapsulate logic for constructing compilation processes
/// from a set of gcc-driver-like command line arguments.
class Driver {
- std::unique_ptr<llvm::opt::OptTable> Opts;
-
DiagnosticsEngine &Diags;
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
@@ -250,9 +250,17 @@ private:
// getFinalPhase - Determine which compilation mode we are in and record
// which option we used to determine the final phase.
+ // TODO: Much of what getFinalPhase returns are not actually true compiler
+ // modes. Fold this functionality into Types::getCompilationPhases and
+ // handleArguments.
phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
llvm::opt::Arg **FinalPhaseArg = nullptr) const;
+ // handleArguments - All code related to claiming and printing diagnostics
+ // related to arguments to the driver are done here.
+ void handleArguments(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
// Before executing jobs, sets up response files for commands that need them.
void setUpResponseFiles(Compilation &C, Command &Cmd);
@@ -292,7 +300,7 @@ public:
const std::string &getConfigFile() const { return ConfigFile; }
- const llvm::opt::OptTable &getOpts() const { return *Opts; }
+ const llvm::opt::OptTable &getOpts() const { return getDriverOptTable(); }
const DiagnosticsEngine &getDiags() const { return Diags; }
diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h
index f8963d48112a..7c5cddd9e896 100644
--- a/include/clang/Driver/Options.h
+++ b/include/clang/Driver/Options.h
@@ -47,7 +47,7 @@ enum ID {
};
}
-std::unique_ptr<llvm::opt::OptTable> createDriverOptTable();
+const llvm::opt::OptTable &getDriverOptTable();
}
}
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index dfd27fab796e..3ce6fcf29f94 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -211,6 +211,10 @@ def clang_ignored_legacy_options_Group : OptionGroup<"<clang legacy flags>">,
def : Flag<["-"], "fslp-vectorize-aggressive">, Group<clang_ignored_legacy_options_Group>;
def : Flag<["-"], "fno-slp-vectorize-aggressive">, Group<clang_ignored_legacy_options_Group>;
+// Retired with clang-10.0. Previously controlled X86 MPX ISA.
+def mmpx : Flag<["-"], "mmpx">, Group<clang_ignored_legacy_options_Group>;
+def mno_mpx : Flag<["-"], "mno-mpx">, Group<clang_ignored_legacy_options_Group>;
+
// Group that ignores all gcc optimizations that won't be implemented
def clang_ignored_gcc_optimization_f_Group : OptionGroup<
"<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>, Flags<[Ignored]>;
@@ -280,6 +284,8 @@ def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">,
Flags<[CC1Option]>;
def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt,
HelpText<"Auto-generates preprocessed source files and a reproduction script">;
+def gen_cdb_fragment_path: Separate<["-"], "gen-cdb-fragment-path">, InternalDebugOpt,
+ HelpText<"Emit a compilation database fragment to the specified directory">;
def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>,
HelpText<"Run the migrator">;
@@ -518,7 +524,7 @@ def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group<opencl_Group>, Flags<[CC
def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow use of less precise no signed zeros computations in the generated binary.">;
def cl_std_EQ : Joined<["-"], "cl-std=">, Group<opencl_Group>, Flags<[CC1Option]>,
- HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,c++">;
+ HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,clc++,CLC++">;
def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow denormals to be flushed to zero.">;
def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group<opencl_Group>, Flags<[CC1Option]>,
@@ -593,9 +599,11 @@ def hip_device_lib_EQ : Joined<["--"], "hip-device-lib=">, Group<Link_Group>,
HelpText<"HIP device library">;
def fhip_dump_offload_linker_script : Flag<["-"], "fhip-dump-offload-linker-script">,
Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
+def fhip_new_launch_api : Flag<["-"], "fhip-new-launch-api">,
+ Flags<[CC1Option]>, HelpText<"Use new kernel launching API for HIP.">;
+def fno_hip_new_launch_api : Flag<["-"], "fno-hip-new-launch-api">;
def libomptarget_nvptx_path_EQ : Joined<["--"], "libomptarget-nvptx-path=">, Group<i_Group>,
HelpText<"Path to libomptarget-nvptx libraries">;
-def dA : Flag<["-"], "dA">, Group<d_Group>;
def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
def dI : Flag<["-"], "dI">, Group<d_Group>, Flags<[CC1Option]>,
@@ -623,9 +631,12 @@ def emit_ast : Flag<["-"], "emit-ast">,
HelpText<"Emit Clang AST files for source inputs">;
def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group<Action_Group>,
HelpText<"Use the LLVM representation for assembler and object files">;
-def emit_iterface_stubs : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group<Action_Group>,
+def emit_interface_stubs : Flag<["-"], "emit-interface-stubs">, Flags<[CC1Option]>, Group<Action_Group>,
HelpText<"Generate Inteface Stub Files.">;
-def iterface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">, Flags<[CC1Option]>;
+def emit_merged_ifs : Flag<["-"], "emit-merged-ifs">,
+ Flags<[CC1Option]>, Group<Action_Group>,
+ HelpText<"Generate Interface Stub Files, emit merged text not binary.">;
+def interface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">, Flags<[CC1Option]>;
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
def e : JoinedOrSeparate<["-"], "e">, Group<Link_Group>;
def fPIC : Flag<["-"], "fPIC">, Group<f_Group>;
@@ -833,6 +844,10 @@ 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 fexperimental_new_constant_interpreter : Flag<["-"], "fexperimental-new-constant-interpreter">, Group<f_Group>,
+ HelpText<"Enable the experimental new constant interpreter">, Flags<[CC1Option]>;
+def fforce_experimental_new_constant_interpreter : Flag<["-"], "fforce-experimental-new-constant-interpreter">, Group<f_Group>,
+ HelpText<"Force the use of the experimental new constant interpreter, failing on missing features">, Flags<[CC1Option]>;
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, CoreOption]>,
@@ -899,6 +914,8 @@ def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">;
def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">;
+def fwasm_exceptions : Flag<["-"], "fwasm-exceptions">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Use WebAssembly style exceptions">;
def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">,
Group<clang_ignored_gcc_optimization_f_Group>;
def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
@@ -1043,8 +1060,14 @@ def fsanitize_minimal_runtime : Flag<["-"], "fsanitize-minimal-runtime">,
Group<f_clang_Group>;
def fno_sanitize_minimal_runtime : Flag<["-"], "fno-sanitize-minimal-runtime">,
Group<f_clang_Group>;
+def fsanitize_link_runtime : Flag<["-"], "fsanitize-link-runtime">,
+ Group<f_clang_Group>;
+def fno_sanitize_link_runtime : Flag<["-"], "fno-sanitize-link-runtime">,
+ Group<f_clang_Group>;
def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">,
Group<f_clang_Group>;
+def fno_sanitize_link_cxx_runtime : Flag<["-"], "fno-sanitize-link-c++-runtime">,
+ Group<f_clang_Group>;
def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">,
Group<f_clang_Group>,
HelpText<"Enable control flow integrity (CFI) checks for cross-DSO calls.">;
@@ -1055,6 +1078,13 @@ def fno_sanitize_cfi_cross_dso : Flag<["-"], "fno-sanitize-cfi-cross-dso">,
def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-generalize-pointers">,
Group<f_clang_Group>,
HelpText<"Generalize pointers in CFI indirect call type signature checks">;
+def fsanitize_cfi_canonical_jump_tables : Flag<["-"], "fsanitize-cfi-canonical-jump-tables">,
+ Group<f_clang_Group>,
+ HelpText<"Make the jump table addresses canonical in the symbol table">;
+def fno_sanitize_cfi_canonical_jump_tables : Flag<["-"], "fno-sanitize-cfi-canonical-jump-tables">,
+ Group<f_clang_Group>,
+ Flags<[CoreOption, DriverOption]>,
+ HelpText<"Do not make the jump table addresses canonical in the symbol table">;
def fsanitize_stats : Flag<["-"], "fsanitize-stats">,
Group<f_clang_Group>,
HelpText<"Enable sanitizer statistics gathering.">;
@@ -1117,7 +1147,8 @@ def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Op
def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>, Flags<[CC1Option]>;
def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
- " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">;
+ " | on (according to FP_CONTRACT pragma) | off (never fuse). Default"
+ " is 'fast' for CUDA/HIP and 'on' otherwise.">, Values<"fast,on,off">;
def fstrict_float_cast_overflow : Flag<["-"],
"fstrict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>,
@@ -1157,6 +1188,9 @@ def fno_use_line_directives : Flag<["-"], "fno-use-line-directives">, Group<f_Gr
def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
+def fgnuc_version_EQ : Joined<["-"], "fgnuc-version=">, Group<f_Group>,
+ HelpText<"Sets various macros to claim compatibility with the given GCC version (default is 4.2.1)">,
+ Flags<[CC1Option, CoreOption]>;
def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allow GNU-extension keywords regardless of language standard">;
def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,
@@ -1254,7 +1288,10 @@ def fno_fine_grained_bitfield_accesses : Flag<["-"],
HelpText<"Use large-integer access for consecutive bitfield runs.">;
def flat__namespace : Flag<["-"], "flat_namespace">;
-def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
+def flax_vector_conversions_EQ : Joined<["-"], "flax-vector-conversions=">, Group<f_Group>,
+ HelpText<"Enable implicit vector bit-casts">, Values<"none,integer,all">, Flags<[CC1Option]>;
+def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>,
+ Alias<flax_vector_conversions_EQ>, AliasArgs<["integer"]>;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def fapple_link_rtlib : Flag<["-"], "fapple-link-rtlib">, Group<f_Group>,
HelpText<"Force linking the clang builtins runtime library">;
@@ -1331,6 +1368,28 @@ def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-hea
HelpText<"Validate the system headers that a module depends on when loading the module">;
def fno_modules_validate_system_headers : Flag<["-"], "fno-modules-validate-system-headers">,
Group<i_Group>, Flags<[DriverOption]>;
+
+def fvalidate_ast_input_files_content:
+ Flag <["-"], "fvalidate-ast-input-files-content">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Compute and store the hash of input files used to build an AST."
+ " Files with mismatching mtime's are considered valid"
+ " if both contents is identical">;
+def fmodules_validate_input_files_content:
+ Flag <["-"], "fmodules-validate-input-files-content">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Validate PCM input files based on content if mtime differs">;
+def fno_modules_validate_input_files_content:
+ Flag <["-"], "fno_modules-validate-input-files-content">,
+ Group<f_Group>, Flags<[DriverOption]>;
+def fpch_validate_input_files_content:
+ Flag <["-"], "fpch-validate-input-files-content">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Validate PCH input files based on content if mtime differs">;
+def fno_pch_validate_input_files_content:
+ Flag <["-"], "fno_pch-validate-input-files-content">,
+ Group<f_Group>, Flags<[DriverOption]>;
+
def fmodules : Flag <["-"], "fmodules">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Enable the 'modules' language feature">;
@@ -1428,7 +1487,7 @@ def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-m
def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use the given vector functions library">, Values<"Accelerate,MASSV,SVML,none">;
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
- HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
+ Alias<flax_vector_conversions_EQ>, AliasArgs<["none"]>;
def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
HelpText<"Disallow merging of constants">;
def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
@@ -1571,8 +1630,6 @@ def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fopenmp_targets_EQ : CommaJoined<["-"], "fopenmp-targets=">, Flags<[DriverOption, CC1Option]>,
HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">;
-def fopenmp_dump_offload_linker_script : Flag<["-"], "fopenmp-dump-offload-linker-script">,
- Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">,
Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">,
@@ -1598,6 +1655,8 @@ def fopenmp_optimistic_collapse : Flag<["-"], "fopenmp-optimistic-collapse">, Gr
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fno_openmp_optimistic_collapse : Flag<["-"], "fno-openmp-optimistic-collapse">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>;
+def static_openmp: Flag<["-"], "static-openmp">,
+ HelpText<"Use the static host OpenMP runtime while linking.">;
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
def fno_escaping_block_tail_calls : Flag<["-"], "fno-escaping-block-tail-calls">, Group<f_Group>, Flags<[CC1Option]>;
@@ -1683,10 +1742,10 @@ def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>,
"alloca, which are of greater size than ssp-buffer-size (default: 8 bytes). "
"All variable sized calls to alloca are considered vulnerable">;
def ftrivial_auto_var_init : Joined<["-"], "ftrivial-auto-var-init=">, Group<f_Group>,
- Flags<[CC1Option]>, HelpText<"Initialize trivial automatic stack variables: uninitialized (default)"
+ Flags<[CC1Option, CoreOption]>, HelpText<"Initialize trivial automatic stack variables: uninitialized (default)"
" | pattern">, Values<"uninitialized,pattern">;
-def enable_trivial_var_init_zero : Joined<["-"], "enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">,
- Flags<[CC1Option]>,
+def enable_trivial_var_init_zero : Flag<["-"], "enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">,
+ Flags<[CC1Option, CoreOption]>,
HelpText<"Trivial automatic variable initialization to zero is only here for benchmarks, it'll eventually be removed, and I'm OK with that because I'm only using it to benchmark">;
def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Emit full debug info for all types used by the program">;
@@ -1757,7 +1816,16 @@ def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Group<f_Group>
def : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>;
def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group<f_Group>;
def ftime_report : Flag<["-"], "ftime-report">, Group<f_Group>, Flags<[CC1Option]>;
-def ftime_trace : Flag<["-"], "ftime-trace">, Group<f_Group>, Flags<[CC1Option, CoreOption]>;
+def ftime_trace : Flag<["-"], "ftime-trace">, Group<f_Group>,
+ HelpText<"Turn on time profiler. Generates JSON file based on output filename.">,
+ DocBrief<[{
+Turn on time profiler. Generates JSON file based on output filename. Results
+can be analyzed with chrome://tracing or `Speedscope App
+<https://www.speedscope.app>`_ for flamegraph visualization.}]>,
+ Flags<[CC1Option, CoreOption]>;
+def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Group<f_Group>,
+ HelpText<"Minimum time granularity (in microseconds) traced by time profiler">,
+ Flags<[CC1Option, CoreOption]>;
def ftlsmodel_EQ : Joined<["-"], "ftls-model=">, Group<f_Group>, Flags<[CC1Option]>;
def ftrapv : Flag<["-"], "ftrapv">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Trap on integer overflow">;
@@ -1791,6 +1859,7 @@ def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1
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 dA : Flag<["-"], "dA">, Alias<fverbose_asm>;
def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">;
def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>,
@@ -1816,6 +1885,13 @@ def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>,
HelpText<"Emits more virtual tables to improve devirtualization">;
def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-vtables">, Group<f_Group>,
Flags<[CoreOption]>;
+
+def fvirtual_function_elimination : Flag<["-"], "fvirtual-function-elimination">, Group<f_Group>,
+ Flags<[CoreOption, CC1Option]>,
+ HelpText<"Enables dead virtual function elimination optimization. Requires -flto=full">;
+def fno_virtual_function_elimination : Flag<["-"], "fno-virtual-function_elimination">, Group<f_Group>,
+ Flags<[CoreOption]>;
+
def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Treat signed integer overflow as two's complement">;
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
@@ -2023,9 +2099,14 @@ def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group<clang_ignored_m_Grou
def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>;
def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_Group>,
HelpText<"Generate branches with extended addressability, usually via indirect jumps.">;
-def mlong_double_64 : Flag<["-"], "mlong-double-64">, Group<f_Group>, Flags<[CC1Option]>,
+def LongDouble_Group : OptionGroup<"<LongDouble group>">, Group<m_Group>,
+ DocName<"Long double flags">,
+ DocBrief<[{Selects the long double implementation}]>;
+def mlong_double_64 : Flag<["-"], "mlong-double-64">, Group<LongDouble_Group>, Flags<[CC1Option]>,
HelpText<"Force long double to be 64 bits">;
-def mlong_double_128 : Flag<["-"], "mlong-double-128">, Group<f_Group>, Flags<[CC1Option]>,
+def mlong_double_80 : Flag<["-"], "mlong-double-80">, Group<LongDouble_Group>, Flags<[CC1Option]>,
+ HelpText<"Force long double to be 80 bits, padded to 128 bits for storage">;
+def mlong_double_128 : Flag<["-"], "mlong-double-128">, Group<LongDouble_Group>, Flags<[CC1Option]>,
HelpText<"Force long double to be 128 bits">;
def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_Group>,
HelpText<"Restore the default behaviour of not generating long calls">;
@@ -2138,6 +2219,12 @@ def msave_restore : Flag<["-"], "msave-restore">, Group<m_riscv_Features_Group>,
HelpText<"Enable using library calls for save and restore">;
def mno_save_restore : Flag<["-"], "mno-save-restore">, Group<m_riscv_Features_Group>,
HelpText<"Disable using library calls for save and restore">;
+def mcmodel_EQ_medlow : Flag<["-"], "mcmodel=medlow">, Group<m_riscv_Features_Group>,
+ Flags<[CC1Option]>, Alias<mcmodel_EQ>, AliasArgs<["small"]>,
+ HelpText<"Equivalent to -mcmodel=small, compatible with RISC-V gcc.">;
+def mcmodel_EQ_medany : Flag<["-"], "mcmodel=medany">, Group<m_riscv_Features_Group>,
+ Flags<[CC1Option]>, Alias<mcmodel_EQ>, AliasArgs<["medium"]>,
+ HelpText<"Equivalent to -mcmodel=medium, compatible with RISC-V gcc.">;
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
@@ -2241,6 +2328,8 @@ def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[DriverOption]>;
def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[DriverOption]>;
def maltivec : Flag<["-"], "maltivec">, Group<m_ppc_Features_Group>;
def mno_altivec : Flag<["-"], "mno-altivec">, Group<m_ppc_Features_Group>;
+def mspe : Flag<["-"], "mspe">, Group<m_ppc_Features_Group>;
+def mno_spe : Flag<["-"], "mno-spe">, Group<m_ppc_Features_Group>;
def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>;
def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>;
def msecure_plt : Flag<["-"], "msecure-plt">, Group<m_ppc_Features_Group>;
@@ -2309,7 +2398,7 @@ def mno_backchain : Flag<["-"], "mno-backchain">, Group<m_Group>, Flags<[DriverO
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]>;
+ HelpText<"Omit frame pointer setup for leaf functions">;
def moslib_EQ : Joined<["-"], "moslib=">, Group<m_Group>;
def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias<fpascal_strings>;
def mred_zone : Flag<["-"], "mred-zone">, Group<m_Group>;
@@ -2340,7 +2429,7 @@ def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group>
Flags<[CC1Option]>,
HelpText<"Use copy relocations support for PIE builds">;
def mno_pie_copy_relocations : Flag<["-"], "mno-pie-copy-relocations">, Group<m_Group>;
-def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86 only)">,
+def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86/SystemZ only)">,
Flags<[CC1Option]>, Group<m_Group>;
def mips16 : Flag<["-"], "mips16">, Group<m_mips_Features_Group>;
def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_mips_Features_Group>;
@@ -2506,7 +2595,9 @@ def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_te
def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option, CoreOption]>,
HelpText<"Disable builtin #include directories">;
def nocudainc : Flag<["-"], "nocudainc">;
-def nocudalib : Flag<["-"], "nocudalib">;
+def nogpulib : Flag<["-"], "nogpulib">,
+ HelpText<"Do not link device library for CUDA/HIP device compilation">;
+def : Flag<["-"], "nocudalib">, Alias<nogpulib>;
def nodefaultlibs : Flag<["-"], "nodefaultlibs">;
def nofixprebinding : Flag<["-"], "nofixprebinding">;
def nolibc : Flag<["-"], "nolibc">;
@@ -2627,11 +2718,15 @@ def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,
const char *Values =
#define LANGSTANDARD(id, name, lang, desc, features) name ","
#define LANGSTANDARD_ALIAS(id, alias) alias ","
- #include "clang/Frontend/LangStandards.def"
+ #include "clang/Basic/LangStandards.def"
;
}]>;
def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>,
HelpText<"C++ standard library to use">, Values<"libc++,libstdc++,platform">;
+def stdlibxx_isystem : JoinedOrSeparate<["-"], "stdlib++-isystem">,
+ Group<clang_i_Group>,
+ HelpText<"Use directory as the C++ standard library include path">,
+ Flags<[DriverOption]>, MetaVarName<"<directory>">;
def unwindlib_EQ : Joined<["-", "--"], "unwindlib=">, Flags<[CC1Option]>,
HelpText<"Unwind library to use">, Values<"libgcc,unwindlib,platform">;
def sub__library : JoinedOrSeparate<["-"], "sub_library">;
@@ -2711,7 +2806,6 @@ def _mhwdiv : 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>;
-def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>;
def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>;
def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>,
HelpText<"Static analyzer report output format (html|plist|plist-multi-file|plist-html|text).">;
@@ -2972,8 +3066,6 @@ def mmovdiri : Flag<["-"], "mmovdiri">, Group<m_x86_Features_Group>;
def mno_movdiri : Flag<["-"], "mno-movdiri">, Group<m_x86_Features_Group>;
def mmovdir64b : Flag<["-"], "mmovdir64b">, Group<m_x86_Features_Group>;
def mno_movdir64b : Flag<["-"], "mno-movdir64b">, Group<m_x86_Features_Group>;
-def mmpx : Flag<["-"], "mmpx">, Group<m_x86_Features_Group>;
-def mno_mpx : Flag<["-"], "mno-mpx">, Group<m_x86_Features_Group>;
def mmwaitx : Flag<["-"], "mmwaitx">, Group<m_x86_Features_Group>;
def mno_mwaitx : Flag<["-"], "mno-mwaitx">, Group<m_x86_Features_Group>;
def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>;
diff --git a/include/clang/Driver/Phases.h b/include/clang/Driver/Phases.h
index 7199c657848c..63931c00c890 100644
--- a/include/clang/Driver/Phases.h
+++ b/include/clang/Driver/Phases.h
@@ -20,7 +20,8 @@ namespace phases {
Compile,
Backend,
Assemble,
- Link
+ Link,
+ IfsMerge,
};
enum {
diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h
index 957e752b6877..c37499e0f201 100644
--- a/include/clang/Driver/SanitizerArgs.h
+++ b/include/clang/Driver/SanitizerArgs.h
@@ -32,6 +32,7 @@ class SanitizerArgs {
bool MsanUseAfterDtor = true;
bool CfiCrossDso = false;
bool CfiICallGeneralizePointers = false;
+ bool CfiCanonicalJumpTables = false;
int AsanFieldPadding = 0;
bool SharedRuntime = false;
bool AsanUseAfterScope = true;
@@ -41,6 +42,7 @@ class SanitizerArgs {
bool AsanInvalidPointerCmp = false;
bool AsanInvalidPointerSub = false;
std::string HwasanAbi;
+ bool LinkRuntimes = true;
bool LinkCXXRuntimes = false;
bool NeedPIE = false;
bool SafeStackRuntime = false;
@@ -59,7 +61,9 @@ class SanitizerArgs {
bool needsSharedRt() const { return SharedRuntime; }
bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); }
- bool needsHwasanRt() const { return Sanitizers.has(SanitizerKind::HWAddress); }
+ bool needsHwasanRt() const {
+ return Sanitizers.has(SanitizerKind::HWAddress);
+ }
bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); }
bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); }
bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); }
@@ -80,6 +84,7 @@ class SanitizerArgs {
bool requiresPIE() const;
bool needsUnwindTables() const;
bool needsLTO() const;
+ bool linkRuntimes() const { return LinkRuntimes; }
bool linkCXXRuntimes() const { return LinkCXXRuntimes; }
bool hasCrossDsoCfi() const { return CfiCrossDso; }
bool hasAnySanitizer() const { return !Sanitizers.empty(); }
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 7dd3db376c8c..f0676eee2d6c 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -136,13 +136,17 @@ private:
mutable std::unique_ptr<Tool> Clang;
mutable std::unique_ptr<Tool> Assemble;
mutable std::unique_ptr<Tool> Link;
+ mutable std::unique_ptr<Tool> IfsMerge;
mutable std::unique_ptr<Tool> OffloadBundler;
+ mutable std::unique_ptr<Tool> OffloadWrapper;
Tool *getClang() const;
Tool *getAssemble() const;
Tool *getLink() const;
+ Tool *getIfsMerge() const;
Tool *getClangAs() const;
Tool *getOffloadBundler() const;
+ Tool *getOffloadWrapper() const;
mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
mutable std::unique_ptr<XRayArgs> XRayArguments;
@@ -542,6 +546,11 @@ public:
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
+ /// AddClangCXXStdlibIsystemArgs - Add the clang -cc1 level arguments to set
+ /// the specified include paths for the C++ standard library.
+ void AddClangCXXStdlibIsystemArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
/// Returns if the C++ standard library should be linked in.
/// Note that e.g. -lm should still be linked even if this returns false.
bool ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const;
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index b45789d4b314..79e8d109cd97 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -29,77 +29,74 @@
// The fourth value is the suffix to use when creating temporary files
// of this type, or null if unspecified.
-// The fifth value is a string containing option flags. Valid values:
-// a - The type should only be assembled.
-// p - The type should only be precompiled.
-// u - The type can be user specified (with -x).
-// m - Precompiling this type produces a module file.
-// A - The type's temporary suffix should be appended when generating
-// outputs of this type.
-
+// The final value is a variadic list of phases for each type. Eventually the
+// options flag string will be replaced with this variadic list.
+// Most of the options in Flags have been removed in favor of subsuming their
+// meaning from the phases list.
// C family source language (with and without preprocessing).
-TYPE("cpp-output", PP_C, INVALID, "i", "u")
-TYPE("c", C, PP_C, "c", "u")
-TYPE("cl", CL, PP_C, "cl", "u")
-TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", "u")
-TYPE("cuda", CUDA, PP_CUDA, "cu", "u")
-TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", "")
-TYPE("hip-cpp-output", PP_HIP, INVALID, "cui", "u")
-TYPE("hip", HIP, PP_HIP, "cu", "u")
-TYPE("hip", HIP_DEVICE, PP_HIP, "cu", "")
-TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
-TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u")
-TYPE("objective-c", ObjC, PP_ObjC, "m", "u")
-TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u")
-TYPE("c++", CXX, PP_CXX, "cpp", "u")
-TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", "u")
-TYPE("objc++-cpp-output", PP_ObjCXX_Alias, INVALID, "mii", "u")
-TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", "u")
-TYPE("renderscript", RenderScript, PP_C, "rs", "u")
+TYPE("cpp-output", PP_C, INVALID, "i", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("c", C, PP_C, "c", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("cl", CL, PP_C, "cl", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("cuda", CUDA, PP_CUDA, "cu", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("hip-cpp-output", PP_HIP, INVALID, "cui", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("hip", HIP, PP_HIP, "cu", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("hip", HIP_DEVICE, PP_HIP, "cu", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("objective-c", ObjC, PP_ObjC, "m", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("c++", CXX, PP_CXX, "cpp", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("objc++-cpp-output", PP_ObjCXX_Alias, INVALID, "mii", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("renderscript", RenderScript, PP_C, "rs", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
// C family input files to precompile.
-TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p")
-TYPE("c-header", CHeader, PP_CHeader, "h", "pu")
-TYPE("cl-header", CLHeader, PP_CHeader, "h", "pu")
-TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p")
-TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, "h", "pu")
-TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p")
-TYPE("c++-header", CXXHeader, PP_CXXHeader, "hh", "pu")
-TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p")
-TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, "h", "pu")
-TYPE("c++-module", CXXModule, PP_CXXModule, "cppm", "mu")
-TYPE("c++-module-cpp-output", PP_CXXModule, INVALID, "iim", "m")
+TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", phases::Precompile)
+TYPE("c-header", CHeader, PP_CHeader, "h", phases::Preprocess, phases::Precompile)
+TYPE("cl-header", CLHeader, PP_CHeader, "h", phases::Preprocess, phases::Precompile)
+TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", phases::Precompile)
+TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, "h", phases::Preprocess, phases::Precompile)
+TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", phases::Precompile)
+TYPE("c++-header", CXXHeader, PP_CXXHeader, "hh", phases::Preprocess, phases::Precompile)
+TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", phases::Precompile)
+TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, "h", phases::Preprocess, phases::Precompile)
+TYPE("c++-module", CXXModule, PP_CXXModule, "cppm", phases::Preprocess, phases::Precompile, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("c++-module-cpp-output", PP_CXXModule, INVALID, "iim", phases::Precompile, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
// Other languages.
-TYPE("ada", Ada, INVALID, nullptr, "u")
-TYPE("assembler", PP_Asm, INVALID, "s", "au")
-TYPE("assembler-with-cpp", Asm, PP_Asm, "S", "au")
-TYPE("f95", PP_Fortran, INVALID, nullptr, "u")
-TYPE("f95-cpp-input", Fortran, PP_Fortran, nullptr, "u")
-TYPE("java", Java, INVALID, nullptr, "u")
+TYPE("ada", Ada, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("assembler", PP_Asm, INVALID, "s", phases::Assemble, phases::Link)
+TYPE("assembler-with-cpp", Asm, PP_Asm, "S", phases::Preprocess, phases::Assemble, phases::Link)
+TYPE("f95", PP_Fortran, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("f95-cpp-input", Fortran, PP_Fortran, nullptr, phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("java", Java, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
// LLVM IR/LTO types. We define separate types for IR and LTO because LTO
// outputs should use the standard suffixes.
-TYPE("ir", LLVM_IR, INVALID, "ll", "u")
-TYPE("ir", LLVM_BC, INVALID, "bc", "u")
-TYPE("lto-ir", LTO_IR, INVALID, "s", "")
-TYPE("lto-bc", LTO_BC, INVALID, "o", "")
+TYPE("ir", LLVM_IR, INVALID, "ll", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("ir", LLVM_BC, INVALID, "bc", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("lto-ir", LTO_IR, INVALID, "s", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("lto-bc", LTO_BC, INVALID, "o", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
// Misc.
-TYPE("ast", AST, INVALID, "ast", "u")
-TYPE("ifs", IFS, INVALID, "ifs", "u")
-TYPE("pcm", ModuleFile, INVALID, "pcm", "u")
-TYPE("plist", Plist, INVALID, "plist", "")
-TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "")
-TYPE("rewritten-legacy-objc", RewrittenLegacyObjC,INVALID, "cpp", "")
-TYPE("remap", Remap, INVALID, "remap", "")
-TYPE("precompiled-header", PCH, INVALID, "gch", "A")
-TYPE("object", Object, INVALID, "o", "")
-TYPE("treelang", Treelang, INVALID, nullptr, "u")
-TYPE("image", Image, INVALID, "out", "")
-TYPE("dSYM", dSYM, INVALID, "dSYM", "A")
-TYPE("dependencies", Dependencies, INVALID, "d", "")
-TYPE("cuda-fatbin", CUDA_FATBIN, INVALID, "fatbin","A")
-TYPE("hip-fatbin", HIP_FATBIN, INVALID, "hipfb", "A")
-TYPE("none", Nothing, INVALID, nullptr, "u")
+TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("ifs", IFS, INVALID, "ifs", phases::IfsMerge)
+TYPE("ifs-cpp", IFS_CPP, INVALID, "ifs", phases::Compile, phases::IfsMerge)
+TYPE("pcm", ModuleFile, INVALID, "pcm", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("plist", Plist, INVALID, "plist", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("rewritten-legacy-objc", RewrittenLegacyObjC,INVALID, "cpp", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("remap", Remap, INVALID, "remap", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("precompiled-header", PCH, INVALID, "gch", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("object", Object, INVALID, "o", phases::Link)
+TYPE("treelang", Treelang, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("image", Image, INVALID, "out", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("dSYM", dSYM, INVALID, "dSYM", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("dependencies", Dependencies, INVALID, "d", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("cuda-fatbin", CUDA_FATBIN, INVALID, "fatbin", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("hip-fatbin", HIP_FATBIN, INVALID, "hipfb", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("none", Nothing, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
index 53afada7abca..a605450e6e3d 100644
--- a/include/clang/Driver/Types.h
+++ b/include/clang/Driver/Types.h
@@ -11,16 +11,18 @@
#include "clang/Driver/Phases.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Option/ArgList.h"
namespace llvm {
class StringRef;
}
namespace clang {
namespace driver {
+class Driver;
namespace types {
enum ID {
TY_INVALID,
-#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) TY_##ID,
+#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) TY_##ID,
#include "clang/Driver/Types.def"
#undef TYPE
TY_LAST
@@ -100,6 +102,9 @@ namespace types {
void getCompilationPhases(
ID Id,
llvm::SmallVectorImpl<phases::ID> &Phases);
+ void getCompilationPhases(const clang::driver::Driver &Driver,
+ llvm::opt::DerivedArgList &DAL, ID Id,
+ 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/Format/Format.h b/include/clang/Format/Format.h
index 6388e4fc1727..7e71b7e8b167 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -216,10 +216,37 @@ struct FormatStyle {
/// \endcode
bool AllowAllParametersOfDeclarationOnNextLine;
- /// Allows contracting simple braced statements to a single line.
- ///
- /// E.g., this allows ``if (a) { return; }`` to be put on a single line.
- bool AllowShortBlocksOnASingleLine;
+ /// Different styles for merging short blocks containing at most one
+ /// statement.
+ enum ShortBlockStyle {
+ /// Never merge blocks into a single line.
+ /// \code
+ /// while (true) {
+ /// }
+ /// while (true) {
+ /// continue;
+ /// }
+ /// \endcode
+ SBS_Never,
+ /// Only merge empty blocks.
+ /// \code
+ /// while (true) {}
+ /// while (true) {
+ /// continue;
+ /// }
+ /// \endcode
+ SBS_Empty,
+ /// Always merge short blocks into a single line.
+ /// \code
+ /// while (true) {}
+ /// while (true) { continue; }
+ /// \endcode
+ SBS_Always,
+ };
+
+ /// Dependent on the value, ``while (true) { continue; }`` can be put on a
+ /// single line.
+ ShortBlockStyle AllowShortBlocksOnASingleLine;
/// If ``true``, short case labels will be contracted to a single line.
/// \code
@@ -462,38 +489,38 @@ struct FormatStyle {
/// Different ways to break after the template declaration.
enum BreakTemplateDeclarationsStyle {
- /// Do not force break before declaration.
- /// ``PenaltyBreakTemplateDeclaration`` is taken into account.
- /// \code
- /// template <typename T> T foo() {
- /// }
- /// template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa,
- /// int bbbbbbbbbbbbbbbbbbbbb) {
- /// }
- /// \endcode
- BTDS_No,
- /// Force break after template declaration only when the following
- /// declaration spans multiple lines.
- /// \code
- /// template <typename T> T foo() {
- /// }
- /// template <typename T>
- /// T foo(int aaaaaaaaaaaaaaaaaaaaa,
- /// int bbbbbbbbbbbbbbbbbbbbb) {
- /// }
- /// \endcode
- BTDS_MultiLine,
- /// Always break after template declaration.
- /// \code
- /// template <typename T>
- /// T foo() {
- /// }
- /// template <typename T>
- /// T foo(int aaaaaaaaaaaaaaaaaaaaa,
- /// int bbbbbbbbbbbbbbbbbbbbb) {
- /// }
- /// \endcode
- BTDS_Yes
+ /// Do not force break before declaration.
+ /// ``PenaltyBreakTemplateDeclaration`` is taken into account.
+ /// \code
+ /// template <typename T> T foo() {
+ /// }
+ /// template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ /// int bbbbbbbbbbbbbbbbbbbbb) {
+ /// }
+ /// \endcode
+ BTDS_No,
+ /// Force break after template declaration only when the following
+ /// declaration spans multiple lines.
+ /// \code
+ /// template <typename T> T foo() {
+ /// }
+ /// template <typename T>
+ /// T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ /// int bbbbbbbbbbbbbbbbbbbbb) {
+ /// }
+ /// \endcode
+ BTDS_MultiLine,
+ /// Always break after template declaration.
+ /// \code
+ /// template <typename T>
+ /// T foo() {
+ /// }
+ /// template <typename T>
+ /// T foo(int aaaaaaaaaaaaaaaaaaaaa,
+ /// int bbbbbbbbbbbbbbbbbbbbb) {
+ /// }
+ /// \endcode
+ BTDS_Yes
};
/// The template declaration breaking style to use.
@@ -706,6 +733,32 @@ struct FormatStyle {
/// B
/// };
/// \endcode
+ BS_Whitesmiths,
+ /// Like ``Allman`` but always indent braces and line up code with braces.
+ /// \code
+ /// try
+ /// {
+ /// foo();
+ /// }
+ /// catch ()
+ /// {
+ /// }
+ /// void foo() { bar(); }
+ /// class foo
+ /// {
+ /// };
+ /// if (foo())
+ /// {
+ /// }
+ /// else
+ /// {
+ /// }
+ /// enum X : int
+ /// {
+ /// A,
+ /// B
+ /// };
+ /// \endcode
BS_GNU,
/// Like ``Attach``, but break before functions.
/// \code
@@ -729,6 +782,40 @@ struct FormatStyle {
/// The brace breaking style to use.
BraceBreakingStyle BreakBeforeBraces;
+ // Different ways to wrap braces after control statements.
+ enum BraceWrappingAfterControlStatementStyle {
+ /// Never wrap braces after a control statement.
+ /// \code
+ /// if (foo()) {
+ /// } else {
+ /// }
+ /// for (int i = 0; i < 10; ++i) {
+ /// }
+ /// \endcode
+ BWACS_Never,
+ /// Only wrap braces after a multi-line control statement.
+ /// \code
+ /// if (foo && bar &&
+ /// baz)
+ /// {
+ /// quux();
+ /// }
+ /// while (foo || bar) {
+ /// }
+ /// \endcode
+ BWACS_MultiLine,
+ /// Always wrap braces after a control statement.
+ /// \code
+ /// if (foo())
+ /// {
+ /// } else
+ /// {}
+ /// for (int i = 0; i < 10; ++i)
+ /// {}
+ /// \endcode
+ BWACS_Always
+ };
+
/// Precise control over the wrapping of braces.
/// \code
/// # Should be declared this way:
@@ -764,23 +851,7 @@ struct FormatStyle {
/// \endcode
bool AfterClass;
/// Wrap control statements (``if``/``for``/``while``/``switch``/..).
- /// \code
- /// true:
- /// if (foo())
- /// {
- /// } else
- /// {}
- /// for (int i = 0; i < 10; ++i)
- /// {}
- ///
- /// false:
- /// if (foo()) {
- /// } else {
- /// }
- /// for (int i = 0; i < 10; ++i) {
- /// }
- /// \endcode
- bool AfterControlStatement;
+ BraceWrappingAfterControlStatementStyle AfterControlStatement;
/// Wrap enum definitions.
/// \code
/// true:
@@ -1238,6 +1309,22 @@ struct FormatStyle {
/// \endcode
bool IndentCaseLabels;
+ /// Indent goto labels.
+ ///
+ /// When ``false``, goto labels are flushed left.
+ /// \code
+ /// true: false:
+ /// int f() { vs. int f() {
+ /// if (foo()) { if (foo()) {
+ /// label1: label1:
+ /// bar(); bar();
+ /// } }
+ /// label2: label2:
+ /// return 1; return 1;
+ /// } }
+ /// \endcode
+ bool IndentGotoLabels;
+
/// Options for indenting preprocessor directives.
enum PPDirectiveIndentStyle {
/// Does not indent any directives.
@@ -1711,8 +1798,8 @@ struct FormatStyle {
/// If ``false``, spaces will be removed before assignment operators.
/// \code
/// true: false:
- /// int a = 5; vs. int a=5;
- /// a += 42 a+=42;
+ /// int a = 5; vs. int a= 5;
+ /// a += 42; a+= 42;
/// \endcode
bool SpaceBeforeAssignmentOperators;
@@ -1799,6 +1886,14 @@ struct FormatStyle {
/// \endcode
bool SpaceBeforeRangeBasedForLoopColon;
+ /// If ``true``, spaces will be inserted into ``{}``.
+ /// \code
+ /// true: false:
+ /// void f() { } vs. void f() {}
+ /// while (true) { } while (true) {}
+ /// \endcode
+ bool SpaceInEmptyBlock;
+
/// If ``true``, spaces may be inserted into ``()``.
/// \code
/// true: false:
@@ -1868,15 +1963,32 @@ struct FormatStyle {
/// \endcode
bool SpacesInSquareBrackets;
- /// Supported language standards.
+ /// Supported language standards for parsing and formatting C++ constructs.
+ /// \code
+ /// Latest: vector<set<int>>
+ /// c++03 vs. vector<set<int> >
+ /// \endcode
+ ///
+ /// The correct way to spell a specific language version is e.g. ``c++11``.
+ /// The historical aliases ``Cpp03`` and ``Cpp11`` are deprecated.
enum LanguageStandard {
- /// Use C++03-compatible syntax.
+ /// c++03: Parse and format as C++03.
LS_Cpp03,
- /// Use features of C++11, C++14 and C++1z (e.g. ``A<A<int>>`` instead of
- /// ``A<A<int> >``).
+ /// c++11: Parse and format as C++11.
LS_Cpp11,
- /// Automatic detection based on the input.
- LS_Auto
+ /// c++14: Parse and format as C++14.
+ LS_Cpp14,
+ /// c++17: Parse and format as C++17.
+ LS_Cpp17,
+ /// c++20: Parse and format as C++20.
+ LS_Cpp20,
+ /// Latest: Parse and format using the latest supported language version.
+ /// 'Cpp11' is an alias for LS_Latest for historical reasons.
+ LS_Latest,
+
+ /// Auto: Automatic detection based on the input.
+ /// Parse using the latest language version. Format based on detected input.
+ LS_Auto,
};
/// Format compatible with this standard, e.g. use ``A<A<int> >``
@@ -1955,6 +2067,7 @@ struct FormatStyle {
IncludeStyle.IncludeBlocks == R.IncludeStyle.IncludeBlocks &&
IncludeStyle.IncludeCategories == R.IncludeStyle.IncludeCategories &&
IndentCaseLabels == R.IndentCaseLabels &&
+ IndentGotoLabels == R.IndentGotoLabels &&
IndentPPDirectives == R.IndentPPDirectives &&
IndentWidth == R.IndentWidth && Language == R.Language &&
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
@@ -1995,6 +2108,7 @@ struct FormatStyle {
SpaceBeforeParens == R.SpaceBeforeParens &&
SpaceBeforeRangeBasedForLoopColon ==
R.SpaceBeforeRangeBasedForLoopColon &&
+ SpaceInEmptyBlock == R.SpaceInEmptyBlock &&
SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
SpacesInAngles == R.SpacesInAngles &&
@@ -2072,6 +2186,10 @@ FormatStyle getWebKitStyle();
/// http://www.gnu.org/prep/standards/standards.html
FormatStyle getGNUStyle();
+/// Returns a format style complying with Microsoft style guide:
+/// https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2017
+FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language);
+
/// Returns style indicating formatting should be not applied at all.
FormatStyle getNoStyle();
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 7fb1d2d93380..a36655150d4e 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -315,7 +315,7 @@ public:
CodeCompletionTUInfo &getCodeCompletionTUInfo() {
if (!CCTUInfo)
- CCTUInfo = llvm::make_unique<CodeCompletionTUInfo>(
+ CCTUInfo = std::make_unique<CodeCompletionTUInfo>(
std::make_shared<GlobalCodeCompletionAllocator>());
return *CCTUInfo;
}
@@ -390,7 +390,7 @@ private:
/// just about any usage.
/// Becomes a noop in release mode; only useful for debug mode checking.
class ConcurrencyState {
- void *Mutex; // a llvm::sys::MutexImpl in debug;
+ void *Mutex; // a std::recursive_mutex in debug;
public:
ConcurrencyState();
@@ -832,6 +832,7 @@ public:
SkipFunctionBodiesScope::None,
bool SingleFileParse = false, bool UserFilesAreVolatile = false,
bool ForSerialization = false,
+ bool RetainExcludedConditionalBlocks = false,
llvm::Optional<StringRef> ModuleFormat = llvm::None,
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index eb49c53ff40b..d15bdc4665a3 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -155,6 +155,12 @@ class CompilerInstance : public ModuleLoader {
/// One or more modules failed to build.
bool ModuleBuildFailed = false;
+ /// The stream for verbose output if owned, otherwise nullptr.
+ std::unique_ptr<raw_ostream> OwnedVerboseOutputStream;
+
+ /// The stream for verbose output.
+ raw_ostream *VerboseOutputStream = &llvm::errs();
+
/// Holds information about the output file.
///
/// If TempFilename is not empty we must rename it to Filename at the end.
@@ -217,9 +223,6 @@ public:
/// \param Act - The action to execute.
/// \return - True on success.
//
- // FIXME: This function should take the stream to write any debugging /
- // verbose output to as an argument.
- //
// FIXME: Eliminate the llvm_shutdown requirement, that should either be part
// of the context or else not CompilerInstance specific.
bool ExecuteAction(FrontendAction &Act);
@@ -350,6 +353,21 @@ public:
}
/// }
+ /// @name VerboseOutputStream
+ /// }
+
+ /// Replace the current stream for verbose output.
+ void setVerboseOutputStream(raw_ostream &Value);
+
+ /// Replace the current stream for verbose output.
+ void setVerboseOutputStream(std::unique_ptr<raw_ostream> Value);
+
+ /// Get the current stream for verbose output.
+ raw_ostream &getVerboseOutputStream() {
+ return *VerboseOutputStream;
+ }
+
+ /// }
/// @name Target Info
/// {
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 413134be4cef..f3253d5b40e3 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -14,13 +14,14 @@
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/LangStandard.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendOptions.h"
-#include "clang/Frontend/LangStandard.h"
#include "clang/Frontend/MigratorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/ArrayRef.h"
#include <memory>
#include <string>
@@ -147,13 +148,14 @@ public:
/// Create a compiler invocation from a list of input options.
/// \returns true on success.
///
+ /// \returns false if an error was encountered while parsing the arguments
+ /// and attempts to recover and continue parsing the rest of the arguments.
+ /// The recovery is best-effort and only guarantees that \p Res will end up in
+ /// one of the vaild-to-access (albeit arbitrary) states.
+ ///
/// \param [out] Res - The resulting invocation.
- /// \param ArgBegin - The first element in the argument vector.
- /// \param ArgEnd - The last element in the argument vector.
- /// \param Diags - The diagnostic engine to use for errors.
static bool CreateFromArgs(CompilerInvocation &Res,
- const char* const *ArgBegin,
- const char* const *ArgEnd,
+ ArrayRef<const char *> CommandLineArgs,
DiagnosticsEngine &Diags);
/// Get the directory where the compiler headers
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 6c7bc6046f33..89ac20075fa4 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -126,14 +126,7 @@ protected:
bool hasASTFileSupport() const override { return false; }
};
-// Support different interface stub formats this way:
-class GenerateInterfaceYAMLExpV1Action : public GenerateInterfaceStubAction {
-protected:
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
-};
-
-class GenerateInterfaceTBEExpV1Action : public GenerateInterfaceStubAction {
+class GenerateInterfaceIfsExpV1Action : public GenerateInterfaceStubAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index a0acb1f066f2..09d83adf579b 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -10,15 +10,16 @@
#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
#include "clang/AST/ASTDumperUtils.h"
+#include "clang/Basic/LangStandard.h"
#include "clang/Frontend/CommandLineSourceLoc.h"
-#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Sema/CodeCompleteOptions.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <memory>
#include <string>
-#include <vector>
#include <unordered_map>
+#include <vector>
namespace llvm {
@@ -89,8 +90,7 @@ enum ActionKind {
GeneratePCH,
/// Generate Interface Stub Files.
- GenerateInterfaceYAMLExpV1,
- GenerateInterfaceTBEExpV1,
+ GenerateInterfaceIfsExpV1,
/// Only execute frontend initialization.
InitOnly,
@@ -143,35 +143,11 @@ enum ActionKind {
/// The kind of a file that we've been handed as an input.
class InputKind {
private:
- unsigned Lang : 4;
+ Language Lang;
unsigned Fmt : 3;
unsigned Preprocessed : 1;
public:
- /// The language for the input, used to select and validate the language
- /// standard and possible actions.
- enum Language {
- Unknown,
-
- /// Assembly: we accept this only so that we can preprocess it.
- Asm,
-
- /// LLVM IR: we accept this so that we can run the optimizer on it,
- /// and compile it to assembly or object code.
- LLVM_IR,
-
- ///@{ Languages that the frontend can parse and compile.
- C,
- CXX,
- ObjC,
- ObjCXX,
- OpenCL,
- CUDA,
- RenderScript,
- HIP,
- ///@}
- };
-
/// The input file format.
enum Format {
Source,
@@ -179,7 +155,7 @@ public:
Precompiled
};
- constexpr InputKind(Language L = Unknown, Format F = Source,
+ constexpr InputKind(Language L = Language::Unknown, Format F = Source,
bool PP = false)
: Lang(L), Fmt(F), Preprocessed(PP) {}
@@ -188,10 +164,12 @@ public:
bool isPreprocessed() const { return Preprocessed; }
/// Is the input kind fully-unknown?
- bool isUnknown() const { return Lang == Unknown && Fmt == Source; }
+ bool isUnknown() const { return Lang == Language::Unknown && Fmt == Source; }
/// Is the language of the input some dialect of Objective-C?
- bool isObjectiveC() const { return Lang == ObjC || Lang == ObjCXX; }
+ bool isObjectiveC() const {
+ return Lang == Language::ObjC || Lang == Language::ObjCXX;
+ }
InputKind getPreprocessed() const {
return InputKind(getLanguage(), getFormat(), true);
@@ -451,6 +429,9 @@ public:
/// Filename to write statistics to.
std::string StatsFile;
+ /// Minimum time granularity (in microseconds) traced by time profiler.
+ unsigned TimeTraceGranularity;
+
public:
FrontendOptions()
: DisableFree(false), RelocatablePCH(false), ShowHelp(false),
@@ -461,12 +442,12 @@ public:
UseGlobalModuleIndex(true), GenerateGlobalModuleIndex(true),
ASTDumpDecls(false), ASTDumpLookups(false),
BuildingImplicitModule(false), ModulesEmbedAllFiles(false),
- IncludeTimestamps(true) {}
+ IncludeTimestamps(true), TimeTraceGranularity(500) {}
/// getInputKindForExtension - Return the appropriate input kind for a file
- /// extension. For example, "c" would return InputKind::C.
+ /// extension. For example, "c" would return Language::C.
///
- /// \return The input kind for the extension, or InputKind::Unknown if the
+ /// \return The input kind for the extension, or Language::Unknown if the
/// extension is not recognized.
static InputKind getInputKindForExtension(StringRef Extension);
};
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 74e563218c31..0f9b17ee5089 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -99,11 +99,11 @@ public:
/// Return true if system files should be passed to sawDependency().
virtual bool needSystemDependencies() { return false; }
- // implementation detail
/// Add a dependency \p Filename if it has not been seen before and
/// sawDependency() returns true.
- void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem,
- bool IsModuleFile, bool IsMissing);
+ virtual void maybeAddDependency(StringRef Filename, bool FromModule,
+ bool IsSystem, bool IsModuleFile,
+ bool IsMissing);
protected:
/// Return true if the filename was added to the list of dependencies, false
@@ -213,13 +213,18 @@ createChainedIncludesSource(CompilerInstance &CI,
/// createInvocationFromCommandLine - Construct a compiler invocation object for
/// a command line argument vector.
///
+/// \param ShouldRecoverOnErrors - whether we should attempt to return a
+/// non-null (and possibly incorrect) CompilerInvocation if any errors were
+/// encountered. When this flag is false, always return null on errors.
+///
/// \return A CompilerInvocation, or 0 if none was built for the given
/// argument vector.
std::unique_ptr<CompilerInvocation> createInvocationFromCommandLine(
ArrayRef<const char *> Args,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
IntrusiveRefCntPtr<DiagnosticsEngine>(),
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr,
+ bool ShouldRecoverOnErrors = false);
/// 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.
diff --git a/include/clang/Index/CodegenNameGenerator.h b/include/clang/Index/CodegenNameGenerator.h
deleted file mode 100644
index 98b3a5de817a..000000000000
--- a/include/clang/Index/CodegenNameGenerator.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- CodegenNameGenerator.h - Codegen name generation -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Determines the name that the symbol will get for code generation.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
-#define LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
-
-#include "clang/AST/Mangle.h"
-#include "clang/Basic/LLVM.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace clang {
- class ASTContext;
- class Decl;
-
-namespace index {
-
-class CodegenNameGenerator {
-public:
- explicit CodegenNameGenerator(ASTContext &Ctx);
- ~CodegenNameGenerator();
-
- /// \returns true on failure to produce a name for the given decl, false on
- /// success.
- bool writeName(const Decl *D, raw_ostream &OS);
-
- /// Version of \c writeName function that returns a string.
- std::string getName(const Decl *D);
-
- /// This can return multiple mangled names when applicable, e.g. for C++
- /// constructors/destructors.
- std::vector<std::string> getAllManglings(const Decl *D);
-
-private:
- struct Implementation;
- std::unique_ptr<ASTNameGenerator> Impl;
-};
-
-} // namespace index
-} // namespace clang
-
-#endif // LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
diff --git a/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h
index bc1d86696df9..72747821bf54 100644
--- a/include/clang/Index/IndexDataConsumer.h
+++ b/include/clang/Index/IndexDataConsumer.h
@@ -32,7 +32,7 @@ public:
const DeclContext *ContainerDC;
};
- virtual ~IndexDataConsumer() {}
+ virtual ~IndexDataConsumer() = default;
virtual void initialize(ASTContext &Ctx) {}
@@ -41,12 +41,16 @@ public:
/// \returns true to continue indexing, or false to abort.
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,
- SourceLocation Loc, ASTNodeInfo ASTNode);
+ SourceLocation Loc, ASTNodeInfo ASTNode) {
+ return true;
+ }
/// \returns true to continue indexing, or false to abort.
virtual bool handleMacroOccurence(const IdentifierInfo *Name,
const MacroInfo *MI, SymbolRoleSet Roles,
- SourceLocation Loc);
+ SourceLocation Loc) {
+ return true;
+ }
/// \returns true to continue indexing, or false to abort.
///
@@ -54,8 +58,10 @@ public:
/// For "@import MyMod.SubMod", there will be a call for 'MyMod' with the
/// 'reference' role, and a call for 'SubMod' with the 'declaration' role.
virtual bool handleModuleOccurence(const ImportDecl *ImportD,
- const Module *Mod,
- SymbolRoleSet Roles, SourceLocation Loc);
+ const Module *Mod, SymbolRoleSet Roles,
+ SourceLocation Loc) {
+ return true;
+ }
virtual void finish() {}
};
diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h
index 9756f3c539e6..9ed2a018f161 100644
--- a/include/clang/Index/IndexingAction.h
+++ b/include/clang/Index/IndexingAction.h
@@ -9,7 +9,9 @@
#ifndef LLVM_CLANG_INDEX_INDEXINGACTION_H
#define LLVM_CLANG_INDEX_INDEXINGACTION_H
+#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Index/IndexingOptions.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/ArrayRef.h"
@@ -17,6 +19,7 @@
namespace clang {
class ASTContext;
+ class ASTConsumer;
class ASTReader;
class ASTUnit;
class Decl;
@@ -29,32 +32,24 @@ namespace serialization {
namespace index {
class IndexDataConsumer;
-struct IndexingOptions {
- enum class SystemSymbolFilterKind {
- None,
- DeclarationsOnly,
- All,
- };
+/// Creates an ASTConsumer that indexes all symbols (macros and AST decls).
+std::unique_ptr<ASTConsumer> createIndexingASTConsumer(
+ std::shared_ptr<IndexDataConsumer> DataConsumer,
+ const IndexingOptions &Opts, std::shared_ptr<Preprocessor> PP,
+ std::function<bool(const Decl *)> ShouldSkipFunctionBody);
- SystemSymbolFilterKind SystemSymbolFilter
- = SystemSymbolFilterKind::DeclarationsOnly;
- bool IndexFunctionLocals = false;
- bool IndexImplicitInstantiation = false;
- // Whether to index macro definitions in the Preprocesor when preprocessor
- // callback is not available (e.g. after parsing has finished). Note that
- // macro references are not available in Proprocessor.
- bool IndexMacrosInPreprocessor = false;
- // Has no effect if IndexFunctionLocals are false.
- bool IndexParametersInDeclarations = false;
- bool IndexTemplateParameters = false;
-};
+inline std::unique_ptr<ASTConsumer> createIndexingASTConsumer(
+ std::shared_ptr<IndexDataConsumer> DataConsumer,
+ const IndexingOptions &Opts, std::shared_ptr<Preprocessor> PP) {
+ return createIndexingASTConsumer(
+ std::move(DataConsumer), Opts, std::move(PP),
+ /*ShouldSkipFunctionBody=*/[](const Decl *) { return false; });
+}
/// Creates a frontend action that indexes all symbols (macros and AST decls).
-/// \param WrappedAction another frontend action to wrap over or null.
std::unique_ptr<FrontendAction>
createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
- IndexingOptions Opts,
- std::unique_ptr<FrontendAction> WrappedAction);
+ const IndexingOptions &Opts);
/// Recursively indexes all decls in the AST.
void indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
diff --git a/include/clang/Index/IndexingOptions.h b/include/clang/Index/IndexingOptions.h
new file mode 100644
index 000000000000..bbfd6e4a72c6
--- /dev/null
+++ b/include/clang/Index/IndexingOptions.h
@@ -0,0 +1,42 @@
+//===--- IndexingOptions.h - Options for indexing ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_INDEXINGOPTIONS_H
+#define LLVM_CLANG_INDEX_INDEXINGOPTIONS_H
+
+#include "clang/Frontend/FrontendOptions.h"
+#include <memory>
+#include <string>
+
+namespace clang {
+namespace index {
+
+struct IndexingOptions {
+ enum class SystemSymbolFilterKind {
+ None,
+ DeclarationsOnly,
+ All,
+ };
+
+ SystemSymbolFilterKind SystemSymbolFilter =
+ SystemSymbolFilterKind::DeclarationsOnly;
+ bool IndexFunctionLocals = false;
+ bool IndexImplicitInstantiation = false;
+ // Whether to index macro definitions in the Preprocesor when preprocessor
+ // callback is not available (e.g. after parsing has finished). Note that
+ // macro references are not available in Proprocessor.
+ bool IndexMacrosInPreprocessor = false;
+ // Has no effect if IndexFunctionLocals are false.
+ bool IndexParametersInDeclarations = false;
+ bool IndexTemplateParameters = false;
+};
+
+} // namespace index
+} // namespace clang
+
+#endif // LLVM_CLANG_INDEX_INDEXINGOPTIONS_H
diff --git a/include/clang/Lex/DependencyDirectivesSourceMinimizer.h b/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
index 41641078afe4..d832df6b6146 100644
--- a/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
+++ b/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
@@ -38,6 +38,7 @@ enum TokenKind {
pp_undef,
pp_import,
pp_pragma_import,
+ pp_pragma_once,
pp_include_next,
pp_if,
pp_ifdef,
@@ -46,6 +47,9 @@ enum TokenKind {
pp_else,
pp_endif,
decl_at_import,
+ cxx_export_decl,
+ cxx_module_decl,
+ cxx_import_decl,
pp_eof,
};
@@ -62,6 +66,24 @@ struct Token {
Token(TokenKind K, int Offset) : K(K), Offset(Offset) {}
};
+/// Simplified token range to track the range of a potentially skippable PP
+/// directive.
+struct SkippedRange {
+ /// Offset into the output byte stream of where the skipped directive begins.
+ int Offset;
+
+ /// The number of bytes that can be skipped before the preprocessing must
+ /// resume.
+ int Length;
+};
+
+/// Computes the potential source ranges that can be skipped by the preprocessor
+/// when skipping a directive like #if, #ifdef or #elsif.
+///
+/// \returns false on success, true on error.
+bool computeSkippedRanges(ArrayRef<Token> Input,
+ llvm::SmallVectorImpl<SkippedRange> &Range);
+
} // end namespace minimize_source_to_dependency_directives
/// Minimize the input down to the preprocessor directives that might have
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index 7c556ac35175..d526319a68c6 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -36,14 +36,17 @@ public:
LT_HeaderMap
};
private:
- union { // This union is discriminated by isHeaderMap.
+ union DLU { // This union is discriminated by isHeaderMap.
/// Dir - This is the actual directory that we're referring to for a normal
/// directory or a framework.
- const DirectoryEntry *Dir;
+ DirectoryEntryRef Dir;
/// Map - This is the HeaderMap if this is a headermap lookup.
///
const HeaderMap *Map;
+
+ DLU(DirectoryEntryRef Dir) : Dir(Dir) {}
+ DLU(const HeaderMap *Map) : Map(Map) {}
} u;
/// DirCharacteristic - The type of directory this is: this is an instance of
@@ -62,24 +65,18 @@ private:
unsigned SearchedAllModuleMaps : 1;
public:
- /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
- /// 'dir'.
- DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT,
+ /// This ctor *does not take ownership* of 'Dir'.
+ DirectoryLookup(DirectoryEntryRef Dir, SrcMgr::CharacteristicKind DT,
bool isFramework)
- : DirCharacteristic(DT),
- LookupType(isFramework ? LT_Framework : LT_NormalDir),
- IsIndexHeaderMap(false), SearchedAllModuleMaps(false) {
- u.Dir = dir;
- }
+ : u(Dir), DirCharacteristic(DT),
+ LookupType(isFramework ? LT_Framework : LT_NormalDir),
+ IsIndexHeaderMap(false), SearchedAllModuleMaps(false) {}
- /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
- /// 'map'.
- DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT,
+ /// This ctor *does not take ownership* of 'Map'.
+ DirectoryLookup(const HeaderMap *Map, SrcMgr::CharacteristicKind DT,
bool isIndexHeaderMap)
- : DirCharacteristic(DT), LookupType(LT_HeaderMap),
- IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) {
- u.Map = map;
- }
+ : u(Map), DirCharacteristic(DT), LookupType(LT_HeaderMap),
+ IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) {}
/// getLookupType - Return the kind of directory lookup that this is: either a
/// normal directory, a framework path, or a HeaderMap.
@@ -92,13 +89,17 @@ public:
/// getDir - Return the directory that this entry refers to.
///
const DirectoryEntry *getDir() const {
- return isNormalDir() ? u.Dir : nullptr;
+ return isNormalDir() ? &u.Dir.getDirEntry() : nullptr;
}
/// getFrameworkDir - Return the directory that this framework refers to.
///
const DirectoryEntry *getFrameworkDir() const {
- return isFramework() ? u.Dir : nullptr;
+ return isFramework() ? &u.Dir.getDirEntry() : nullptr;
+ }
+
+ Optional<DirectoryEntryRef> getFrameworkDirRef() const {
+ return isFramework() ? Optional<DirectoryEntryRef>(u.Dir) : None;
}
/// getHeaderMap - Return the directory that this entry refers to.
@@ -176,27 +177,20 @@ public:
/// \param [out] MappedName if this is a headermap which maps the filename to
/// a framework include ("Foo.h" -> "Foo/Foo.h"), set the new name to this
/// vector and point Filename to it.
- const FileEntry *LookupFile(StringRef &Filename, HeaderSearch &HS,
- SourceLocation IncludeLoc,
- SmallVectorImpl<char> *SearchPath,
- SmallVectorImpl<char> *RelativePath,
- Module *RequestingModule,
- ModuleMap::KnownHeader *SuggestedModule,
- bool &InUserSpecifiedSystemFramework,
- bool &IsFrameworkFound,
- bool &HasBeenMapped,
- SmallVectorImpl<char> &MappedName) const;
+ Optional<FileEntryRef>
+ LookupFile(StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc,
+ SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,
+ bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName) const;
private:
- const FileEntry *DoFrameworkLookup(
- StringRef Filename, HeaderSearch &HS,
- SmallVectorImpl<char> *SearchPath,
- SmallVectorImpl<char> *RelativePath,
- Module *RequestingModule,
+ Optional<FileEntryRef> DoFrameworkLookup(
+ StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
- bool &InUserSpecifiedSystemFramework,
- bool &IsFrameworkFound) const;
-
+ bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const;
};
} // end namespace clang
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index eca8755d4525..accb061e51ba 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_LEX_HEADERMAP_H
#define LLVM_CLANG_LEX_HEADERMAP_H
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
@@ -21,8 +22,6 @@
namespace clang {
-class FileEntry;
-class FileManager;
struct HMapBucket;
struct HMapHeader;
@@ -78,7 +77,7 @@ public:
/// NULL and the file is found, RawPath will be set to the raw path at which
/// the file was found in the file system. For example, for a search path
/// ".." and a filename "../file.h" this would be "../../file.h".
- const FileEntry *LookupFile(StringRef Filename, FileManager &FM) const;
+ Optional<FileEntryRef> LookupFile(StringRef Filename, FileManager &FM) const;
using HeaderMapImpl::lookupFilename;
using HeaderMapImpl::getFileName;
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index c5e66242444a..0d20dafe2cb1 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -250,12 +250,6 @@ class HeaderSearch {
/// Entity used to look up stored header file information.
ExternalHeaderFileInfoSource *ExternalSource = nullptr;
- // Various statistics we track for performance analysis.
- unsigned NumIncluded = 0;
- unsigned NumMultiIncludeFileOptzn = 0;
- unsigned NumFrameworkLookups = 0;
- unsigned NumSubFrameworkLookups = 0;
-
public:
HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
SourceManager &SourceMgr, DiagnosticsEngine &Diags,
@@ -395,7 +389,7 @@ public:
/// found in any of searched SearchDirs. Will be set to false if a framework
/// is found only through header maps. Doesn't guarantee the requested file is
/// found.
- const FileEntry *LookupFile(
+ Optional<FileEntryRef> LookupFile(
StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
@@ -410,7 +404,7 @@ public:
/// within ".../Carbon.framework/Headers/Carbon.h", check to see if
/// HIToolbox is a subframework within Carbon.framework. If so, return
/// the FileEntry for the designated file, otherwise return null.
- const FileEntry *LookupSubframeworkHeader(
+ Optional<FileEntryRef> LookupSubframeworkHeader(
StringRef Filename, const FileEntry *ContextFileEnt,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
@@ -544,8 +538,6 @@ public:
const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir,
bool IsFramework);
- void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
-
/// Determine whether there is a module map that may map the header
/// with the given file name to a (sub)module.
/// Always returns false if modules are disabled.
@@ -649,7 +641,7 @@ private:
/// Look up the file with the specified name and determine its owning
/// module.
- const FileEntry *
+ Optional<FileEntryRef>
getFileAndSuggestModule(StringRef FileName, SourceLocation IncludeLoc,
const DirectoryEntry *Dir, bool IsSystemHeaderDir,
Module *RequestingModule,
diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index ed128bce485f..5c19a41986b5 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -11,6 +11,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/CachedHashString.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
#include <cstdint>
@@ -195,6 +196,10 @@ public:
/// Whether to validate system input files when a module is loaded.
unsigned ModulesValidateSystemHeaders : 1;
+ // Whether the content of input files should be hashed and used to
+ // validate consistency.
+ unsigned ValidateASTInputFilesContent : 1;
+
/// Whether the module includes debug information (-gmodules).
unsigned UseDebugInfo : 1;
@@ -202,14 +207,23 @@ public:
unsigned ModulesHashContent : 1;
+ /// Whether we should include all things that could impact the module in the
+ /// hash.
+ ///
+ /// This includes things like the full header search path, and enabled
+ /// diagnostics.
+ unsigned ModulesStrictContextHash : 1;
+
HeaderSearchOptions(StringRef _Sysroot = "/")
: Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false),
ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false),
UseBuiltinIncludes(true), UseStandardSystemIncludes(true),
UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false),
ModulesValidateOncePerBuildSession(false),
- ModulesValidateSystemHeaders(false), UseDebugInfo(false),
- ModulesValidateDiagnosticOptions(true), ModulesHashContent(false) {}
+ ModulesValidateSystemHeaders(false),
+ ValidateASTInputFilesContent(false), UseDebugInfo(false),
+ ModulesValidateDiagnosticOptions(true), ModulesHashContent(false),
+ ModulesStrictContextHash(false) {}
/// AddPath - Add the \p Path path to the specified \p Group list.
void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
@@ -233,6 +247,15 @@ public:
}
};
+inline llvm::hash_code hash_value(const HeaderSearchOptions::Entry &E) {
+ return llvm::hash_combine(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot);
+}
+
+inline llvm::hash_code
+hash_value(const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
+ return llvm::hash_combine(SHP.Prefix, SHP.IsSystemHeader);
+}
+
} // namespace clang
#endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 69cfe62e4bdb..97a222f4a703 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -265,6 +265,21 @@ public:
/// Return the current location in the buffer.
const char *getBufferLocation() const { return BufferPtr; }
+ /// Returns the current lexing offset.
+ unsigned getCurrentBufferOffset() {
+ assert(BufferPtr >= BufferStart && "Invalid buffer state");
+ return BufferPtr - BufferStart;
+ }
+
+ /// Skip over \p NumBytes bytes.
+ ///
+ /// If the skip is successful, the next token will be lexed from the new
+ /// offset. The lexer also assumes that we skipped to the start of the line.
+ ///
+ /// \returns true if the skip failed (new offset would have been past the
+ /// end of the buffer), false otherwise.
+ bool skipOver(unsigned NumBytes);
+
/// Stringify - Convert the specified string into a C string by i) escaping
/// '\\' and " characters and ii) replacing newline character(s) with "\\n".
/// If Charify is true, this escapes the ' character instead of ".
diff --git a/include/clang/Lex/MacroArgs.h b/include/clang/Lex/MacroArgs.h
index 8806f2d8c656..59676c30e0a5 100644
--- a/include/clang/Lex/MacroArgs.h
+++ b/include/clang/Lex/MacroArgs.h
@@ -48,10 +48,6 @@ class MacroArgs final
/// stream.
std::vector<std::vector<Token> > PreExpArgTokens;
- /// StringifiedArgs - This contains arguments in 'stringified' form. If the
- /// stringified form of an argument has not yet been computed, this is empty.
- std::vector<Token> StringifiedArgs;
-
/// ArgCache - This is a linked list of MacroArgs objects that the
/// Preprocessor owns which we use to avoid thrashing malloc/free.
MacroArgs *ArgCache;
@@ -94,12 +90,6 @@ public:
const std::vector<Token> &
getPreExpArgument(unsigned Arg, Preprocessor &PP);
- /// getStringifiedArgument - Compute, cache, and return the specified argument
- /// that has been 'stringified' as required by the # operator.
- const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP,
- SourceLocation ExpansionLocStart,
- SourceLocation ExpansionLocEnd);
-
/// getNumMacroArguments - Return the number of arguments the invoked macro
/// expects.
unsigned getNumMacroArguments() const { return NumMacroArgs; }
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index f3f3796b1a30..1edcb567de66 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -57,10 +57,9 @@ public:
/// \param FilenameTok The file name token in \#include "FileName" directive
/// or macro expanded file name token from \#include MACRO(PARAMS) directive.
/// Note that FilenameTok contains corresponding quotes/angles symbols.
- virtual void FileSkipped(const FileEntry &SkippedFile,
+ virtual void FileSkipped(const FileEntryRef &SkippedFile,
const Token &FilenameTok,
- SrcMgr::CharacteristicKind FileType) {
- }
+ SrcMgr::CharacteristicKind FileType) {}
/// Callback invoked whenever an inclusion directive results in a
/// file-not-found error.
@@ -308,7 +307,7 @@ public:
/// Hook called when a '__has_include' or '__has_include_next' directive is
/// read.
virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
- const FileEntry *File,
+ Optional<FileEntryRef> File,
SrcMgr::CharacteristicKind FileType) {}
/// Hook called when a source range is skipped.
@@ -390,8 +389,7 @@ public:
Second->FileChanged(Loc, Reason, FileType, PrevFID);
}
- void FileSkipped(const FileEntry &SkippedFile,
- const Token &FilenameTok,
+ void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
SrcMgr::CharacteristicKind FileType) override {
First->FileSkipped(SkippedFile, FilenameTok, FileType);
Second->FileSkipped(SkippedFile, FilenameTok, FileType);
@@ -491,7 +489,7 @@ public:
}
void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
- const FileEntry *File,
+ Optional<FileEntryRef> File,
SrcMgr::CharacteristicKind FileType) override {
First->HasInclude(Loc, FileName, IsAngled, File, FileType);
Second->HasInclude(Loc, FileName, IsAngled, File, FileType);
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index f65b0cda462f..1bdd2be04c0e 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -28,6 +28,7 @@
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
@@ -370,9 +371,9 @@ class Preprocessor {
/// it expects a '.' or ';'.
bool ModuleImportExpectsIdentifier = false;
- /// The source location of the currently-active
+ /// The identifier and source location of the currently-active
/// \#pragma clang arc_cf_code_audited begin.
- SourceLocation PragmaARCCFCodeAuditedLoc;
+ std::pair<IdentifierInfo *, SourceLocation> PragmaARCCFCodeAuditedInfo;
/// The source location of the currently-active
/// \#pragma clang assume_nonnull begin.
@@ -994,7 +995,7 @@ public:
PPCallbacks *getPPCallbacks() const { return Callbacks.get(); }
void addPPCallbacks(std::unique_ptr<PPCallbacks> C) {
if (Callbacks)
- C = llvm::make_unique<PPChainedCallbacks>(std::move(C),
+ C = std::make_unique<PPChainedCallbacks>(std::move(C),
std::move(Callbacks));
Callbacks = std::move(C);
}
@@ -1471,7 +1472,7 @@ public:
if (LexLevel) {
// It's not correct in general to enter caching lex mode while in the
// middle of a nested lexing action.
- auto TokCopy = llvm::make_unique<Token[]>(1);
+ auto TokCopy = std::make_unique<Token[]>(1);
TokCopy[0] = Tok;
EnterTokenStream(std::move(TokCopy), 1, true, IsReinject);
} else {
@@ -1601,14 +1602,16 @@ public:
/// arc_cf_code_audited begin.
///
/// Returns an invalid location if there is no such pragma active.
- SourceLocation getPragmaARCCFCodeAuditedLoc() const {
- return PragmaARCCFCodeAuditedLoc;
+ std::pair<IdentifierInfo *, SourceLocation>
+ getPragmaARCCFCodeAuditedInfo() const {
+ return PragmaARCCFCodeAuditedInfo;
}
/// Set the location of the currently-active \#pragma clang
/// arc_cf_code_audited begin. An invalid location ends the pragma.
- void setPragmaARCCFCodeAuditedLoc(SourceLocation Loc) {
- PragmaARCCFCodeAuditedLoc = Loc;
+ void setPragmaARCCFCodeAuditedInfo(IdentifierInfo *Ident,
+ SourceLocation Loc) {
+ PragmaARCCFCodeAuditedInfo = {Ident, Loc};
}
/// The location of the currently-active \#pragma clang
@@ -1949,17 +1952,15 @@ public:
/// Given a "foo" or \<foo> reference, look up the indicated file.
///
- /// Returns null on failure. \p isAngled indicates whether the file
+ /// Returns None on failure. \p isAngled indicates whether the file
/// reference is for system \#include's or not (i.e. using <> instead of "").
- const FileEntry *LookupFile(SourceLocation FilenameLoc, StringRef Filename,
- bool isAngled, const DirectoryLookup *FromDir,
- const FileEntry *FromFile,
- const DirectoryLookup *&CurDir,
- SmallVectorImpl<char> *SearchPath,
- SmallVectorImpl<char> *RelativePath,
- ModuleMap::KnownHeader *SuggestedModule,
- bool *IsMapped, bool *IsFrameworkFound,
- bool SkipCache = false);
+ Optional<FileEntryRef>
+ LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
+ const DirectoryLookup *FromDir, const FileEntry *FromFile,
+ const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath,
+ ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped,
+ bool *IsFrameworkFound, bool SkipCache = false);
/// Get the DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable.
@@ -2202,6 +2203,15 @@ private:
}
};
+ Optional<FileEntryRef> LookupHeaderIncludeOrImport(
+ const DirectoryLookup *&CurDir, StringRef Filename,
+ SourceLocation FilenameLoc, CharSourceRange FilenameRange,
+ const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
+ bool &IsMapped, const DirectoryLookup *LookupFrom,
+ const FileEntry *LookupFromFile, StringRef LookupFilename,
+ SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath,
+ ModuleMap::KnownHeader &SuggestedModule, bool isAngled);
+
// File inclusion.
void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok,
const DirectoryLookup *LookupFrom = nullptr,
@@ -2313,6 +2323,15 @@ public:
/// A macro is used, update information about macros that need unused
/// warnings.
void markMacroAsUsed(MacroInfo *MI);
+
+private:
+ Optional<unsigned>
+ getSkippedRangeForExcludedConditionalBlock(SourceLocation HashLoc);
+
+ /// Contains the currently active skipped range mappings for skipping excluded
+ /// conditional directives.
+ ExcludedPreprocessorDirectiveSkipMapping
+ *ExcludedConditionalDirectiveSkipMappings;
};
/// Abstract base class that describes a handler that will receive
diff --git a/include/clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h b/include/clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h
new file mode 100644
index 000000000000..893b7ba7a9f5
--- /dev/null
+++ b/include/clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h
@@ -0,0 +1,31 @@
+//===- PreprocessorExcludedConditionalDirectiveSkipMapping.h - --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSOR_EXCLUDED_COND_DIRECTIVE_SKIP_MAPPING_H
+#define LLVM_CLANG_LEX_PREPROCESSOR_EXCLUDED_COND_DIRECTIVE_SKIP_MAPPING_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+
+/// A mapping from an offset into a buffer to the number of bytes that can be
+/// skipped by the preprocessor when skipping over excluded conditional
+/// directive ranges.
+using PreprocessorSkippedRangeMapping = llvm::DenseMap<unsigned, unsigned>;
+
+/// The datastructure that holds the mapping between the active memory buffers
+/// and the individual skip mappings.
+using ExcludedPreprocessorDirectiveSkipMapping =
+ llvm::DenseMap<const llvm::MemoryBuffer *,
+ const PreprocessorSkippedRangeMapping *>;
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_LEX_PREPROCESSOR_EXCLUDED_COND_DIRECTIVE_SKIP_MAPPING_H
diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h
index 1480548c7fbe..344afa894172 100644
--- a/include/clang/Lex/PreprocessorOptions.h
+++ b/include/clang/Lex/PreprocessorOptions.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
#include "clang/Basic/LLVM.h"
+#include "clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include <memory>
@@ -142,6 +143,9 @@ public:
/// compiler invocation and its buffers will be reused.
bool RetainRemappedFileBuffers = false;
+ /// When enabled, excluded conditional blocks retain in the main file.
+ bool RetainExcludedConditionalBlocks = false;
+
/// The Objective-C++ ARC standard library that we should support,
/// by providing appropriate definitions to retrofit the standard library
/// with support for lifetime-qualified pointers.
@@ -169,6 +173,17 @@ public:
/// build it again.
std::shared_ptr<FailedModulesSet> FailedModules;
+ /// Contains the currently active skipped range mappings for skipping excluded
+ /// conditional directives.
+ ///
+ /// The pointer is passed to the Preprocessor when it's constructed. The
+ /// pointer is unowned, the client is responsible for its lifetime.
+ ExcludedPreprocessorDirectiveSkipMapping
+ *ExcludedConditionalDirectiveSkipMappings = nullptr;
+
+ /// Set up preprocessor for RunAnalysis action.
+ bool SetUpStaticAnalyzer = false;
+
public:
PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {}
@@ -201,6 +216,7 @@ public:
RetainRemappedFileBuffers = true;
PrecompiledPreambleBytes.first = 0;
PrecompiledPreambleBytes.second = false;
+ RetainExcludedConditionalBlocks = false;
}
};
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 7c67c35f615a..52d159062cd7 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -766,6 +766,22 @@ private:
Tok.setAnnotationValue(T.getAsOpaquePtr());
}
+ static NamedDecl *getNonTypeAnnotation(const Token &Tok) {
+ return static_cast<NamedDecl*>(Tok.getAnnotationValue());
+ }
+
+ static void setNonTypeAnnotation(Token &Tok, NamedDecl *ND) {
+ Tok.setAnnotationValue(ND);
+ }
+
+ static IdentifierInfo *getIdentifierAnnotation(const Token &Tok) {
+ return static_cast<IdentifierInfo*>(Tok.getAnnotationValue());
+ }
+
+ static void setIdentifierAnnotation(Token &Tok, IdentifierInfo *ND) {
+ Tok.setAnnotationValue(ND);
+ }
+
/// Read an already-translated primary expression out of an annotation
/// token.
static ExprResult getExprAnnotation(const Token &Tok) {
@@ -799,8 +815,7 @@ private:
/// Annotation was successful.
ANK_Success
};
- AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC = nullptr);
+ AnnotatedNameKind TryAnnotateName(CorrectionCandidateCallback *CCC = nullptr);
/// Push a tok::annot_cxxscope token onto the token stream.
void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation);
@@ -972,7 +987,7 @@ private:
};
/// Consume any extra semi-colons until the end of the line.
- void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified);
+ void ConsumeExtraSemi(ExtraSemiKind Kind, DeclSpec::TST T = TST_unspecified);
/// Return false if the next token is an identifier. An 'expected identifier'
/// error is emitted otherwise.
@@ -2107,12 +2122,13 @@ private:
DeclGroupPtrTy ParseDeclaration(DeclaratorContext Context,
SourceLocation &DeclEnd,
- ParsedAttributesWithRange &attrs);
- DeclGroupPtrTy ParseSimpleDeclaration(DeclaratorContext Context,
- SourceLocation &DeclEnd,
- ParsedAttributesWithRange &attrs,
- bool RequireSemi,
- ForRangeInit *FRI = nullptr);
+ ParsedAttributesWithRange &attrs,
+ SourceLocation *DeclSpecStart = nullptr);
+ DeclGroupPtrTy
+ ParseSimpleDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs, bool RequireSemi,
+ ForRangeInit *FRI = nullptr,
+ SourceLocation *DeclSpecStart = nullptr);
bool MightBeDeclarator(DeclaratorContext Context);
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context,
SourceLocation *DeclEnd = nullptr,
@@ -2160,7 +2176,7 @@ private:
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS, DeclSpecContext DSC);
void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
- void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
+ void ParseStructUnionBody(SourceLocation StartLoc, DeclSpec::TST TagType,
Decl *TagDecl);
void ParseStructDeclaration(
@@ -2833,6 +2849,17 @@ private:
DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr,
CachedTokens &Toks,
SourceLocation Loc);
+ /// Parses OpenMP context selectors and calls \p Callback for each
+ /// successfully parsed context selector.
+ bool parseOpenMPContextSelectors(
+ SourceLocation Loc,
+ llvm::function_ref<
+ void(SourceRange, const Sema::OpenMPDeclareVariantCtsSelectorData &)>
+ Callback);
+
+ /// Parse clauses for '#pragma omp declare variant'.
+ void ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr, CachedTokens &Toks,
+ SourceLocation Loc);
/// Parse clauses for '#pragma omp declare target'.
DeclGroupPtrTy ParseOMPDeclareTargetClauses();
/// Parse '#pragma omp end declare target'.
@@ -2926,7 +2953,8 @@ public:
/// Parses simple expression in parens for single-expression clauses of OpenMP
/// constructs.
/// \param RLoc Returned location of right paren.
- ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc);
+ ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc,
+ bool IsAddressOfOperand = false);
/// Data used for parsing list of variables in OpenMP clauses.
struct OpenMPVarListDataTy {
diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h
index 84c5ac3d72ee..c89015e40558 100644
--- a/include/clang/Rewrite/Core/Rewriter.h
+++ b/include/clang/Rewrite/Core/Rewriter.h
@@ -46,6 +46,17 @@ public:
/// If true and removing some text leaves a blank line
/// also remove the empty line (false by default).
+ ///
+ /// FIXME: This sometimes corrupts the file's rewrite buffer due to
+ /// incorrect indexing in the implementation (see the FIXME in
+ /// clang::RewriteBuffer::RemoveText). Moreover, it's inefficient because
+ /// it must scan the buffer from the beginning to find the start of the
+ /// line. When feasible, it's better for the caller to check for a blank
+ /// line and then, if found, expand the removal range to include it.
+ /// Checking for a blank line is easy if, for example, the caller can
+ /// guarantee this is the first edit of a line. In that case, it can just
+ /// scan before and after the removal range until the next newline or
+ /// begin/end of the input.
bool RemoveLineIfEmpty = false;
RewriteOptions() {}
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 96aadeac2ba3..a97a7181f7d5 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -71,6 +71,30 @@ class Sema;
OCD_ViableCandidates
};
+ /// The parameter ordering that will be used for the candidate. This is
+ /// used to represent C++20 binary operator rewrites that reverse the order
+ /// of the arguments. If the parameter ordering is Reversed, the Args list is
+ /// reversed (but obviously the ParamDecls for the function are not).
+ ///
+ /// After forming an OverloadCandidate with reversed parameters, the list
+ /// of conversions will (as always) be indexed by argument, so will be
+ /// in reverse parameter order.
+ enum class OverloadCandidateParamOrder : char { Normal, Reversed };
+
+ /// The kinds of rewrite we perform on overload candidates. Note that the
+ /// values here are chosen to serve as both bitflags and as a rank (lower
+ /// values are preferred by overload resolution).
+ enum OverloadCandidateRewriteKind : unsigned {
+ /// Candidate is not a rewritten candidate.
+ CRK_None = 0x0,
+
+ /// Candidate is a rewritten candidate with a different operator name.
+ CRK_DifferentOperator = 0x1,
+
+ /// Candidate is a rewritten candidate with a reversed order of parameters.
+ CRK_Reversed = 0x2,
+ };
+
/// ImplicitConversionKind - The kind of implicit conversion used to
/// convert an argument to a parameter's type. The enumerator values
/// match with the table titled 'Conversions' in [over.ics.scs] and are listed
@@ -757,7 +781,8 @@ class Sema;
CXXConversionDecl *Surrogate;
/// The conversion sequences used to convert the function arguments
- /// to the function parameters.
+ /// to the function parameters. Note that these are indexed by argument,
+ /// so may not match the parameter order of Function.
ConversionSequenceList Conversions;
/// The FixIt hints which can be used to fix the Bad candidate.
@@ -783,6 +808,9 @@ class Sema;
/// True if the candidate was found using ADL.
CallExpr::ADLCallKind IsADLCandidate : 1;
+ /// Whether this is a rewritten candidate, and if so, of what kind?
+ OverloadCandidateRewriteKind RewriteKind : 2;
+
/// FailureKind - The reason why this candidate is not viable.
/// Actually an OverloadFailureKind.
unsigned char FailureKind;
@@ -826,10 +854,10 @@ class Sema;
unsigned getNumParams() const {
if (IsSurrogate) {
- auto STy = Surrogate->getConversionType();
+ QualType STy = Surrogate->getConversionType();
while (STy->isPointerType() || STy->isReferenceType())
STy = STy->getPointeeType();
- return STy->getAs<FunctionProtoType>()->getNumParams();
+ return STy->castAs<FunctionProtoType>()->getNumParams();
}
if (Function)
return Function->getNumParams();
@@ -838,7 +866,8 @@ class Sema;
private:
friend class OverloadCandidateSet;
- OverloadCandidate() : IsADLCandidate(CallExpr::NotADL) {}
+ OverloadCandidate()
+ : IsADLCandidate(CallExpr::NotADL), RewriteKind(CRK_None) {}
};
/// OverloadCandidateSet - A set of overload candidates, used in C++
@@ -867,9 +896,54 @@ class Sema;
CSK_InitByConstructor,
};
+ /// Information about operator rewrites to consider when adding operator
+ /// functions to a candidate set.
+ struct OperatorRewriteInfo {
+ OperatorRewriteInfo()
+ : OriginalOperator(OO_None), AllowRewrittenCandidates(false) {}
+ OperatorRewriteInfo(OverloadedOperatorKind Op, bool AllowRewritten)
+ : OriginalOperator(Op), AllowRewrittenCandidates(AllowRewritten) {}
+
+ /// The original operator as written in the source.
+ OverloadedOperatorKind OriginalOperator;
+ /// Whether we should include rewritten candidates in the overload set.
+ bool AllowRewrittenCandidates;
+
+ /// Would use of this function result in a rewrite using a different
+ /// operator?
+ bool isRewrittenOperator(const FunctionDecl *FD) {
+ return OriginalOperator &&
+ FD->getDeclName().getCXXOverloadedOperator() != OriginalOperator;
+ }
+
+ bool isAcceptableCandidate(const FunctionDecl *FD) {
+ return AllowRewrittenCandidates || !isRewrittenOperator(FD);
+ }
+
+ /// Determine the kind of rewrite that should be performed for this
+ /// candidate.
+ OverloadCandidateRewriteKind
+ getRewriteKind(const FunctionDecl *FD, OverloadCandidateParamOrder PO) {
+ OverloadCandidateRewriteKind CRK = CRK_None;
+ if (isRewrittenOperator(FD))
+ CRK = OverloadCandidateRewriteKind(CRK | CRK_DifferentOperator);
+ if (PO == OverloadCandidateParamOrder::Reversed)
+ CRK = OverloadCandidateRewriteKind(CRK | CRK_Reversed);
+ return CRK;
+ }
+
+ /// Determine whether we should consider looking for and adding reversed
+ /// candidates for operator Op.
+ bool shouldAddReversed(OverloadedOperatorKind Op);
+
+ /// Determine whether we should add a rewritten candidate for \p FD with
+ /// reversed parameter order.
+ bool shouldAddReversed(ASTContext &Ctx, const FunctionDecl *FD);
+ };
+
private:
SmallVector<OverloadCandidate, 16> Candidates;
- llvm::SmallPtrSet<Decl *, 16> Functions;
+ llvm::SmallPtrSet<uintptr_t, 16> Functions;
// Allocator for ConversionSequenceLists. We store the first few of these
// inline to avoid allocation for small sets.
@@ -877,11 +951,12 @@ class Sema;
SourceLocation Loc;
CandidateSetKind Kind;
+ OperatorRewriteInfo RewriteInfo;
constexpr static unsigned NumInlineBytes =
24 * sizeof(ImplicitConversionSequence);
unsigned NumInlineBytesUsed = 0;
- llvm::AlignedCharArray<alignof(void *), NumInlineBytes> InlineSpace;
+ alignas(void *) char InlineSpace[NumInlineBytes];
// Address space of the object being constructed.
LangAS DestAS = LangAS::Default;
@@ -904,7 +979,7 @@ class Sema;
unsigned NBytes = sizeof(T) * N;
if (NBytes > NumInlineBytes - NumInlineBytesUsed)
return SlabAllocator.Allocate<T>(N);
- char *FreeSpaceStart = InlineSpace.buffer + NumInlineBytesUsed;
+ char *FreeSpaceStart = InlineSpace + NumInlineBytesUsed;
assert(uintptr_t(FreeSpaceStart) % alignof(void *) == 0 &&
"Misaligned storage!");
@@ -915,19 +990,24 @@ class Sema;
void destroyCandidates();
public:
- OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK)
- : Loc(Loc), Kind(CSK) {}
+ OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
+ OperatorRewriteInfo RewriteInfo = {})
+ : Loc(Loc), Kind(CSK), RewriteInfo(RewriteInfo) {}
OverloadCandidateSet(const OverloadCandidateSet &) = delete;
OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
~OverloadCandidateSet() { destroyCandidates(); }
SourceLocation getLocation() const { return Loc; }
CandidateSetKind getKind() const { return Kind; }
+ OperatorRewriteInfo getRewriteInfo() const { return RewriteInfo; }
/// Determine when this overload candidate will be new to the
/// overload set.
- bool isNewCandidate(Decl *F) {
- return Functions.insert(F->getCanonicalDecl()).second;
+ bool isNewCandidate(Decl *F, OverloadCandidateParamOrder PO =
+ OverloadCandidateParamOrder::Normal) {
+ uintptr_t Key = reinterpret_cast<uintptr_t>(F->getCanonicalDecl());
+ Key |= static_cast<uintptr_t>(PO);
+ return Functions.insert(Key).second;
}
/// Clear out all of the candidates.
diff --git a/include/clang/Sema/ParsedAttr.h b/include/clang/Sema/ParsedAttr.h
index d87d5da04acc..d9d8585970d9 100644
--- a/include/clang/Sema/ParsedAttr.h
+++ b/include/clang/Sema/ParsedAttr.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
#include "clang/Basic/AttrSubjectMatchRules.h"
+#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
@@ -114,7 +115,8 @@ using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
///
class ParsedAttr final
- : private llvm::TrailingObjects<
+ : public AttributeCommonInfo,
+ private llvm::TrailingObjects<
ParsedAttr, ArgsUnion, detail::AvailabilityData,
detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
friend TrailingObjects;
@@ -134,54 +136,15 @@ class ParsedAttr final
return IsProperty;
}
-public:
- /// The style used to specify an attribute.
- enum Syntax {
- /// __attribute__((...))
- AS_GNU,
-
- /// [[...]]
- AS_CXX11,
-
- /// [[...]]
- AS_C2x,
-
- /// __declspec(...)
- AS_Declspec,
-
- /// [uuid("...")] class Foo
- AS_Microsoft,
-
- /// __ptr16, alignas(...), etc.
- AS_Keyword,
-
- /// #pragma ...
- AS_Pragma,
-
- // Note TableGen depends on the order above. Do not add or change the order
- // without adding related code to TableGen/ClangAttrEmitter.cpp.
- /// Context-sensitive version of a keyword attribute.
- AS_ContextSensitiveKeyword,
- };
-
private:
- IdentifierInfo *AttrName;
- IdentifierInfo *ScopeName;
IdentifierInfo *MacroII = nullptr;
SourceLocation MacroExpansionLoc;
- SourceRange AttrRange;
- SourceLocation ScopeLoc;
SourceLocation EllipsisLoc;
- unsigned AttrKind : 16;
-
/// The number of expression arguments this attribute has.
/// The expressions themselves are stored after the object.
unsigned NumArgs : 16;
- /// Corresponds to the Syntax enum.
- unsigned SyntaxUsed : 3;
-
/// True if already diagnosed as invalid.
mutable unsigned Invalid : 1;
@@ -239,14 +202,14 @@ private:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed,
SourceLocation ellipsisLoc)
- : 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), HasProcessingCache(false),
- IsPragmaClangAttribute(false) {
- if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
- AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ if (numArgs)
+ memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
}
/// Constructor for availability attributes.
@@ -257,9 +220,9 @@ private:
const AvailabilityChange &obsoleted, SourceLocation unavailable,
const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict,
const Expr *replacementExpr)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
- UsedAsTypeAttr(false), IsAvailability(true),
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
HasProcessingCache(false), IsPragmaClangAttribute(false),
UnavailableLoc(unavailable), MessageExpr(messageExpr) {
@@ -267,7 +230,6 @@ private:
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
new (getAvailabilityData()) detail::AvailabilityData(
introduced, deprecated, obsoleted, strict, replacementExpr);
- AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Constructor for objc_bridge_related attributes.
@@ -275,16 +237,16 @@ private:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false),
- UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
- HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(3), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(false), HasProcessingCache(false),
+ IsPragmaClangAttribute(false) {
ArgsUnion *Args = getArgsBuffer();
Args[0] = Parm1;
Args[1] = Parm2;
Args[2] = Parm3;
- AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Constructor for type_tag_for_datatype attribute.
@@ -292,31 +254,31 @@ private:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierLoc *ArgKind, ParsedType matchingCType,
bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
- UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
- HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(1), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false),
+ HasParsedType(false), HasProcessingCache(false),
+ IsPragmaClangAttribute(false) {
ArgsUnion PVal(ArgKind);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
new (&ExtraData.MatchingCType) ParsedType(matchingCType);
ExtraData.LayoutCompatible = layoutCompatible;
ExtraData.MustBeNull = mustBeNull;
- AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Constructor for attributes with a single type argument.
ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
ParsedType typeArg, Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
- UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
- HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(true), HasProcessingCache(false),
+ IsPragmaClangAttribute(false) {
new (&getTypeBuffer()) ParsedType(typeArg);
- AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Constructor for microsoft __declspec(property) attribute.
@@ -324,13 +286,13 @@ private:
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *getterId, IdentifierInfo *setterId,
Syntax syntaxUsed)
- : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
- ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
- UsedAsTypeAttr(false), IsAvailability(false),
- IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
- HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true),
+ HasParsedType(false), HasProcessingCache(false),
+ IsPragmaClangAttribute(false) {
new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
- AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
/// Type tag information is stored immediately following the arguments, if
@@ -372,27 +334,6 @@ public:
void operator delete(void *) = delete;
- enum Kind {
- #define PARSED_ATTR(NAME) AT_##NAME,
- #include "clang/Sema/AttrParsedAttrList.inc"
- #undef PARSED_ATTR
- IgnoredAttribute,
- UnknownAttribute
- };
-
- IdentifierInfo *getName() const { return AttrName; }
- SourceLocation getLoc() const { return AttrRange.getBegin(); }
- SourceRange getRange() const { return AttrRange; }
-
- bool hasScope() const { return ScopeName; }
- IdentifierInfo *getScopeName() const { return ScopeName; }
- SourceLocation getScopeLoc() const { return ScopeLoc; }
-
- bool isGNUScope() const {
- return ScopeName &&
- (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
- }
-
bool hasParsedType() const { return HasParsedType; }
/// Is this the Microsoft __declspec(property) attribute?
@@ -400,30 +341,6 @@ public:
return IsProperty;
}
- bool isAlignasAttribute() const {
- // FIXME: Use a better mechanism to determine this.
- return getKind() == AT_Aligned && isKeywordAttribute();
- }
-
- bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
- bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
-
- bool isCXX11Attribute() const {
- return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
- }
-
- bool isC2xAttribute() const {
- return SyntaxUsed == AS_C2x;
- }
-
- bool isKeywordAttribute() const {
- return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
- }
-
- bool isContextSensitiveKeywordAttribute() const {
- return SyntaxUsed == AS_ContextSensitiveKeyword;
- }
-
bool isInvalid() const { return Invalid; }
void setInvalid(bool b = true) const { Invalid = b; }
@@ -450,10 +367,6 @@ public:
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
- Kind getKind() const { return Kind(AttrKind); }
- static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
- Syntax SyntaxUsed);
-
/// getNumArgs - Return the number of actual arguments to this attribute.
unsigned getNumArgs() const { return NumArgs; }
@@ -480,54 +393,61 @@ public:
}
const AvailabilityChange &getAvailabilityIntroduced() const {
- assert(getKind() == AT_Availability && "Not an availability attribute");
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
return getAvailabilityData()->Changes[detail::IntroducedSlot];
}
const AvailabilityChange &getAvailabilityDeprecated() const {
- assert(getKind() == AT_Availability && "Not an availability attribute");
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
return getAvailabilityData()->Changes[detail::DeprecatedSlot];
}
const AvailabilityChange &getAvailabilityObsoleted() const {
- assert(getKind() == AT_Availability && "Not an availability attribute");
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
return getAvailabilityData()->Changes[detail::ObsoletedSlot];
}
SourceLocation getStrictLoc() const {
- assert(getKind() == AT_Availability && "Not an availability attribute");
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
return getAvailabilityData()->StrictLoc;
}
SourceLocation getUnavailableLoc() const {
- assert(getKind() == AT_Availability && "Not an availability attribute");
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
return UnavailableLoc;
}
const Expr * getMessageExpr() const {
- assert(getKind() == AT_Availability && "Not an availability attribute");
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
return MessageExpr;
}
const Expr *getReplacementExpr() const {
- assert(getKind() == AT_Availability && "Not an availability attribute");
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
return getAvailabilityData()->Replacement;
}
const ParsedType &getMatchingCType() const {
- assert(getKind() == AT_TypeTagForDatatype &&
+ assert(getParsedKind() == AT_TypeTagForDatatype &&
"Not a type_tag_for_datatype attribute");
return getTypeTagForDatatypeDataSlot().MatchingCType;
}
bool getLayoutCompatible() const {
- assert(getKind() == AT_TypeTagForDatatype &&
+ assert(getParsedKind() == AT_TypeTagForDatatype &&
"Not a type_tag_for_datatype attribute");
return getTypeTagForDatatypeDataSlot().LayoutCompatible;
}
bool getMustBeNull() const {
- assert(getKind() == AT_TypeTagForDatatype &&
+ assert(getParsedKind() == AT_TypeTagForDatatype &&
"Not a type_tag_for_datatype attribute");
return getTypeTagForDatatypeDataSlot().MustBeNull;
}
@@ -570,11 +490,6 @@ public:
return MacroExpansionLoc;
}
- /// Get an index into the attribute spelling list
- /// defined in Attr.td. This index is used by an attribute
- /// to pretty print itself.
- unsigned getAttributeSpellingListIndex() const;
-
bool isTargetSpecificAttr() const;
bool isTypeAttr() const;
bool isStmtAttr() const;
@@ -603,7 +518,7 @@ public:
/// If this is an OpenCL addr space attribute returns its representation
/// in LangAS, otherwise returns default addr space.
LangAS asOpenCLLangAS() const {
- switch (getKind()) {
+ switch (getParsedKind()) {
case ParsedAttr::AT_OpenCLConstantAddressSpace:
return LangAS::opencl_constant;
case ParsedAttr::AT_OpenCLGlobalAddressSpace:
@@ -618,6 +533,8 @@ public:
return LangAS::Default;
}
}
+
+ AttributeCommonInfo::Kind getKind() const { return getParsedKind(); }
};
class AttributePool;
@@ -889,8 +806,9 @@ public:
}
bool hasAttribute(ParsedAttr::Kind K) const {
- return llvm::any_of(
- AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; });
+ return llvm::any_of(AttrList, [K](const ParsedAttr *AL) {
+ return AL->getParsedKind() == K;
+ });
}
private:
@@ -1038,28 +956,28 @@ enum AttributeDeclKind {
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const ParsedAttr &At) {
- DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getAttrName()),
DiagnosticsEngine::ak_identifierinfo);
return DB;
}
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const ParsedAttr &At) {
- PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getAttrName()),
DiagnosticsEngine::ak_identifierinfo);
return PD;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const ParsedAttr *At) {
- DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getAttrName()),
DiagnosticsEngine::ak_identifierinfo);
return DB;
}
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const ParsedAttr *At) {
- PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getAttrName()),
DiagnosticsEngine::ak_identifierinfo);
return PD;
}
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index ea2595113d58..4f7534f9ef1a 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -756,13 +756,16 @@ public:
unsigned short CapRegionKind;
unsigned short OpenMPLevel;
+ unsigned short OpenMPCaptureLevel;
CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
RecordDecl *RD, ImplicitParamDecl *Context,
- CapturedRegionKind K, unsigned OpenMPLevel)
+ CapturedRegionKind K, unsigned OpenMPLevel,
+ unsigned OpenMPCaptureLevel)
: CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
- ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel) {
+ ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel),
+ OpenMPCaptureLevel(OpenMPCaptureLevel) {
Kind = SK_CapturedRegion;
}
@@ -817,6 +820,9 @@ public:
/// Whether the lambda contains an unexpanded parameter pack.
bool ContainsUnexpandedParameterPack = false;
+ /// Packs introduced by this lambda, if any.
+ SmallVector<NamedDecl*, 4> LocalPacks;
+
/// If this is a generic lambda, use this as the depth of
/// each 'auto' parameter, during initial AST construction.
unsigned AutoTemplateParameterDepth = 0;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index af762f74d745..a911c61a07f8 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -57,6 +57,7 @@
#include <deque>
#include <memory>
#include <string>
+#include <tuple>
#include <vector>
namespace llvm {
@@ -158,6 +159,8 @@ namespace clang {
class OMPClause;
struct OMPVarListLocTy;
struct OverloadCandidate;
+ enum class OverloadCandidateParamOrder : char;
+ enum OverloadCandidateRewriteKind : unsigned;
class OverloadCandidateSet;
class OverloadExpr;
class ParenListExpr;
@@ -405,13 +408,20 @@ public:
/// Source location for newly created implicit MSInheritanceAttrs
SourceLocation ImplicitMSInheritanceAttrLoc;
+ /// Holds TypoExprs that are created from `createDelayedTypo`. This is used by
+ /// `TransformTypos` in order to keep track of any TypoExprs that are created
+ /// recursively during typo correction and wipe them away if the correction
+ /// fails.
+ llvm::SmallVector<TypoExpr *, 2> TypoExprs;
+
/// pragma clang section kind
enum PragmaClangSectionKind {
PCSK_Invalid = 0,
PCSK_BSS = 1,
PCSK_Data = 2,
PCSK_Rodata = 3,
- PCSK_Text = 4
+ PCSK_Text = 4,
+ PCSK_Relro = 5
};
enum PragmaClangSectionAction {
@@ -432,6 +442,7 @@ public:
PragmaClangSection PragmaClangBSSSection;
PragmaClangSection PragmaClangDataSection;
PragmaClangSection PragmaClangRodataSection;
+ PragmaClangSection PragmaClangRelroSection;
PragmaClangSection PragmaClangTextSection;
enum PragmaMsStackAction {
@@ -1039,13 +1050,6 @@ public:
/// suffice, e.g., in a default function argument.
Decl *ManglingContextDecl;
- /// The context information used to mangle lambda expressions
- /// and block literals within this context.
- ///
- /// This mangling information is allocated lazily, since most contexts
- /// do not have lambda expressions or block literals.
- std::unique_ptr<MangleNumberingContext> MangleNumbering;
-
/// If we are processing a decltype type, a set of call expressions
/// for which we have deferred checking the completeness of the return type.
SmallVector<CallExpr *, 8> DelayedDecltypeCalls;
@@ -1056,6 +1060,11 @@ public:
llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
+ /// Expressions appearing as the LHS of a volatile assignment in this
+ /// context. We produce a warning for these when popping the context if
+ /// they are not discarded-value expressions nor unevaluated operands.
+ SmallVector<Expr*, 2> VolatileAssignmentLHSs;
+
/// \brief Describes whether we are in an expression constext which we have
/// to handle differently.
enum ExpressionKind {
@@ -1069,12 +1078,7 @@ public:
ExpressionKind ExprContext)
: Context(Context), ParentCleanup(ParentCleanup),
NumCleanupObjects(NumCleanupObjects), NumTypos(0),
- ManglingContextDecl(ManglingContextDecl), MangleNumbering(),
- ExprContext(ExprContext) {}
-
- /// Retrieve the mangling numbering context, used to consistently
- /// number constructs like lambdas for mangling.
- MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx);
+ ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext) {}
bool isUnevaluated() const {
return Context == ExpressionEvaluationContext::Unevaluated ||
@@ -1093,15 +1097,12 @@ public:
void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
/// Compute the mangling number context for a lambda expression or
- /// block literal.
+ /// block literal. Also return the extra mangling decl if any.
///
/// \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);
+ std::tuple<MangleNumberingContext *, Decl *>
+ getCurrentMangleNumberContext(const DeclContext *DC);
/// SpecialMemberOverloadResult - The overloading result for a special member
@@ -1272,6 +1273,8 @@ public:
void addImplicitTypedef(StringRef Name, QualType T);
+ bool WarnedStackExhausted = false;
+
public:
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind = TU_Complete,
@@ -1303,6 +1306,16 @@ public:
void PrintStats() const;
+ /// Warn that the stack is nearly exhausted.
+ void warnStackExhausted(SourceLocation Loc);
+
+ /// Run some code with "sufficient" stack space. (Currently, at least 256K is
+ /// guaranteed). Produces a warning if we're low on stack space and allocates
+ /// more in that case. Use this in code that may recurse deeply (for example,
+ /// in template instantiation) to avoid stack overflow.
+ void runWithSufficientStackSpace(SourceLocation Loc,
+ llvm::function_ref<void()> Fn);
+
/// Helper class that creates diagnostics with optional
/// template instantiation stacks.
///
@@ -1415,8 +1428,8 @@ public:
void RecordParsingTemplateParameterDepth(unsigned Depth);
void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
- RecordDecl *RD,
- CapturedRegionKind K);
+ RecordDecl *RD, CapturedRegionKind K,
+ unsigned OpenMPCaptureLevel = 0);
/// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
/// time after they've been popped.
@@ -1456,6 +1469,11 @@ public:
/// Retrieve the current block, if any.
sema::BlockScopeInfo *getCurBlock();
+ /// Get the innermost lambda enclosing the current location, if any. This
+ /// looks through intervening non-lambda scopes such as local functions and
+ /// blocks.
+ sema::LambdaScopeInfo *getEnclosingLambda() const;
+
/// Retrieve the current lambda scope info, if any.
/// \param IgnoreNonLambdaCapturingScope true if should find the top-most
/// lambda scope info ignoring all inner capturing scopes that are not
@@ -1499,6 +1517,8 @@ public:
QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
SourceLocation AttrLoc);
+ bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
+
bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
/// Build a function type.
@@ -1621,7 +1641,7 @@ public:
template <std::size_t... Is>
void emit(const SemaDiagnosticBuilder &DB,
- llvm::index_sequence<Is...>) const {
+ std::index_sequence<Is...>) const {
// Apply all tuple elements to the builder in order.
bool Dummy[] = {false, (DB << getPrintable(std::get<Is>(Args)))...};
(void)Dummy;
@@ -1635,7 +1655,7 @@ public:
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
- emit(DB, llvm::index_sequence_for<Ts...>());
+ emit(DB, std::index_sequence_for<Ts...>());
DB << T;
}
};
@@ -1839,29 +1859,52 @@ public:
/// Describes the result of the name lookup and resolution performed
/// by \c ClassifyName().
enum NameClassificationKind {
+ /// This name is not a type or template in this context, but might be
+ /// something else.
NC_Unknown,
+ /// Classification failed; an error has been produced.
NC_Error,
+ /// The name has been typo-corrected to a keyword.
NC_Keyword,
+ /// The name was classified as a type.
NC_Type,
- NC_Expression,
- NC_NestedNameSpecifier,
+ /// The name was classified as a specific non-type, non-template
+ /// declaration. ActOnNameClassifiedAsNonType should be called to
+ /// convert the declaration to an expression.
+ NC_NonType,
+ /// The name was classified as an ADL-only function name.
+ /// ActOnNameClassifiedAsUndeclaredNonType should be called to convert the
+ /// result to an expression.
+ NC_UndeclaredNonType,
+ /// The name denotes a member of a dependent type that could not be
+ /// resolved. ActOnNameClassifiedAsDependentNonType should be called to
+ /// convert the result to an expression.
+ NC_DependentNonType,
+ /// The name was classified as a non-type, and an expression representing
+ /// that name has been formed.
+ NC_ContextIndependentExpr,
+ /// The name was classified as a template whose specializations are types.
NC_TypeTemplate,
+ /// The name was classified as a variable template name.
NC_VarTemplate,
+ /// The name was classified as a function template name.
NC_FunctionTemplate,
+ /// The name was classified as an ADL-only function template name.
NC_UndeclaredTemplate,
};
class NameClassification {
NameClassificationKind Kind;
- ExprResult Expr;
- TemplateName Template;
- ParsedType Type;
+ union {
+ ExprResult Expr;
+ NamedDecl *NonTypeDecl;
+ TemplateName Template;
+ ParsedType Type;
+ };
explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {}
public:
- NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {}
-
NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {}
NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {}
@@ -1874,8 +1917,24 @@ public:
return NameClassification(NC_Unknown);
}
- static NameClassification NestedNameSpecifier() {
- return NameClassification(NC_NestedNameSpecifier);
+ static NameClassification ContextIndependentExpr(ExprResult E) {
+ NameClassification Result(NC_ContextIndependentExpr);
+ Result.Expr = E;
+ return Result;
+ }
+
+ static NameClassification NonType(NamedDecl *D) {
+ NameClassification Result(NC_NonType);
+ Result.NonTypeDecl = D;
+ return Result;
+ }
+
+ static NameClassification UndeclaredNonType() {
+ return NameClassification(NC_UndeclaredNonType);
+ }
+
+ static NameClassification DependentNonType() {
+ return NameClassification(NC_DependentNonType);
}
static NameClassification TypeTemplate(TemplateName Name) {
@@ -1904,14 +1963,19 @@ public:
NameClassificationKind getKind() const { return Kind; }
+ ExprResult getExpression() const {
+ assert(Kind == NC_ContextIndependentExpr);
+ return Expr;
+ }
+
ParsedType getType() const {
assert(Kind == NC_Type);
return Type;
}
- ExprResult getExpression() const {
- assert(Kind == NC_Expression);
- return Expr;
+ NamedDecl *getNonTypeDecl() const {
+ assert(Kind == NC_NonType);
+ return NonTypeDecl;
}
TemplateName getTemplateName() const {
@@ -1955,17 +2019,29 @@ public:
/// \param NextToken The token following the identifier. Used to help
/// disambiguate the name.
///
- /// \param IsAddressOfOperand True if this name is the operand of a unary
- /// address of ('&') expression, assuming it is classified as an
- /// expression.
- ///
/// \param CCC The correction callback, if typo correction is desired.
NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS,
IdentifierInfo *&Name, SourceLocation NameLoc,
const Token &NextToken,
- bool IsAddressOfOperand,
CorrectionCandidateCallback *CCC = nullptr);
+ /// Act on the result of classifying a name as an undeclared (ADL-only)
+ /// non-type declaration.
+ ExprResult ActOnNameClassifiedAsUndeclaredNonType(IdentifierInfo *Name,
+ SourceLocation NameLoc);
+ /// Act on the result of classifying a name as an undeclared member of a
+ /// dependent base class.
+ ExprResult ActOnNameClassifiedAsDependentNonType(const CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsAddressOfOperand);
+ /// Act on the result of classifying a name as a specific non-type
+ /// declaration.
+ ExprResult ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS,
+ NamedDecl *Found,
+ SourceLocation NameLoc,
+ const Token &NextToken);
+
/// Describes the detailed kind of a template name. Used in diagnostics.
enum class TemplateNameKindForDiagnostics {
ClassTemplate,
@@ -2076,8 +2152,16 @@ public:
bool &AddToScope);
bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
- bool CheckConstexprFunctionDecl(const FunctionDecl *FD);
- bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body);
+ enum class CheckConstexprKind {
+ /// Diagnose issues that are non-constant or that are extensions.
+ Diagnose,
+ /// Identify whether this function satisfies the formal rules for constexpr
+ /// functions in the current lanugage mode (with no extensions).
+ CheckValid
+ };
+
+ bool CheckConstexprFunctionDefinition(const FunctionDecl *FD,
+ CheckConstexprKind Kind);
void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
void FindHiddenVirtualMethods(CXXMethodDecl *MD,
@@ -2634,48 +2718,44 @@ public:
};
/// Attribute merging methods. Return true if a new attribute was added.
- AvailabilityAttr *mergeAvailabilityAttr(
- NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, bool Implicit,
- VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted,
- bool IsUnavailable, StringRef Message, bool IsStrict,
- StringRef Replacement, AvailabilityMergeKind AMK, int Priority,
- unsigned AttrSpellingListIndex);
- TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
- TypeVisibilityAttr::VisibilityType Vis,
- unsigned AttrSpellingListIndex);
- VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range,
- VisibilityAttr::VisibilityType Vis,
- unsigned AttrSpellingListIndex);
- UuidAttr *mergeUuidAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex, StringRef Uuid);
- DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex);
- DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex);
+ AvailabilityAttr *
+ mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI,
+ IdentifierInfo *Platform, bool Implicit,
+ VersionTuple Introduced, VersionTuple Deprecated,
+ VersionTuple Obsoleted, bool IsUnavailable,
+ StringRef Message, bool IsStrict, StringRef Replacement,
+ AvailabilityMergeKind AMK, int Priority);
+ TypeVisibilityAttr *
+ mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
+ TypeVisibilityAttr::VisibilityType Vis);
+ VisibilityAttr *mergeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
+ VisibilityAttr::VisibilityType Vis);
+ UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef Uuid);
+ DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI);
+ DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI);
MSInheritanceAttr *
- mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
- unsigned AttrSpellingListIndex,
+ mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI, bool BestCase,
MSInheritanceAttr::Spelling SemanticSpelling);
- FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range,
+ FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
IdentifierInfo *Format, int FormatIdx,
- int FirstArg, unsigned AttrSpellingListIndex);
- SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
- unsigned AttrSpellingListIndex);
- CodeSegAttr *mergeCodeSegAttr(Decl *D, SourceRange Range, StringRef Name,
- unsigned AttrSpellingListIndex);
- AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
- IdentifierInfo *Ident,
- unsigned AttrSpellingListIndex);
- MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex);
+ int FirstArg);
+ SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef Name);
+ CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef Name);
+ AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D,
+ const AttributeCommonInfo &CI,
+ const IdentifierInfo *Ident);
+ MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
NoSpeculativeLoadHardeningAttr *
mergeNoSpeculativeLoadHardeningAttr(Decl *D,
const NoSpeculativeLoadHardeningAttr &AL);
SpeculativeLoadHardeningAttr *
mergeSpeculativeLoadHardeningAttr(Decl *D,
const SpeculativeLoadHardeningAttr &AL);
- OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex);
+ OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
+ const AttributeCommonInfo &CI);
InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D,
const InternalLinkageAttr &AL);
@@ -2786,6 +2866,9 @@ public:
Expr *Value,
bool AllowNRVO = true);
+ bool CanPerformAggregateInitializationForOverloadResolution(
+ const InitializedEntity &Entity, InitListExpr *From);
+
bool CanPerformCopyInitialization(const InitializedEntity &Entity,
ExprResult Init);
ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
@@ -2938,7 +3021,8 @@ public:
bool AllowExplicit = true,
bool AllowExplicitConversion = false,
ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
- ConversionSequenceList EarlyConversions = None);
+ ConversionSequenceList EarlyConversions = None,
+ OverloadCandidateParamOrder PO = {});
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
@@ -2951,7 +3035,8 @@ public:
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversion = false);
+ bool SuppressUserConversion = false,
+ OverloadCandidateParamOrder PO = {});
void AddMethodCandidate(CXXMethodDecl *Method,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
@@ -2960,7 +3045,8 @@ public:
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false,
- ConversionSequenceList EarlyConversions = None);
+ ConversionSequenceList EarlyConversions = None,
+ OverloadCandidateParamOrder PO = {});
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
@@ -2970,23 +3056,22 @@ public:
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
- bool PartialOverloading = false);
+ bool PartialOverloading = false,
+ OverloadCandidateParamOrder PO = {});
void AddTemplateOverloadCandidate(
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
bool PartialOverloading = false, bool AllowExplicit = true,
- ADLCallKind IsADLCandidate = ADLCallKind::NotADL);
- bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
- ArrayRef<QualType> ParamTypes,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- ConversionSequenceList &Conversions,
- bool SuppressUserConversions,
- CXXRecordDecl *ActingContext = nullptr,
- QualType ObjectType = QualType(),
- Expr::Classification
- ObjectClassification = {});
+ ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
+ OverloadCandidateParamOrder PO = {});
+ bool CheckNonDependentConversions(
+ FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes,
+ ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet,
+ ConversionSequenceList &Conversions, bool SuppressUserConversions,
+ CXXRecordDecl *ActingContext = nullptr, QualType ObjectType = QualType(),
+ Expr::Classification ObjectClassification = {},
+ OverloadCandidateParamOrder PO = {});
void AddConversionCandidate(
CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
@@ -3003,10 +3088,14 @@ public:
const FunctionProtoType *Proto,
Expr *Object, ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet);
+ void AddNonMemberOperatorCandidates(
+ const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
SourceLocation OpLoc, ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- SourceRange OpRange = SourceRange());
+ OverloadCandidateSet &CandidateSet,
+ OverloadCandidateParamOrder PO = {});
void AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool IsAssignmentOperator = false,
@@ -3022,9 +3111,10 @@ public:
bool PartialOverloading = false);
// Emit as a 'note' the specific overload candidate
- void NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
- QualType DestType = QualType(),
- bool TakingAddress = false);
+ void NoteOverloadCandidate(
+ NamedDecl *Found, FunctionDecl *Fn,
+ OverloadCandidateRewriteKind RewriteKind = OverloadCandidateRewriteKind(),
+ QualType DestType = QualType(), bool TakingAddress = false);
// Emit as a series of 'note's all template and non-templates identified by
// the expression Expr
@@ -3156,7 +3246,8 @@ public:
BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS,
- bool RequiresADL = true);
+ bool RequiresADL = true,
+ bool AllowRewrittenCandidates = true);
ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
SourceLocation RLoc,
@@ -3384,6 +3475,7 @@ public:
LookupNameKind NameKind,
RedeclarationKind Redecl
= NotForRedeclaration);
+ bool LookupBuiltin(LookupResult &R);
bool LookupName(LookupResult &R, Scope *S,
bool AllowBuiltinCreation = false);
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
@@ -3426,6 +3518,19 @@ public:
bool DiagnoseMissing);
bool isKnownName(StringRef name);
+ /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
+ enum class FunctionEmissionStatus {
+ Emitted,
+ CUDADiscarded, // Discarded due to CUDA/HIP hostness
+ OMPDiscarded, // Discarded due to OpenMP hostness
+ TemplateDiscarded, // Discarded due to uninstantiated templates
+ Unknown,
+ };
+ FunctionEmissionStatus getEmissionStatus(FunctionDecl *Decl);
+
+ // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
+ bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
+
void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
ArrayRef<Expr *> Args, ADLResult &Functions);
@@ -4007,7 +4112,8 @@ public:
typedef std::pair<StringRef, QualType> CapturedParamNameType;
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
CapturedRegionKind Kind,
- ArrayRef<CapturedParamNameType> Params);
+ ArrayRef<CapturedParamNameType> Params,
+ unsigned OpenMPCaptureLevel = 0);
StmtResult ActOnCapturedRegionEnd(Stmt *S);
void ActOnCapturedRegionError();
RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
@@ -4215,6 +4321,9 @@ public:
ExprResult TransformToPotentiallyEvaluated(Expr *E);
ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
+ ExprResult CheckUnevaluatedOperand(Expr *E);
+ void CheckUnusedVolatileAssignment(Expr *E);
+
ExprResult ActOnConstantExpression(ExprResult Res);
// Functions for marking a declaration referenced. These functions also
@@ -4349,6 +4458,10 @@ public:
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
ArrayRef<Expr *> Args = None, TypoExpr **Out = nullptr);
+ DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
+ IdentifierInfo *II);
+ ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
+
ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
IdentifierInfo *II,
bool AllowBuiltinCreation=false);
@@ -4606,6 +4719,12 @@ public:
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig = nullptr,
bool IsExecConfig = false);
+ enum class AtomicArgumentOrder { API, AST };
+ ExprResult
+ BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
+ SourceLocation RParenLoc, MultiExprArg Args,
+ AtomicExpr::AtomicOp Op,
+ AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API);
ExprResult
BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
ArrayRef<Expr *> Arg, SourceLocation RParenLoc,
@@ -4646,8 +4765,12 @@ public:
MultiExprArg InitArgList,
SourceLocation RBraceLoc);
+ ExprResult BuildInitList(SourceLocation LBraceLoc,
+ MultiExprArg InitArgList,
+ SourceLocation RBraceLoc);
+
ExprResult ActOnDesignatedInitializer(Designation &Desig,
- SourceLocation Loc,
+ SourceLocation EqualOrColonLoc,
bool GNUSyntax,
ExprResult Init);
@@ -5803,12 +5926,17 @@ public:
LambdaCaptureDefault CaptureDefault);
/// Start the definition of a lambda expression.
- CXXMethodDecl *
- startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange,
- TypeSourceInfo *MethodType, SourceLocation EndLoc,
- ArrayRef<ParmVarDecl *> Params,
- ConstexprSpecKind ConstexprKind,
- Optional<std::pair<unsigned, Decl *>> Mangling = None);
+ CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
+ SourceRange IntroducerRange,
+ TypeSourceInfo *MethodType,
+ SourceLocation EndLoc,
+ ArrayRef<ParmVarDecl *> Params,
+ ConstexprSpecKind ConstexprKind);
+
+ /// Number lambda for linkage purposes if necessary.
+ void handleLambdaNumbering(
+ CXXRecordDecl *Class, CXXMethodDecl *Method,
+ Optional<std::tuple<unsigned, bool, Decl *>> Mangling = None);
/// Endow the lambda scope info with the relevant properties.
void buildLambdaScope(sema::LambdaScopeInfo *LSI,
@@ -5936,6 +6064,21 @@ public:
CXXConversionDecl *Conv,
Expr *Src);
+ /// Check whether the given expression is a valid constraint expression.
+ /// A diagnostic is emitted if it is not, and false is returned.
+ bool CheckConstraintExpression(Expr *CE);
+
+ bool CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
+ MultiLevelTemplateArgumentList &MLTAL,
+ Expr *ConstraintExpr,
+ bool &IsSatisfied);
+
+ /// Check that the associated constraints of a template declaration match the
+ /// associated constraints of an older declaration of which it is a
+ /// redeclaration.
+ bool CheckRedeclarationConstraintMatch(TemplateParameterList *Old,
+ TemplateParameterList *New);
+
// ParseObjCStringLiteral - Parse Objective-C string literals.
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
ArrayRef<Expr *> Strings);
@@ -6150,6 +6293,17 @@ public:
ClassTemplateSpecializationDecl *BaseTemplateSpec,
SourceLocation BaseLoc);
+ /// Add gsl::Pointer attribute to std::container::iterator
+ /// \param ND The declaration that introduces the name
+ /// std::container::iterator. \param UnderlyingRecord The record named by ND.
+ void inferGslPointerAttribute(NamedDecl *ND, CXXRecordDecl *UnderlyingRecord);
+
+ /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
+ void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
+
+ /// Add [[gsl::Pointer]] attributes for std:: types.
+ void inferGslPointerAttribute(TypedefNameDecl *TD);
+
void CheckCompletedCXXClass(CXXRecordDecl *Record);
/// Check that the C++ class annoated with "trivial_abi" satisfies all the
@@ -6596,9 +6750,9 @@ public:
ExprResult
CheckConceptTemplateId(const CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- ConceptDecl *Template,
- SourceLocation TemplateLoc,
+ SourceLocation TemplateKWLoc,
+ SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept,
const TemplateArgumentListInfo *TemplateArgs);
void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
@@ -7517,6 +7671,18 @@ public:
/// member).
DefiningSynthesizedFunction,
+ // We are checking the constraints associated with a constrained entity or
+ // the constraint expression of a concept. This includes the checks that
+ // atomic constraints have the type 'bool' and that they can be constant
+ // evaluated.
+ ConstraintsCheck,
+
+ // We are substituting template arguments into a constraint expression.
+ ConstraintSubstitution,
+
+ /// We are rewriting a comparison operator in terms of an operator<=>.
+ RewritingOperatorAsSpaceship,
+
/// Added for Template instantiation observation.
/// Memoization means we are _not_ instantiating a template because
/// it is already instantiated (but we entered a context where we
@@ -7777,6 +7943,23 @@ public:
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
+ struct ConstraintsCheck {};
+ /// \brief Note that we are checking the constraints associated with some
+ /// constrained entity (a concept declaration or a template with associated
+ /// constraints).
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ConstraintsCheck, TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange);
+
+ struct ConstraintSubstitution {};
+ /// \brief Note that we are checking a constraint expression associated
+ /// with a template declaration or as part of the satisfaction check of a
+ /// concept.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ConstraintSubstitution, TemplateDecl *Template,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange);
/// Note that we have finished instantiating this template.
void Clear();
@@ -8225,6 +8408,11 @@ public:
LocalInstantiationScope *StartingScope,
bool InstantiatingVarTemplate = false,
VarTemplateSpecializationDecl *PrevVTSD = nullptr);
+
+ VarDecl *getVarTemplateSpecialization(
+ VarTemplateDecl *VarTempl, const TemplateArgumentListInfo *TemplateArgs,
+ const DeclarationNameInfo &MemberNameInfo, SourceLocation TemplateKWLoc);
+
void InstantiateVariableInitializer(
VarDecl *Var, VarDecl *OldVar,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -8844,51 +9032,50 @@ public:
void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
- void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
- unsigned SpellingListIndex, bool IsPackExpansion);
- void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T,
- unsigned SpellingListIndex, bool IsPackExpansion);
+ void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+ bool IsPackExpansion);
+ void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, TypeSourceInfo *T,
+ bool IsPackExpansion);
/// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
/// declaration.
- void AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, Expr *OE,
- unsigned SpellingListIndex);
+ void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+ Expr *OE);
/// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
/// declaration.
- void AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
- unsigned SpellingListIndex);
+ void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *ParamExpr);
/// AddAlignValueAttr - Adds an align_value attribute to a particular
/// declaration.
- void AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
- unsigned SpellingListIndex);
+ void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
/// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
/// declaration.
- void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
- Expr *MinBlocks, unsigned SpellingListIndex);
+ void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *MaxThreads, Expr *MinBlocks);
/// AddModeAttr - Adds a mode attribute to a particular declaration.
- void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
- unsigned SpellingListIndex, bool InInstantiation = false);
+ void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,
+ bool InInstantiation = false);
- void AddParameterABIAttr(SourceRange AttrRange, Decl *D,
- ParameterABI ABI, unsigned SpellingListIndex);
+ void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
+ ParameterABI ABI);
enum class RetainOwnershipKind {NS, CF, OS};
- void AddXConsumedAttr(Decl *D, SourceRange SR, unsigned SpellingIndex,
+ void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
RetainOwnershipKind K, bool IsTemplateInstantiation);
/// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
/// attribute to a particular declaration.
- void addAMDGPUFlatWorkGroupSizeAttr(SourceRange AttrRange, Decl *D, Expr *Min,
- Expr *Max, unsigned SpellingListIndex);
+ void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *Min, Expr *Max);
/// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
/// particular declaration.
- void addAMDGPUWavesPerEUAttr(SourceRange AttrRange, Decl *D, Expr *Min,
- Expr *Max, unsigned SpellingListIndex);
+ void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *Min, Expr *Max);
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
@@ -9002,6 +9189,10 @@ private:
void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
unsigned Level) const;
+ /// Returns the number of scopes associated with the construct on the given
+ /// OpenMP level.
+ int getNumberOfConstructScopes(unsigned Level) const;
+
/// Push new OpenMP function region for non-capturing function.
void pushOpenMPFunctionRegion();
@@ -9009,12 +9200,21 @@ private:
void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI);
/// Check whether we're allowed to call Callee from the current function.
- void checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee);
+ void checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee,
+ bool CheckForDelayedContext = true);
+
+ /// Check whether we're allowed to call Callee from the current function.
+ void checkOpenMPHostFunction(SourceLocation Loc, FunctionDecl *Callee,
+ bool CheckCaller = true);
/// Check if the expression is allowed to be used in expressions for the
/// OpenMP devices.
void checkOpenMPDeviceExpr(const Expr *E);
+ /// Finishes analysis of the deferred functions calls that may be declared as
+ /// host/nohost during device/host compilation.
+ void finalizeOpenMPDelayedAnalysis();
+
/// Checks if a type or a declaration is disabled due to the owning extension
/// being disabled, and emits diagnostic messages if it is disabled.
/// \param D type or declaration to be checked.
@@ -9030,7 +9230,39 @@ private:
MapT &Map, unsigned Selector = 0,
SourceRange SrcRange = SourceRange());
+ /// Marks all the functions that might be required for the currently active
+ /// OpenMP context.
+ void markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc,
+ FunctionDecl *Func,
+ bool MightBeOdrUse);
+
public:
+ /// Struct to store the context selectors info for declare variant directive.
+ struct OpenMPDeclareVariantCtsSelectorData {
+ OMPDeclareVariantAttr::CtxSelectorSetType CtxSet =
+ OMPDeclareVariantAttr::CtxSetUnknown;
+ OMPDeclareVariantAttr::CtxSelectorType Ctx =
+ OMPDeclareVariantAttr::CtxUnknown;
+ MutableArrayRef<StringRef> ImplVendors;
+ ExprResult CtxScore;
+ explicit OpenMPDeclareVariantCtsSelectorData() = default;
+ explicit OpenMPDeclareVariantCtsSelectorData(
+ OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
+ OMPDeclareVariantAttr::CtxSelectorType Ctx,
+ MutableArrayRef<StringRef> ImplVendors, ExprResult CtxScore)
+ : CtxSet(CtxSet), Ctx(Ctx), ImplVendors(ImplVendors),
+ CtxScore(CtxScore) {}
+ };
+
+ /// Checks if the variant/multiversion functions are compatible.
+ bool areMultiversionVariantFunctionsCompatible(
+ const FunctionDecl *OldFD, const FunctionDecl *NewFD,
+ const PartialDiagnostic &NoProtoDiagID,
+ const PartialDiagnosticAt &NoteCausedDiagIDAt,
+ const PartialDiagnosticAt &NoSupportDiagIDAt,
+ const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported,
+ bool ConstexprSupported, bool CLinkageMayDiffer);
+
/// Function tries to capture lambda's captured variables in the OpenMP region
/// before the original lambda is captured.
void tryCaptureOpenMPLambdas(ValueDecl *V);
@@ -9039,7 +9271,9 @@ public:
/// reference.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
- bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const;
+ /// \param OpenMPCaptureLevel Capture level within an OpenMP construct.
+ bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
+ unsigned OpenMPCaptureLevel) const;
/// Check if the specified variable is used in one of the private
/// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
@@ -9053,6 +9287,10 @@ public:
/// construct.
void startOpenMPLoop();
+ /// If the current region is a range loop-based region, mark the start of the
+ /// loop construct.
+ void startOpenMPCXXRangeFor();
+
/// Check if the specified variable is used in 'private' clause.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
@@ -9159,11 +9397,16 @@ public:
bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc);
/// Called at the end of target region i.e. '#pragme omp end declare target'.
void ActOnFinishOpenMPDeclareTargetDirective();
+ /// Searches for the provided declaration name for OpenMP declare target
+ /// directive.
+ NamedDecl *
+ lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id,
+ NamedDeclSetType &SameDirectiveDecls);
/// Called on correct id-expression from the '#pragma omp declare target'.
- void ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
- const DeclarationNameInfo &Id,
+ void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
OMPDeclareTargetDeclAttr::MapTypeTy MT,
- NamedDeclSetType &SameDirectiveDecls);
+ OMPDeclareTargetDeclAttr::DevTypeTy DT);
/// Check declaration inside target region.
void
checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
@@ -9348,6 +9591,21 @@ public:
StmtResult ActOnOpenMPTaskLoopSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp master taskloop' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPMasterTaskLoopDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp master taskloop simd' after parsing of
+ /// the associated statement.
+ StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp parallel master taskloop' after
+ /// parsing of the associated statement.
+ StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
/// Called on well-formed '\#pragma omp distribute' after parsing
/// of the associated statement.
StmtResult
@@ -9448,6 +9706,29 @@ public:
ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR);
+ /// Checks '\#pragma omp declare variant' variant function and original
+ /// functions after parsing of the associated method/function.
+ /// \param DG Function declaration to which declare variant directive is
+ /// applied to.
+ /// \param VariantRef Expression that references the variant function, which
+ /// must be used instead of the original one, specified in \p DG.
+ /// \returns None, if the function/variant function are not compatible with
+ /// the pragma, pair of original function/variant ref expression otherwise.
+ Optional<std::pair<FunctionDecl *, Expr *>> checkOpenMPDeclareVariantFunction(
+ DeclGroupPtrTy DG, Expr *VariantRef, SourceRange SR);
+
+ /// Called on well-formed '\#pragma omp declare variant' after parsing of
+ /// the associated method/function.
+ /// \param FD Function declaration to which declare variant directive is
+ /// applied to.
+ /// \param VariantRef Expression that references the variant function, which
+ /// must be used instead of the original one, specified in \p DG.
+ /// \param Data Set of context-specific data for the specified context
+ /// selector.
+ void ActOnOpenMPDeclareVariantDirective(
+ FunctionDecl *FD, Expr *VariantRef, SourceRange SR,
+ const Sema::OpenMPDeclareVariantCtsSelectorData &Data);
+
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
SourceLocation StartLoc,
@@ -10051,6 +10332,7 @@ public:
QualType CheckShiftOperands( // C99 6.5.7
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc, bool IsCompAssign = false);
+ void CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE);
QualType CheckCompareOperands( // C99 6.5.8/9
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc);
@@ -10137,11 +10419,11 @@ public:
Ref_Compatible
};
- ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
- QualType T1, QualType T2,
- bool &DerivedToBase,
- bool &ObjCConversion,
- bool &ObjCLifetimeConversion);
+ ReferenceCompareResult
+ CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
+ bool &DerivedToBase, bool &ObjCConversion,
+ bool &ObjCLifetimeConversion,
+ bool &FunctionConversion);
ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
Expr *CastExpr, CastKind &CastKind,
@@ -10546,6 +10828,21 @@ public:
/// // Otherwise, continue parsing as normal.
DeviceDiagBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID);
+ /// Creates a DeviceDiagBuilder that emits the diagnostic if the current
+ /// context is "used as host code".
+ ///
+ /// - If CurContext is a `declare target` function or it is known that the
+ /// function is emitted for the host, emits the diagnostics immediately.
+ /// - If CurContext is a non-host function, just ignore it.
+ ///
+ /// Example usage:
+ ///
+ /// // Variable-length arrays are not allowed in NVPTX device code.
+ /// if (diagIfOpenMPHostode(Loc, diag::err_vla_unsupported))
+ /// return ExprError();
+ /// // Otherwise, continue parsing as normal.
+ DeviceDiagBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID);
+
DeviceDiagBuilder targetDiag(SourceLocation Loc, unsigned DiagID);
enum CUDAFunctionTarget {
@@ -10907,6 +11204,7 @@ private:
bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall);
bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
@@ -11165,6 +11463,7 @@ public:
// Emitting members of dllexported classes is delayed until the class
// (including field initializers) is fully parsed.
SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
+ SmallVector<CXXMethodDecl*, 4> DelayedDllExportMemberFunctions;
private:
class SavePendingParsedClassStateRAII {
diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
index dfb34daa14d3..cdaf7b70a92f 100644
--- a/include/clang/Sema/SemaInternal.h
+++ b/include/clang/Sema/SemaInternal.h
@@ -97,7 +97,7 @@ public:
bool EnteringContext)
: Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0),
SavedTCIndex(0), SemaRef(SemaRef), S(S),
- SS(SS ? llvm::make_unique<CXXScopeSpec>(*SS) : nullptr),
+ SS(SS ? std::make_unique<CXXScopeSpec>(*SS) : nullptr),
CorrectionValidator(std::move(CCC)), MemberContext(MemberContext),
Result(SemaRef, TypoName, LookupKind),
Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index b49a96c0b93f..e0f8d152dbe5 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/include/clang/Sema/TypoCorrection.h
@@ -356,7 +356,7 @@ public:
: CorrectionCandidateCallback(Typo, TypoNNS) {}
std::unique_ptr<CorrectionCandidateCallback> clone() override {
- return llvm::make_unique<DefaultFilterCCC>(*this);
+ return std::make_unique<DefaultFilterCCC>(*this);
}
};
@@ -369,7 +369,7 @@ public:
return candidate.getCorrectionDeclAs<C>();
}
std::unique_ptr<CorrectionCandidateCallback> clone() override {
- return llvm::make_unique<DeclFilterCCC>(*this);
+ return std::make_unique<DeclFilterCCC>(*this);
}
};
@@ -384,7 +384,7 @@ public:
bool ValidateCandidate(const TypoCorrection &candidate) override;
std::unique_ptr<CorrectionCandidateCallback> clone() override {
- return llvm::make_unique<FunctionCallFilterCCC>(*this);
+ return std::make_unique<FunctionCallFilterCCC>(*this);
}
private:
@@ -409,7 +409,7 @@ public:
return false;
}
std::unique_ptr<CorrectionCandidateCallback> clone() override {
- return llvm::make_unique<NoTypoCorrectionCCC>(*this);
+ return std::make_unique<NoTypoCorrectionCCC>(*this);
}
};
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 0e1b9e0af9e6..f31057275479 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -41,7 +41,7 @@ namespace serialization {
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
- const unsigned VERSION_MAJOR = 7;
+ const unsigned VERSION_MAJOR = 8;
/// AST file minor version number supported by this version of
/// Clang.
@@ -382,7 +382,10 @@ namespace serialization {
/// inside the control block.
enum InputFileRecordTypes {
/// An input file.
- INPUT_FILE = 1
+ INPUT_FILE = 1,
+
+ /// The input file content hash
+ INPUT_FILE_HASH
};
/// Record types that occur within the AST block itself.
@@ -1018,6 +1021,9 @@ namespace serialization {
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
PREDEF_TYPE_##Id##_ID,
#include "clang/Basic/OpenCLExtensionTypes.def"
+ // \brief SVE types with auto numeration
+#define SVE_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
+#include "clang/Basic/AArch64SVEACLETypes.def"
};
/// The number of predefined type IDs that are reserved for
@@ -1839,6 +1845,9 @@ namespace serialization {
/// A CXXMemberCallExpr record.
EXPR_CXX_MEMBER_CALL,
+ /// A CXXRewrittenBinaryOperator record.
+ EXPR_CXX_REWRITTEN_BINARY_OPERATOR,
+
/// A CXXConstructExpr record.
EXPR_CXX_CONSTRUCT,
@@ -1909,6 +1918,7 @@ namespace serialization {
EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
EXPR_CXX_FOLD, // CXXFoldExpr
+ EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr
// CUDA
EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
@@ -1958,6 +1968,9 @@ namespace serialization {
STMT_OMP_CANCEL_DIRECTIVE,
STMT_OMP_TASKLOOP_DIRECTIVE,
STMT_OMP_TASKLOOP_SIMD_DIRECTIVE,
+ STMT_OMP_MASTER_TASKLOOP_DIRECTIVE,
+ STMT_OMP_MASTER_TASKLOOP_SIMD_DIRECTIVE,
+ STMT_OMP_PARALLEL_MASTER_TASKLOOP_DIRECTIVE,
STMT_OMP_DISTRIBUTE_DIRECTIVE,
STMT_OMP_TARGET_UPDATE_DIRECTIVE,
STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 37bea48d8846..7495c2b17aa2 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -930,6 +930,9 @@ private:
/// Whether validate system input files.
bool ValidateSystemInputs;
+ /// Whether validate headers and module maps using hash based on contents.
+ bool ValidateASTInputFilesContent;
+
/// Whether we are allowed to use the global module index.
bool UseGlobalIndex;
@@ -1203,6 +1206,7 @@ private:
struct InputFileInfo {
std::string Filename;
+ uint64_t ContentHash;
off_t StoredSize;
time_t StoredTime;
bool Overridden;
@@ -1437,6 +1441,8 @@ private:
void Error(StringRef Msg) const;
void Error(unsigned DiagID, StringRef Arg1 = StringRef(),
StringRef Arg2 = StringRef()) const;
+ void Error(unsigned DiagID, StringRef Arg1, StringRef Arg2,
+ unsigned Select) const;
void Error(llvm::Error &&Err) const;
public:
@@ -1485,7 +1491,9 @@ public:
StringRef isysroot = "", bool DisableValidation = false,
bool AllowASTWithCompilerErrors = false,
bool AllowConfigurationMismatch = false,
- bool ValidateSystemInputs = false, bool UseGlobalIndex = true,
+ bool ValidateSystemInputs = false,
+ bool ValidateASTInputFilesContent = false,
+ bool UseGlobalIndex = true,
std::unique_ptr<llvm::Timer> ReadTimer = {});
ASTReader(const ASTReader &) = delete;
ASTReader &operator=(const ASTReader &) = delete;
@@ -1578,7 +1586,7 @@ public:
/// Takes ownership of \p L.
void addListener(std::unique_ptr<ASTReaderListener> L) {
if (Listener)
- L = llvm::make_unique<ChainedASTReaderListener>(std::move(L),
+ L = std::make_unique<ChainedASTReaderListener>(std::move(L),
std::move(Listener));
Listener = std::move(L);
}
@@ -1594,7 +1602,7 @@ public:
auto Old = Reader.takeListener();
if (Old) {
Chained = true;
- L = llvm::make_unique<ChainedASTReaderListener>(std::move(L),
+ L = std::make_unique<ChainedASTReaderListener>(std::move(L),
std::move(Old));
}
Reader.setListener(std::move(L));
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 2b29efba66a4..4d52655045b3 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -504,6 +504,15 @@ def MoveChecker: Checker<"Move">,
]>,
Documentation<HasDocumentation>;
+def VirtualCallModeling : Checker<"VirtualCallModeling">,
+ HelpText<"Auxiliary modeling for the virtual method call checkers">,
+ Documentation<NotDocumented>,
+ Hidden;
+
+def PureVirtualCallChecker : Checker<"PureVirtualCall">,
+ HelpText<"Check pure virtual function calls during construction/destruction">,
+ Dependencies<[VirtualCallModeling]>,
+ Documentation<HasDocumentation>;
} // end: "cplusplus"
let ParentPackage = CplusplusOptIn in {
@@ -552,14 +561,22 @@ def UninitializedObjectChecker: Checker<"UninitializedObject">,
Documentation<HasAlphaDocumentation>;
def VirtualCallChecker : Checker<"VirtualCall">,
- HelpText<"Check virtual function calls during construction or destruction">,
+ HelpText<"Check virtual function calls during construction/destruction">,
CheckerOptions<[
CmdLineOption<Boolean,
+ "ShowFixIts",
+ "Enable fix-it hints for this checker",
+ "false",
+ InAlpha>,
+ CmdLineOption<Boolean,
"PureOnly",
- "Whether to only report calls to pure virtual methods.",
+ "Disables the checker. Keeps cplusplus.PureVirtualCall "
+ "enabled. This option is only provided for backwards "
+ "compatibility.",
"false",
- Released>
+ InAlpha>
]>,
+ Dependencies<[VirtualCallModeling]>,
Documentation<HasDocumentation>;
} // end: "optin.cplusplus"
@@ -636,6 +653,19 @@ let ParentPackage = DeadCode in {
def DeadStoresChecker : Checker<"DeadStores">,
HelpText<"Check for values stored to variables that are never read "
"afterwards">,
+ CheckerOptions<[
+ CmdLineOption<Boolean,
+ "WarnForDeadNestedAssignments",
+ "Warns for deadstores in nested assignments."
+ "E.g.: if ((P = f())) where P is unused.",
+ "true",
+ Released>,
+ CmdLineOption<Boolean,
+ "ShowFixIts",
+ "Enable fix-it hints for this checker",
+ "false",
+ InAlpha>
+ ]>,
Documentation<HasDocumentation>;
} // end DeadCode
@@ -799,6 +829,13 @@ let ParentPackage = Taint in {
def GenericTaintChecker : Checker<"TaintPropagation">,
HelpText<"Generate taint information used by other checkers">,
+ CheckerOptions<[
+ CmdLineOption<String,
+ "Config",
+ "Specifies the name of the configuration file.",
+ "",
+ InAlpha>,
+ ]>,
Documentation<HasAlphaDocumentation>;
} // end "alpha.security.taint"
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
index 70bd476b6c43..d853fb74f9c7 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -294,12 +294,20 @@ ANALYZER_OPTION(bool, DisplayCTUProgress, "display-ctu-progress",
ANALYZER_OPTION(bool, ShouldTrackConditions, "track-conditions",
"Whether to track conditions that are a control dependency of "
"an already tracked variable.",
- false)
+ true)
ANALYZER_OPTION(bool, ShouldTrackConditionsDebug, "track-conditions-debug",
"Whether to place an event at each tracked condition.",
false)
+ANALYZER_OPTION(bool, ShouldEmitFixItHintsAsRemarks, "fixits-as-remarks",
+ "Emit fix-it hints as remarks for testing purposes",
+ false)
+
+//===----------------------------------------------------------------------===//
+// Unsigned analyzer options.
+//===----------------------------------------------------------------------===//
+
ANALYZER_OPTION(unsigned, CTUImportThreshold, "ctu-import-threshold",
"The maximal amount of translation units that is considered "
"for import when inlining functions during CTU analysis. "
@@ -308,10 +316,6 @@ ANALYZER_OPTION(unsigned, CTUImportThreshold, "ctu-import-threshold",
"various translation units.",
100u)
-//===----------------------------------------------------------------------===//
-// Unsinged analyzer options.
-//===----------------------------------------------------------------------===//
-
ANALYZER_OPTION(
unsigned, AlwaysInlineSize, "ipa-always-inline-size",
"The size of the functions (in basic blocks), which should be considered "
@@ -380,12 +384,6 @@ ANALYZER_OPTION(
"Value: \"constructors\", \"destructors\", \"methods\".",
"destructors")
-ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
- StringRef, IPAMode, "ipa",
- "Controls the mode of inter-procedural analysis. Value: \"none\", "
- "\"basic-inlining\", \"inlining\", \"dynamic\", \"dynamic-bifurcate\".",
- /* SHALLOW_VAL */ "inlining", /* DEEP_VAL */ "dynamic-bifurcate")
-
ANALYZER_OPTION(
StringRef, ExplorationStrategy, "exploration_strategy",
"Value: \"dfs\", \"bfs\", \"unexplored_first\", "
@@ -393,5 +391,17 @@ ANALYZER_OPTION(
"\"bfs_block_dfs_contents\".",
"unexplored_first_queue")
+ANALYZER_OPTION(
+ StringRef, RawSilencedCheckersAndPackages, "silence-checkers",
+ "A semicolon separated list of checker and package names to silence. "
+ "Silenced checkers will not emit reports, but the modeling remain enabled.",
+ "")
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ StringRef, IPAMode, "ipa",
+ "Controls the mode of inter-procedural analysis. Value: \"none\", "
+ "\"basic-inlining\", \"inlining\", \"dynamic\", \"dynamic-bifurcate\".",
+ /* SHALLOW_VAL */ "inlining", /* DEEP_VAL */ "dynamic-bifurcate")
+
#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
#undef ANALYZER_OPTION
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 9630a229bd3b..ce16095e10c0 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -163,9 +163,16 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
public:
using ConfigTable = llvm::StringMap<std::string>;
+ /// Retrieves the list of checkers generated from Checkers.td. This doesn't
+ /// contain statically linked but non-generated checkers and plugin checkers!
static std::vector<StringRef>
getRegisteredCheckers(bool IncludeExperimental = false);
+ /// Retrieves the list of packages generated from Checkers.td. This doesn't
+ /// contain statically linked but non-generated packages and plugin packages!
+ static std::vector<StringRef>
+ getRegisteredPackages(bool IncludeExperimental = false);
+
/// Convenience function for printing options or checkers and their
/// description in a formatted manner. If \p MinLineWidth is set to 0, no line
/// breaks are introduced for the description.
@@ -188,9 +195,11 @@ public:
std::pair<StringRef, StringRef> EntryDescPair,
size_t EntryWidth, size_t InitialPad, size_t MinLineWidth = 0);
+ /// Pairs of checker/package name and enable/disable.
+ std::vector<std::pair<std::string, bool>> CheckersAndPackages;
- /// Pair of checker name and enable/disable.
- std::vector<std::pair<std::string, bool>> CheckersControlList;
+ /// Vector of checker/package names which will not emit warnings.
+ std::vector<std::string> SilencedCheckersAndPackages;
/// A key-value table of use-specified configuration values.
// TODO: This shouldn't be public.
@@ -212,12 +221,12 @@ public:
/// The maximum number of times the analyzer visits a block.
unsigned maxBlockVisitOnPath;
- /// Disable all analyzer checks.
+ /// Disable all analyzer checkers.
///
- /// This flag allows one to disable analyzer checks on the code processed by
+ /// This flag allows one to disable analyzer checkers on the code processed by
/// the given analysis consumer. Note, the code will get parsed and the
/// command-line options will get checked.
- unsigned DisableAllChecks : 1;
+ unsigned DisableAllCheckers : 1;
unsigned ShowCheckerHelp : 1;
unsigned ShowCheckerHelpAlpha : 1;
@@ -269,13 +278,13 @@ public:
// Create an array of all -analyzer-config command line options. Sort it in
// the constructor.
- std::vector<StringRef> AnalyzerConfigCmdFlags = {
+ std::vector<llvm::StringLiteral> AnalyzerConfigCmdFlags = {
#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
SHALLOW_VAL, DEEP_VAL) \
ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
- CMDFLAG,
+ llvm::StringLiteral(CMDFLAG),
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
#undef ANALYZER_OPTION
@@ -292,7 +301,7 @@ public:
}
AnalyzerOptions()
- : DisableAllChecks(false), ShowCheckerHelp(false),
+ : DisableAllCheckers(false), ShowCheckerHelp(false),
ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false),
ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false),
ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false),
@@ -310,7 +319,7 @@ public:
/// If an option value is not provided, returns the given \p DefaultVal.
/// @param [in] CheckerName The *full name* of the checker. One may retrieve
/// this from the checker object's field \c Name, or through \c
- /// CheckerManager::getCurrentCheckName within the checker's registry
+ /// CheckerManager::getCurrentCheckerName within the checker's registry
/// function.
/// Checker options are retrieved in the following format:
/// `-analyzer-config CheckerName:OptionName=Value.
@@ -330,7 +339,7 @@ public:
/// If an option value is not provided, returns the given \p DefaultVal.
/// @param [in] CheckerName The *full name* of the checker. One may retrieve
/// this from the checker object's field \c Name, or through \c
- /// CheckerManager::getCurrentCheckName within the checker's registry
+ /// CheckerManager::getCurrentCheckerName within the checker's registry
/// function.
/// Checker options are retrieved in the following format:
/// `-analyzer-config CheckerName:OptionName=Value.
@@ -350,7 +359,7 @@ public:
/// If an option value is not provided, returns the given \p DefaultVal.
/// @param [in] CheckerName The *full name* of the checker. One may retrieve
/// this from the checker object's field \c Name, or through \c
- /// CheckerManager::getCurrentCheckName within the checker's registry
+ /// CheckerManager::getCurrentCheckerName within the checker's registry
/// function.
/// Checker options are retrieved in the following format:
/// `-analyzer-config CheckerName:OptionName=Value.
@@ -404,6 +413,43 @@ inline UserModeKind AnalyzerOptions::getUserMode() const {
return K.getValue();
}
+inline std::vector<StringRef>
+AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental) {
+ static constexpr llvm::StringLiteral StaticAnalyzerCheckerNames[] = {
+#define GET_CHECKERS
+#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
+ llvm::StringLiteral(FULLNAME),
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+ };
+ std::vector<StringRef> Checkers;
+ for (StringRef CheckerName : StaticAnalyzerCheckerNames) {
+ if (!CheckerName.startswith("debug.") &&
+ (IncludeExperimental || !CheckerName.startswith("alpha.")))
+ Checkers.push_back(CheckerName);
+ }
+ return Checkers;
+}
+
+inline std::vector<StringRef>
+AnalyzerOptions::getRegisteredPackages(bool IncludeExperimental) {
+ static constexpr llvm::StringLiteral StaticAnalyzerPackageNames[] = {
+#define GET_PACKAGES
+#define PACKAGE(FULLNAME) llvm::StringLiteral(FULLNAME),
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef PACKAGE
+#undef GET_PACKAGES
+ };
+ std::vector<StringRef> Packages;
+ for (StringRef PackageName : StaticAnalyzerPackageNames) {
+ if (PackageName != "debug" &&
+ (IncludeExperimental || PackageName != "alpha"))
+ Packages.push_back(PackageName);
+ }
+ return Packages;
+}
+
} // namespace clang
#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index d30ad19b20f8..e94b544172a0 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -14,10 +14,10 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
+#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
@@ -70,59 +70,253 @@ class SValBuilder;
using DiagnosticForConsumerMapTy =
llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>;
-/// This class provides an interface through which checkers can create
-/// individual bug reports.
-class BugReport : public llvm::ilist_node<BugReport> {
+/// Interface for classes constructing Stack hints.
+///
+/// If a PathDiagnosticEvent occurs in a different frame than the final
+/// diagnostic the hints can be used to summarize the effect of the call.
+class StackHintGenerator {
public:
- class NodeResolver {
- virtual void anchor();
+ virtual ~StackHintGenerator() = 0;
- public:
- virtual ~NodeResolver() = default;
+ /// Construct the Diagnostic message for the given ExplodedNode.
+ virtual std::string getMessage(const ExplodedNode *N) = 0;
+};
- virtual const ExplodedNode*
- getOriginalNode(const ExplodedNode *N) = 0;
- };
+/// Constructs a Stack hint for the given symbol.
+///
+/// The class knows how to construct the stack hint message based on
+/// traversing the CallExpr associated with the call and checking if the given
+/// symbol is returned or is one of the arguments.
+/// The hint can be customized by redefining 'getMessageForX()' methods.
+class StackHintGeneratorForSymbol : public StackHintGenerator {
+private:
+ SymbolRef Sym;
+ std::string Msg;
- using ranges_iterator = const SourceRange *;
- using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
- using visitor_iterator = VisitorList::iterator;
- using ExtraTextList = SmallVector<StringRef, 2>;
- using NoteList = SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4>;
+public:
+ StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
+ ~StackHintGeneratorForSymbol() override = default;
+
+ /// Search the call expression for the symbol Sym and dispatch the
+ /// 'getMessageForX()' methods to construct a specific message.
+ std::string getMessage(const ExplodedNode *N) override;
+
+ /// Produces the message of the following form:
+ /// 'Msg via Nth parameter'
+ virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
+
+ virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
+ return Msg;
+ }
+
+ virtual std::string getMessageForSymbolNotFound() {
+ return Msg;
+ }
+};
+
+/// This class provides an interface through which checkers can create
+/// individual bug reports.
+class BugReport {
+public:
+ enum class Kind { Basic, PathSensitive };
protected:
friend class BugReportEquivClass;
friend class BugReporter;
+ Kind K;
const BugType& BT;
- const Decl *DeclWithIssue = nullptr;
std::string ShortDescription;
std::string Description;
+
+ SmallVector<SourceRange, 4> Ranges;
+ SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> Notes;
+ SmallVector<FixItHint, 4> Fixits;
+
+ BugReport(Kind kind, const BugType &bt, StringRef desc)
+ : K(kind), BT(bt), Description(desc) {}
+
+ BugReport(Kind K, const BugType &BT, StringRef ShortDescription,
+ StringRef Description)
+ : K(K), BT(BT), ShortDescription(ShortDescription),
+ Description(Description) {}
+
+public:
+ virtual ~BugReport() = default;
+
+ Kind getKind() const { return K; }
+
+ const BugType& getBugType() const { return BT; }
+
+ /// A verbose warning message that is appropriate for displaying next to
+ /// the source code that introduces the problem. The description should be
+ /// at least a full sentence starting with a capital letter. The period at
+ /// the end of the warning is traditionally omitted. If the description
+ /// consists of multiple sentences, periods between the sentences are
+ /// encouraged, but the period at the end of the description is still omitted.
+ StringRef getDescription() const { return Description; }
+
+ /// A short general warning message that is appropriate for displaying in
+ /// the list of all reported bugs. It should describe what kind of bug is found
+ /// but does not need to try to go into details of that specific bug.
+ /// Grammatical conventions of getDescription() apply here as well.
+ StringRef getShortDescription(bool UseFallback = true) const {
+ if (ShortDescription.empty() && UseFallback)
+ return Description;
+ return ShortDescription;
+ }
+
+ /// The primary location of the bug report that points at the undesirable
+ /// behavior in the code. UIs should attach the warning description to this
+ /// location. The warning description should describe the bad behavior
+ /// at this location.
+ virtual PathDiagnosticLocation getLocation() const = 0;
+
+ /// The smallest declaration that contains the bug location.
+ /// This is purely cosmetic; the declaration can be displayed to the user
+ /// but it does not affect whether the report is emitted.
+ virtual const Decl *getDeclWithIssue() const = 0;
+
+ /// Get the location on which the report should be uniqued. Two warnings are
+ /// considered to be equivalent whenever they have the same bug types,
+ /// descriptions, and uniqueing locations. Out of a class of equivalent
+ /// warnings only one gets displayed to the user. For most warnings the
+ /// uniqueing location coincides with their location, but sometimes
+ /// it makes sense to use different locations. For example, a leak
+ /// checker can place the warning at the location where the last reference
+ /// to the leaking resource is dropped but at the same time unique the warning
+ /// by where that resource is acquired (allocated).
+ virtual PathDiagnosticLocation getUniqueingLocation() const = 0;
+
+ /// Get the declaration that corresponds to (usually contains) the uniqueing
+ /// location. This is not actively used for uniqueing, i.e. otherwise
+ /// identical reports that have different uniqueing decls will be considered
+ /// equivalent.
+ virtual const Decl *getUniqueingDecl() const = 0;
+
+ /// Add new item to the list of additional notes that need to be attached to
+ /// this report. If the report is path-sensitive, these notes will not be
+ /// displayed as part of the execution path explanation, but will be displayed
+ /// separately. Use bug visitors if you need to add an extra path note.
+ void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
+ ArrayRef<SourceRange> Ranges = {}) {
+ auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);
+
+ for (const auto &R : Ranges)
+ P->addRange(R);
+
+ Notes.push_back(std::move(P));
+ }
+
+ ArrayRef<std::shared_ptr<PathDiagnosticNotePiece>> getNotes() {
+ return Notes;
+ }
+
+ /// Add a range to a bug report.
+ ///
+ /// Ranges are used to highlight regions of interest in the source code.
+ /// They should be at the same source code line as the BugReport location.
+ /// By default, the source range of the statement corresponding to the error
+ /// node will be used; add a single invalid range to specify absence of
+ /// ranges.
+ void addRange(SourceRange R) {
+ assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
+ "to specify that the report does not have a range.");
+ Ranges.push_back(R);
+ }
+
+ /// Get the SourceRanges associated with the report.
+ virtual ArrayRef<SourceRange> getRanges() const {
+ return Ranges;
+ }
+
+ /// Add a fix-it hint to the bug report.
+ ///
+ /// Fix-it hints are the suggested edits to the code that would resolve
+ /// the problem explained by the bug report. Fix-it hints should be
+ /// as conservative as possible because it is not uncommon for the user
+ /// to blindly apply all fixits to their project. Note that it is very hard
+ /// to produce a good fix-it hint for most path-sensitive warnings.
+ void addFixItHint(const FixItHint &F) {
+ Fixits.push_back(F);
+ }
+
+ llvm::ArrayRef<FixItHint> getFixits() const { return Fixits; }
+
+ /// Reports are uniqued to ensure that we do not emit multiple diagnostics
+ /// for each bug.
+ virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0;
+};
+
+class BasicBugReport : public BugReport {
PathDiagnosticLocation Location;
- PathDiagnosticLocation UniqueingLocation;
- const Decl *UniqueingDecl;
+ const Decl *DeclWithIssue = nullptr;
+
+public:
+ BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
+ : BugReport(Kind::Basic, bt, desc), Location(l) {}
+
+ static bool classof(const BugReport *R) {
+ return R->getKind() == Kind::Basic;
+ }
+
+ PathDiagnosticLocation getLocation() const override {
+ assert(Location.isValid());
+ return Location;
+ }
+
+ const Decl *getDeclWithIssue() const override {
+ return DeclWithIssue;
+ }
+
+ PathDiagnosticLocation getUniqueingLocation() const override {
+ return getLocation();
+ }
+
+ const Decl *getUniqueingDecl() const override {
+ return getDeclWithIssue();
+ }
+
+ /// Specifically set the Decl where an issue occurred. This isn't necessary
+ /// for BugReports that cover a path as it will be automatically inferred.
+ void setDeclWithIssue(const Decl *declWithIssue) {
+ DeclWithIssue = declWithIssue;
+ }
+ void Profile(llvm::FoldingSetNodeID& hash) const override;
+};
+
+class PathSensitiveBugReport : public BugReport {
+public:
+ using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
+ using visitor_iterator = VisitorList::iterator;
+ using visitor_range = llvm::iterator_range<visitor_iterator>;
+
+protected:
+ /// The ExplodedGraph node against which the report was thrown. It corresponds
+ /// to the end of the execution path that demonstrates the bug.
const ExplodedNode *ErrorNode = nullptr;
- SmallVector<SourceRange, 4> Ranges;
- ExtraTextList ExtraText;
- NoteList Notes;
- using Symbols = llvm::DenseSet<SymbolRef>;
- using Regions = llvm::DenseSet<const MemRegion *>;
+ /// The range that corresponds to ErrorNode's program point. It is usually
+ /// highlighted in the report.
+ const SourceRange ErrorNodeRange;
+
+ /// Profile to identify equivalent bug reports for error report coalescing.
/// A (stack of) a set of symbols that are registered with this
/// report as being "interesting", and thus used to help decide which
/// diagnostics to include when constructing the final path diagnostic.
/// The stack is largely used by BugReporter when generating PathDiagnostics
/// for multiple PathDiagnosticConsumers.
- SmallVector<Symbols *, 2> interestingSymbols;
+ llvm::DenseMap<SymbolRef, bugreporter::TrackingKind> InterestingSymbols;
/// A (stack of) set of regions that are registered with this report as being
/// "interesting", and thus used to help decide which diagnostics
/// to include when constructing the final path diagnostic.
/// The stack is largely used by BugReporter when generating PathDiagnostics
/// for multiple PathDiagnosticConsumers.
- SmallVector<Regions *, 2> interestingRegions;
+ llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>
+ InterestingRegions;
/// A set of location contexts that correspoind to call sites which should be
/// considered "interesting".
@@ -156,66 +350,58 @@ protected:
/// Conditions we're already tracking.
llvm::SmallSet<const ExplodedNode *, 4> TrackedConditions;
-private:
- // Used internally by BugReporter.
- Symbols &getInterestingSymbols();
- Regions &getInterestingRegions();
-
- void lazyInitializeInterestingSets();
- void pushInterestingSymbolsAndRegions();
- void popInterestingSymbolsAndRegions();
-
-public:
- BugReport(const BugType& bt, StringRef desc, const ExplodedNode *errornode)
- : BT(bt), Description(desc), ErrorNode(errornode) {}
+ /// Reports with different uniqueing locations are considered to be different
+ /// for the purposes of deduplication.
+ PathDiagnosticLocation UniqueingLocation;
+ const Decl *UniqueingDecl;
- BugReport(const BugType& bt, StringRef shortDesc, StringRef desc,
- const ExplodedNode *errornode)
- : BT(bt), ShortDescription(shortDesc), Description(desc),
- ErrorNode(errornode) {}
+ const Stmt *getStmt() const;
- BugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
- : BT(bt), Description(desc), Location(l) {}
+ /// If an event occurs in a different frame than the final diagnostic,
+ /// supply a message that will be used to construct an extra hint on the
+ /// returns from all the calls on the stack from this event to the final
+ /// diagnostic.
+ // FIXME: Allow shared_ptr keys in DenseMap?
+ std::map<PathDiagnosticPieceRef, std::unique_ptr<StackHintGenerator>>
+ StackHints;
- /// Create a BugReport with a custom uniqueing location.
+public:
+ PathSensitiveBugReport(const BugType &bt, StringRef desc,
+ const ExplodedNode *errorNode)
+ : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
+ ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
+ : SourceRange()) {}
+
+ PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
+ const ExplodedNode *errorNode)
+ : BugReport(Kind::PathSensitive, bt, shortDesc, desc),
+ ErrorNode(errorNode),
+ ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
+ : SourceRange()) {}
+
+ /// Create a PathSensitiveBugReport with a custom uniqueing location.
///
/// The reports that have the same report location, description, bug type, and
/// ranges are uniqued - only one of the equivalent reports will be presented
/// to the user. This method allows to rest the location which should be used
/// for uniquing reports. For example, memory leaks checker, could set this to
/// the allocation site, rather then the location where the bug is reported.
- BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
- PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
- : BT(bt), Description(desc), UniqueingLocation(LocationToUnique),
- UniqueingDecl(DeclToUnique), ErrorNode(errornode) {}
-
- virtual ~BugReport();
-
- const BugType& getBugType() const { return BT; }
- //BugType& getBugType() { return BT; }
+ PathSensitiveBugReport(BugType &bt, StringRef desc,
+ const ExplodedNode *errorNode,
+ PathDiagnosticLocation LocationToUnique,
+ const Decl *DeclToUnique)
+ : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
+ ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()),
+ UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {
+ assert(errorNode);
+ }
- /// True when the report has an execution path associated with it.
- ///
- /// A report is said to be path-sensitive if it was thrown against a
- /// particular exploded node in the path-sensitive analysis graph.
- /// Path-sensitive reports have their intermediate path diagnostics
- /// auto-generated, perhaps with the help of checker-defined visitors,
- /// and may contain extra notes.
- /// Path-insensitive reports consist only of a single warning message
- /// in a specific location, and perhaps extra notes.
- /// Path-sensitive checkers are allowed to throw path-insensitive reports.
- bool isPathSensitive() const { return ErrorNode != nullptr; }
+ static bool classof(const BugReport *R) {
+ return R->getKind() == Kind::PathSensitive;
+ }
const ExplodedNode *getErrorNode() const { return ErrorNode; }
- StringRef getDescription() const { return Description; }
-
- StringRef getShortDescription(bool UseFallback = true) const {
- if (ShortDescription.empty() && UseFallback)
- return Description;
- return ShortDescription;
- }
-
/// Indicates whether or not any path pruning should take place
/// when generating a PathDiagnostic from this BugReport.
bool shouldPrunePath() const { return !DoNotPrunePath; }
@@ -223,15 +409,54 @@ public:
/// Disable all path pruning when generating a PathDiagnostic.
void disablePathPruning() { DoNotPrunePath = true; }
- void markInteresting(SymbolRef sym);
- void markInteresting(const MemRegion *R);
- void markInteresting(SVal V);
+ /// Get the location on which the report should be uniqued.
+ PathDiagnosticLocation getUniqueingLocation() const override {
+ return UniqueingLocation;
+ }
+
+ /// Get the declaration containing the uniqueing location.
+ const Decl *getUniqueingDecl() const override {
+ return UniqueingDecl;
+ }
+
+ const Decl *getDeclWithIssue() const override;
+
+ ArrayRef<SourceRange> getRanges() const override;
+
+ PathDiagnosticLocation getLocation() const override;
+
+ /// Marks a symbol as interesting. Different kinds of interestingness will
+ /// be processed differently by visitors (e.g. if the tracking kind is
+ /// condition, will append "will be used as a condition" to the message).
+ void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind =
+ bugreporter::TrackingKind::Thorough);
+
+ /// Marks a region as interesting. Different kinds of interestingness will
+ /// be processed differently by visitors (e.g. if the tracking kind is
+ /// condition, will append "will be used as a condition" to the message).
+ void markInteresting(
+ const MemRegion *R,
+ bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough);
+
+ /// Marks a symbolic value as interesting. Different kinds of interestingness
+ /// will be processed differently by visitors (e.g. if the tracking kind is
+ /// condition, will append "will be used as a condition" to the message).
+ void markInteresting(SVal V, bugreporter::TrackingKind TKind =
+ bugreporter::TrackingKind::Thorough);
void markInteresting(const LocationContext *LC);
- bool isInteresting(SymbolRef sym);
- bool isInteresting(const MemRegion *R);
- bool isInteresting(SVal V);
- bool isInteresting(const LocationContext *LC);
+ bool isInteresting(SymbolRef sym) const;
+ bool isInteresting(const MemRegion *R) const;
+ bool isInteresting(SVal V) const;
+ bool isInteresting(const LocationContext *LC) const;
+
+ Optional<bugreporter::TrackingKind>
+ getInterestingnessKind(SymbolRef sym) const;
+
+ Optional<bugreporter::TrackingKind>
+ getInterestingnessKind(const MemRegion *R) const;
+
+ Optional<bugreporter::TrackingKind> getInterestingnessKind(SVal V) const;
/// Returns whether or not this report should be considered valid.
///
@@ -254,87 +479,10 @@ public:
Invalidations.insert(std::make_pair(Tag, Data));
}
- /// Return the canonical declaration, be it a method or class, where
- /// this issue semantically occurred.
- const Decl *getDeclWithIssue() const;
-
- /// Specifically set the Decl where an issue occurred. This isn't necessary
- /// for BugReports that cover a path as it will be automatically inferred.
- void setDeclWithIssue(const Decl *declWithIssue) {
- DeclWithIssue = declWithIssue;
- }
-
- /// Add new item to the list of additional notes that need to be attached to
- /// this path-insensitive report. If you want to add extra notes to a
- /// path-sensitive report, you need to use a BugReporterVisitor because it
- /// allows you to specify where exactly in the auto-generated path diagnostic
- /// the extra note should appear.
- void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
- ArrayRef<SourceRange> Ranges) {
- auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);
-
- for (const auto &R : Ranges)
- P->addRange(R);
-
- Notes.push_back(std::move(P));
- }
-
- // FIXME: Instead of making an override, we could have default-initialized
- // Ranges with {}, however it crashes the MSVC 2013 compiler.
- void addNote(StringRef Msg, const PathDiagnosticLocation &Pos) {
- std::vector<SourceRange> Ranges;
- addNote(Msg, Pos, Ranges);
- }
-
- virtual const NoteList &getNotes() {
- return Notes;
- }
-
- /// This allows for addition of meta data to the diagnostic.
- ///
- /// Currently, only the HTMLDiagnosticClient knows how to display it.
- void addExtraText(StringRef S) {
- ExtraText.push_back(S);
- }
-
- virtual const ExtraTextList &getExtraText() {
- return ExtraText;
- }
-
- /// Return the "definitive" location of the reported bug.
- ///
- /// While a bug can span an entire path, usually there is a specific
- /// location that can be used to identify where the key issue occurred.
- /// This location is used by clients rendering diagnostics.
- virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const;
-
- /// Get the location on which the report should be uniqued.
- PathDiagnosticLocation getUniqueingLocation() const {
- return UniqueingLocation;
- }
-
- /// Get the declaration containing the uniqueing location.
- const Decl *getUniqueingDecl() const {
- return UniqueingDecl;
- }
-
- const Stmt *getStmt() const;
-
- /// Add a range to a bug report.
- ///
- /// Ranges are used to highlight regions of interest in the source code.
- /// They should be at the same source code line as the BugReport location.
- /// By default, the source range of the statement corresponding to the error
- /// node will be used; add a single invalid range to specify absence of
- /// ranges.
- void addRange(SourceRange R) {
- assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
- "to specify that the report does not have a range.");
- Ranges.push_back(R);
- }
-
- /// Get the SourceRanges associated with the report.
- virtual llvm::iterator_range<ranges_iterator> getRanges();
+ /// Profile to identify equivalent bug reports for error report coalescing.
+ /// Reports are uniqued to ensure that we do not emit multiple diagnostics
+ /// for each bug.
+ void Profile(llvm::FoldingSetNodeID &hash) const override;
/// Add custom or predefined bug report visitors to this report.
///
@@ -351,6 +499,7 @@ public:
/// Iterators through the custom diagnostic visitors.
visitor_iterator visitor_begin() { return Callbacks.begin(); }
visitor_iterator visitor_end() { return Callbacks.end(); }
+ visitor_range visitors() { return {visitor_begin(), visitor_end()}; }
/// Notes that the condition of the CFGBlock associated with \p Cond is
/// being tracked.
@@ -359,10 +508,25 @@ public:
return TrackedConditions.insert(Cond).second;
}
- /// Profile to identify equivalent bug reports for error report coalescing.
- /// Reports are uniqued to ensure that we do not emit multiple diagnostics
- /// for each bug.
- virtual void Profile(llvm::FoldingSetNodeID& hash) const;
+ void addCallStackHint(PathDiagnosticPieceRef Piece,
+ std::unique_ptr<StackHintGenerator> StackHint) {
+ StackHints[Piece] = std::move(StackHint);
+ }
+
+ bool hasCallStackHint(PathDiagnosticPieceRef Piece) const {
+ return StackHints.count(Piece) > 0;
+ }
+
+ /// Produce the hint for the given node. The node contains
+ /// information about the call for which the diagnostic can be generated.
+ std::string
+ getCallStackMessage(PathDiagnosticPieceRef Piece,
+ const ExplodedNode *N) const {
+ auto I = StackHints.find(Piece);
+ if (I != StackHints.end())
+ return I->second->getMessage(N);
+ return "";
+ }
};
//===----------------------------------------------------------------------===//
@@ -373,29 +537,21 @@ class BugReportEquivClass : public llvm::FoldingSetNode {
friend class BugReporter;
/// List of *owned* BugReport objects.
- llvm::ilist<BugReport> Reports;
+ llvm::SmallVector<std::unique_ptr<BugReport>, 4> Reports;
- void AddReport(std::unique_ptr<BugReport> R) {
- Reports.push_back(R.release());
+ void AddReport(std::unique_ptr<BugReport> &&R) {
+ Reports.push_back(std::move(R));
}
public:
BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); }
- ~BugReportEquivClass();
+
+ ArrayRef<std::unique_ptr<BugReport>> getReports() const { return Reports; }
void Profile(llvm::FoldingSetNodeID& ID) const {
assert(!Reports.empty());
- Reports.front().Profile(ID);
+ Reports.front()->Profile(ID);
}
-
- using iterator = llvm::ilist<BugReport>::iterator;
- using const_iterator = llvm::ilist<BugReport>::const_iterator;
-
- iterator begin() { return Reports.begin(); }
- iterator end() { return Reports.end(); }
-
- const_iterator begin() const { return Reports.begin(); }
- const_iterator end() const { return Reports.end(); }
};
//===----------------------------------------------------------------------===//
@@ -404,9 +560,8 @@ public:
class BugReporterData {
public:
- virtual ~BugReporterData();
+ virtual ~BugReporterData() = default;
- virtual DiagnosticsEngine& getDiagnostic() = 0;
virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
virtual ASTContext &getASTContext() = 0;
virtual SourceManager &getSourceManager() = 0;
@@ -419,60 +574,29 @@ public:
///
/// The base class is used for generating path-insensitive
class BugReporter {
-public:
- enum Kind { BaseBRKind, GRBugReporterKind };
-
private:
- using BugTypesTy = llvm::ImmutableSet<BugType *>;
-
- BugTypesTy::Factory F;
- BugTypesTy BugTypes;
-
- const Kind kind;
BugReporterData& D;
/// Generate and flush the diagnostics for the given bug report.
void FlushReport(BugReportEquivClass& EQ);
- /// Generate the diagnostics for the given bug report.
- std::unique_ptr<DiagnosticForConsumerMapTy>
- generateDiagnosticForConsumerMap(BugReport *exampleReport,
- ArrayRef<PathDiagnosticConsumer *> consumers,
- ArrayRef<BugReport *> bugReports);
-
/// The set of bug reports tracked by the BugReporter.
llvm::FoldingSet<BugReportEquivClass> EQClasses;
/// A vector of BugReports for tracking the allocated pointers and cleanup.
std::vector<BugReportEquivClass *> EQClassesVector;
-protected:
- BugReporter(BugReporterData& d, Kind k)
- : BugTypes(F.getEmptySet()), kind(k), D(d) {}
-
public:
- BugReporter(BugReporterData& d)
- : BugTypes(F.getEmptySet()), kind(BaseBRKind), D(d) {}
+ BugReporter(BugReporterData &d) : D(d) {}
virtual ~BugReporter();
/// Generate and flush diagnostics for all bug reports.
void FlushReports();
- Kind getKind() const { return kind; }
-
- DiagnosticsEngine& getDiagnostic() {
- return D.getDiagnostic();
- }
-
ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
return D.getPathDiagnosticConsumers();
}
- /// Iterator over the set of BugTypes tracked by the BugReporter.
- using iterator = BugTypesTy::iterator;
- iterator begin() { return BugTypes.begin(); }
- iterator end() { return BugTypes.end(); }
-
/// Iterator over the set of BugReports tracked by the BugReporter.
using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator;
EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
@@ -480,126 +604,116 @@ public:
ASTContext &getContext() { return D.getASTContext(); }
- SourceManager &getSourceManager() { return D.getSourceManager(); }
-
- AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); }
-
- virtual std::unique_ptr<DiagnosticForConsumerMapTy>
- generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers,
- ArrayRef<BugReport *> &bugReports) {
- return {};
- }
+ const SourceManager &getSourceManager() { return D.getSourceManager(); }
- void Register(const BugType *BT);
+ const AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); }
/// Add the given report to the set of reports tracked by BugReporter.
///
/// The reports are usually generated by the checkers. Further, they are
/// folded based on the profile value, which is done to coalesce similar
/// reports.
- void emitReport(std::unique_ptr<BugReport> R);
+ virtual void emitReport(std::unique_ptr<BugReport> R);
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
StringRef BugName, StringRef BugCategory,
StringRef BugStr, PathDiagnosticLocation Loc,
- ArrayRef<SourceRange> Ranges = None);
+ ArrayRef<SourceRange> Ranges = None,
+ ArrayRef<FixItHint> Fixits = None);
- void EmitBasicReport(const Decl *DeclWithIssue, CheckName CheckName,
+ void EmitBasicReport(const Decl *DeclWithIssue, CheckerNameRef CheckerName,
StringRef BugName, StringRef BugCategory,
StringRef BugStr, PathDiagnosticLocation Loc,
- ArrayRef<SourceRange> Ranges = None);
+ ArrayRef<SourceRange> Ranges = None,
+ ArrayRef<FixItHint> Fixits = None);
private:
llvm::StringMap<BugType *> StrBugTypes;
/// Returns a BugType that is associated with the given name and
/// category.
- BugType *getBugTypeForName(CheckName CheckName, StringRef name,
+ BugType *getBugTypeForName(CheckerNameRef CheckerName, StringRef name,
StringRef category);
+
+ virtual BugReport *
+ findReportInEquivalenceClass(BugReportEquivClass &eqClass,
+ SmallVectorImpl<BugReport *> &bugReports) {
+ return eqClass.getReports()[0].get();
+ }
+
+protected:
+ /// Generate the diagnostics for the given bug report.
+ virtual std::unique_ptr<DiagnosticForConsumerMapTy>
+ generateDiagnosticForConsumerMap(BugReport *exampleReport,
+ ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<BugReport *> bugReports);
};
/// GRBugReporter is used for generating path-sensitive reports.
-class GRBugReporter : public BugReporter {
+class PathSensitiveBugReporter final : public BugReporter {
ExprEngine& Eng;
-public:
- GRBugReporter(BugReporterData& d, ExprEngine& eng)
- : BugReporter(d, GRBugReporterKind), Eng(eng) {}
+ BugReport *findReportInEquivalenceClass(
+ BugReportEquivClass &eqClass,
+ SmallVectorImpl<BugReport *> &bugReports) override;
- ~GRBugReporter() override;
+ /// Generate the diagnostics for the given bug report.
+ std::unique_ptr<DiagnosticForConsumerMapTy>
+ generateDiagnosticForConsumerMap(BugReport *exampleReport,
+ ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<BugReport *> bugReports) override;
+public:
+ PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng)
+ : BugReporter(d), Eng(eng) {}
/// getGraph - Get the exploded graph created by the analysis engine
/// for the analyzed method or function.
- ExplodedGraph &getGraph();
+ const ExplodedGraph &getGraph() const;
/// getStateManager - Return the state manager used by the analysis
/// engine.
- ProgramStateManager &getStateManager();
+ ProgramStateManager &getStateManager() const;
/// \p bugReports A set of bug reports within a *single* equivalence class
///
/// \return A mapping from consumers to the corresponding diagnostics.
/// Iterates through the bug reports within a single equivalence class,
/// stops at a first non-invalidated report.
- std::unique_ptr<DiagnosticForConsumerMapTy>
- generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers,
- ArrayRef<BugReport *> &bugReports) override;
+ std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics(
+ ArrayRef<PathDiagnosticConsumer *> consumers,
+ ArrayRef<PathSensitiveBugReport *> &bugReports);
- /// classof - Used by isa<>, cast<>, and dyn_cast<>.
- static bool classof(const BugReporter* R) {
- return R->getKind() == GRBugReporterKind;
- }
+ void emitReport(std::unique_ptr<BugReport> R) override;
};
-class NodeMapClosure : public BugReport::NodeResolver {
- InterExplodedGraphMap &M;
-
-public:
- NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
-
- const ExplodedNode *getOriginalNode(const ExplodedNode *N) override {
- return M.lookup(N);
- }
-};
-
class BugReporterContext {
- GRBugReporter &BR;
- NodeMapClosure NMC;
+ PathSensitiveBugReporter &BR;
virtual void anchor();
public:
- BugReporterContext(GRBugReporter &br, InterExplodedGraphMap &Backmap)
- : BR(br), NMC(Backmap) {}
+ BugReporterContext(PathSensitiveBugReporter &br) : BR(br) {}
virtual ~BugReporterContext() = default;
- GRBugReporter& getBugReporter() { return BR; }
+ PathSensitiveBugReporter& getBugReporter() { return BR; }
- ExplodedGraph &getGraph() { return BR.getGraph(); }
-
- ProgramStateManager& getStateManager() {
+ ProgramStateManager& getStateManager() const {
return BR.getStateManager();
}
- SValBuilder &getSValBuilder() {
- return getStateManager().getSValBuilder();
- }
-
- ASTContext &getASTContext() {
+ ASTContext &getASTContext() const {
return BR.getContext();
}
- SourceManager& getSourceManager() {
+ const SourceManager& getSourceManager() const {
return BR.getSourceManager();
}
- AnalyzerOptions &getAnalyzerOptions() {
+ const AnalyzerOptions &getAnalyzerOptions() const {
return BR.getAnalyzerOptions();
}
-
- NodeMapClosure& getNodeResolver() { return NMC; }
};
@@ -648,7 +762,7 @@ public:
public:
const NoteTag *makeNoteTag(Callback &&Cb, bool IsPrunable = false) {
- // We cannot use make_unique because we cannot access the private
+ // We cannot use std::make_unique because we cannot access the private
// constructor from inside it.
std::unique_ptr<NoteTag> T(new NoteTag(std::move(Cb), IsPrunable));
Tags.push_back(std::move(T));
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index ef5d327d39da..de0ee5de81b5 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -33,11 +33,12 @@ class Stmt;
namespace ento {
-class BugReport;
+class PathSensitiveBugReport;
class BugReporterContext;
class ExplodedNode;
class MemRegion;
class PathDiagnosticPiece;
+using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
/// BugReporterVisitors are used to add custom diagnostics along a path.
class BugReporterVisitor : public llvm::FoldingSetNode {
@@ -57,32 +58,68 @@ public:
///
/// The last parameter can be used to register a new visitor with the given
/// BugReport while processing a node.
- virtual std::shared_ptr<PathDiagnosticPiece>
- VisitNode(const ExplodedNode *Succ,
- BugReporterContext &BRC, BugReport &BR) = 0;
+ virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) = 0;
/// Last function called on the visitor, no further calls to VisitNode
/// would follow.
virtual void finalizeVisitor(BugReporterContext &BRC,
const ExplodedNode *EndPathNode,
- BugReport &BR);
+ PathSensitiveBugReport &BR);
/// Provide custom definition for the final diagnostic piece on the
/// path - the piece, which is displayed before the path is expanded.
///
/// NOTE that this function can be implemented on at most one used visitor,
/// and otherwise it crahes at runtime.
- virtual std::shared_ptr<PathDiagnosticPiece>
- getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR);
+ virtual PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
+ const ExplodedNode *N,
+ PathSensitiveBugReport &BR);
virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
/// Generates the default final diagnostic piece.
- static std::shared_ptr<PathDiagnosticPiece>
- getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N,
- BugReport &BR);
+ static PathDiagnosticPieceRef
+ getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N,
+ const PathSensitiveBugReport &BR);
};
+namespace bugreporter {
+
+/// Specifies the type of tracking for an expression.
+enum class TrackingKind {
+ /// Default tracking kind -- specifies that as much information should be
+ /// gathered about the tracked expression value as possible.
+ Thorough,
+ /// Specifies that a more moderate tracking should be used for the expression
+ /// value. This will essentially make sure that functions relevant to the it
+ /// aren't pruned, but otherwise relies on the user reading the code or
+ /// following the arrows.
+ Condition
+};
+
+/// Attempts to add visitors to track expression value back to its point of
+/// origin.
+///
+/// \param N A node "downstream" from the evaluation of the statement.
+/// \param E The expression value which we are tracking
+/// \param R The bug report to which visitors should be attached.
+/// \param EnableNullFPSuppression Whether we should employ false positive
+/// suppression (inlined defensive checks, returned null).
+///
+/// \return Whether or not the function was able to add visitors for this
+/// statement. Note that returning \c true does not actually imply
+/// that any visitors were added.
+bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
+ PathSensitiveBugReport &R,
+ TrackingKind TKind = TrackingKind::Thorough,
+ bool EnableNullFPSuppression = true);
+
+const Expr *getDerefExpr(const Stmt *S);
+
+} // namespace bugreporter
+
/// Finds last store into the given region,
/// which is different from a given symbolic value.
class FindLastStoreBRVisitor final : public BugReporterVisitor {
@@ -94,21 +131,34 @@ class FindLastStoreBRVisitor final : public BugReporterVisitor {
/// bug, we are going to employ false positive suppression.
bool EnableNullFPSuppression;
-public:
- /// Creates a visitor for every VarDecl inside a Stmt and registers it with
- /// the BugReport.
- static void registerStatementVarDecls(BugReport &BR, const Stmt *S,
- bool EnableNullFPSuppression);
+ using TrackingKind = bugreporter::TrackingKind;
+ TrackingKind TKind;
+ const StackFrameContext *OriginSFC;
+public:
+ /// \param V We're searching for the store where \c R received this value.
+ /// \param R The region we're tracking.
+ /// \param TKind May limit the amount of notes added to the bug report.
+ /// \param OriginSFC Only adds notes when the last store happened in a
+ /// different stackframe to this one. Disregarded if the tracking kind
+ /// is thorough.
+ /// This is useful, because for non-tracked regions, notes about
+ /// changes to its value in a nested stackframe could be pruned, and
+ /// this visitor can prevent that without polluting the bugpath too
+ /// much.
FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R,
- bool InEnableNullFPSuppression)
- : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression) {}
+ bool InEnableNullFPSuppression, TrackingKind TKind,
+ const StackFrameContext *OriginSFC = nullptr)
+ : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression),
+ TKind(TKind), OriginSFC(OriginSFC) {
+ assert(R);
+ }
void Profile(llvm::FoldingSetNodeID &ID) const override;
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
};
class TrackConstraintBRVisitor final : public BugReporterVisitor {
@@ -132,9 +182,9 @@ public:
/// to make all PathDiagnosticPieces created by this visitor.
static const char *getTag();
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
private:
/// Checks if the constraint is valid in the current state.
@@ -150,9 +200,9 @@ public:
ID.AddPointer(&x);
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
/// If the statement is a message send expression with nil receiver, returns
/// the receiver expression. Returns NULL otherwise.
@@ -162,8 +212,10 @@ public:
/// Visitor that tries to report interesting diagnostics from conditions.
class ConditionBRVisitor final : public BugReporterVisitor {
// FIXME: constexpr initialization isn't supported by MSVC2013.
- static const char *const GenericTrueMessage;
- static const char *const GenericFalseMessage;
+ constexpr static llvm::StringLiteral GenericTrueMessage =
+ "Assuming the condition is true";
+ constexpr static llvm::StringLiteral GenericFalseMessage =
+ "Assuming the condition is false";
public:
void Profile(llvm::FoldingSetNodeID &ID) const override {
@@ -175,41 +227,44 @@ public:
/// to make all PathDiagnosticPieces created by this visitor.
static const char *getTag();
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
- std::shared_ptr<PathDiagnosticPiece> VisitNodeImpl(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR);
+ PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR);
- std::shared_ptr<PathDiagnosticPiece>
+ PathDiagnosticPieceRef
VisitTerminator(const Stmt *Term, const ExplodedNode *N,
- const CFGBlock *srcBlk, const CFGBlock *dstBlk, BugReport &R,
- BugReporterContext &BRC);
+ const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
+ PathSensitiveBugReport &R, BugReporterContext &BRC);
- std::shared_ptr<PathDiagnosticPiece>
- VisitTrueTest(const Expr *Cond, BugReporterContext &BRC, BugReport &R,
- const ExplodedNode *N, bool TookTrue);
+ PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue);
- std::shared_ptr<PathDiagnosticPiece>
- VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
- BugReporterContext &BRC, BugReport &R, const ExplodedNode *N,
- bool TookTrue, bool IsAssuming);
+ PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue,
+ bool IsAssuming);
- std::shared_ptr<PathDiagnosticPiece>
+ PathDiagnosticPieceRef
VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
- BugReporterContext &BRC, BugReport &R, const ExplodedNode *N,
- bool TookTrue, bool IsAssuming);
+ BugReporterContext &BRC, PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue, bool IsAssuming);
- std::shared_ptr<PathDiagnosticPiece>
- VisitTrueTest(const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC,
- BugReport &R, const ExplodedNode *N, bool TookTrue,
- bool IsAssuming);
+ PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const MemberExpr *ME,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue,
+ bool IsAssuming);
- std::shared_ptr<PathDiagnosticPiece>
+ PathDiagnosticPieceRef
VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr,
- BugReporterContext &BRC, BugReport &R,
+ BugReporterContext &BRC, PathSensitiveBugReport &R,
const ExplodedNode *N, bool TookTrue);
/// Tries to print the value of the given expression.
@@ -228,7 +283,7 @@ public:
const Expr *ParentEx,
raw_ostream &Out,
BugReporterContext &BRC,
- BugReport &R,
+ PathSensitiveBugReport &R,
const ExplodedNode *N,
Optional<bool> &prunable,
bool IsSameFieldName);
@@ -251,14 +306,13 @@ public:
ID.AddPointer(getTag());
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *,
- BugReporterContext &,
- BugReport &) override {
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *, BugReporterContext &,
+ PathSensitiveBugReport &) override {
return nullptr;
}
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
- BugReport &BR) override;
+ PathSensitiveBugReport &BR) override;
};
/// When a region containing undefined value or '0' value is passed
@@ -279,9 +333,9 @@ public:
ID.AddPointer(R);
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
};
class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor {
@@ -308,9 +362,9 @@ public:
/// to make all PathDiagnosticPieces created by this visitor.
static const char *getTag();
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
};
/// The bug visitor will walk all the nodes in a path and collect all the
@@ -326,12 +380,12 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
- BugReport &BR) override;
+ PathSensitiveBugReport &BR) override;
};
@@ -340,32 +394,11 @@ class TagVisitor : public BugReporterVisitor {
public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &R) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R) override;
};
-namespace bugreporter {
-
-/// Attempts to add visitors to track expression value back to its point of
-/// origin.
-///
-/// \param N A node "downstream" from the evaluation of the statement.
-/// \param E The expression value which we are tracking
-/// \param R The bug report to which visitors should be attached.
-/// \param EnableNullFPSuppression Whether we should employ false positive
-/// suppression (inlined defensive checks, returned null).
-///
-/// \return Whether or not the function was able to add visitors for this
-/// statement. Note that returning \c true does not actually imply
-/// that any visitors were added.
-bool trackExpressionValue(const ExplodedNode *N, const Expr *E, BugReport &R,
- bool EnableNullFPSuppression = true);
-
-const Expr *getDerefExpr(const Stmt *S);
-
-} // namespace bugreporter
-
} // namespace ento
} // namespace clang
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 324b5312e790..237053df7e44 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -28,8 +28,8 @@ class ExprEngine;
class BugType {
private:
- const CheckName Check;
- const std::string Name;
+ const CheckerNameRef CheckerName;
+ const std::string Description;
const std::string Category;
const CheckerBase *Checker;
bool SuppressOnSink;
@@ -37,28 +37,27 @@ private:
virtual void anchor();
public:
- BugType(CheckName Check, StringRef Name, StringRef Cat,
- bool SuppressOnSink=false)
- : Check(Check), Name(Name), Category(Cat), Checker(nullptr),
- SuppressOnSink(SuppressOnSink) {}
+ BugType(CheckerNameRef CheckerName, StringRef Name, StringRef Cat,
+ bool SuppressOnSink = false)
+ : CheckerName(CheckerName), Description(Name), Category(Cat),
+ Checker(nullptr), SuppressOnSink(SuppressOnSink) {}
BugType(const CheckerBase *Checker, StringRef Name, StringRef Cat,
- bool SuppressOnSink=false)
- : Check(Checker->getCheckName()), Name(Name), Category(Cat),
- Checker(Checker), SuppressOnSink(SuppressOnSink) {}
+ bool SuppressOnSink = false)
+ : CheckerName(Checker->getCheckerName()), Description(Name),
+ Category(Cat), Checker(Checker), SuppressOnSink(SuppressOnSink) {}
virtual ~BugType() = default;
- StringRef getName() const { return Name; }
+ StringRef getDescription() const { return Description; }
StringRef getCategory() const { return Category; }
- StringRef getCheckName() const {
- // FIXME: This is a workaround to ensure that the correct check name is used
- // The check names are set after the constructors are run.
+ StringRef getCheckerName() const {
+ // FIXME: This is a workaround to ensure that the correct checerk name is
+ // used. The checker names are set after the constructors are run.
// In case the BugType object is initialized in the checker's ctor
- // the Check field will be empty. To circumvent this problem we use
+ // the CheckerName field will be empty. To circumvent this problem we use
// CheckerBase whenever it is possible.
- StringRef CheckName =
- Checker ? Checker->getCheckName().getName() : Check.getName();
- assert(!CheckName.empty() && "Check name is not set properly.");
- return CheckName;
+ StringRef Ret = Checker ? Checker->getCheckerName() : CheckerName;
+ assert(!Ret.empty() && "Checker name is not set properly.");
+ return Ret;
}
/// isSuppressOnSink - Returns true if bug reports associated with this bug
@@ -71,8 +70,9 @@ class BuiltinBug : public BugType {
const std::string desc;
void anchor() override;
public:
- BuiltinBug(class CheckName check, const char *name, const char *description)
- : BugType(check, name, categories::LogicError), desc(description) {}
+ BuiltinBug(class CheckerNameRef checker, const char *name,
+ const char *description)
+ : BugType(checker, name, categories::LogicError), desc(description) {}
BuiltinBug(const CheckerBase *checker, const char *name,
const char *description)
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
index 85526eb49f0c..22c1a7dd98cc 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
@@ -18,6 +18,7 @@ namespace clang {
extern const char * const MemoryRefCount;
extern const char * const MemoryError;
extern const char * const UnixAPI;
+ extern const char * const CXXObjectLifecycle;
}
}
}
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index d0fe15f8b896..0c7acdbc3a97 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -490,12 +490,12 @@ public:
} // end eval namespace
class CheckerBase : public ProgramPointTag {
- CheckName Name;
+ CheckerNameRef Name;
friend class ::clang::ento::CheckerManager;
public:
StringRef getTagDescription() const override;
- CheckName getCheckName() const;
+ CheckerNameRef getCheckerName() const;
/// See CheckerManager::runCheckersForPrintState.
virtual void printState(raw_ostream &Out, ProgramStateRef State,
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 6cc4baa1687f..38a9aaf72c27 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -90,21 +90,23 @@ enum PointerEscapeKind {
PSK_EscapeOther
};
-// This wrapper is used to ensure that only StringRefs originating from the
-// CheckerRegistry are used as check names. We want to make sure all check
-// name strings have a lifetime that keeps them alive at least until the path
-// diagnostics have been processed.
-class CheckName {
+/// This wrapper is used to ensure that only StringRefs originating from the
+/// CheckerRegistry are used as check names. We want to make sure all checker
+/// name strings have a lifetime that keeps them alive at least until the path
+/// diagnostics have been processed, since they are expected to be constexpr
+/// string literals (most likely generated by TblGen).
+class CheckerNameRef {
friend class ::clang::ento::CheckerRegistry;
StringRef Name;
- explicit CheckName(StringRef Name) : Name(Name) {}
+ explicit CheckerNameRef(StringRef Name) : Name(Name) {}
public:
- CheckName() = default;
+ CheckerNameRef() = default;
StringRef getName() const { return Name; }
+ operator StringRef() const { return Name; }
};
enum class ObjCMessageVisitKind {
@@ -117,7 +119,7 @@ class CheckerManager {
ASTContext &Context;
const LangOptions LangOpts;
AnalyzerOptions &AOptions;
- CheckName CurrentCheckName;
+ CheckerNameRef CurrentCheckerName;
public:
CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions)
@@ -125,8 +127,8 @@ public:
~CheckerManager();
- void setCurrentCheckName(CheckName name) { CurrentCheckName = name; }
- CheckName getCurrentCheckName() const { return CurrentCheckName; }
+ void setCurrentCheckerName(CheckerNameRef name) { CurrentCheckerName = name; }
+ CheckerNameRef getCurrentCheckerName() const { return CurrentCheckerName; }
bool hasPathSensitiveCheckers() const;
@@ -162,7 +164,7 @@ public:
assert(!ref && "Checker already registered, use getChecker!");
CHECKER *checker = new CHECKER(std::forward<AT>(Args)...);
- checker->Name = CurrentCheckName;
+ checker->Name = CurrentCheckerName;
CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
CHECKER::_register(checker, *this);
ref = checker;
diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index ef6e7e0f45d5..8601966c91e5 100644
--- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -20,17 +20,19 @@ namespace clang {
class AnalyzerOptions;
class Preprocessor;
+namespace cross_tu {
+class CrossTranslationUnitContext;
+}
namespace ento {
class PathDiagnosticConsumer;
typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
-void CREATEFN(AnalyzerOptions &AnalyzerOpts,\
- PathDiagnosticConsumers &C,\
- const std::string &Prefix,\
- const Preprocessor &PP);
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
+ void CREATEFN(AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, \
+ const std::string &Prefix, const Preprocessor &PP, \
+ const cross_tu::CrossTranslationUnitContext &CTU);
#include "clang/StaticAnalyzer/Core/Analyses.def"
} // end 'ento' namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index b0dda78a00a9..d605a6a667f6 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -15,9 +15,9 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
namespace clang {
@@ -32,7 +32,6 @@ class AnalysisManager : public BugReporterData {
AnalysisDeclContextManager AnaCtxMgr;
ASTContext &Ctx;
- DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
PathDiagnosticConsumers PathConsumers;
@@ -45,7 +44,7 @@ class AnalysisManager : public BugReporterData {
public:
AnalyzerOptions &options;
- AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
+ AnalysisManager(ASTContext &ctx,
const PathDiagnosticConsumers &Consumers,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
@@ -84,10 +83,6 @@ public:
return getASTContext().getSourceManager();
}
- DiagnosticsEngine &getDiagnostic() override {
- return Diags;
- }
-
const LangOptions &getLangOpts() const {
return LangOpts;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index db84102983af..fc1cc9138826 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -347,7 +347,7 @@ public:
ProgramStateRef invalidateRegions(unsigned BlockCount,
ProgramStateRef Orig = nullptr) const;
- using FrameBindingTy = std::pair<Loc, SVal>;
+ using FrameBindingTy = std::pair<SVal, SVal>;
using BindingsTy = SmallVectorImpl<FrameBindingTy>;
/// Populates the given SmallVector with the bindings in the callee's stack
@@ -386,11 +386,12 @@ public:
/// during analysis if the call is inlined, but it may still be useful
/// in intermediate calculations even if the call isn't inlined.
/// May fail; returns null on failure.
- const StackFrameContext *getCalleeStackFrame() const;
+ const StackFrameContext *getCalleeStackFrame(unsigned BlockCount) const;
/// Returns memory location for a parameter variable within the callee stack
/// frame. May fail; returns null on failure.
- const VarRegion *getParameterLocation(unsigned Index) const;
+ const VarRegion *getParameterLocation(unsigned Index,
+ unsigned BlockCount) const;
/// Returns true if on the current path, the argument was constructed by
/// calling a C++ constructor over it. This is an internal detail of the
@@ -1063,8 +1064,19 @@ class CallDescription {
// e.g. "{a, b}" represent the qualified names, like "a::b".
std::vector<const char *> QualifiedName;
Optional<unsigned> RequiredArgs;
+ Optional<size_t> RequiredParams;
int Flags;
+ // A constructor helper.
+ static Optional<size_t> readRequiredParams(Optional<unsigned> RequiredArgs,
+ Optional<size_t> RequiredParams) {
+ if (RequiredParams)
+ return RequiredParams;
+ if (RequiredArgs)
+ return static_cast<size_t>(*RequiredArgs);
+ return None;
+ }
+
public:
/// Constructs a CallDescription object.
///
@@ -1077,14 +1089,17 @@ public:
/// call. Omit this parameter to match every occurrence of call with a given
/// name regardless the number of arguments.
CallDescription(int Flags, ArrayRef<const char *> QualifiedName,
- Optional<unsigned> RequiredArgs = None)
+ Optional<unsigned> RequiredArgs = None,
+ Optional<size_t> RequiredParams = None)
: QualifiedName(QualifiedName), RequiredArgs(RequiredArgs),
+ RequiredParams(readRequiredParams(RequiredArgs, RequiredParams)),
Flags(Flags) {}
/// Construct a CallDescription with default flags.
CallDescription(ArrayRef<const char *> QualifiedName,
- Optional<unsigned> RequiredArgs = None)
- : CallDescription(0, QualifiedName, RequiredArgs) {}
+ Optional<unsigned> RequiredArgs = None,
+ Optional<size_t> RequiredParams = None)
+ : CallDescription(0, QualifiedName, RequiredArgs, RequiredParams) {}
/// Get the name of the function that this object matches.
StringRef getFunctionName() const { return QualifiedName.back(); }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 981133e66977..7f4df0d88def 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -103,7 +103,7 @@ public:
return Eng.getBugReporter();
}
- SourceManager &getSourceManager() {
+ const SourceManager &getSourceManager() {
return getBugReporter().getSourceManager();
}
@@ -234,7 +234,7 @@ public:
}
/// A shorthand version of getNoteTag that doesn't require you to accept
- /// the BugReporterContext arguments when you don't need it.
+ /// the 'BugReporterContext' argument when you don't need it.
///
/// @param Cb Callback only with 'BugReport &' parameter.
/// @param IsPrunable Whether the note is prunable. It allows BugReporter
@@ -247,6 +247,19 @@ public:
IsPrunable);
}
+ /// A shorthand version of getNoteTag that doesn't require you to accept
+ /// the arguments when you don't need it.
+ ///
+ /// @param Cb Callback without parameters.
+ /// @param IsPrunable Whether the note is prunable. It allows BugReporter
+ /// to omit the note from the report if it would make the displayed
+ /// bug path significantly shorter.
+ const NoteTag *getNoteTag(std::function<std::string()> &&Cb,
+ bool IsPrunable = false) {
+ return getNoteTag([Cb](BugReporterContext &, BugReport &) { return Cb(); },
+ IsPrunable);
+ }
+
/// A shorthand version of getNoteTag that accepts a plain note.
///
/// @param Note The note.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h
new file mode 100644
index 000000000000..f5a710c77a6a
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h
@@ -0,0 +1,55 @@
+//===- DynamicCastInfo.h - Runtime cast information -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICCASTINFO_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICCASTINFO_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace ento {
+
+class DynamicCastInfo {
+public:
+ enum CastResult { Success, Failure };
+
+ DynamicCastInfo(QualType from, QualType to, CastResult resultKind)
+ : From(from), To(to), ResultKind(resultKind) {}
+
+ QualType from() const { return From; }
+ QualType to() const { return To; }
+
+ bool equals(QualType from, QualType to) const {
+ return From == from && To == to;
+ }
+
+ bool succeeds() const { return ResultKind == CastResult::Success; }
+ bool fails() const { return ResultKind == CastResult::Failure; }
+
+ bool operator==(const DynamicCastInfo &RHS) const {
+ return From == RHS.From && To == RHS.To;
+ }
+ bool operator<(const DynamicCastInfo &RHS) const {
+ return From < RHS.From && To < RHS.To;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.Add(From);
+ ID.Add(To);
+ ID.AddInteger(ResultKind);
+ }
+
+private:
+ QualType From, To;
+ CastResult ResultKind;
+};
+
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICCASTINFO_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h
new file mode 100644
index 000000000000..356401d77561
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h
@@ -0,0 +1,73 @@
+//===- DynamicType.h - Dynamic type related APIs ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines APIs that track and query dynamic type information. This
+// information can be used to devirtualize calls during the symbolic execution
+// or do type checking.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPE_H
+
+#include "clang/AST/Type.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/Optional.h"
+#include <utility>
+
+namespace clang {
+namespace ento {
+
+/// Get dynamic type information for the region \p MR.
+DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR);
+
+/// Get raw dynamic type information for the region \p MR.
+const DynamicTypeInfo *getRawDynamicTypeInfo(ProgramStateRef State,
+ const MemRegion *MR);
+
+/// Get dynamic cast information from \p CastFromTy to \p CastToTy of \p MR.
+const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State,
+ const MemRegion *MR,
+ QualType CastFromTy,
+ QualType CastToTy);
+
+/// Set dynamic type information of the region; return the new state.
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR,
+ DynamicTypeInfo NewTy);
+
+/// Set dynamic type information of the region; return the new state.
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR,
+ QualType NewTy, bool CanBeSubClassed = true);
+
+/// Set dynamic type and cast information of the region; return the new state.
+ProgramStateRef setDynamicTypeAndCastInfo(ProgramStateRef State,
+ const MemRegion *MR,
+ QualType CastFromTy,
+ QualType CastToTy,
+ bool IsCastSucceeds);
+
+/// Removes the dead type informations from \p State.
+ProgramStateRef removeDeadTypes(ProgramStateRef State, SymbolReaper &SR);
+
+/// Removes the dead cast informations from \p State.
+ProgramStateRef removeDeadCasts(ProgramStateRef State, SymbolReaper &SR);
+
+void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
+ const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false);
+
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPE_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
index 9bb1e2137566..6262c4a1ce37 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
@@ -1,10 +1,11 @@
-//== DynamicTypeInfo.h - Runtime type information ----------------*- C++ -*--=//
+//===- DynamicTypeInfo.h - Runtime type information -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
@@ -16,36 +17,37 @@ namespace ento {
/// Stores the currently inferred strictest bound on the runtime type
/// of a region in a given state along the analysis path.
class DynamicTypeInfo {
-private:
- QualType T;
- bool CanBeASubClass;
-
public:
+ DynamicTypeInfo() : DynTy(QualType()) {}
- DynamicTypeInfo() : T(QualType()) {}
- DynamicTypeInfo(QualType WithType, bool CanBeSub = true)
- : T(WithType), CanBeASubClass(CanBeSub) {}
+ DynamicTypeInfo(QualType Ty, bool CanBeSub = true)
+ : DynTy(Ty), CanBeASubClass(CanBeSub) {}
+
+ /// Returns false if the type information is precise (the type 'DynTy' is
+ /// the only type in the lattice), true otherwise.
+ bool canBeASubClass() const { return CanBeASubClass; }
- /// Return false if no dynamic type info is available.
- bool isValid() const { return !T.isNull(); }
+ /// Returns true if the dynamic type info is available.
+ bool isValid() const { return !DynTy.isNull(); }
/// Returns the currently inferred upper bound on the runtime type.
- QualType getType() const { return T; }
+ QualType getType() const { return DynTy; }
- /// Returns false if the type information is precise (the type T is
- /// the only type in the lattice), true otherwise.
- bool canBeASubClass() const { return CanBeASubClass; }
+ bool operator==(const DynamicTypeInfo &RHS) const {
+ return DynTy == RHS.DynTy && CanBeASubClass == RHS.CanBeASubClass;
+ }
void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.Add(T);
- ID.AddInteger((unsigned)CanBeASubClass);
- }
- bool operator==(const DynamicTypeInfo &X) const {
- return T == X.T && CanBeASubClass == X.CanBeASubClass;
+ ID.Add(DynTy);
+ ID.AddBoolean(CanBeASubClass);
}
+
+private:
+ QualType DynTy;
+ bool CanBeASubClass;
};
-} // end ento
-} // end clang
+} // namespace ento
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
deleted file mode 100644
index a84b24872061..000000000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===- DynamicTypeMap.h - Dynamic type map ----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides APIs for tracking dynamic type information.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "llvm/ADT/ImmutableMap.h"
-#include "clang/AST/Type.h"
-
-namespace clang {
-namespace ento {
-
-class MemRegion;
-
-/// The GDM component containing the dynamic type info. This is a map from a
-/// symbol to its most likely type.
-struct DynamicTypeMap {};
-
-using DynamicTypeMapTy = llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>;
-
-template <>
-struct ProgramStateTrait<DynamicTypeMap>
- : public ProgramStatePartialTrait<DynamicTypeMapTy> {
- static void *GDMIndex();
-};
-
-/// Get dynamic type information for a region.
-DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
- const MemRegion *Reg);
-
-/// Set dynamic type information of the region; return the new state.
-ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
- DynamicTypeInfo NewTy);
-
-/// Set dynamic type information of the region; return the new state.
-inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
- const MemRegion *Reg, QualType NewTy,
- bool CanBeSubClassed = true) {
- return setDynamicTypeInfo(State, Reg,
- DynamicTypeInfo(NewTy, CanBeSubClassed));
-}
-
-void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
- const char *NL = "\n", unsigned int Space = 0,
- bool IsDot = false);
-
-} // namespace ento
-} // namespace clang
-
-#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 727d04cba278..e87772c04b9b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -131,10 +131,12 @@ class ExplodedNode : public llvm::FoldingSetNode {
/// Succs - The successors of this node.
NodeGroup Succs;
+ int64_t Id;
+
public:
explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
- bool IsSink)
- : Location(loc), State(std::move(state)), Succs(IsSink) {
+ int64_t Id, bool IsSink)
+ : Location(loc), State(std::move(state)), Succs(IsSink), Id(Id) {
assert(isSink() == IsSink);
}
@@ -153,7 +155,11 @@ public:
CFG &getCFG() const { return *getLocationContext()->getCFG(); }
- ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
+ const CFGBlock *getCFGBlock() const;
+
+ const ParentMap &getParentMap() const {
+ return getLocationContext()->getParentMap();
+ }
template <typename T>
T &getAnalysis() const {
@@ -219,12 +225,20 @@ public:
// Iterators over successor and predecessor vertices.
using succ_iterator = ExplodedNode * const *;
+ using succ_range = llvm::iterator_range<succ_iterator>;
+
using const_succ_iterator = const ExplodedNode * const *;
+ using const_succ_range = llvm::iterator_range<const_succ_iterator>;
+
using pred_iterator = ExplodedNode * const *;
+ using pred_range = llvm::iterator_range<pred_iterator>;
+
using const_pred_iterator = const ExplodedNode * const *;
+ using const_pred_range = llvm::iterator_range<const_pred_iterator>;
pred_iterator pred_begin() { return Preds.begin(); }
pred_iterator pred_end() { return Preds.end(); }
+ pred_range preds() { return {Preds.begin(), Preds.end()}; }
const_pred_iterator pred_begin() const {
return const_cast<ExplodedNode*>(this)->pred_begin();
@@ -232,9 +246,11 @@ public:
const_pred_iterator pred_end() const {
return const_cast<ExplodedNode*>(this)->pred_end();
}
+ const_pred_range preds() const { return {Preds.begin(), Preds.end()}; }
succ_iterator succ_begin() { return Succs.begin(); }
succ_iterator succ_end() { return Succs.end(); }
+ succ_range succs() { return {Succs.begin(), Succs.end()}; }
const_succ_iterator succ_begin() const {
return const_cast<ExplodedNode*>(this)->succ_begin();
@@ -242,8 +258,9 @@ public:
const_succ_iterator succ_end() const {
return const_cast<ExplodedNode*>(this)->succ_end();
}
+ const_succ_range succs() const { return {Succs.begin(), Succs.end()}; }
- int64_t getID(ExplodedGraph *G) const;
+ int64_t getID() const { return Id; }
/// The node is trivial if it has only one successor, only one predecessor,
/// it's predecessor has only one successor,
@@ -252,6 +269,30 @@ public:
/// Trivial nodes may be skipped while printing exploded graph.
bool isTrivial() const;
+ /// If the node's program point corresponds to a statement, retrieve that
+ /// statement. Useful for figuring out where to put a warning or a note.
+ /// If the statement belongs to a body-farmed definition,
+ /// retrieve the call site for that definition.
+ const Stmt *getStmtForDiagnostics() const;
+
+ /// Find the next statement that was executed on this node's execution path.
+ /// Useful for explaining control flow that follows the current node.
+ /// If the statement belongs to a body-farmed definition, retrieve the
+ /// call site for that definition.
+ const Stmt *getNextStmtForDiagnostics() const;
+
+ /// Find the statement that was executed immediately before this node.
+ /// Useful when the node corresponds to a CFG block entrance.
+ /// If the statement belongs to a body-farmed definition, retrieve the
+ /// call site for that definition.
+ const Stmt *getPreviousStmtForDiagnostics() const;
+
+ /// Find the statement that was executed at or immediately before this node.
+ /// Useful when any nearby statement will do.
+ /// If the statement belongs to a body-farmed definition, retrieve the
+ /// call site for that definition.
+ const Stmt *getCurrentOrPreviousStmtForDiagnostics() const;
+
private:
void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
@@ -285,7 +326,7 @@ protected:
BumpVectorContext BVC;
/// NumNodes - The number of nodes in the graph.
- unsigned NumNodes = 0;
+ int64_t NumNodes = 0;
/// A list of recently allocated nodes that can potentially be recycled.
NodeVector ChangedNodes;
@@ -319,10 +360,11 @@ public:
/// ExplodedGraph for further processing.
ExplodedNode *createUncachedNode(const ProgramPoint &L,
ProgramStateRef State,
+ int64_t Id,
bool IsSink = false);
std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
- return llvm::make_unique<ExplodedGraph>();
+ return std::make_unique<ExplodedGraph>();
}
/// addRoot - Add an untyped node to the set of roots.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 2629d7121de4..2d0967616ff2 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -145,9 +145,9 @@ private:
ObjCNoReturn ObjCNoRet;
/// The BugReporter associated with this engine. It is important that
- /// this object be placed at the very end of member variables so that its
- /// destructor is called before the rest of the ExprEngine is destroyed.
- GRBugReporter BR;
+ /// this object be placed at the very end of member variables so that its
+ /// destructor is called before the rest of the ExprEngine is destroyed.
+ PathSensitiveBugReporter BR;
/// The functions which have been analyzed through inlining. This is owned by
/// AnalysisConsumer. It can be null.
@@ -530,7 +530,7 @@ public:
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
const Stmt *S, bool IsBaseDtor,
ExplodedNode *Pred, ExplodedNodeSet &Dst,
- const EvalCallOptions &Options);
+ EvalCallOptions &Options);
void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
ExplodedNode *Pred,
@@ -666,7 +666,7 @@ public:
const LocationContext *LCtx,
ProgramStateRef State);
- /// Evaluate a call, running pre- and post-call checks and allowing checkers
+ /// Evaluate a call, running pre- and post-call checkers and allowing checkers
/// to be responsible for handling the evaluation of the call itself.
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
const CallEvent &Call);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 071e35085a5f..71cbbe28fc25 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -169,6 +169,7 @@ public:
Kind getKind() const { return kind; }
template<typename RegionTy> const RegionTy* getAs() const;
+ template<typename RegionTy> const RegionTy* castAs() const;
virtual bool isBoundable() const { return false; }
@@ -1231,6 +1232,11 @@ const RegionTy* MemRegion::getAs() const {
return nullptr;
}
+template<typename RegionTy>
+const RegionTy* MemRegion::castAs() const {
+ return cast<RegionTy>(this);
+}
+
//===----------------------------------------------------------------------===//
// MemRegionManager - Factory object for creating regions.
//===----------------------------------------------------------------------===//
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index d38058f9af56..07920790c80a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -507,6 +507,10 @@ public:
return *svalBuilder;
}
+ const SValBuilder &getSValBuilder() const {
+ return *svalBuilder;
+ }
+
SymbolManager &getSymbolManager() {
return svalBuilder->getSymbolManager();
}
diff --git a/include/clang/Tooling/ASTDiff/ASTDiff.h b/include/clang/Tooling/ASTDiff/ASTDiff.h
index d6cbc09dcede..c1cc124e1e9f 100644
--- a/include/clang/Tooling/ASTDiff/ASTDiff.h
+++ b/include/clang/Tooling/ASTDiff/ASTDiff.h
@@ -71,7 +71,7 @@ public:
/// Constructs a tree from any AST node.
template <class T>
SyntaxTree(T *Node, ASTContext &AST)
- : TreeImpl(llvm::make_unique<Impl>(this, Node, AST)) {}
+ : TreeImpl(std::make_unique<Impl>(this, Node, AST)) {}
SyntaxTree(SyntaxTree &&Other) = default;
~SyntaxTree();
diff --git a/include/clang/Tooling/AllTUsExecution.h b/include/clang/Tooling/AllTUsExecution.h
index e670f54234a6..1e618b5ba2f0 100644
--- a/include/clang/Tooling/AllTUsExecution.h
+++ b/include/clang/Tooling/AllTUsExecution.h
@@ -44,8 +44,6 @@ public:
StringRef getExecutorName() const override { return ExecutorName; }
- bool isSingleProcess() const override { return true; }
-
using ToolExecutor::execute;
llvm::Error
@@ -71,6 +69,7 @@ private:
unsigned ThreadCount;
};
+extern llvm::cl::opt<unsigned> ExecutorConcurrency;
extern llvm::cl::opt<std::string> Filter;
} // end namespace tooling
diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h
index bf0886034324..c48a8725aae9 100644
--- a/include/clang/Tooling/ArgumentsAdjusters.h
+++ b/include/clang/Tooling/ArgumentsAdjusters.h
@@ -43,6 +43,10 @@ ArgumentsAdjuster getClangSyntaxOnlyAdjuster();
/// arguments.
ArgumentsAdjuster getClangStripOutputAdjuster();
+/// Gets an argument adjuster which removes command line arguments related to
+/// diagnostic serialization.
+ArgumentsAdjuster getClangStripSerializeDiagnosticAdjuster();
+
/// Gets an argument adjuster which removes dependency-file
/// related command line arguments.
ArgumentsAdjuster getClangStripDependencyFileAdjuster();
diff --git a/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
new file mode 100644
index 000000000000..7d0881343478
--- /dev/null
+++ b/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
@@ -0,0 +1,188 @@
+//===- DependencyScanningFilesystem.h - clang-scan-deps fs ===---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_FILESYSTEM_H
+#define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_FILESYSTEM_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <mutex>
+
+namespace clang {
+namespace tooling {
+namespace dependencies {
+
+/// An in-memory representation of a file system entity that is of interest to
+/// the dependency scanning filesystem.
+///
+/// It represents one of the following:
+/// - an opened source file with minimized contents and a stat value.
+/// - an opened source file with original contents and a stat value.
+/// - a directory entry with its stat value.
+/// - an error value to represent a file system error.
+/// - a placeholder with an invalid stat indicating a not yet initialized entry.
+class CachedFileSystemEntry {
+public:
+ /// Default constructor creates an entry with an invalid stat.
+ CachedFileSystemEntry() : MaybeStat(llvm::vfs::Status()) {}
+
+ CachedFileSystemEntry(std::error_code Error) : MaybeStat(std::move(Error)) {}
+
+ /// Create an entry that represents an opened source file with minimized or
+ /// original contents.
+ ///
+ /// The filesystem opens the file even for `stat` calls open to avoid the
+ /// issues with stat + open of minimized files that might lead to a
+ /// mismatching size of the file. If file is not minimized, the full file is
+ /// read and copied into memory to ensure that it's not memory mapped to avoid
+ /// running out of file descriptors.
+ static CachedFileSystemEntry createFileEntry(StringRef Filename,
+ llvm::vfs::FileSystem &FS,
+ bool Minimize = true);
+
+ /// Create an entry that represents a directory on the filesystem.
+ static CachedFileSystemEntry createDirectoryEntry(llvm::vfs::Status &&Stat);
+
+ /// \returns True if the entry is valid.
+ bool isValid() const { return !MaybeStat || MaybeStat->isStatusKnown(); }
+
+ /// \returns True if the current entry points to a directory.
+ bool isDirectory() const { return MaybeStat && MaybeStat->isDirectory(); }
+
+ /// \returns The error or the file's contents.
+ llvm::ErrorOr<StringRef> getContents() const {
+ if (!MaybeStat)
+ return MaybeStat.getError();
+ assert(!MaybeStat->isDirectory() && "not a file");
+ assert(isValid() && "not initialized");
+ return StringRef(Contents);
+ }
+
+ /// \returns The error or the status of the entry.
+ llvm::ErrorOr<llvm::vfs::Status> getStatus() const {
+ assert(isValid() && "not initialized");
+ return MaybeStat;
+ }
+
+ /// \returns the name of the file.
+ StringRef getName() const {
+ assert(isValid() && "not initialized");
+ return MaybeStat->getName();
+ }
+
+ /// Return the mapping between location -> distance that is used to speed up
+ /// the block skipping in the preprocessor.
+ const PreprocessorSkippedRangeMapping &getPPSkippedRangeMapping() const {
+ return PPSkippedRangeMapping;
+ }
+
+ CachedFileSystemEntry(CachedFileSystemEntry &&) = default;
+ CachedFileSystemEntry &operator=(CachedFileSystemEntry &&) = default;
+
+ CachedFileSystemEntry(const CachedFileSystemEntry &) = delete;
+ CachedFileSystemEntry &operator=(const CachedFileSystemEntry &) = delete;
+
+private:
+ llvm::ErrorOr<llvm::vfs::Status> MaybeStat;
+ // Store the contents in a small string to allow a
+ // move from the small string for the minimized contents.
+ // Note: small size of 1 allows us to store an empty string with an implicit
+ // null terminator without any allocations.
+ llvm::SmallString<1> Contents;
+ PreprocessorSkippedRangeMapping PPSkippedRangeMapping;
+};
+
+/// This class is a shared cache, that caches the 'stat' and 'open' calls to the
+/// underlying real file system.
+///
+/// It is sharded based on the hash of the key to reduce the lock contention for
+/// the worker threads.
+class DependencyScanningFilesystemSharedCache {
+public:
+ struct SharedFileSystemEntry {
+ std::mutex ValueLock;
+ CachedFileSystemEntry Value;
+ };
+
+ DependencyScanningFilesystemSharedCache();
+
+ /// Returns a cache entry for the corresponding key.
+ ///
+ /// A new cache entry is created if the key is not in the cache. This is a
+ /// thread safe call.
+ SharedFileSystemEntry &get(StringRef Key);
+
+private:
+ struct CacheShard {
+ std::mutex CacheLock;
+ llvm::StringMap<SharedFileSystemEntry, llvm::BumpPtrAllocator> Cache;
+ };
+ std::unique_ptr<CacheShard[]> CacheShards;
+ unsigned NumShards;
+};
+
+/// A virtual file system optimized for the dependency discovery.
+///
+/// It is primarily designed to work with source files whose contents was was
+/// preprocessed to remove any tokens that are unlikely to affect the dependency
+/// computation.
+///
+/// This is not a thread safe VFS. A single instance is meant to be used only in
+/// one thread. Multiple instances are allowed to service multiple threads
+/// running in parallel.
+class DependencyScanningWorkerFilesystem : public llvm::vfs::ProxyFileSystem {
+public:
+ DependencyScanningWorkerFilesystem(
+ DependencyScanningFilesystemSharedCache &SharedCache,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ ExcludedPreprocessorDirectiveSkipMapping *PPSkipMappings)
+ : ProxyFileSystem(std::move(FS)), SharedCache(SharedCache),
+ PPSkipMappings(PPSkipMappings) {}
+
+ llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override;
+ llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
+ openFileForRead(const Twine &Path) override;
+
+ /// The set of files that should not be minimized.
+ llvm::StringSet<> IgnoredFiles;
+
+private:
+ void setCachedEntry(StringRef Filename, const CachedFileSystemEntry *Entry) {
+ bool IsInserted = Cache.try_emplace(Filename, Entry).second;
+ (void)IsInserted;
+ assert(IsInserted && "local cache is updated more than once");
+ }
+
+ const CachedFileSystemEntry *getCachedEntry(StringRef Filename) {
+ auto It = Cache.find(Filename);
+ return It == Cache.end() ? nullptr : It->getValue();
+ }
+
+ llvm::ErrorOr<const CachedFileSystemEntry *>
+ getOrCreateFileSystemEntry(const StringRef Filename);
+
+ DependencyScanningFilesystemSharedCache &SharedCache;
+ /// The local cache is used by the worker thread to cache file system queries
+ /// locally instead of querying the global cache every time.
+ llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator> Cache;
+ /// The optional mapping structure which records information about the
+ /// excluded conditional directive skip mappings that are used by the
+ /// currently active preprocessor.
+ ExcludedPreprocessorDirectiveSkipMapping *PPSkipMappings;
+};
+
+} // end namespace dependencies
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_FILESYSTEM_H
diff --git a/include/clang/Tooling/DependencyScanning/DependencyScanningService.h b/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
new file mode 100644
index 000000000000..fd8ed80b143c
--- /dev/null
+++ b/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
@@ -0,0 +1,65 @@
+//===- DependencyScanningService.h - clang-scan-deps service ===-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_SERVICE_H
+#define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_SERVICE_H
+
+#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"
+
+namespace clang {
+namespace tooling {
+namespace dependencies {
+
+/// The mode in which the dependency scanner will operate to find the
+/// dependencies.
+enum class ScanningMode {
+ /// This mode is used to compute the dependencies by running the preprocessor
+ /// over
+ /// the unmodified source files.
+ CanonicalPreprocessing,
+
+ /// This mode is used to compute the dependencies by running the preprocessor
+ /// over
+ /// the source files that have been minimized to contents that might affect
+ /// the dependencies.
+ MinimizedSourcePreprocessing
+};
+
+/// The dependency scanning service contains the shared state that is used by
+/// the invidual dependency scanning workers.
+class DependencyScanningService {
+public:
+ DependencyScanningService(ScanningMode Mode, bool ReuseFileManager = true,
+ bool SkipExcludedPPRanges = true);
+
+ ScanningMode getMode() const { return Mode; }
+
+ bool canReuseFileManager() const { return ReuseFileManager; }
+
+ bool canSkipExcludedPPRanges() const { return SkipExcludedPPRanges; }
+
+ DependencyScanningFilesystemSharedCache &getSharedCache() {
+ return SharedCache;
+ }
+
+private:
+ const ScanningMode Mode;
+ const bool ReuseFileManager;
+ /// Set to true to use the preprocessor optimization that skips excluded PP
+ /// ranges by bumping the buffer pointer in the lexer instead of lexing the
+ /// tokens in the range until reaching the corresponding directive.
+ const bool SkipExcludedPPRanges;
+ /// The global file system cache.
+ DependencyScanningFilesystemSharedCache SharedCache;
+};
+
+} // end namespace dependencies
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_SERVICE_H
diff --git a/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
new file mode 100644
index 000000000000..0c9efccb1d8b
--- /dev/null
+++ b/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -0,0 +1,48 @@
+//===- DependencyScanningTool.h - clang-scan-deps service ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_TOOL_H
+#define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_TOOL_H
+
+#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
+#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
+#include "clang/Tooling/JSONCompilationDatabase.h"
+#include <string>
+
+namespace clang{
+namespace tooling{
+namespace dependencies{
+
+/// The high-level implementation of the dependency discovery tool that runs on
+/// an individual worker thread.
+class DependencyScanningTool {
+public:
+ /// Construct a dependency scanning tool.
+ ///
+ /// \param Compilations The reference to the compilation database that's
+ /// used by the clang tool.
+ DependencyScanningTool(DependencyScanningService &Service, const clang::tooling::CompilationDatabase &Compilations);
+
+ /// Print out the dependency information into a string using the dependency
+ /// file format that is specified in the options (-MD is the default) and
+ /// return it.
+ ///
+ /// \returns A \c StringError with the diagnostic output if clang errors
+ /// occurred, dependency file contents otherwise.
+ llvm::Expected<std::string> getDependencyFile(const std::string &Input, StringRef CWD);
+
+private:
+ DependencyScanningWorker Worker;
+ const tooling::CompilationDatabase &Compilations;
+};
+
+} // end namespace dependencies
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_TOOL_H
diff --git a/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
index 3ea261a30d0f..45c9fb4f029d 100644
--- a/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
+++ b/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
@@ -10,17 +10,35 @@
#define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_WORKER_H
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include <string>
namespace clang {
+
+class DependencyOutputOptions;
+
namespace tooling {
namespace dependencies {
+class DependencyScanningService;
+class DependencyScanningWorkerFilesystem;
+
+class DependencyConsumer {
+public:
+ virtual ~DependencyConsumer() {}
+
+ virtual void handleFileDependency(const DependencyOutputOptions &Opts,
+ StringRef Filename) = 0;
+
+ // FIXME: Add support for reporting modular dependencies.
+};
+
/// An individual dependency scanning worker that is able to run on its own
/// thread.
///
@@ -29,26 +47,32 @@ namespace dependencies {
/// using the regular processing run.
class DependencyScanningWorker {
public:
- DependencyScanningWorker();
+ DependencyScanningWorker(DependencyScanningService &Service);
- /// Print out the dependency information into a string using the dependency
- /// file format that is specified in the options (-MD is the default) and
- /// return it.
+ /// Run the dependency scanning tool for a given clang driver invocation (as
+ /// specified for the given Input in the CDB), and report the discovered
+ /// dependencies to the provided consumer.
///
/// \returns A \c StringError with the diagnostic output if clang errors
- /// occurred, dependency file contents otherwise.
- llvm::Expected<std::string> getDependencyFile(const std::string &Input,
- StringRef WorkingDirectory,
- const CompilationDatabase &CDB);
+ /// occurred, success otherwise.
+ llvm::Error computeDependencies(const std::string &Input,
+ StringRef WorkingDirectory,
+ const CompilationDatabase &CDB,
+ DependencyConsumer &Consumer);
private:
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+ std::unique_ptr<ExcludedPreprocessorDirectiveSkipMapping> PPSkipMappings;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> RealFS;
/// The file system that is used by each worker when scanning for
/// dependencies. This filesystem persists accross multiple compiler
/// invocations.
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> WorkerFS;
+ llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
+ /// The file manager that is reused accross multiple invocations by this
+ /// worker. If null, the file manager will not be reused.
+ llvm::IntrusiveRefCntPtr<FileManager> Files;
};
} // end namespace dependencies
diff --git a/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h
index 74f0df5a5b91..ca6f22c5da3b 100644
--- a/include/clang/Tooling/Execution.h
+++ b/include/clang/Tooling/Execution.h
@@ -115,13 +115,6 @@ public:
/// Returns the name of a specific executor.
virtual StringRef getExecutorName() const = 0;
- /// Should return true iff executor runs all actions in a single process.
- /// Clients can use this signal to find out if they can collect results
- /// in-memory (e.g. to avoid serialization costs of using ToolResults).
- /// The single-process executors can still run multiple threads, but all
- /// executions are guaranteed to share the same memory.
- virtual bool isSingleProcess() const = 0;
-
/// Executes each action with a corresponding arguments adjuster.
virtual llvm::Error
execute(llvm::ArrayRef<
diff --git a/include/clang/Tooling/Inclusions/HeaderIncludes.h b/include/clang/Tooling/Inclusions/HeaderIncludes.h
index ec6f0ea45ffe..6e6d6d8fb024 100644
--- a/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ b/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -32,6 +32,7 @@ public:
/// 0. Otherwise, returns the priority of the matching category or INT_MAX.
/// NOTE: this API is not thread-safe!
int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
+ int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
private:
bool isMainHeader(StringRef IncludeName) const;
diff --git a/include/clang/Tooling/Inclusions/IncludeStyle.h b/include/clang/Tooling/Inclusions/IncludeStyle.h
index a0f236e6fc46..266763a5b1bd 100644
--- a/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -58,6 +58,8 @@ struct IncludeStyle {
std::string Regex;
/// The priority to assign to this category.
int Priority;
+ /// The custom priority to sort before grouping.
+ int SortPriority;
bool operator==(const IncludeCategory &Other) const {
return Regex == Other.Regex && Priority == Other.Priority;
}
diff --git a/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h b/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
new file mode 100755
index 000000000000..034a0aaaf6db
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -0,0 +1,51 @@
+//===--- SourceExtraction.cpp - Clang refactoring library -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+
+class LangOptions;
+class SourceManager;
+class SourceRange;
+class Stmt;
+
+namespace tooling {
+
+/// Determines which semicolons should be inserted during extraction.
+class ExtractionSemicolonPolicy {
+public:
+ bool isNeededInExtractedFunction() const {
+ return IsNeededInExtractedFunction;
+ }
+
+ bool isNeededInOriginalFunction() const { return IsNeededInOriginalFunction; }
+
+ /// Returns the semicolon insertion policy that is needed for extraction of
+ /// the given statement from the given source range.
+ static ExtractionSemicolonPolicy compute(const Stmt *S,
+ SourceRange &ExtractedRange,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+private:
+ ExtractionSemicolonPolicy(bool IsNeededInExtractedFunction,
+ bool IsNeededInOriginalFunction)
+ : IsNeededInExtractedFunction(IsNeededInExtractedFunction),
+ IsNeededInOriginalFunction(IsNeededInOriginalFunction) {}
+ bool IsNeededInExtractedFunction;
+ bool IsNeededInOriginalFunction;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif //LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
diff --git a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index 41a448f035a4..c0f995d85c14 100644
--- a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -98,7 +98,17 @@ public:
TypeBeginLoc, TypeEndLoc))
return false;
}
- return visit(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc);
+ if (const Type *TP = Loc.getTypePtr()) {
+ if (TP->getTypeClass() == clang::Type::Record)
+ return visit(TP->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc);
+ }
+ return true;
+ }
+
+ bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ const SourceLocation TypeEndLoc =
+ Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts);
+ return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc);
}
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
@@ -122,8 +132,7 @@ private:
ND, SourceRange(BeginLoc, EndLoc));
}
bool visit(const NamedDecl *ND, SourceLocation Loc) {
- return visit(ND, Loc,
- Loc.getLocWithOffset(ND->getNameAsString().length() - 1));
+ return visit(ND, Loc, Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts));
}
};
diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h b/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
index cc6ae83202f1..fb373fcf5029 100644
--- a/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
+++ b/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
@@ -47,7 +47,7 @@ template <typename RuleType, typename... RequirementTypes, size_t... Is>
void invokeRuleAfterValidatingRequirements(
RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context,
const std::tuple<RequirementTypes...> &Requirements,
- llvm::index_sequence<Is...>) {
+ std::index_sequence<Is...>) {
// Check if the requirements we're interested in can be evaluated.
auto Values =
std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...);
@@ -87,7 +87,7 @@ template <typename... RequirementTypes, size_t... Is>
void visitRefactoringOptions(
RefactoringOptionVisitor &Visitor,
const std::tuple<RequirementTypes...> &Requirements,
- llvm::index_sequence<Is...>) {
+ std::index_sequence<Is...>) {
visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...);
}
@@ -131,7 +131,7 @@ createRefactoringActionRule(const RequirementTypes &... Requirements) {
RefactoringRuleContext &Context) override {
internal::invokeRuleAfterValidatingRequirements<RuleType>(
Consumer, Context, Requirements,
- llvm::index_sequence_for<RequirementTypes...>());
+ std::index_sequence_for<RequirementTypes...>());
}
bool hasSelectionRequirement() override {
@@ -142,13 +142,13 @@ createRefactoringActionRule(const RequirementTypes &... Requirements) {
void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
internal::visitRefactoringOptions(
Visitor, Requirements,
- llvm::index_sequence_for<RequirementTypes...>());
+ std::index_sequence_for<RequirementTypes...>());
}
private:
std::tuple<RequirementTypes...> Requirements;
};
- return llvm::make_unique<Rule>(std::make_tuple(Requirements...));
+ return std::make_unique<Rule>(std::make_tuple(Requirements...));
}
} // end namespace tooling
diff --git a/include/clang/Tooling/StandaloneExecution.h b/include/clang/Tooling/StandaloneExecution.h
index 5fbc1e479c59..8db6229acf7f 100644
--- a/include/clang/Tooling/StandaloneExecution.h
+++ b/include/clang/Tooling/StandaloneExecution.h
@@ -52,8 +52,6 @@ public:
StringRef getExecutorName() const override { return ExecutorName; }
- bool isSingleProcess() const override { return true; }
-
using ToolExecutor::execute;
llvm::Error
diff --git a/include/clang/Tooling/Syntax/Tokens.h b/include/clang/Tooling/Syntax/Tokens.h
index 4640ccb2d30a..301432d3888b 100644
--- a/include/clang/Tooling/Syntax/Tokens.h
+++ b/include/clang/Tooling/Syntax/Tokens.h
@@ -236,6 +236,16 @@ public:
/// #pragma, etc.
llvm::ArrayRef<syntax::Token> spelledTokens(FileID FID) const;
+ /// Get all tokens that expand a macro in \p FID. For the following input
+ /// #define FOO B
+ /// #define FOO2(X) int X
+ /// FOO2(XY)
+ /// int B;
+ /// FOO;
+ /// macroExpansions() returns {"FOO2", "FOO"} (from line 3 and 5
+ /// respecitvely).
+ std::vector<const syntax::Token *> macroExpansions(FileID FID) const;
+
const SourceManager &sourceManager() const { return *SourceMgr; }
std::string dumpForTests() const;
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index 83fe43ac59e0..19421f0a39f3 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -99,9 +99,7 @@ public:
DiagnosticConsumer *DiagConsumer) override;
/// Returns a new clang::FrontendAction.
- ///
- /// The caller takes ownership of the returned action.
- virtual FrontendAction *create() = 0;
+ virtual std::unique_ptr<FrontendAction> create() = 0;
};
/// Returns a new FrontendActionFactory for a given type.
@@ -156,7 +154,7 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
/// clang modules.
///
/// \return - True if 'ToolAction' was successfully executed.
-bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code,
+bool runToolOnCode(std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
const Twine &FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
@@ -179,7 +177,7 @@ using FileContentMappings = std::vector<std::pair<std::string, std::string>>;
///
/// \return - True if 'ToolAction' was successfully executed.
bool runToolOnCodeWithArgs(
- FrontendAction *ToolAction, const Twine &Code,
+ std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
const Twine &ToolName = "clang-tool",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
@@ -188,7 +186,7 @@ bool runToolOnCodeWithArgs(
// Similar to the overload except this takes a VFS.
bool runToolOnCodeWithArgs(
- FrontendAction *ToolAction, const Twine &Code,
+ std::unique_ptr<FrontendAction> ToolAction, const Twine &Code,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
const Twine &ToolName = "clang-tool",
@@ -237,13 +235,13 @@ public:
/// 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 FAction The action to be executed. Class takes ownership.
+ /// \param FAction The action to be executed.
/// \param Files The FileManager used for the execution. Class does not take
/// ownership.
/// \param PCHContainerOps The PCHContainerOperations for loading and creating
/// clang modules.
- ToolInvocation(std::vector<std::string> CommandLine, FrontendAction *FAction,
- FileManager *Files,
+ ToolInvocation(std::vector<std::string> CommandLine,
+ std::unique_ptr<FrontendAction> FAction, FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
@@ -314,12 +312,15 @@ public:
/// clang modules.
/// \param BaseFS VFS used for all underlying file accesses when running the
/// tool.
+ /// \param Files The file manager to use for underlying file operations when
+ /// running the tool.
ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>(),
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS =
- llvm::vfs::getRealFileSystem());
+ llvm::vfs::getRealFileSystem(),
+ IntrusiveRefCntPtr<FileManager> Files = nullptr);
~ClangTool();
@@ -397,7 +398,9 @@ template <typename T>
std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
class SimpleFrontendActionFactory : public FrontendActionFactory {
public:
- FrontendAction *create() override { return new T; }
+ std::unique_ptr<FrontendAction> create() override {
+ return std::make_unique<T>();
+ }
};
return std::unique_ptr<FrontendActionFactory>(
@@ -413,8 +416,9 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
SourceFileCallbacks *Callbacks)
: ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
- FrontendAction *create() override {
- return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
+ std::unique_ptr<FrontendAction> create() override {
+ return std::make_unique<ConsumerFactoryAdaptor>(ConsumerFactory,
+ Callbacks);
}
private:
diff --git a/include/clang/Tooling/Transformer/MatchConsumer.h b/include/clang/Tooling/Transformer/MatchConsumer.h
new file mode 100644
index 000000000000..0a1dbe13ea1e
--- /dev/null
+++ b/include/clang/Tooling/Transformer/MatchConsumer.h
@@ -0,0 +1,62 @@
+//===--- MatchConsumer.h - MatchConsumer abstraction ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This file defines the *MatchConsumer* abstraction: a computation over
+/// match results, specifically the `ast_matchers::MatchFinder::MatchResult`
+/// class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_MATCH_CONSUMER_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_MATCH_CONSUMER_H_
+
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace transformer {
+/// A failable computation over nodes bound by AST matchers.
+///
+/// The computation should report any errors though its return value (rather
+/// than terminating the program) to enable usage in interactive scenarios like
+/// clang-query.
+///
+/// This is a central abstraction of the Transformer framework.
+template <typename T>
+using MatchConsumer =
+ std::function<Expected<T>(const ast_matchers::MatchFinder::MatchResult &)>;
+
+/// Creates an error that signals that a `MatchConsumer` expected a certain node
+/// to be bound by AST matchers, but it was not actually bound.
+inline llvm::Error notBoundError(llvm::StringRef Id) {
+ return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+ "Id not bound: " + Id);
+}
+
+/// Chooses between the two consumers, based on whether \p ID is bound in the
+/// match.
+template <typename T>
+MatchConsumer<T> ifBound(std::string ID, MatchConsumer<T> TrueC,
+ MatchConsumer<T> FalseC) {
+ return [=](const ast_matchers::MatchFinder::MatchResult &Result) {
+ auto &Map = Result.Nodes.getMap();
+ return (Map.find(ID) != Map.end() ? TrueC : FalseC)(Result);
+ };
+}
+} // namespace transformer
+
+namespace tooling {
+// DEPRECATED: Temporary alias supporting client migration to the `transformer`
+// namespace.
+using transformer::ifBound;
+} // namespace tooling
+} // namespace clang
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_MATCH_CONSUMER_H_
diff --git a/include/clang/Tooling/Refactoring/RangeSelector.h b/include/clang/Tooling/Transformer/RangeSelector.h
index b117e4d82ad4..9f556d206321 100644
--- a/include/clang/Tooling/Refactoring/RangeSelector.h
+++ b/include/clang/Tooling/Transformer/RangeSelector.h
@@ -17,14 +17,14 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Transformer/MatchConsumer.h"
#include "llvm/Support/Error.h"
#include <functional>
#include <string>
namespace clang {
-namespace tooling {
-using RangeSelector = std::function<Expected<CharSourceRange>(
- const ast_matchers::MatchFinder::MatchResult &)>;
+namespace transformer {
+using RangeSelector = MatchConsumer<CharSourceRange>;
inline RangeSelector charRange(CharSourceRange R) {
return [R](const ast_matchers::MatchFinder::MatchResult &)
@@ -79,10 +79,34 @@ RangeSelector statements(std::string ID);
// (all source between the braces).
RangeSelector initListElements(std::string ID);
+/// Given an \IfStmt (bound to \p ID), selects the range of the else branch,
+/// starting from the \c else keyword.
+RangeSelector elseBranch(std::string ID);
+
/// Selects the range from which `S` was expanded (possibly along with other
/// source), if `S` is an expansion, and `S` itself, otherwise. Corresponds to
/// `SourceManager::getExpansionRange`.
RangeSelector expansion(RangeSelector S);
+} // namespace transformer
+
+namespace tooling {
+// DEPRECATED: These are temporary aliases supporting client migration to the
+// `transformer` namespace.
+using RangeSelector = transformer::RangeSelector;
+
+using transformer::after;
+using transformer::before;
+using transformer::callArgs;
+using transformer::charRange;
+using transformer::elseBranch;
+using transformer::expansion;
+using transformer::initListElements;
+using transformer::member;
+using transformer::name;
+using transformer::node;
+using transformer::range;
+using transformer::statement;
+using transformer::statements;
} // namespace tooling
} // namespace clang
diff --git a/include/clang/Tooling/Refactoring/Transformer.h b/include/clang/Tooling/Transformer/RewriteRule.h
index 6d9c5a37cc18..6e99151c1c7f 100644
--- a/include/clang/Tooling/Refactoring/Transformer.h
+++ b/include/clang/Tooling/Transformer/RewriteRule.h
@@ -1,4 +1,4 @@
-//===--- Transformer.h - Clang source-rewriting library ---------*- C++ -*-===//
+//===--- RewriteRule.h - RewriteRule class ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,42 +7,30 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// Defines a library supporting the concise specification of clang-based
-/// source-to-source transformations.
+/// Defines the RewriteRule class and related functions for creating,
+/// modifying and interpreting RewriteRules.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_TRANSFORMER_H_
-#define LLVM_CLANG_TOOLING_REFACTOR_TRANSFORMER_H_
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_REWRITE_RULE_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_REWRITE_RULE_H_
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/Tooling/Refactoring/AtomicChange.h"
-#include "clang/Tooling/Refactoring/RangeSelector.h"
+#include "clang/Tooling/Transformer/MatchConsumer.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
-#include <deque>
#include <functional>
#include <string>
-#include <type_traits>
#include <utility>
namespace clang {
-namespace tooling {
-
-// Note that \p TextGenerator is allowed to fail, e.g. when trying to access a
-// matched node that was not bound. Allowing this to fail simplifies error
-// handling for interactive tools like clang-query.
-using TextGenerator = std::function<Expected<std::string>(
- const ast_matchers::MatchFinder::MatchResult &)>;
-
-/// Wraps a string as a TextGenerator.
-inline TextGenerator text(std::string M) {
- return [M](const ast_matchers::MatchFinder::MatchResult &)
- -> Expected<std::string> { return M; };
-}
+namespace transformer {
+using TextGenerator = MatchConsumer<std::string>;
// Description of a source-code edit, expressed in terms of an AST node.
// Includes: an ID for the (bound) node, a selector for source related to the
@@ -160,11 +148,9 @@ inline RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
void addInclude(RewriteRule &Rule, llvm::StringRef Header,
IncludeFormat Format = IncludeFormat::Quoted);
-/// Applies the first rule whose pattern matches; other rules are ignored.
-///
-/// N.B. All of the rules must use the same kind of matcher (that is, share a
-/// base class in the AST hierarchy). However, this constraint is caused by an
-/// implementation detail and should be lifted in the future.
+/// Applies the first rule whose pattern matches; other rules are ignored. If
+/// the matchers are independent then order doesn't matter. In that case,
+/// `applyFirst` is simply joining the set of rules into one.
//
// `applyFirst` is like an `anyOf` matcher with an edit action attached to each
// of its cases. Anywhere you'd use `anyOf(m1.bind("id1"), m2.bind("id2"))` and
@@ -230,7 +216,9 @@ inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) {
/// Removes the source selected by \p S.
inline ASTEdit remove(RangeSelector S) {
- return change(std::move(S), text(""));
+ return change(std::move(S),
+ [](const ast_matchers::MatchFinder::MatchResult &)
+ -> Expected<std::string> { return ""; });
}
/// The following three functions are a low-level part of the RewriteRule
@@ -243,8 +231,25 @@ inline ASTEdit remove(RangeSelector S) {
// public and well-supported and move them out of `detail`.
namespace detail {
/// Builds a single matcher for the rule, covering all of the rule's cases.
+/// Only supports Rules whose cases' matchers share the same base "kind"
+/// (`Stmt`, `Decl`, etc.) Deprecated: use `buildMatchers` instead, which
+/// supports mixing matchers of different kinds.
ast_matchers::internal::DynTypedMatcher buildMatcher(const RewriteRule &Rule);
+/// Builds a set of matchers that cover the rule (one for each distinct node
+/// matcher base kind: Stmt, Decl, etc.). Node-matchers for `QualType` and
+/// `Type` are not permitted, since such nodes carry no source location
+/// information and are therefore not relevant for rewriting. If any such
+/// matchers are included, will return an empty vector.
+std::vector<ast_matchers::internal::DynTypedMatcher>
+buildMatchers(const RewriteRule &Rule);
+
+/// Gets the beginning location of the source matched by a rewrite rule. If the
+/// match occurs within a macro expansion, returns the beginning of the
+/// expansion point. `Result` must come from the matching of a rewrite rule.
+SourceLocation
+getRuleMatchLoc(const ast_matchers::MatchFinder::MatchResult &Result);
+
/// Returns the \c Case of \c Rule that was selected in the match result.
/// Assumes a matcher built with \c buildMatcher.
const RewriteRule::Case &
@@ -273,36 +278,32 @@ Expected<SmallVector<Transformation, 1>>
translateEdits(const ast_matchers::MatchFinder::MatchResult &Result,
llvm::ArrayRef<ASTEdit> Edits);
} // namespace detail
+} // namespace transformer
-/// Handles the matcher and callback registration for a single rewrite rule, as
-/// defined by the arguments of the constructor.
-class Transformer : public ast_matchers::MatchFinder::MatchCallback {
-public:
- using ChangeConsumer =
- std::function<void(Expected<clang::tooling::AtomicChange> Change)>;
-
- /// \param Consumer Receives each rewrite or error. Will not necessarily be
- /// called for each match; for example, if the rewrite is not applicable
- /// because of macros, but doesn't fail. Note that clients are responsible
- /// for handling the case that independent \c AtomicChanges conflict with each
- /// other.
- Transformer(RewriteRule Rule, ChangeConsumer Consumer)
- : Rule(std::move(Rule)), Consumer(std::move(Consumer)) {}
-
- /// N.B. Passes `this` pointer to `MatchFinder`. So, this object should not
- /// be moved after this call.
- void registerMatchers(ast_matchers::MatchFinder *MatchFinder);
+namespace tooling {
+// DEPRECATED: These are temporary aliases supporting client migration to the
+// `transformer` namespace.
+/// Wraps a string as a TextGenerator.
+using TextGenerator = transformer::TextGenerator;
- /// Not called directly by users -- called by the framework, via base class
- /// pointer.
- void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+inline TextGenerator text(std::string M) {
+ return [M](const ast_matchers::MatchFinder::MatchResult &)
+ -> Expected<std::string> { return M; };
+}
-private:
- RewriteRule Rule;
- /// Receives each successful rewrites as an \c AtomicChange.
- ChangeConsumer Consumer;
-};
+using transformer::addInclude;
+using transformer::applyFirst;
+using transformer::change;
+using transformer::insertAfter;
+using transformer::insertBefore;
+using transformer::makeRule;
+using transformer::remove;
+using transformer::RewriteRule;
+using transformer::IncludeFormat;
+namespace detail {
+using namespace transformer::detail;
+} // namespace detail
} // namespace tooling
} // namespace clang
-#endif // LLVM_CLANG_TOOLING_REFACTOR_TRANSFORMER_H_
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_REWRITE_RULE_H_
diff --git a/include/clang/Tooling/Refactoring/SourceCode.h b/include/clang/Tooling/Transformer/SourceCode.h
index 498dbea96c70..bc9cc3d2a258 100644
--- a/include/clang/Tooling/Refactoring/SourceCode.h
+++ b/include/clang/Tooling/Transformer/SourceCode.h
@@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_H
-#define LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_H
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H
+#define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceLocation.h"
@@ -72,6 +72,19 @@ StringRef getExtendedText(const T &Node, tok::TokenKind Next,
ASTContext &Context) {
return getText(getExtendedRange(Node, Next, Context), Context);
}
+
+// Attempts to resolve the given range to one that can be edited by a rewrite;
+// generally, one that starts and ends within a particular file. It supports
+// a limited set of cases involving source locations in macro expansions.
+llvm::Optional<CharSourceRange>
+getRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+inline llvm::Optional<CharSourceRange>
+getRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context) {
+ return getRangeForEdit(EditRange, Context.getSourceManager(),
+ Context.getLangOpts());
+}
} // namespace tooling
} // namespace clang
-#endif // LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_H
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H
diff --git a/include/clang/Tooling/Transformer/SourceCodeBuilders.h b/include/clang/Tooling/Transformer/SourceCodeBuilders.h
new file mode 100644
index 000000000000..6c79a7588f28
--- /dev/null
+++ b/include/clang/Tooling/Transformer/SourceCodeBuilders.h
@@ -0,0 +1,86 @@
+//===--- SourceCodeBuilders.h - Source-code building facilities -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file collects facilities for generating source code strings.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_BUILDERS_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_BUILDERS_H_
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include <string>
+
+namespace clang {
+namespace tooling {
+
+/// \name Code analysis utilities.
+/// @{
+/// Ignores implicit object-construction expressions in addition to the normal
+/// implicit expressions that are ignored.
+const Expr *reallyIgnoreImplicit(const Expr &E);
+
+/// Determines whether printing this expression in *any* expression requires
+/// parentheses to preserve its meaning. This analyses is necessarily
+/// conservative because it lacks information about the target context.
+bool mayEverNeedParens(const Expr &E);
+
+/// Determines whether printing this expression to the left of a dot or arrow
+/// operator requires a parentheses to preserve its meaning. Given that
+/// dot/arrow are (effectively) the highest precedence, this is equivalent to
+/// asking whether it ever needs parens.
+inline bool needParensBeforeDotOrArrow(const Expr &E) {
+ return mayEverNeedParens(E);
+}
+
+/// Determines whether printing this expression to the right of a unary operator
+/// requires a parentheses to preserve its meaning.
+bool needParensAfterUnaryOperator(const Expr &E);
+/// @}
+
+/// \name Basic code-string generation utilities.
+/// @{
+
+/// Builds source for an expression, adding parens if needed for unambiguous
+/// parsing.
+llvm::Optional<std::string> buildParens(const Expr &E,
+ const ASTContext &Context);
+
+/// Builds idiomatic source for the dereferencing of `E`: prefix with `*` but
+/// simplify when it already begins with `&`. \returns empty string on failure.
+llvm::Optional<std::string> buildDereference(const Expr &E,
+ const ASTContext &Context);
+
+/// Builds idiomatic source for taking the address of `E`: prefix with `&` but
+/// simplify when it already begins with `*`. \returns empty string on failure.
+llvm::Optional<std::string> buildAddressOf(const Expr &E,
+ const ASTContext &Context);
+
+/// Adds a dot to the end of the given expression, but adds parentheses when
+/// needed by the syntax, and simplifies to `->` when possible, e.g.:
+///
+/// `x` becomes `x.`
+/// `*a` becomes `a->`
+/// `a+b` becomes `(a+b).`
+llvm::Optional<std::string> buildDot(const Expr &E, const ASTContext &Context);
+
+/// Adds an arrow to the end of the given expression, but adds parentheses
+/// when needed by the syntax, and simplifies to `.` when possible, e.g.:
+///
+/// `x` becomes `x->`
+/// `&a` becomes `a.`
+/// `a+b` becomes `(a+b)->`
+llvm::Optional<std::string> buildArrow(const Expr &E,
+ const ASTContext &Context);
+/// @}
+
+} // namespace tooling
+} // namespace clang
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_BUILDERS_H_
diff --git a/include/clang/Tooling/Refactoring/Stencil.h b/include/clang/Tooling/Transformer/Stencil.h
index e57a576e5575..66d1388f9710 100644
--- a/include/clang/Tooling/Refactoring/Stencil.h
+++ b/include/clang/Tooling/Transformer/Stencil.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
///
-/// /file
+/// \file
/// This file defines the *Stencil* abstraction: a code-generating object,
/// parameterized by named references to (bound) AST nodes. Given a match
/// result, a stencil can be evaluated to a string of source code.
@@ -17,21 +17,21 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_
-#define LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Tooling/Refactoring/RangeSelector.h"
+#include "clang/Tooling/Transformer/MatchConsumer.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include <string>
#include <vector>
namespace clang {
-namespace tooling {
-
+namespace transformer {
/// A stencil is represented as a sequence of "parts" that can each individually
/// generate a code string based on a match result. The different kinds of
/// parts include (raw) text, references to bound nodes and assorted operations
@@ -47,21 +47,18 @@ public:
virtual llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match,
std::string *Result) const = 0;
- virtual bool isEqual(const StencilPartInterface &other) const = 0;
-
- const void *typeId() const { return TypeId; }
+ /// Constructs a string representation of the StencilPart. StencilParts
+ /// generated by the `selection` and `run` functions do not have a unique
+ /// string representation.
+ virtual std::string toString() const = 0;
protected:
- StencilPartInterface(const void *DerivedId) : TypeId(DerivedId) {}
+ StencilPartInterface() = default;
// Since this is an abstract class, copying/assigning only make sense for
// derived classes implementing `clone()`.
StencilPartInterface(const StencilPartInterface &) = default;
StencilPartInterface &operator=(const StencilPartInterface &) = default;
-
- /// Unique identifier of the concrete type of this instance. Supports safe
- /// downcasting.
- const void *TypeId;
};
/// A copyable facade for a std::unique_ptr<StencilPartInterface>. Copies result
@@ -77,12 +74,10 @@ public:
return Impl->eval(Match, Result);
}
- bool operator==(const StencilPart &Other) const {
- if (Impl == Other.Impl)
- return true;
- if (Impl == nullptr || Other.Impl == nullptr)
- return false;
- return Impl->isEqual(*Other.Impl);
+ std::string toString() const {
+ if (Impl == nullptr)
+ return "";
+ return Impl->toString();
}
private:
@@ -119,8 +114,17 @@ public:
return eval(Result);
}
+ /// Constructs a string representation of the Stencil. The string is not
+ /// guaranteed to be unique.
+ std::string toString() const {
+ std::vector<std::string> PartStrings;
+ PartStrings.reserve(Parts.size());
+ for (const auto &Part : Parts)
+ PartStrings.push_back(Part.toString());
+ return llvm::join(PartStrings, ", ");
+ }
+
private:
- friend bool operator==(const Stencil &A, const Stencil &B);
static StencilPart wrap(llvm::StringRef Text);
static StencilPart wrap(RangeSelector Selector);
static StencilPart wrap(StencilPart Part) { return Part; }
@@ -128,14 +132,10 @@ private:
std::vector<StencilPart> Parts;
};
-inline bool operator==(const Stencil &A, const Stencil &B) {
- return A.Parts == B.Parts;
-}
-
-inline bool operator!=(const Stencil &A, const Stencil &B) { return !(A == B); }
-
+//
// Functions for conveniently building stencils.
-namespace stencil {
+//
+
/// Convenience wrapper for Stencil::cat that can be imported with a using decl.
template <typename... Ts> Stencil cat(Ts &&... Parts) {
return Stencil::cat(std::forward<Ts>(Parts)...);
@@ -147,27 +147,75 @@ StencilPart text(llvm::StringRef Text);
/// \returns the source corresponding to the selected range.
StencilPart selection(RangeSelector Selector);
-/// \returns the source corresponding to the identified node.
-/// FIXME: Deprecated. Write `selection(node(Id))` instead.
-inline StencilPart node(llvm::StringRef Id) {
- return selection(tooling::node(Id));
+/// Generates the source of the expression bound to \p Id, wrapping it in
+/// parentheses if it may parse differently depending on context. For example, a
+/// binary operation is always wrapped, while a variable reference is never
+/// wrapped.
+StencilPart expression(llvm::StringRef Id);
+
+/// Constructs an idiomatic dereferencing of the expression bound to \p ExprId.
+/// \p ExprId is wrapped in parentheses, if needed.
+StencilPart deref(llvm::StringRef ExprId);
+
+/// Constructs an expression that idiomatically takes the address of the
+/// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if
+/// needed.
+StencilPart addressOf(llvm::StringRef ExprId);
+
+/// Constructs a `MemberExpr` that accesses the named member (\p Member) of the
+/// object bound to \p BaseId. The access is constructed idiomatically: if \p
+/// BaseId is bound to `e` and \p Member identifies member `m`, then returns
+/// `e->m`, when e is a pointer, `e2->m` when e = `*e2` and `e.m` otherwise.
+/// Additionally, `e` is wrapped in parentheses, if needed.
+StencilPart access(llvm::StringRef BaseId, StencilPart Member);
+inline StencilPart access(llvm::StringRef BaseId, llvm::StringRef Member) {
+ return access(BaseId, text(Member));
}
-/// Variant of \c node() that identifies the node as a statement, for purposes
-/// of deciding whether to include any trailing semicolon. Only relevant for
-/// Expr nodes, which, by default, are *not* considered as statements.
-/// \returns the source corresponding to the identified node, considered as a
-/// statement.
-/// FIXME: Deprecated. Write `selection(statement(Id))` instead.
-inline StencilPart sNode(llvm::StringRef Id) {
- return selection(tooling::statement(Id));
+/// Chooses between the two stencil parts, based on whether \p ID is bound in
+/// the match.
+StencilPart ifBound(llvm::StringRef Id, StencilPart TruePart,
+ StencilPart FalsePart);
+
+/// Chooses between the two strings, based on whether \p ID is bound in the
+/// match.
+inline StencilPart ifBound(llvm::StringRef Id, llvm::StringRef TrueText,
+ llvm::StringRef FalseText) {
+ return ifBound(Id, text(TrueText), text(FalseText));
}
+/// Wraps a MatchConsumer in a StencilPart, so that it can be used in a Stencil.
+/// This supports user-defined extensions to the Stencil language.
+StencilPart run(MatchConsumer<std::string> C);
+
/// For debug use only; semantics are not guaranteed.
///
/// \returns the string resulting from calling the node's print() method.
StencilPart dPrint(llvm::StringRef Id);
+} // namespace transformer
+
+namespace tooling {
+// DEPRECATED: These are temporary aliases supporting client migration to the
+// `transformer` namespace.
+using Stencil = transformer::Stencil;
+using StencilPart = transformer::StencilPart;
+namespace stencil {
+using transformer::access;
+using transformer::addressOf;
+using transformer::cat;
+using transformer::deref;
+using transformer::dPrint;
+using transformer::expression;
+using transformer::ifBound;
+using transformer::run;
+using transformer::selection;
+using transformer::text;
+/// \returns the source corresponding to the identified node.
+/// FIXME: Deprecated. Write `selection(node(Id))` instead.
+inline transformer::StencilPart node(llvm::StringRef Id) {
+ return selection(tooling::node(Id));
+}
} // namespace stencil
} // namespace tooling
} // namespace clang
-#endif // LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
diff --git a/include/clang/Tooling/Transformer/Transformer.h b/include/clang/Tooling/Transformer/Transformer.h
new file mode 100644
index 000000000000..31feacba5e28
--- /dev/null
+++ b/include/clang/Tooling/Transformer/Transformer.h
@@ -0,0 +1,52 @@
+//===--- Transformer.h - Transformer class ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Transformer/RewriteRule.h"
+#include "llvm/Support/Error.h"
+#include <functional>
+#include <utility>
+
+namespace clang {
+namespace tooling {
+/// Handles the matcher and callback registration for a single `RewriteRule`, as
+/// defined by the arguments of the constructor.
+class Transformer : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ using ChangeConsumer =
+ std::function<void(Expected<clang::tooling::AtomicChange> Change)>;
+
+ /// \param Consumer Receives each rewrite or error. Will not necessarily be
+ /// called for each match; for example, if the rewrite is not applicable
+ /// because of macros, but doesn't fail. Note that clients are responsible
+ /// for handling the case that independent \c AtomicChanges conflict with each
+ /// other.
+ Transformer(transformer::RewriteRule Rule, ChangeConsumer Consumer)
+ : Rule(std::move(Rule)), Consumer(std::move(Consumer)) {}
+
+ /// N.B. Passes `this` pointer to `MatchFinder`. So, this object should not
+ /// be moved after this call.
+ void registerMatchers(ast_matchers::MatchFinder *MatchFinder);
+
+ /// Not called directly by users -- called by the framework, via base class
+ /// pointer.
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ transformer::RewriteRule Rule;
+ /// Receives each successful rewrites as an \c AtomicChange.
+ ChangeConsumer Consumer;
+};
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_
diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap
index 1f32ffe0c159..2cbe865bce87 100644
--- a/include/clang/module.modulemap
+++ b/include/clang/module.modulemap
@@ -18,9 +18,9 @@ module Clang_AST {
umbrella "AST"
textual header "AST/BuiltinTypes.def"
+ textual header "AST/CXXRecordDeclDefinitionBits.def"
textual header "AST/OperationKinds.def"
textual header "AST/TypeLocNodes.def"
- textual header "AST/TypeNodes.def"
module * { export * }
}
@@ -31,9 +31,11 @@ module Clang_Basic {
requires cplusplus
umbrella "Basic"
+ textual header "Basic/AArch64SVEACLETypes.def"
textual header "Basic/BuiltinsAArch64.def"
textual header "Basic/BuiltinsAMDGPU.def"
textual header "Basic/BuiltinsARM.def"
+ textual header "Basic/BuiltinsBPF.def"
textual header "Basic/Builtins.def"
textual header "Basic/BuiltinsHexagon.def"
textual header "Basic/BuiltinsLe64.def"
@@ -100,7 +102,7 @@ module Clang_Frontend {
requires cplusplus
umbrella "Frontend"
- textual header "Frontend/LangStandards.def"
+ textual header "Basic/LangStandards.def"
module * { export * }
}